SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor

آموزش رمزنگاری فایل‌ها در Ansible Vault برای Git

با استفاده از دستور ansible-vault encrypt فایل‌های حساس شامل رمز عبور و API token را در مخزن Git امن کنید. این راهنما نحوه مدیریت متغیرها و تغییر کلید را توضیح می‌دهد.

آنچه Ansible Vault محافظت می‌کند و آنچه محافظت نمی‌کند

ابزار Ansible Vault اسرار موجود در مخزن playbook شما را رمزنگاری می‌کند، بنابراین آنچه در git ذخیره می‌شود متن رمزنگاری‌شده (ciphertext) است و نه رمز عبور به صورت متن ساده (plaintext). دستور ansible-vault یک فایل کامل یا یک مقدار واحد درون یک فایل را با استفاده از یک کلید متقارن که از رمز عبوری که انتخاب می‌کنید مشتق شده است، رمزنگاری می‌کند. Ansible هنگام اجرای play، آن محتوا را در حافظه رمزگشایی می‌کند، بنابراین متغیر مانند هر متغیر دیگری رفتار می‌کند.

این مدل یک مرز مشخص دارد. Vault از یک راز در حالت سکون (at rest) در مخزن محافظت می‌کند و نه بیشتر. هنگامی که یک task اجرا می‌شود، مقدار در حافظه، در قالب (template) رندر شده، در آرگومان‌های ماژول و در خروجی اجرا به صورت متن ساده است، مگر اینکه جلوی آن را بگیرید. هر کسی که بتواند playbook را اجرا کند، رمز عبور vault را در اختیار دارد؛ بنابراین vault برای شما محرمانگی در برابر افراد خارج از تیم فراهم می‌کند، نه کنترل دسترسی فردی در داخل تیم.

اگر هنوز playbook ننوشته‌اید، با اولین Ansible playbook برای یک VPS شروع کنید و زمانی که آن playbook به رمز عبور نیاز پیدا کرد، به اینجا بازگردید.

رمزنگاری یک فایل کامل یا یک رشته تکی؟

ansible-vault encrypt یک فایل را با متن رمزنگاری‌شده جایگزین می‌کند. فایل به یک بلوک متن base64 تحت یک خط سرآیند که با $ANSIBLE_VAULT شروع می‌شود، تبدیل می‌گردد. زمانی از این روش استفاده کنید که فایل فقط حاوی اطلاعات محرمانه باشد.

ansible-vault encrypt_string یک مقدار را رمزنگاری کرده و یک قطعه کد YAML چاپ می‌کند که می‌توانید آن را در یک فایل متغیرهای معمولی کپی کنید. نام متغیر خوانا باقی می‌ماند و فقط مقدار آن به صورت رمزنگاری‌شده است. زمانی از این روش استفاده کنید که اطلاعات محرمانه در کنار تنظیمات متنی ساده (plaintext) قرار دارند.

تفاوت مهم در کار روزمره، در خروجی diff مشخص می‌شود. یک فایل vault هر بار که آن را ذخیره می‌کنید با یک salt تصادفی جدید دوباره رمزنگاری می‌شود، بنابراین تمام بایت‌های متن رمزنگاری‌شده تغییر می‌کنند. در این حالت git diff یک بلوک غیرقابل خواندن را نشان می‌دهد که با بلوک غیرقابل خواندن دیگری جایگزین شده است؛ این یعنی بازبین (reviewer) نمی‌تواند تشخیص دهد که آیا شما یک رمز عبور را تغییر داده‌اید یا کل فایل را بازنویسی کرده‌اید. با encrypt_string، هر مورد محرمانه یک بلوک مجزا در داخل یک فایل متنی ساده است، بنابراین diff دقیقاً نشان می‌دهد که کدام متغیر تغییر کرده و بقیه فایل دست‌نخورده باقی می‌ماند.

فرم درون‌خطی (inline) هزینه‌ای دارد که هنگام چرخش (rotation) کلیدها مشخص می‌شود: ansible-vault rekey بلوک‌های درون‌خطی را تغییر نمی‌دهد. زمانی که لیست اطلاعات محرمانه طولانی است و به‌ندرت تغییر می‌کند، فرم فایلی را انتخاب کنید. زمانی که فایل ترکیبی از اطلاعات محرمانه و متغیرهای عادی است و می‌خواهید بازبینی کد (code review) معنای واقعی داشته باشد، فرم درون‌خطی را انتخاب کنید.

