Ansible Vault மூலம் Git-ல் ரகசியங்களை பாதுகாப்பது எப்படி?
Git repository-ல் உள்ள கடவுச்சொற்கள் மற்றும் API tokens-களை Ansible Vault கொண்டு encrypt செய்வது எப்படி என்பதை அறிக. கோப்புகளை encrypt செய்தல், rekey மற்றும் பாதுகாப்பான முறைகளை இதில்
Ansible Vault எவற்றைப் பாதுகாக்கிறது, எவற்றைப் பாதுகாப்பதில்லை
Ansible Vault உங்கள் playbook repository-ல் உள்ள ரகசியங்களை encrypt செய்கிறது. இதனால் git-ல் சேமிக்கப்படுவது plaintext கடவுச்சொற்களுக்குப் பதிலாக ciphertext ஆக இருக்கும். ansible-vault கட்டளை, நீங்கள் தேர்ந்தெடுக்கும் கடவுச்சொல்லிலிருந்து பெறப்பட்ட symmetric key-ஐப் பயன்படுத்தி, ஒரு முழு கோப்பையோ அல்லது கோப்பிற்குள் உள்ள ஒரு தனி மதிப்பையோ encrypt செய்கிறது. play இயங்கும்போது, Ansible அந்த உள்ளடக்கத்தை நினைவகத்தில் (memory) decrypt செய்கிறது; எனவே அந்த variable மற்ற சாதாரண variable-களைப் போலவே செயல்படுகிறது.
இந்த மாதிரியில் ஒரு தெளிவான எல்லை உள்ளது. Vault ஒரு ரகசியத்தை repository-ல் ஓய்வு நிலையில் (at rest) இருக்கும்போது மட்டுமே பாதுகாக்கிறது, அதற்கு மேல் இல்லை. ஒரு task இயங்கத் தொடங்கியதும், அந்த மதிப்பு நினைவகத்தில், உருவாக்கப்பட்ட template-ல், module arguments-ல் மற்றும் run output-ல் plaintext ஆக இருக்கும்; நீங்கள் அதைத் தடுக்காவிட்டால் இதுவே நடக்கும். playbook-ஐ இயக்கக்கூடிய அனைவரும் vault கடவுச்சொல்லை வைத்திருப்பார்கள். எனவே, குழுவிற்கு வெளியே உள்ளவர்களிடமிருந்து மட்டுமே vault உங்களுக்கு ரகசியத்தன்மையை வழங்குகிறது, குழுவிற்குள் இருக்கும் நபர்களுக்கிடையிலான access control-ஐ இது வழங்குவதில்லை.
நீங்கள் இன்னும் playbook எழுதவில்லை என்றால், ஒரு VPS-க்கான முதல் Ansible playbook மூலம் தொடங்கி, அந்த playbook-க்கு கடவுச்சொல் தேவைப்படும்போது மீண்டும் இங்கே வரவும்.
முழு கோப்பையும் குறியாக்க வேண்டுமா அல்லது ஒரு குறிப்பிட்ட சரத்தை (string) மட்டும் குறியாக்க வேண்டுமா?
ansible-vault encrypt ஒரு கோப்பை முழுமையாக ciphertext-ஆக மாற்றுகிறது. அந்த கோப்பு $ANSIBLE_VAULT என்று தொடங்கும் தலைப்பு வரியின் கீழ், base64 உரை கொண்ட ஒரே தொகுதியாக மாறிவிடும். கோப்பில் ரகசியங்கள் (secrets) மட்டுமே இருக்கும்போது இதைப் பயன்படுத்தவும்.
ansible-vault encrypt_string ஒரு மதிப்பை மட்டும் குறியாக்கம் செய்து, அதை நீங்கள் சாதாரண vars கோப்பில் ஒட்டிக்கொள்ளக்கூடிய YAML துணுக்காக (snippet) வழங்குகிறது. இதில் மாறியின் பெயர் (variable name) வாசிக்கக்கூடியதாக இருக்கும், மதிப்பு மட்டும் ciphertext-ஆக இருக்கும். சாதாரண அமைப்புகளுடன் (plaintext settings) ரகசியங்களும் கலந்திருக்கும்போது இதைப் பயன்படுத்தவும்.
தினசரி வேலையில் இவற்றிற்கு இடையேயான முக்கிய வேறுபாடு diff-ல் தெரியும். ஒரு vault கோப்பைச் சேமிக்கும்போதெல்லாம், அது புதிய random salt கொண்டு மீண்டும் குறியாக்கம் செய்யப்படும்; எனவே ciphertext-ன் ஒவ்வொரு பைட்டும் மாறிவிடும். அப்போது git diff ஒரு படிக்க முடியாத தொகுதியை மற்றொரு படிக்க முடியாத தொகுதியாக மாற்றப்பட்டதாகக் காட்டும். இதனால், ஒரு கடவுச்சொல்லை மட்டும் மாற்றினீர்களா அல்லது முழு கோப்பையும் மாற்றினீர்களா என்பதை மதிப்பாய்வு செய்பவரால் (reviewer) கண்டறிய முடியாது. encrypt_string பயன்படுத்தும்போது, ஒவ்வொரு ரகசியமும் plaintext கோப்பிற்குள் தனித்தனி தொகுதியாக இருக்கும். எனவே, எந்த மாறி மாற்றப்பட்டது என்பதை diff துல்லியமாகக் காட்டும், மற்ற பகுதிகள் மாறாமல் இருக்கும்.
inline வடிவத்தைப் பயன்படுத்துவதில் ஒரு குறைபாடு உள்ளது, அது ரகசியங்களை மாற்றும் (rotation) போது வெளிப்படும்: ansible-vault rekey inline தொகுதிகளைப் பாதிக்காது. ரகசியங்களின் பட்டியல் நீளமாகவும், அரிதாகவே மாற்றப்படும் வகையிலும் இருந்தால் கோப்பு வடிவத்தைத் (file form) தேர்ந்தெடுக்கவும். ரகசியங்களும் சாதாரண மாறிகளும் கலந்துள்ள கோப்புகளில், code review பயனுள்ளதாக இருக்க வேண்டும் எனில் inline வடிவத்தைத் தேர்ந்தெடுக்கவும்.
பாதுகாக்கப்பட்டவை எவை என்பதைக் காட்டும் group_vars அமைப்பு
Ansible, group_vars/<group>.yml-ஐ ஏற்றுகிறது, மேலும் group_vars/<group>/ கோப்பகத்திற்குள் உள்ள ஒவ்வொரு கோப்பையும் ஏற்றுகிறது. கோப்பக முறையே சிறந்தது, ஏனெனில் இது ஒரே குழுவிற்குள் plaintext கோப்பையும், encrypted கோப்பையும் அருகருகே வைத்திருக்க அனுமதிக்கிறது.
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-ம் plaintext வடிவில் உள்ளது. கோப்பின் பெயரே எதைக் குறிக்கிறது என்பதால், எதையும் திறக்காமலேயே எந்தெந்த மதிப்புகள் பாதுகாக்கப்பட்டுள்ளன என்பதை ஒரு வாசகரால் பார்க்க முடியும்.
இந்த அமைப்பின் இரண்டாம் பகுதி மறைமுகக் குறிப்பு (indirection) ஆகும். என்க்ரிப்ட் செய்யப்பட்ட கோப்பிற்குள், ஒவ்வொரு மாறியையும் (variable) vault_ என்ற முன்னொட்டுடன் குறிப்பிடவும்.
vault_db_password: "a real password"
vault_grafana_admin_token: "a real token"பின்னர், அதற்கு அருகிலுள்ள plaintext கோப்பிலிருந்து அந்தப் பெயர்களைக் குறிப்பிடவும்.
db_password: "{{ vault_db_password }}"
grafana_admin_token: "{{ vault_grafana_admin_token }}"Roles மற்றும் templates ஆகியவை db_password-ஐப் பயன்படுத்துகின்றன. அந்த மதிப்பு எங்கிருந்து வந்தது என்பதை அவை அறிந்துகொள்வதில்லை, இது playbook மற்றும் role இடையிலான பிரிவை தெளிவாக வைத்திருக்கிறது. plaintext vars.yml, தேடக்கூடிய குறியீட்டுப் பட்டியலாகவும் (searchable index) செயல்படுகிறது: grep -r vault_ group_vars/, எதையும் டிக்ரிப்ட் செய்யாமலேயே, களஞ்சியத்திற்குத் தேவையான அனைத்து ரகசியங்களையும் பட்டியலிடுகிறது. இதற்கான விலை, ஒவ்வொரு ரகசியத்திற்கும் ஒரு கூடுதல் பெயரை உருவாக்க வேண்டியதுதான். மேலும், vault_ பெயரில் ஏதேனும் தட்டச்சுப் பிழை இருந்தால், அது syntax பிழையாக இல்லாமல், run time-ல் வரையறுக்கப்படாத மாறியாக (undefined variable) வெளிப்படும்.
encrypt_string மூலம் ஒரு மாறியை குறியாக்கப்படுத்துதல் (Encrypt)
ansible-vault encrypt_string --vault-id prod@~/.ansible/vault-prod.txt \
--stdin-name 'vault_db_password'ரகசிய மதிப்பை உள்ளீடு செய்து, பின் Ctrl-D விசையை அழுத்தவும். --stdin-name கட்டளையானது standard input மூலம் மதிப்பை வாசிக்கும், இதனால் அது உங்கள் shell history கோப்பில் சேமிக்கப்படாது. மற்றொரு முறையில் மதிப்பை நேரடியாக command line-ல் உள்ளிடலாம், ஆனால் அவ்வாறு செய்தால் shell அதை history கோப்பில் பதிவு செய்துவிடும்:
ansible-vault encrypt_string --vault-id prod@~/.ansible/vault-prod.txt \
'a real password' --name 'vault_db_password'எந்த முறையைப் பயன்படுத்தினாலும், இந்த கட்டளை ஒரு YAML தொகுதியை வெளியீடாகத் தரும். அதை அப்படியே உங்கள் vars கோப்பில் நகலெடுத்து ஒட்டவும். ஏனெனில், !vault குறிச்சொல்லுக்குக் கீழே உள்ள indentation (இடைவெளி) அந்த மதிப்பின் ஒரு பகுதியாகும்.
vault_db_password: !vault |
$ANSIBLE_VAULT;1.2;AES256;prod
6638643965323633646262656665306333616466396630323136393465356136396436383331
3131303163306665326539353837343663313762616561306534373963383531613664393332!vault குறிச்சொல், அந்த scalar ஒரு சாதாரண உரை அல்ல, அது ciphertext என்பதை YAML loader-க்கு உணர்த்துகிறது. இந்த header பகுதியில் format version, cipher, மற்றும் அதை குறியாக்கப்படுத்திய vault ID label ஆகியவை இருக்கும். vault ID இல்லாமல் குறியாக்கப்படுத்தப்பட்ட மதிப்பில் 1.1 header இருக்கும், அதில் label இருக்காது. இதுவும் சரியாகச் செயல்படும், ஆனால் அந்த கடவுச்சொல் எங்கிருந்து வந்தது என்பது குறித்த கூடுதல் தகவல்கள் இதில் இருக்காது.
Vault password எங்கே சேமிக்கப்படுகிறது?
Repository-க்கு வெளியே. இதற்கு விதிவிலக்கே கிடையாது.
--ask-vault-pass ஒவ்வொரு முறை இயக்கும்போதும் ஒருமுறை கேட்கும், எதையும் சேமிக்காது. இது laptop-க்கு ஏற்றது, ஆனால் cron job அல்லது CI runner-க்கு ஏற்றதல்ல.
Password file என்பது அதன் முதல் வரியில் password-ஐக் கொண்ட ஒரு plain text file ஆகும். இதை இறுக்கமான permissions-உடன் காலியாக உருவாக்கி, பின் editor-ல் நிரப்பவும். இதனால் password உங்கள் shell history-க்குச் செல்லாது:
mkdir -p ~/.ansible
install -m 600 /dev/null ~/.ansible/vault-prod.txt
$EDITOR ~/.ansible/vault-prod.txt--vault-password-file-ஐப் பயன்படுத்தி எந்தவொரு command-உடனும் இதைக் குறிப்பிடலாம்:
ansible-playbook -i inventory/hosts.ini playbooks/site.yml \
--vault-password-file ~/.ansible/vault-prod.txtஒவ்வொரு command-லும் இந்த flag-ஐ மீண்டும் மீண்டும் குறிப்பிடுவது மறக்கப்படலாம், எனவே repository-ன் root-ல் உள்ள ansible.cfg-ல் இதை ஒருமுறை அமைக்கவும்.
[defaults]
inventory = inventory/hosts.ini
vault_password_file = ~/.ansible/vault-prod.txtஇதே அமைப்பை ANSIBLE_VAULT_PASSWORD_FILE environment variable மூலமும் படிக்கலாம், இதுவே CI job-களில் பொதுவாகப் பயன்படுத்தப்படும் முறையாகும். அந்த job, தனது credential store-லிருந்து password-ஐ எடுத்து ஒரு temporary directory-ல் உள்ள கோப்பில் எழுதி, variable-ஐ export செய்து, run முடிந்ததும் கோப்பை நீக்கிவிடும். .gitignore-லும் அந்த கோப்பின் பெயரைச் சேர்க்கவும், ஏனெனில் ansible.cfg-ல் உள்ள path commit செய்யப்படுகிறது, எனவே யாராவது தவறுதலாக உண்மையான கோப்பை checkout-க்குள் உருவாக்கிவிட வாய்ப்புள்ளது.
Password file executable ஆக இருந்தால், Ansible அதை இயக்கி, கோப்பை text-ஆகப் படிப்பதற்குப் பதிலாக அதன் standard output-லிருந்து password-ஐப் படிக்கும். வட்டில் எதையும் எழுதாமல், system keyring அல்லது cloud secret manager-லிருந்து vault password-ஐப் பெறுவதற்கு இதுவே வழி. --vault-id வழியாகப் பயன்படுத்தப்படும் script-க்கு கூடுதல் தேவைகள் உள்ளன: அதன் பெயர் -client அல்லது -client மற்றும் ஒரு extension-ல் முடிய வேண்டும், அது executable ஆக இருக்க வேண்டும், --vault-id option-ஐ ஏற்க வேண்டும், மேலும் password-ஐ standard output-ல் அச்சிட வேண்டும்.
இரண்டு vault ID-கள்: staging மற்றும் production
Vault ID என்பது vault password-உடன் இணைக்கப்பட்ட ஒரு label ஆகும், இது label@source என எழுதப்படுகிறது. இதன் மூலம் prompt, அதாவது ஒரு password கோப்பின் பாதை அல்லது client script-ன் பாதை ஆகும். இந்த label-களைப் பயன்படுத்துவதன் மூலம், ஒரே repository-ல் ஒன்றுக்கும் மேற்பட்ட password-களின் கீழ் ரகசியங்களைச் சேமிக்க முடியும். இதனால், staging password-ஐக் கொண்டு 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ஒரு run-க்குத் தேவையான ஒவ்வொரு ID-யையும் வழங்கவும்:
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ஒரு செயல்பாடு பயனர்களுக்கு ஆச்சரியத்தை அளிக்கலாம். இயல்பாக, இந்த label ஒரு குறிப்பு மட்டுமே, பூட்டு அல்ல. Ansible தான் வைத்திருக்கும் ஒவ்வொரு ரகசியத்தையும் கோப்பின் மீது முயற்சி செய்து, ஏதேனும் ஒன்று கோப்பை decrypt செய்யும் வரை தொடரும். எனவே, staging என label செய்யப்பட்ட கோப்பு, production password சரியான key-ஆக இருந்தால் கூடத் திறந்துவிடும். [defaults]-ன் கீழ் vault_id_match = True-ஐ அமைக்கவும், அல்லது ANSIBLE_VAULT_ID_MATCH என்ற environment variable-ஐப் பயன்படுத்தவும். அப்போதுதான், கோப்பின் header-உடன் label பொருந்தும் ரகசியத்தை மட்டுமே Ansible பயன்படுத்தும். இந்தச் சரிபார்ப்பிற்கு 1.2 header தேவை, எனவே இது vault ID மூலம் encrypt செய்யப்பட்ட உள்ளடக்கத்திற்கு மட்டுமே பொருந்தும்.
ஒன்றுக்கும் மேற்பட்ட ID-கள் loaded நிலையில் இருக்கும்போது, எந்த password-ஐக் கொண்டு encrypt செய்வது என்று ansible-vault encrypt-க்குத் தெரியாது. --encrypt-vault-id prod மூலம் அதைக் குறிப்பிடவும், அல்லது ansible.cfg-ல் vault_encrypt_identity-ஐ அமைக்கவும்; இதன் மூலம் repository-க்கு ஒரு default அமையும்.
இதன் பயன் deployment scope-ல் உள்ளது. Staging-ஐ deploy செய்யும் ஒரு CI job-க்கு staging password மட்டுமே வழங்கப்படும். இதனால், ஒரு compromised runner-ஆல் production credentials-ஐப் படிக்க முடியாது. நீங்கள் ஒரே control machine-லிருந்து பல Linux servers-க்கு plays-ஐ இயக்கும்போது, இந்தத் தனிமைப்படுத்தல் ஒரு சிறிய பாதிப்பிற்கும் மிகப்பெரிய பாதிப்பிற்கும் உள்ள வித்தியாசத்தை ஏற்படுத்தும்.
ஒருவர் வெளியேறும்போது vault-ஐ rekey செய்தல்
Rekeying என்பது vault கடவுச்சொல்லை மாற்றி, புதிய கடவுச்சொல்லைக் கொண்டு உள்ளடக்கத்தை மீண்டும் குறியாக்கம் (re-encrypt) செய்யும் செயலாகும். இது எதையும் பழைய நிலைக்கு மாற்றாது. பழைய கடவுச்சொல்லை வைத்திருந்த எவரும், தன்னிடம் உள்ள repository நகல்களைக் கொண்டு பழைய தரவுகளைத் தொடர்ந்து decrypt செய்ய முடியும்; அந்த நகலில் உள்ள ஒவ்வொரு பழைய commit-ம் இதில் அடங்கும். எனவே, ஒரு பயனர் வெளியேறிய கணமே, அந்த vault கடவுச்சொல் பாதுகாப்பற்றதாகிவிட்டது எனக் கருதி, பின்வரும் வரிசையில் மாற்றங்களைச் செய்யவும்.
- Servers மற்றும் third-party services-ல் உள்ள உண்மையான credentials-ஐ மாற்றவும். இந்த படிநிலையே உண்மையில் அணுகலைத் தடுக்கும்.
ansible-vault editமூலம் புதிய மதிப்புகளை vault கோப்புகளில் சேர்க்கவும்.- குறியாக்கம் செய்யப்பட்ட ஒவ்வொரு கோப்பையும் புதிய vault கடவுச்சொல்லுக்கு rekey செய்யவும்.
- புதிய vault கடவுச்சொல்லை, repository அல்லாத ஒரு பாதுகாப்பான தகவல் தொடர்பு வழிமுறை மூலம் தேவைப்படுபவர்களுக்கு மட்டும் வழங்கவும்.
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.ymlrekey ஒரே கட்டளையில் பல கோப்புகளை ஏற்கும், மேலும் --new-vault-id prod@prompt வட்டில் இருந்து வாசிப்பதற்குப் பதிலாக புதிய கடவுச்சொல்லை ஒருமுறை மட்டும் கேட்கும். லேபிளை மாற்ற வேண்டிய கட்டாயம் இல்லையெனில், பழைய லேபிளையே பயன்படுத்தவும்; ஏனெனில், கட்டளை மாற்றியமைக்கும் ஒவ்வொரு கோப்பின் header-லும் அந்த லேபிள் எழுதப்படும்.
இங்குதான் inline வடிவம் உங்களுக்கு கூடுதல் வேலையைத் தருகிறது. ansible-vault rekey முழுமையாக குறியாக்கம் செய்யப்பட்ட கோப்புகளில் மட்டுமே செயல்படும், எனவே plaintext vars கோப்பில் உள்ள !vault தொகுதி மாற்றப்படாமல் அப்படியே இருக்கும். முதலில் அவற்றை கண்டறிந்து, பின் புதிய கடவுச்சொல்லின் கீழ் encrypt_string மூலம் ஒவ்வொன்றையும் மீண்டும் உருவாக்கவும்:
grep -rl '!vault' group_vars/ host_vars/இதுவே இதிலுள்ள சமரசமாகும். Inline தொகுதிகள் உங்களுக்கு வாசிக்கக்கூடிய diff-களைத் தரும், ஆனால் சுழற்சி (rotation) நேரத்தில் நீங்கள் கைமுறையாகச் செயல்பட வேண்டியிருக்கும். முழுமையாக குறியாக்கம் செய்யப்பட்ட கோப்புகள் ஒரே கட்டளையில் சுழற்சி செய்யப்படும், ஆனால் review செய்யும்போது அவை பயனுள்ள தகவலைத் தராது.
உங்கள் வெளியீட்டில் ரகசியத் தகவல் ஏன் இன்னும் காட்டப்படுகிறது
மதிப்பு மறைகுறியாக்கம் (decryption) செய்யப்பட்டவுடன் Vault-ன் பணி முடிந்துவிடுகிறது. ஒரு task-ன் முடிவை Ansible அறிக்கையாகத் தருகிறது. அதன் arguments-ஐ வெளியிடும் ஒரு module, அந்தச் சான்றுகளை (credentials) அந்த அறிக்கைக்குள் கொண்டு செல்கிறது. ஒரு verbose run, template task-ல் உள்ள --diff, தோல்வியடைந்த task-ன் arguments-ஐக் காட்டுதல் அல்லது callback plugin கோப்பில் வெளியீட்டை எழுதுதல் என ஒவ்வொன்றும் plaintext-ஐக் கொண்டிருக்கும். கோப்பை மறைகுறியாக்கம் (encrypt) செய்ததால் மட்டும் இவற்றில் எந்தப் பயனும் இல்லை.
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அப்போதுதான் அந்த task-ன் முடிவை Ansible வெளியீட்டில் காட்டாது. இதனால், அந்த task என்ன கையாண்டது என்பதைப் பதிவு செய்யாமல், அது இயங்கியதை மட்டும் log பதிவு செய்யும். குறிப்பாக loops-ல் இதை அமைக்கவும், ஏனெனில் ஒரு loop ஒவ்வொரு item-க்கும் ஒரு முடிவை அறிக்கையிடும், மேலும் சான்றுகள் அடங்கிய பட்டியலை loop செய்தால் முழுப் பட்டியலும் வெளியீட்டில் வந்துவிடும்.
மறைகுறியாக்கம் நீக்கப்பட்ட ரகசியம் கசியும் பிற நான்கு இடங்கள் கீழே உள்ளன. இவற்றை no_log கட்டுப்படுத்தாது:
- Template மூலம் உருவாக்கப்படும் கோப்பு, நீங்கள் அதற்கு வழங்கிய
modeமற்றும்owner-ஐப் பெற்றுக்கொள்ளும். சான்றுகளைக் கொண்ட எதற்கும்mode: "0600"மற்றும் ஒரு குறிப்பிட்ட உரிமையாளரை (owner) அமைக்கவும், இல்லையெனில் அந்த ரகசியம் target host-ல் அனைவரும் படிக்கும் வகையில் அமைந்துவிடும். ansible.builtin.commandஅல்லதுansible.builtin.shell-க்கு அனுப்பப்படும் ரகசியம், command இயங்கும்போது target host-ன் process list-ல் தோன்றும். அங்குள்ள எந்தவொரு local user-ம் அதைப் படிக்க முடியும். அதற்குப் பதிலாக, அதை ஒரு கோப்பு அல்லது environment variable வழியாக அனுப்பவும்.- Fact caching, சேகரிக்கப்பட்ட தகவல்களை control machine-ன் வட்டில் எழுதும். எனவே, ரகசியத்தைச் சேமித்து வைத்திருக்கும் ஒரு registered variable, யாரும் கவனிக்காத ஒரு cache கோப்பில் முடிவடையலாம்.
- அதே ரகசியம் பொதுவாக இரண்டாவது இடத்திலும் இருக்கும், உதாரணமாக container-ஆல் படிக்கப்படும் environment கோப்பு. அதற்கான விதிகள் தனித்தனியானவை, Compose env கோப்புகளில் சான்றுகளைத் தவிர்த்தல் என்ற பகுதி அதைப் பற்றி விளக்குகிறது.
no_log பிழைத்திருத்தத்தை (debugging) கடினமாக்குகிறது, அதுவே அதன் நோக்கமும் கூட. ஒரு task சரியாக இயங்காதபோது test host-ல் தற்காலிகமாக இதை நீக்கிவிட்டு, மாற்றத்தை production-க்குக் கொண்டு செல்லும் முன் மீண்டும் சேர்த்துவிடவும்.
Plaintext கோப்புகளை விட்டுச் செல்லாமல் encrypted கோப்புகளைப் படித்தல் மற்றும் திருத்துதல்
ansible-vault view group_vars/prod/vault.yml கோப்பை decrypt செய்து ஒரு pager-ல் காட்டும், வட்டில் (disk) எதையும் எழுதாது. ansible-vault edit கோப்பை decrypt செய்து ஒரு தற்காலிகக் கோப்பில் (temporary file) வைக்கும், உங்கள் $EDITOR-ஐத் திறந்து காட்டும், நீங்கள் அதை மூடியதும் மீண்டும் encrypt செய்யும். ansible-vault decrypt-ஐத் தவிர்த்துவிட்டு, மேற்சொன்ன இரண்டையும் பயன்படுத்தவும்; ஏனெனில் ansible-vault decrypt plaintext கோப்பை working tree-ல் அப்படியே விட்டுவிடும். தற்செயலாக stage செய்யப்படும் decrypted vault கோப்புதான், உண்மையான நற்சான்றிதழ்கள் (credentials) பொதுவான repository-க்குச் செல்வதற்கான மிக முக்கியமான வழியாகும்.
Git முழுமையாக encrypt செய்யப்பட்ட கோப்புகளை decrypt செய்து, படிக்கக்கூடிய 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 secrets-ஐ உங்கள் terminal-ல் அச்சிடும்; இது உங்கள் scrollback-லும், screen share-லும் அந்தத் தகவல்கள் பதிவாக வழிவகுக்கும். இது ஒரு கணினியில் ஒரு பயனர் பயன்படுத்தும் உள்ளூர் வசதி மட்டுமே. எனவே git config-ஐ உள்ளூர் அமைப்பாகவே வைத்திருக்கவும். மற்றவர்கள் அதே அமைப்பைச் செய்யாதவரை, அவர்களின் checkout-கள் வேறுவிதமாகச் செயல்படும் என்பதை நினைவில் கொள்ளவும்.
Vault சரியான கருவியாக இல்லாத சூழல்கள்
Vault என்பது ஒவ்வொரு label-க்கும் ஒரு கடவுச்சொல்லைக் கொண்ட கோப்பு வடிவமாகும்; இந்த அமைப்பே அது எப்போது அதன் வரம்பை அடைகிறது என்பதைத் தீர்மானிக்கிறது. பின்வரும் சூழல்களில் ஏதேனும் ஒன்று உண்மையாக இருந்தால், உண்மையான secret store-க்கு மாறவும்.
- உங்களுக்கு தனிநபர் வாரியான அணுகல் தேவைப்படும்போது. Playbook-ஐ இயக்கும் அனைவரும் ஒரே கடவுச்சொல்லைப் பயன்படுத்துகின்றனர்; Vault ID-கள் சூழல் வாரியாகவே அணுகலைப் பிரிக்கின்றன, தனிநபர் வாரியாக அல்ல.
- உங்களுக்கு தணிக்கை சுவடு (audit trail) தேவைப்படும்போது. யார் எதை, எப்போது decrypt செய்தார்கள் என்பது குறித்த எந்தப் பதிவையும் Vault வைப்பதில்லை.
- கால அட்டவணைப்படி கடவுச்சொற்களை மாற்ற (rotation) வேண்டியிருக்கும்போது. Vault-ல் காலாவதி அல்லது பதிப்பு மேலாண்மை கிடையாது; எனவே, ஒரு credential இரண்டு ஆண்டுகளாக மாற்றப்படாமல் இருப்பதை எவரும் அறிய முடியாது.
- இயங்கும் நேரத்தில் (run time) application-க்கே அந்த ரகசியம் தேவைப்படும்போது. ஒரு service தனது database கடவுச்சொல்லை boot செய்யும்போது வாசிக்கிறது என்றால், அதை உங்கள் deployment repository-லிருந்து எடுக்கக்கூடாது.
இந்த நிலையில் முறை மாறுகிறது. Ansible ரகசியங்களைச் சேமிப்பதை நிறுத்திவிட்டு, இயங்கும் நேரத்தில் lookup plugin மூலம் அவற்றை HashiCorp Vault (குழப்பத்தை ஏற்படுத்தும் வகையில் ஒத்த பெயருடைய மற்றொரு தயாரிப்பு), cloud provider-ன் secret manager, அல்லது control machine-ல் உள்ள keyring ஆகியவற்றிலிருந்து பெற்றுக்கொள்ளும். Repository ஒரு பாதையை (path) வைத்திருக்கும், store அந்த மதிப்பை வைத்திருக்கும், மேலும் store அணுகல் பதிவை (access log) பராமரிக்கும். சிறிய குழுக்களுக்கு, API வசதி கொண்ட self-hosted password manager, உதாரணமாக ஒரு Vaultwarden server, அதே பணியைச் சிறிய அளவில் செய்யும்.
ஒரு credential மட்டும் இதிலிருந்து தனித்து நிற்கும். உங்கள் control machine servers-ஐ அடையப் பயன்படுத்தும் SSH key, Vault-ன் சிக்கல் அல்ல; ஏனெனில் எந்தவொரு play-ஐயும் இயக்குவதற்கு முன்பே Ansible-க்கு அது தேவைப்படுகிறது. இதை ஒரு agent மற்றும் passphrase மூலம் கையாளவும், இது SSH key மேலாண்மையின் அடிப்படைகள் குறித்த வழிகாட்டுதலுக்கு இணங்க இருக்க வேண்டும்.
FAQ
முழு vars கோப்பையும் குறியாக்க வேண்டுமா அல்லது ரகசிய சரத்தை (secret string) மட்டும் குறியாக்க வேண்டுமா?
கோப்பில் ரகசியங்கள் மட்டுமே இருந்தால் முழு கோப்பையும் குறியாக்கம் செய்யவும், ஏனெனில் ஒரே கட்டளையில் அனைத்தையும் மாற்ற முடியும் மற்றும் அமைப்பு எளிமையாக இருக்கும். சாதாரண மாறிகளுடன் (ordinary variables) ரகசியங்கள் கலந்திருந்தால் ansible-vault encrypt_string-ஐப் பயன்படுத்தவும், ஏனெனில் அப்போது குறியாக்கம் செய்யப்பட்ட மதிப்பு மட்டுமே diff-ல் மாறும், எந்த மாறி மாற்றப்பட்டது என்பதை மதிப்பாய்வு செய்பவரால் பார்க்க முடியும். இதில் உள்ள சிக்கல் என்னவென்றால், மாற்றும் முறை (rotation) மாறுபடும். ansible-vault rekey முழு கோப்புகளையும் உள்ளடக்கும், ஆனால் உள்ளமைக்கப்பட்ட (inline) !vault தொகுதிகளைத் தொடாது, எனவே புதிய கடவுச்சொல்லின் கீழ் அவற்றை கைமுறையாக மீண்டும் உருவாக்க வேண்டும்.
Ansible Vault கடவுச்சொல் கோப்பை எங்கே சேமிக்க வேண்டும்?
Repository-க்கு வெளியே, 0600 பயன்முறையில் (mode), ~/.ansible/vault-prod.txt போன்ற பாதையில் சேமிக்க வேண்டும். --vault-password-file மூலம் அதைச் சுட்டிக்காட்டவும், அல்லது ansible.cfg-ல் உள்ள [defaults]-ன் கீழ் vault_password_file-ஐ அமைக்கவும், அல்லது சூழலில் (environment) ANSIBLE_VAULT_PASSWORD_FILE-ஐ அமைக்கவும். CI-ல், அந்தந்த credential store-லிருந்து கடவுச்சொல்லை ஒரு தற்காலிகக் கோப்பில் எழுதி, மாறியை export செய்து, பணி முடிந்ததும் கோப்பை நீக்க வேண்டும். கோப்பு executable ஆக இருந்தால், Ansible அதை இயக்கி standard output-லிருந்து கடவுச்சொல்லைப் படிக்கும், இது வட்டில் சேமிப்பதற்குப் பதிலாக keyring-லிருந்து கடவுச்சொல்லைப் பெற அனுமதிக்கிறது.
Staging மற்றும் production-க்கு வெவ்வேறு vault கடவுச்சொற்களை எவ்வாறு பயன்படுத்துவது?
ஒவ்வொரு கடவுச்சொல்லுக்கும் --vault-id staging@/path/to/file மற்றும் --vault-id prod@/path/to/file மூலம் ஒரு லேபிளை வழங்கவும், ஒவ்வொரு சூழலின் கோப்புகளையும் அதன் சொந்த லேபிளின் கீழ் குறியாக்கம் செய்யவும். இயங்கும் நேரத்தில் (run time) இரண்டு ID-களையும் வழங்கவும், அல்லது [defaults]-ன் கீழ் vault_identity_list-ல் அவற்றைப் பட்டியலிடவும். இயல்பாக, Ansible கோப்பைத் திறக்க (decrypt) முயற்சிக்கும் வரை அது வைத்திருக்கும் அனைத்து ரகசியங்களையும் சோதிக்கும், எனவே கோப்பின் தலைப்புடன் (header) பொருந்தும் ரகசியத்தை மட்டும் அது பயன்படுத்த வேண்டும் எனில் vault_id_match = True-ஐ அமைக்கவும். பல ID-கள் ஏற்றப்பட்டிருக்கும்போது, --encrypt-vault-id மூலம் குறியாக்கத்திற்குத் தேவையான ஒன்றைத் தேர்ந்தெடுக்கவும்.
Ansible Vault ரகசியங்கள் run output-ல் தெரிவதைத் தடுக்கிறதா?
இல்லை. Vault என்பது repository-ல் சேமிக்கப்பட்டுள்ள ரகசியங்களை மட்டுமே பாதுகாக்கிறது. ஒரு task இயங்கும்போது, அதன் மதிப்பு plaintext ஆகிவிடும், மேலும் verbose run அல்லது தோல்வியுற்ற task மூலம் அது log-ல் பதிவாகலாம். நற்சான்றிதழ்களைக் (credential) கையாளும் ஒவ்வொரு task-லும் no_log: true-ஐச் சேர்க்கவும், நீங்கள் உருவாக்கும் எந்தவொரு கோப்பிலும் கட்டுப்படுத்தப்பட்ட mode மற்றும் owner-ஐ அமைக்கவும், மேலும் ரகசியங்களை command arguments-ஆக அனுப்புவதைத் தவிர்க்கவும், ஏனெனில் கட்டளை இயங்கும்போது target host-ன் process list-ல் அவை தெரியும்.