私はubuntu 12.04で新しいユーザーを作成するansibleタスクがあります。
- name: Add deployment user
action: user name=deployer password=mypassword
期待どおりに完了しますが、そのユーザーとしてログインしてパスワードでsudoを実行しようとすると、常に正しくないと表示されます。何が悪いのですか?
私はubuntu 12.04で新しいユーザーを作成するansibleタスクがあります。
- name: Add deployment user
action: user name=deployer password=mypassword
期待どおりに完了しますが、そのユーザーとしてログインしてパスワードでsudoを実行しようとすると、常に正しくないと表示されます。何が悪いのですか?
回答:
user
モジュールの Ansibleのマニュアルを読んだ場合、パラメーターの使用方法の詳細については、Ansible-examples githubリポジトリにアクセスでき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ワンライナーではなく、を使用してパスワードハッシュを生成することを推奨していることを指摘したいと思います。Pythonから正しい出力を取得するのにいくつかの問題がありました。おそらく自分の能力不足のためで、opensslコマンドの方がうまく機能していました。
/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フィルターを使用して、渡されたパスワードを暗号化していることに注意してください。
これに関連する以下のチュートリアルを私のブログに追加しました
password={{upassword|password_hash('sha512', upassword_salt)}}
。これにより、saltを変数ボールトに配置できるようになります。おそらくupassword
同じように、両方をtasks.ymlから除外します。
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の演劇はべき等である必要があります。これらは、命令型の一連のアクションではなく、望ましい状態の宣言型のスタイルと考える必要があります。その結果、それを複数回実行して、同じ結果、同じサーバー状態を取得できるはずです。
これはすべてすばらしいように聞こえますが、いくつかのニュアンスがあります。その1つはユーザーの管理です。「望ましい状態」とは、ユーザーを作成するプレイを実行するたびに、その状態に完全に一致するように更新されることを意味します。「更新」とは、彼のパスワードも変更されることを意味します。しかし、おそらくそれはあなたが必要とするものではありません。通常、ユーザーの作成、パスワードの設定と有効期限の設定は1回だけで済みます。それ以降のプレイ実行ではパスワードが更新されません。
幸い、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を宣言しています。注意してください ' 登録:newuser最初のアクションの」は、2番目のアクションがユーザーが新しい(newuser.changed == True)か既存(newuser.changed==False
)である、パスワードを1回だけ生成するのにます。
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を使用してアドホックコマンドを投稿します。
まず、ほとんどの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を使用した暗号化はこちらとここをください:
$ 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の答えは正しいですが、Python 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-playbookを作成しました。
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プレイが必要でした。これは私が思いついたもので、上からいくつかの例を使用し、いくつかの変更を加えてまとめました。
create-user-with-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
、プレーンテキストではなく、ハッシュ化されている必要があります。