ساختار group_vars که نشان می‌دهد چه چیزی محافظت‌شده است

Ansible فایل group_vars/<group>.yml را بارگذاری می‌کند و همچنین تمام فایل‌های موجود در دایرکتوری group_vars/<group>/ را فراخوانی می‌نماید. استفاده از فرم دایرکتوری توصیه می‌شود، زیرا به یک گروه اجازه می‌دهد تا یک فایل متنی ساده (plaintext) و یک فایل رمزنگاری‌شده را در کنار هم داشته باشد.

inventory/
  hosts.ini
group_vars/
  all/
    vars.yml
    vault.yml
  web/
    vars.yml
    vault.yml
host_vars/
  db01/
    vars.yml
    vault.yml
playbooks/
  site.yml

هر vault.yml رمزنگاری‌شده است. هر vars.yml متن ساده است. خواننده می‌تواند بدون باز کردن فایل‌ها تشخیص دهد کدام مقادیر محافظت‌شده هستند، زیرا نام فایل گویای این موضوع است.

نیمه دوم این الگو، استفاده از ارجاع غیرمستقیم (indirection) است. در داخل فایل رمزنگاری‌شده، پیشوند vault_ را به ابتدای هر متغیر اضافه کنید.

vault_db_password: "a real password"
vault_grafana_admin_token: "a real token"

سپس از فایل متنی ساده که در کنار آن قرار دارد، به آن نام‌ها ارجاع دهید.

db_password: "{{ vault_db_password }}"
grafana_admin_token: "{{ vault_grafana_admin_token }}"

نقش‌ها (Roles) و قالب‌ها (Templates) از db_password استفاده می‌کنند و هرگز متوجه نمی‌شوند که مقدار از کجا آمده است؛ این کار باعث می‌شود تفکیک بین playbook و role تمیز باقی بماند. فایل متنی ساده vars.yml به عنوان یک فهرست قابل جستجو عمل می‌کند: grep -r vault_ group_vars/ تمام اسراری که مخزن انتظار دارد را بدون نیاز به رمزگشایی لیست می‌کند. هزینه این کار، یک نام اضافه برای هر مورد محرمانه است و بروز غلط تایپی در نام vault_ در زمان اجرا به صورت یک متغیر تعریف‌نشده ظاهر می‌شود، نه به عنوان یک خطای نحوی (syntax error).

رمزنگاری یک متغیر با encrypt_string

ansible-vault encrypt_string --vault-id prod@~/.ansible/vault-prod.txt \
  --stdin-name 'vault_db_password'

مقدار محرمانه را تایپ کرده و سپس Ctrl-D را فشار دهید. ابزار --stdin-name مقدار را از ورودی استاندارد می‌خواند که باعث می‌شود این مقدار در فایل تاریخچه (history) شل شما ذخیره نشود. روش دیگر، قرار دادن مقدار در خط فرمان است که در آن صورت شل آن را ثبت می‌کند:

ansible-vault encrypt_string --vault-id prod@~/.ansible/vault-prod.txt \
  'a real password' --name 'vault_db_password'

در هر دو حالت، دستور یک بلوک YAML چاپ می‌کند. آن را دقیقاً همان‌طور که چاپ شده است در فایل vars جای‌گذاری کنید، زیرا تورفتگی زیر برچسب !vault بخشی از مقدار است.

vault_db_password: !vault |
          $ANSIBLE_VAULT;1.2;AES256;prod
          6638643965323633646262656665306333616466396630323136393465356136396436383331
          3131303163306665326539353837343663313762616561306534373963383531613664393332

برچسب !vault به لودر YAML می‌گوید که این مقدار، متن رمزنگاری‌شده است و نه متن ساده. سرآیند (header) شامل نسخه فرمت، الگوریتم رمزنگاری و برچسب شناسه vault است که آن را رمزنگاری کرده است. مقداری که بدون شناسه vault رمزنگاری شده باشد، دارای سرآیند 1.1 بدون برچسب است که همچنان کار می‌کند و صرفاً اطلاعات کمتری درباره منبع رمز عبور به شما می‌دهد.

