우분투 12.04에서 새 사용자를 만드는 ansible 작업이 있습니다.
- name: Add deployment user
action: user name=deployer password=mypassword
예상대로 완료되지만 해당 사용자로 로그인하고 암호로 sudo를 시도하면 항상 잘못되었다고 설정합니다. 내가 뭘 잘못하고 있죠?
우분투 12.04에서 새 사용자를 만드는 ansible 작업이 있습니다.
- name: Add deployment user
action: user name=deployer password=mypassword
예상대로 완료되지만 해당 사용자로 로그인하고 암호로 sudo를 시도하면 항상 잘못되었다고 설정합니다. 내가 뭘 잘못하고 있죠?
답변:
user
모듈 에 대한 Ansible의 매뉴얼을 읽으면 parameter 사용 방법에 대한 자세한 내용을 Ansible-examples github repo 로 안내합니다 .password
암호가 해시되어야 함을 알 수 있습니다.
- hosts: all
user: root
vars:
# created with:
# python -c 'import crypt; print crypt.crypt("This is my Password", "$1$SomeSalt$")'
password: $1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.
tasks:
- user: name=tset password={{password}}
플레이 북 또는 ansible 명령 줄에 일반 텍스트로 된 암호가있는 경우 이는 섀도우 파일에 기록 된 암호 해시 가 잘못 되었음을 의미합니다 . 즉, 암호로 인증을 시도하면 해시가 일치하지 않습니다.
또한 암호 매개 변수의 일부 뉘앙스와이를 올바르게 사용하는 방법에 대해서는 Ansible FAQ 를 참조하십시오 .
openssl passwd -salt <salt> -1 <plaintext>
의 Python 한 줄이 아닌 암호 해시를 생성하는 데 를 사용하도록 권장한다는 점을 지적하고 싶었습니다 . 내 자신의 무능력과 openssl 명령이 더 잘 작동했기 때문에 Python에서 올바른 출력을 얻는 데 어려움이있었습니다.
/etc/shadow
사용하여 수동으로 비밀번호를 설정 한 후 해시를 찾았습니다 passwd <user>
.
답장하기에는 너무 늦었지만 최근에 jinja2 필터가 암호화 된 암호 생성을 처리 할 수 있다는 것을 알아 냈습니다. 내 main.yml
에서 암호화 된 암호를 다음과 같이 생성하고 있습니다.
- name: Creating user "{{ uusername }}" with admin access
user:
name: {{ uusername }}
password: {{ upassword | password_hash('sha512') }}
groups: admin append=yes
when: assigned_role == "yes"
- name: Creating users "{{ uusername }}" without admin access
user:
name: {{ uusername }}
password: {{ upassword | password_hash('sha512') }}
when: assigned_role == "no"
- name: Expiring password for user "{{ uusername }}"
shell: chage -d 0 "{{ uusername }}"
"uusername"및 "upassword"가 --extra-vars
플레이 북 으로 전달되고 여기에서 jinja2 필터를 사용하여 전달 된 암호를 암호화 한 것을 알 수 있습니다.
나는 이것과 관련된 튜토리얼을 내 블로그에 추가했습니다.
update_password: on_create
하고 이미 생성 된 사용자의 암호 만료를 방지하기 위해이 답변에 사용자 모듈을 추가 합니다.
pip install passlib
. 그런 다음 인라인 볼트 암호화 문자열을 사용할 수 있으려면 다음을 추가하여 다시 포맷해야했습니다 password: {{ upassword | string | password_hash('sha512') }}
.. 이 오류 메시지를 피할 수secret must be unicode or bytes, not ansible.parsing.yaml.objects.AnsibleVaultEncryptedUnicode
또 다른 해결책을 제안하고 싶습니다.
- name: Create madhead user
user:
name: madhead
password: "{{ 'password' | password_hash('sha512') }}"
shell: /bin/zsh
update_password: on_create
register: madhead
- name: Force madhead to change password
shell: chage -d 0 madhead
when: madhead.changed
왜 더 낫습니까? 여기에서 이미 언급했듯이 Ansible 플레이는 멱 등성이어야합니다. 명령형의 일련의 동작이 아니라 원하는 상태, 선언적 스타일로 생각해야합니다. 결과적으로 여러 번 실행하고 동일한 결과, 동일한 서버 상태를 얻을 수 있어야합니다.
이 모든 것이 훌륭하게 들리지만 약간의 뉘앙스가 있습니다. 그중 하나는 사용자를 관리하는 것입니다. "원하는 상태"는 사용자를 생성하는 플레이를 실행할 때마다 해당 상태와 정확히 일치하도록 업데이트됨을 의미합니다. "업데이트 됨"이란 그의 비밀번호도 변경된다는 것을 의미합니다. 그러나 아마도 그것은 당신이 필요로하는 것이 아닙니다. 일반적으로 사용자를 생성하고 비밀번호를 한 번만 설정 및 만료해야하며, 추가 플레이를 실행해도 비밀번호를 업데이트하면 안됩니다.
다행히 Ansible 은이 문제를 해결 update_password
하는 user
모듈에 속성을 가지고 있습니다. 이것을 등록 된 변수 와 혼합 하면 사용자가 실제로 업데이트 될 때만 그의 암호를 만료시킬 수도 있습니다.
사용자의 셸을 수동으로 변경하면 (예를 들어 악의적 인 관리자가 자신의 플레이에서 강제 한 셸이 마음에 들지 않는다고 가정) 사용자가 업데이트되므로 암호가 만료됩니다.
또한 연극에서 일반 텍스트 초기 암호를 쉽게 사용할 수있는 방법에 유의하십시오. 다른 곳에서 인코딩하고 해시를 붙여 넣을 필요가 없습니다 . Jinja2 필터 를 사용할 수 있습니다 . 그러나 처음 로그인하기 전에 누군가가 로그인하는 경우 보안 결함이 될 수 있습니다.
"{{ '{{vaulted_password}}' | password_hash('sha512') }}"
작동하지 않는 것 같습니다 ...
{{ vaulted_password | password_hash('sha512') }}
경우, vaulted_password
볼트의 값의 열쇠는?
update_password: on_create
작동하지 않는 것 같으므로 (2017 년부터 공개 된 버그가 있음 ) 사용자의 상태 가 변경 될 때마다 암호가 변경됩니다 .
Ansible 'user'모듈은 멱등적인 방식으로 사용자를 관리합니다 . 아래 플레이 북에서 첫 번째 작업은 사용자에 대해 state = present 를 선언 합니다. 첫 번째 작업의 ' register : newuser '는 두 번째 작업에서 사용자가 새 사용자 (newuser.changed == True)인지 기존 ( newuser.changed==False
) 인지 확인 하여 암호를 한 번만 생성하는 데 도움이됩니다.
Ansible 플레이 북에는 다음이 포함됩니다.
tasks:
- name: create deployment user
user:
name: deployer
createhome: yes
state: present
register: newuser
- name: generate random password for user only on creation
shell: /usr/bin/openssl rand -base64 32 | passwd --stdin deployer
when: newuser.changed
이렇게 해봐
vars_prompt:
- name: "user_password"
prompt: "Enter a password for the user"
private: yes
encrypt: "md5_crypt" #need to have python-passlib installed in local machine before we can use it
confirm: yes
salt_size: 7
- name: "add new user" user: name="{{user_name}}" comment="{{description_user}}" password="{{user_password}}" home="{{home_dir}}" shell="/bin/bash"
이 답변의 역할의 목적은 new_user_name에 대한 임의의 암호를 생성하고 암호를 즉시 만료하는 것입니다. new_user_name은 처음 로그온 할 때 암호를 변경하는 데 필요합니다.
create_user.yml :
---
# create_user playbook
- hosts: your_host_group
become: True
user: ansible
roles:
- create_user
roles / create_user / tasks / main.yml :
---
# Generate random password for new_user_name and the new_user_name
# is required to change his/her password on first logon.
- name: Generate password for new user
shell: makepasswd --chars=20
register: user_password
- name: Generate encrypted password
shell: mkpasswd --method=SHA-512 {{ user_password.stdout }}
register: encrypted_user_password
- name: Create user account
user: name={{ new_user_name }}
password={{ encrypted_user_password.stdout }}
state=present
append=yes
shell="/bin/bash"
update_password=always
when: new_user_name is defined and new_user_name in uids
register: user_created
- name: Force user to change password
shell: chage -d 0 {{ new_user_name }}
when: user_created.changed
- name: User created
debug: msg="Password for {{ new_user_name }} is {{ user_password.stdout }}"
when: user_created.changed
새 사용자를 생성하려는 경우 :
ansible-playbook -i hosts.ini create_user.yml --extra-vars "new_user_name=kelvin"
이것은 쉬운 방법입니다.
---
- name: Create user
user: name=user shell=/bin/bash home=/srv/user groups=admin,sudo generate_ssh_key=yes ssh_key_bits=2048
- name: Set password to user
shell: echo user:plain_text_password | sudo chpasswd
no_log: True
이것이 나를 위해 일한 방법입니다.
- hosts: main
vars:
# created with:
# python -c "from passlib.hash import sha512_crypt; print sha512_crypt.encrypt('<password>')"
# above command requires the PassLib library: sudo pip install passlib
- password: '$6$rounds=100000$H/83rErWaObIruDw$DEX.DgAuZuuF.wOyCjGHnVqIetVt3qRDnTUvLJHBFKdYr29uVYbfXJeHg.IacaEQ08WaHo9xCsJQgfgZjqGZI0'
tasks:
- user: name=spree password={{password}} groups=sudo,www-data shell=/bin/bash append=yes
sudo: yes
완성을 위해 ansible을 사용하여 ad-hoc 명령을 게시 할 것입니다.
먼저 대부분의 Linux 시스템에서 사용 가능한 mkpasswd 유틸리티를 사용하여 암호화 된 비밀번호를 생성 해보십시오.
mkpasswd --method=SHA-512
그런 다음 ansible ad-hock 명령을 시도합니다.
ansible all -m user -a 'name=testuser shell=/bin/bash \
comment="Test User" password=$6$XXXX' -k -u admin --sudo
그러나 다음 사항을 확인하십시오.
--sudo
하거나 ( useradd: cannot lock /etc/passwd; try again later
) 와 같은 오류가 발생합니다.위의 몇 가지 솔루션을 결합하여 암호화 된 로컬 ansible 볼트 파일에 저장된 일반 텍스트 암호를 기반으로 올바른 암호 해시를 자동으로 생성하는 플레이 북을 만들었습니다.
---
- hosts: [your hosts]
tasks:
- include_vars: [path to your encrypted vault file]
- local_action: "command openssl passwd -salt '{{password_salt}}' -1 '{{password}}'"
register: password_hash
- user: >
name=[your username]
state=present
password="{{password_hash.stdout}}"
볼트 파일의 암호를 해독하려면 "--ask-vault-pass"옵션을 사용하여이 명령을 실행하십시오 (암호화 된 볼트 관리 방법에 대한 정보는 ansible-vault 참조).
password
var에 Ansible user
작업 에 전달하기 위해 암호화 된 암호를 만드는 방법 (@Brendan Wood의 의견에서) :
openssl passwd -salt 'some_plain_salt' -1 'some_plain_pass'
결과는 다음과 같습니다.
$1$some_pla$lmVKJwdV3Baf.o.F0OOy71
user
작업 예 :
- name: Create user
user: name="my_user" password="$1$some_pla$lmVKJwdV3Baf.o.F0OOy71"
UPD : SHA-512를 사용한 crypt here and here 참조 :
$ python -c "import crypt, getpass, pwd; print crypt.crypt('password', '\$6\$saltsalt\$')"
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
$ perl -e 'print crypt("password","\$6\$saltsalt\$") . "\n"'
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
$ ruby -e 'puts "password".crypt("$6$saltsalt$")'
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
플레이 북에서 비밀 키를 사용하기 위해 ansible-vault를 사용할 수 있습니다. yml에서 비밀번호를 정의하십시오.
전의. 통과 : 비밀 또는
user:
pass: secret
name: fake
다음을 사용하여 비밀 파일을 암호화하십시오.
ansible-vault encrypt /path/to/credential.yml
ansible은 암호화를 위해 암호를 묻습니다. (이 패스 사용 방법을 설명하겠습니다)
그런 다음 원하는 곳에서 변수를 사용할 수 있습니다. 볼트 키 없이는 아무도 읽을 수 없습니다.
Vault 키 사용 :
플레이 북을 실행할 때 인수 전달을 통해.
--ask-vault-pass: secret
또는 password.txt와 같은 파일에 저장하고 어딘가에 숨길 수 있습니다. (CI 사용자에게 유용)
--vault-password-file=/path/to/file.txt
귀하의 경우 : vars yml을 포함하고 변수를 사용하십시오.
- include_vars: /path/credential.yml
- name: Add deployment user
action: user name={{user.name}} password={{user.pass}}
password={{user.pass}}
ansible은 거기에 해시를 예상하는 동안 실제 암호를 포함하도록 확장 되기 때문이라고 생각합니다 .
사용자에 대한 임의 비밀번호 생성
먼저 사용자 변수를 정의한 다음 아래를 따라야합니다.
작업 :
- name: Generate Passwords
become: no
local_action: command pwgen -N 1 8
with_items: '{{ users }}'
register: user_passwords
- name: Update User Passwords
user:
name: '{{ item.item }}'
password: "{{ item.stdout | password_hash('sha512')}}"
update_password: on_create
with_items: '{{ user_passwords.results }}'
- name: Save Passwords Locally
become: no
local_action: copy content={{ item.stdout }} dest=./{{ item.item }}.txt
with_items: '{{ user_passwords.results }}'
Mxx의 대답은 정확하지만 crypt.crypt()
다른 운영 체제가 관련되어있을 때 파이썬 방법은 안전하지 않습니다 (시스템에서 사용되는 glibc 해시 알고리즘 관련).
예를 들어 MacOS에서 해시를 생성하고 Linux에서 플레이 북을 실행하면 작동하지 않습니다. 이 경우 passlib를 사용 pip install passlib
하여 로컬로 설치할 수 있습니다 .
from passlib.hash import md5_crypt
python -c 'import crypt; print md5_crypt.encrypt("This is my Password,salt="SomeSalt")'
'$1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.'
두 솔루션 모두 Ubuntu를 제어하는 Mac에서 직접 작동하지 않았습니다. 따라서 다른 사람들을 위해 Mxx 및 JoelB 답변을 결합하여 현재 Python 3 솔루션은 다음과 같습니다.
pip3 install passlib
python3 -c 'from passlib.hash import md5_crypt; \
print(md5_crypt.encrypt("This is my Password", salt="SomeSalt"))'
결과는 $1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.
Mxx의 대답과 같이입니다.
더 나은 방법 은 MD5 대신 SHA512를 사용하는 것입니다.
python3 -c 'from passlib.hash import sha512_crypt; \
print(sha512_crypt.encrypt("This is my Password", salt="SomeSalt"))'
결과:
$ 6 $ rounds = 656000 $ SomeSalt $ oYpmnpZahIsvn5FK8g4bDFEAmGpEN114Fe6Ko4HvinzFaz5Rq2UXQxoJZ9ZQyQoi9zaBo3gBH / FEAov3FHv48
암호 인증을 허용하는 Linux 계정을 만들 수있는 ansible 플레이 북을 만들었습니다.
CreateLinuxAccountWithAnsible을 참조하십시오 .
해시 된 암호는 mkpasswd
명령을 사용하여 생성됩니다 . mkpasswd
다른 운영 체제에 설치하는 방법을 제공했습니다 .
내 스크립트를 사용하는 데 필요한 단계는 다음과 같습니다.
교체 <your_user_name>
및 <your_password>
내부 run.sh
원하는 사용자 이름과 암호.
inventory
ansible이 시스템에 연결하여 사용자를 생성 할 수 있도록 연결 정보를 변경합니다 .
./run.sh
스크립트를 실행 하려면 실행하십시오.
이 작업을 Ansible 임시 명령으로 수행하려면 다음을 수행 할 수 있습니다.
$ password='SomethingSecret!'
$ ansible 192.168.1.10 -i some_inventory -b -m user -a "name=joe_user \
update_password=always password=\"{{ \"$password\" | password_hash('sha512') }}\""
위 명령의 출력 :
192.168.1.10 | SUCCESS => {
"append": false,
"changed": true,
"comment": "Joe User",
"group": 999,
"home": "/home/joe_user",
"move_home": false,
"name": "joe_user",
"password": "NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"uid": 999
}
나는 내가 파티에 늦었다는 것을 알고 있지만 내가 사용하고있는 또 다른 해결책이있다. --stdin
passwd 바이너리 가없는 배포판에 유용 할 수 있습니다 .
- hosts: localhost
become: True
tasks:
- name: Change user password
shell: "yes '{{ item.pass }}' | passwd {{ item.user }}"
loop:
- { pass: 123123, user: foo }
- { pass: asdf, user: bar }
loop_control:
label: "{{ item.user }}"
라벨 입력은 사용자 이름 만loop_control
인쇄 합니다 . 전체 플레이 북 또는 사용자 변수 (를 사용할 수 있음 vars_files:
) 만 ansible-vault로 암호화해야합니다.
내 솔루션은 조회를 사용하고 암호를 자동으로 생성합니다.
---
- hosts: 'all'
remote_user: root
gather_facts: no
vars:
deploy_user: deploy
deploy_password: "{{ lookup('password', '/tmp/password chars=ascii_letters') }}"
tasks:
- name: Create deploy user
user:
name: "{{ deploy_user }}"
password: "{{ deploy_password | password_hash('sha512') }}"
mkpasswd, Python 등을 포함한 많은 유틸리티를 시도했습니다.하지만 다른 도구에서 생성 된 HASH 값을 읽을 때 Ansible과의 호환성 문제가있는 것 같습니다. 그래서 마침내 ansible # 값 자체로 작동했습니다.
ansible all -i localhost, -m debug -a "msg = {{ 'yourpasswd'| password_hash ( 'sha512', 'mysecretsalt')}}"
플레이 북-
- name: User creation
user:
name: username
uid: UID
group: grpname
shell: /bin/bash
comment: "test user"
password: "$6$mysecretsalt$1SMjoVXjYf.3sJR3a1WUxlDCmdJwC613.SUD4DOf40ASDFASJHASDFCDDDWERWEYbs8G00NHmOg29E0"
나는 파티에 완전히 늦었습니다. :) 무작위 암호로 여러 로컬 사용자를 생성하는 ansible 플레이가 필요했습니다. 이것은 내가 생각해 낸 것, 위에서 몇 가지 예를 사용하고 몇 가지 변경 사항을 결합했습니다.
password.yml로 사용자 생성
---
# create_user playbook
- hosts: all
become: True
user: root
vars:
#Create following user
users:
- test24
- test25
#with group
group: wheel
roles:
- create-user-with-password
/roles/create-user-with-password/tasks/main.yml
- name: Generate password for new user
local_action: shell pwgen -s -N 1 20
register: user_password
with_items: "{{ users }}"
run_once: true
- name: Generate encrypted password
local_action: shell python -c 'import crypt; print(crypt.crypt( "{{ item.stdout }}", crypt.mksalt(crypt.METHOD_SHA512)))'
register: encrypted_user_password
with_items: "{{ user_password.results }}"
run_once: true
- name: Create new user with group
user:
name: "{{ item }}"
groups: "{{ group }}"
shell: /bin/bash
append: yes
createhome: yes
comment: 'Created with ansible'
with_items:
- "{{ users }}"
register: user_created
- name: Update user Passwords
user:
name: '{{ item.0 }}'
password: '{{ item.1.stdout }}'
with_together:
- "{{ users }}"
- "{{ encrypted_user_password.results }}"
when: user_created.changed
- name: Force user to change the password at first login
shell: chage -d 0 "{{ item }}"
with_items:
- "{{ users }}"
when: user_created.changed
- name: Save Passwords Locally
become: no
local_action: copy content={{ item.stdout }} dest=./{{ item.item }}.txt
with_items: "{{ user_password.results }}"
when: user_created.changed
password
은 일반 텍스트가 아니라 미리 해시되어 있어야합니다.