رمز عبور vault کجا نگهداری می‌شود؟

خارج از مخزن (repository). این تنها قانونی است که هیچ استثنایی ندارد.

--ask-vault-pass در هر بار اجرا یک بار درخواست رمز می‌کند و چیزی را ذخیره نمی‌کند. این روش برای لپ‌تاپ مناسب است، اما برای cron job یا CI runner مناسب نیست.

فایل رمز عبور یک فایل متنی ساده است که خط اول آن همان رمز عبور است. آن را با دسترسی‌های محدود ایجاد کنید و سپس در یک ویرایشگر پر کنید تا رمز عبور هرگز به تاریخچه shell شما وارد نشود:

mkdir -p ~/.ansible
install -m 600 /dev/null ~/.ansible/vault-prod.txt
$EDITOR ~/.ansible/vault-prod.txt

با استفاده از --vault-password-file هر دستوری را به آن ارجاع دهید:

ansible-playbook -i inventory/hosts.ini playbooks/site.yml \
  --vault-password-file ~/.ansible/vault-prod.txt

تکرار این پرچم در هر دستور ممکن است فراموش شود، بنابراین آن را یک بار در ansible.cfg در ریشه مخزن تنظیم کنید.

[defaults]
inventory = inventory/hosts.ini
vault_password_file = ~/.ansible/vault-prod.txt

همین تنظیم از متغیر محیطی ANSIBLE_VAULT_PASSWORD_FILE نیز خوانده می‌شود؛ این همان روشی است که یک job در CI معمولاً رمز را تأمین می‌کند. job رمز عبور را از محل ذخیره اعتبارنامه‌های خود در فایلی در یک دایرکتوری موقت می‌نویسد، متغیر را export می‌کند و پس از پایان اجرا، فایل را حذف می‌کند. الگوی نام فایل را نیز به .gitignore اضافه کنید، زیرا مسیر موجود در ansible.cfg در مخزن commit می‌شود و دیر یا زود کسی فایل واقعی را داخل checkout ایجاد خواهد کرد.

اگر فایل رمز عبور قابل‌اجرا (executable) باشد، Ansible آن را اجرا کرده و رمز عبور را از خروجی استاندارد (standard output) می‌خواند، به جای اینکه فایل را به عنوان متن بخواند. این روشی است که می‌توانید رمز عبور vault را از یک keyring سیستمی یا یک مدیریت‌کننده اسرار ابری (cloud secret manager) بدون نوشتن آن روی دیسک دریافت کنید. اسکریپتی که از طریق --vault-id استفاده می‌شود، الزامات اضافه‌ای دارد: نام آن باید به -client یا -client به همراه یک پسوند ختم شود، باید قابل‌اجرا باشد، باید گزینه --vault-id را بپذیرد و باید رمز عبور را در خروجی استاندارد چاپ کند.

دو شناسه vault: staging و production

شناسه vault یک برچسب است که به رمز عبور vault متصل می‌شود و به صورت label@source نوشته می‌شود. منبع آن prompt، مسیر فایل رمز عبور یا مسیر اسکریپت کلاینت است. برچسب‌ها به یک مخزن اجازه می‌دهند تا اسرار را تحت بیش از یک رمز عبور نگه دارد، بنابراین رمز عبور staging فایل production را باز نمی‌کند.

ansible-vault encrypt --vault-id staging@~/.ansible/vault-staging.txt \
  group_vars/staging/vault.yml
ansible-vault encrypt --vault-id prod@~/.ansible/vault-prod.txt \
  group_vars/prod/vault.yml

هر شناسه‌ای که یک اجرا ممکن است به آن نیاز داشته باشد را ارسال کنید:

ansible-playbook playbooks/site.yml \
  --vault-id staging@~/.ansible/vault-staging.txt \
  --vault-id prod@~/.ansible/vault-prod.txt

یا آن‌ها را یک‌بار در ansible.cfg لیست کنید:

[defaults]
vault_identity_list = staging@~/.ansible/vault-staging.txt, prod@~/.ansible/vault-prod.txt

یک رفتار کاربران را غافلگیر می‌کند. به‌طور پیش‌فرض، برچسب یک راهنما است، نه یک قفل. Ansible هر رازی را که در حال حاضر در اختیار دارد روی فایل امتحان می‌کند تا زمانی که یکی از آن‌ها فایل را رمزگشایی کند، بنابراین فایلی که با staging برچسب‌گذاری شده است، همچنان باز می‌شود اگر رمز عبور production به‌طور اتفاقی کلید درست باشد. گزینه vault_id_match = True را در زیر [defaults] تنظیم کنید، یا متغیر محیطی ANSIBLE_VAULT_ID_MATCH را مقداردهی کنید تا Ansible فقط از رازی استفاده کند که برچسب آن با هدر فایل مطابقت دارد. این بررسی به هدر 1.2 نیاز دارد، بنابراین فقط برای محتوایی اعمال می‌شود که در وهله اول با یک شناسه vault رمزگذاری شده باشد.

با بارگذاری بیش از یک شناسه، ansible-vault encrypt دیگر نمی‌داند با کدام رمز عبور رمزگذاری را انجام دهد. آن را با --encrypt-vault-id prod نام‌گذاری کنید، یا vault_encrypt_identity را در ansible.cfg تنظیم کنید تا مخزن یک مقدار پیش‌فرض داشته باشد.

مزیت این کار، دامنه استقرار است. به یک job در CI که staging را مستقر می‌کند، فقط رمز عبور staging داده می‌شود، بنابراین یک runner نفوذپذیر نمی‌تواند اعتبارنامه‌های production را بخواند. هنگامی که در حال اجرای playها در مجموعه‌ای از سرورهای لینوکس از یک ماشین کنترل هستید، این جداسازی تفاوت بین یک حادثه کوچک و یک حادثه بسیار بزرگ است.

تغییر کلید vault هنگام خروج یکی از اعضا

تغییر کلید (Rekeying) رمز عبور vault را تغییر داده و محتوا را با رمز جدید دوباره رمزنگاری می‌کند. این کار هیچ تغییری را به حالت قبل برنمی‌گرداند. هر کسی که در گذشته رمز عبور قدیمی را در اختیار داشته، همچنان می‌تواند هر نسخه‌ای از مخزن (repository) را که نزد خود نگه داشته است، از جمله تمام commitهای قدیمی در آن نسخه را رمزگشایی کند. بنابراین، به محض خروج یکی از دارندگان رمز، رمز عبور vault را سوخته تلقی کنید و چرخش (rotation) را به ترتیب زیر انجام دهید:

  1. اعتبارنامه‌های واقعی را در سرورها و سرویس‌های شخص ثالث تغییر دهید. این مرحله تنها بخشی است که دسترسی را واقعاً لغو می‌کند.
  2. مقادیر جدید را با استفاده از ansible-vault edit در فایل‌های vault قرار دهید.
  3. تمام فایل‌های رمزنگاری‌شده را با یک رمز عبور جدید برای vault دوباره کلیدگذاری (rekey) کنید.
  4. رمز عبور جدید vault را از طریق کانالی غیر از مخزن، به افرادی که همچنان به آن نیاز دارند، تحویل دهید.
ansible-vault rekey --vault-id prod@~/.ansible/vault-prod-old.txt \
  --new-vault-id prod@prompt \
  group_vars/prod/vault.yml host_vars/db01/vault.yml

دستور rekey چندین فایل را در یک فرمان می‌پذیرد و --new-vault-id prod@prompt به جای خواندن از دیسک، یک بار رمز عبور جدید را درخواست می‌کند. برچسب (label) را تغییر ندهید مگر اینکه دلیل خاصی برای آن داشته باشید، زیرا این برچسب در هدر تمام فایل‌هایی که دستور بازنویسی می‌کند، نوشته می‌شود.

اینجاست که فرمت inline برای شما هزینه دارد. دستور ansible-vault rekey روی فایل‌های کاملاً رمزنگاری‌شده عمل می‌کند، بنابراین بلوک !vault که درون یک فایل vars متنی ساده قرار دارد، دست‌نخورده باقی می‌ماند. ابتدا آن‌ها را پیدا کنید و سپس هر کدام را با encrypt_string تحت رمز عبور جدید بازتولید کنید:

grep -rl '!vault' group_vars/ host_vars/

این تمام ماجرا و بده‌بستان در این روش است. بلوک‌های inline به شما diffهای خوانا می‌دهند و در زمان چرخش رمز، هزینه یک بررسی دستی را به شما تحمیل می‌کنند. فایل‌های کاملاً رمزنگاری‌شده با یک دستور تغییر می‌کنند اما در هنگام بررسی (review)، هیچ اطلاعات مفیدی به شما نمی‌دهند.

چرا رمز همچنان در خروجی شما ظاهر می‌شود

لحظه‌ای که مقدار رمزگشایی می‌شود، کار Vault به پایان می‌رسد. Ansible نتیجه یک task را گزارش می‌دهد و ماژولی که آرگومان‌های خود را بازتاب می‌دهد، اعتبارنامه را به آن گزارش منتقل می‌کند. اجرای verbose، استفاده از --diff در یک task از نوع template، شکست خوردن یک task که آرگومان‌هایش را چاپ می‌کند، یا یک callback plugin که خروجی را در فایلی می‌نویسد، همگی حاوی متن ساده (plaintext) خواهند بود. رمزگذاری فایل هیچ تأثیری بر هیچ‌کدام از این موارد ندارد.

no_log: true سوئیچ مورد نظر است. آن را روی هر task که اعتبارنامه‌ای دریافت می‌کند، تنظیم کنید.

- name: Write the application environment file
  ansible.builtin.template:
    src: app.env.j2
    dest: /etc/myapp/app.env
    owner: myapp
    group: myapp
    mode: "0600"
  no_log: true

در این صورت Ansible نتیجه آن task را از خروجی حذف می‌کند، بنابراین لاگ ثبت می‌کند که task اجرا شده است بدون اینکه محتوایی که پردازش کرده را ثبت کند. این مورد را به‌ویژه برای حلقه‌ها (loops) تنظیم کنید، زیرا یک حلقه به ازای هر آیتم یک نتیجه گزارش می‌دهد و حلقه روی یک لیست از اعتبارنامه‌ها، کل لیست را گزارش خواهد کرد.

چهار جای دیگر وجود دارد که رمز رمزگشایی‌شده نشت می‌کند و no_log هیچ‌کدام را پوشش نمی‌دهد:

  • فایلی که از یک template رندر می‌شود، mode و owner که به آن داده‌اید را به ارث می‌برد. برای هر چیزی که حاوی اعتبارنامه است، mode: "0600" و یک مالک (owner) مشخص تنظیم کنید، در غیر این صورت رمز روی میزبان مقصد برای همه قابل خواندن خواهد بود.
  • رمزی که به ansible.builtin.command یا ansible.builtin.shell پاس داده می‌شود، در حین اجرای دستور در لیست پردازش‌های (process list) میزبان مقصد ظاهر می‌شود، جایی که هر کاربر محلی می‌تواند آن را بخواند. به‌جای آن، رمز را از طریق یک فایل یا یک متغیر محیطی (environment variable) پاس دهید.
  • کش کردن فکت‌ها (Fact caching)، فکت‌های جمع‌آوری‌شده را روی دیسک در ماشین کنترل می‌نویسد، بنابراین یک متغیر ثبت‌شده (registered variable) که حاوی رمز است، ممکن است در یک فایل کش قرار بگیرد که هیچ‌کس آن را حساس تلقی نمی‌کند.
  • همان رمز معمولاً در جای دومی نیز وجود دارد، مانند یک فایل محیطی که توسط یک container خوانده می‌شود. قوانین آنجا متفاوت است و دور نگه داشتن اعتبارنامه‌ها از فایل‌های env در Compose آن بخش را پوشش می‌دهد.

no_log عیب‌یابی را دشوارتر می‌کند، که دقیقاً هدف آن همین است. هنگامی که یک task به درستی کار نمی‌کند، آن را به‌طور موقت روی یک میزبان تست حذف کنید و پیش از آنکه تغییرات به محیط production برسد، دوباره آن را قرار دهید.

خواندن و ویرایش فایل‌های رمزنگاری‌شده بدون باقی ماندن متن ساده

ansible-vault view group_vars/prod/vault.yml فایل را در یک pager رمزگشایی می‌کند و هیچ چیزی روی دیسک نمی‌نویسد. ansible-vault edit فایل را در یک فایل موقت رمزگشایی کرده، $EDITOR شما را باز می‌کند و پس از بستن آن، دوباره فایل را رمزنگاری می‌کند. هر دو روش را به ansible-vault decrypt ترجیح دهید، زیرا در روش دوم یک فایل متن ساده در دایرکتوری کاری باقی می‌ماند. استیج شدن تصادفی یک فایل vault رمزگشایی‌شده، رایج‌ترین راه نشت اعتبارنامه‌های واقعی به یک مخزن عمومی است.

Git می‌تواند با رمزگشایی لحظه‌ای فایل‌های کاملاً رمزنگاری‌شده، یک diff خوانا برای آن‌ها نمایش دهد:

git config --local diff.ansible-vault.textconv "ansible-vault view --vault-password-file ~/.ansible/vault-prod.txt"
printf '%s\n' 'group_vars/**/vault.yml diff=ansible-vault' >> .gitattributes

پیش از فعال‌سازی، درک کنید که این دستور چه کاری انجام می‌دهد. git diff اکنون اسرار محیط عملیاتی (production) را در ترمینال شما چاپ می‌کند که باعث می‌شود آن‌ها در تاریخچه اسکرول (scrollback) و هرگونه اشتراک‌گذاری صفحه نمایش ظاهر شوند. این یک ابزار راحتی محلی برای یک نفر روی یک ماشین است، بنابراین git config را محلی نگه دارید و انتظار نداشته باشید که مخازن سایر افراد به همین شکل رفتار کنند، مگر اینکه آن‌ها نیز تنظیمات مشابهی را اعمال کرده باشند.

چه زمانی Vault دیگر ابزار مناسبی نیست

Vault یک فرمت فایل است که برای هر برچسب یک رمز عبور در نظر می‌گیرد و همین ساختار، محدودیت‌های آن را تعیین می‌کند. در صورت صادق بودن هر یک از موارد زیر، به یک مخزن مدیریت اسرار (Secret Store) واقعی مهاجرت کنید:

  • نیاز به دسترسی سطح کاربر دارید. هر کسی که Playbook را اجرا می‌کند، رمز عبور یکسانی در اختیار دارد و شناسه‌های Vault دسترسی را بر اساس محیط تفکیک می‌کنند، نه بر اساس شخص.
  • نیاز به گزارش حسابرسی (Audit Trail) دارید. Vault هیچ رکوردی از اینکه چه کسی چه چیزی را رمزگشایی کرده یا چه زمانی این کار انجام شده، ثبت نمی‌کند.
  • نیاز به چرخش دوره‌ای (Rotation) دارید. Vault فاقد قابلیت انقضا و نسخه‌بندی است، بنابراین هیچ مکانیزمی به شما نمی‌گوید که یک اعتبارنامه در 2 سال گذشته تغییر نکرده است.
  • خودِ برنامه در زمان اجرا به آن Secret نیاز دارد. سرویسی که رمز عبور دیتابیس خود را هنگام بوت می‌خواند، نباید آن را از مخزن استقرار (Deployment Repository) شما بخواند.

در این حالت، الگو معکوس می‌شود. Ansible دیگر اسرار را ذخیره نمی‌کند، بلکه آن‌ها را در زمان اجرا از طریق یک Lookup Plugin از HashiCorp Vault (محصولی متفاوت با نامی مشابه و گیج‌کننده)، سرویس مدیریت اسرار یک ارائه‌دهنده ابری، یا یک Keyring روی ماشین کنترل‌کننده دریافت می‌کند. مخزن کد فقط مسیر (Path) را نگه می‌دارد، مخزن اسرار مقدار را نگه می‌دارد و لاگ دسترسی را ثبت می‌کند. برای تیم‌های کوچک، یک Password Manager خودمیزبان (Self-hosted) دارای API، مانند یک سرور Vaultwarden، همین کار را با مقیاسی کوچک‌تر انجام می‌دهد.

یک اعتبارنامه خارج از تمام این موارد باقی می‌ماند. کلید SSH که ماشین کنترل‌کننده شما برای دسترسی به سرورها استفاده می‌کند، مسئله‌ای مربوط به Vault نیست؛ زیرا Ansible پیش از اجرای هر Play به آن نیاز دارد. این مورد را با استفاده از یک Agent و یک Passphrase، مطابق با اصول مدیریت کلید SSH، مدیریت کنید.

FAQ

آیا باید کل فایل vars را رمزنگاری کنم یا فقط رشتهٔ محرمانه را؟

وقتی فایل فقط شامل داده‌های محرمانه است، کل آن را رمزنگاری کنید؛ زیرا با یک دستور، کل فایل تغییر می‌کند و ساختار آن ساده باقی می‌ماند. زمانی که داده‌های محرمانه در کنار متغیرهای معمولی قرار دارند، از ansible-vault encrypt_string استفاده کنید، زیرا در این حالت فقط مقدار رمزنگاری‌شده در diff تغییر می‌کند و بازبین می‌تواند تشخیص دهد کدام متغیر دستخوش تغییر شده است. هزینهٔ این کار، دشوارتر شدن چرخش (rotation) است. ansible-vault rekey کل فایل‌ها را پوشش می‌دهد و بلوک‌های درون‌خطی !vault را دست‌نخورده باقی می‌گذارد؛ بنابراین این بلوک‌ها باید تحت رمز عبور جدید به‌صورت دستی بازتولید شوند.

فایل رمز عبور Ansible Vault باید کجا ذخیره شود؟

خارج از مخزن (repository)، با مجوز 0600 و در مسیری مانند ~/.ansible/vault-prod.txt. با استفاده از --vault-password-file به آن اشاره کنید، یا vault_password_file را در بخش [defaults] از فایل ansible.cfg تنظیم کنید، یا ANSIBLE_VAULT_PASSWORD_FILE را در محیط (environment) تعریف نمایید. در CI، اجازه دهید job رمز عبور را از مخزن اعتبارنامه‌های خود در یک فایل موقت بنویسد، متغیر را export کند و پس از پایان job، فایل را حذف نماید. اگر فایل قابل‌اجرا (executable) باشد، Ansible آن را اجرا کرده و رمز عبور را از خروجی استاندارد می‌خواند؛ این کار به شما امکان می‌دهد رمز را به‌جای ذخیره روی دیسک، از یک keyring فراخوانی کنید.

چگونه از رمزهای عبور مختلف Vault برای staging و production استفاده کنم؟

به هر رمز عبور با استفاده از --vault-id staging@/path/to/file و --vault-id prod@/path/to/file یک برچسب (label) اختصاص دهید و فایل‌های هر محیط را با برچسب مخصوص به خود رمزنگاری کنید. هر دو شناسه را در زمان اجرا (run time) ارسال کنید یا آن‌ها را در vault_identity_list زیر بخش [defaults] فهرست نمایید. به‌صورت پیش‌فرض، Ansible تمام اسرار موجود را امتحان می‌کند تا فایل رمزگشایی شود؛ بنابراین اگر می‌خواهید فقط رمزی که برچسب آن با هدر فایل مطابقت دارد امتحان شود، vault_id_match = True را تنظیم کنید. با بارگذاری چندین شناسه، از --encrypt-vault-id برای انتخاب شناسهٔ رمزنگاری استفاده کنید.

آیا Ansible Vault از نمایش رمز عبور در خروجی اجرا جلوگیری می‌کند؟

خیر. Vault فقط از داده‌های محرمانه در حالت سکون (at rest) در مخزن محافظت می‌کند. هنگامی که یک task اجرا می‌شود، مقدار به‌صورت متن ساده (plaintext) است و اجرای verbose یا یک task ناموفق می‌تواند آن را به لاگ منتقل کند. به هر task که با اعتبارنامه‌ها سروکار دارد، no_log: true را اضافه کنید، برای هر فایلی که template می‌کنید mode و owner محدودکننده تنظیم نمایید و از ارسال داده‌های محرمانه به‌عنوان آرگومان‌های دستور خودداری کنید؛ زیرا این آرگومان‌ها در حین اجرای دستور، در لیست پردازش‌های میزبان مقصد قابل‌مشاهده هستند.