Ansibleで新しいユーザーとパスワードを作成する


103

私はubuntu 12.04で新しいユーザーを作成するansibleタスクがあります。

- name: Add deployment user
    action: user name=deployer password=mypassword

期待どおりに完了しますが、そのユーザーとしてログインしてパスワードでsudoを実行しようとすると、常に正しくないと表示されます。何が悪いのですか?


1
同じパスワードまたはSSHキーでログインしていますか?シャドウファイルをチェックして、その内容が期待どおりであることを確認しましたか?またpassword、プレーンテキストではなく、ハッシュ化されている必要があります。
Mxx 2013年

パスワードはプレーンテキストですが、そのように使用できませんか?暗号化する方法がわかりません。または、本当に暗号化する必要があります。
raphael_turtle 2013年

回答:


101

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を参照してください。


25
先端をありがとう。上記のリンクされたユーザーモジュールのドキュメントopenssl passwd -salt <salt> -1 <plaintext>では、上記のPythonワンライナーではなく、を使用してパスワードハッシュを生成することを推奨していることを指摘したいと思います。Pythonから正しい出力を取得するのにいくつかの問題がありました。おそらく自分の能力不足のためで、opensslコマンドの方がうまく機能していました。
Brendan Wood

6
OSで使用するソルトをどのように同期しますか?
Breedly

5
@ブリードリー:必要はありません。ソルトは常にパスワードの一部として保存されます($ 1 $ thesalt $ thepasswordhash)。つまり、同じハッシュ関数を使用してOS間で移植可能です
Benjamin Dale

3
このpythonコマンドを使用してハッシュを生成することはできませんでした。しかし/etc/shadow、を使用して手動でパスワードを設定した後、ハッシュが見つかりましたpasswd <user>
dokaspar

172

私はこれに答えるには遅すぎるかもしれませんが、最近私は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フィルターを使用して、渡されたパスワードを暗号化していることに注意してください。

これに関連する以下のチュートリアルを私のブログに追加しました


6
アイテムが常に「変更」されることを回避するために、秘密の「塩」を2番目のパラメーターとしてpassword_hashに追加できます。
マイケルウィラス

11
@MichaelWyrazの提案に従って:2番目の「塩」パラメーターを追加すると、「変更」が回避されます。変数などを使用して設定できますpassword={{upassword|password_hash('sha512', upassword_salt)}}。これにより、saltを変数ボールトに配置できるようになります。おそらくupassword同じように、両方をtasks.ymlから除外します。
user85461 2016

また、@ bbaassssiieeの状態チェックを適用update_password: on_createし、この回答にユーザーモジュールを追加して、既に作成されているユーザーのパスワードが期限切れにならないようにします。
madhead

あなたの素晴らしい例をありがとう、これは私を正しい軌道に乗せました。それにもかかわらず、私はそれがansibleバージョン2.8.2のMacで動作するようにするためにいくつかのことをしなければなりませんでした。まず、Macではcryptを使用できないため、でpasslibライブラリをインストールする必要がありpip install passlibます。次に、インラインのボールトで暗号化された文字列を使用できるようにするには、次の追加を行って再フォーマットする必要がありましたpassword: {{ upassword | string | password_hash('sha512') }}。これにより、エラーメッセージが回避されますsecret must be unicode or bytes, not ansible.parsing.yaml.objects.AnsibleVaultEncryptedUnicode
Michael Aicher

このメソッドを使用してパスワードを設定したにもかかわらず、「{{my_password | string | password_hash( 'sha512')}}」が引き続き取得されます-[警告]:入力パスワードはハッシュされていないようです。このモジュールが正しく機能するには、「パスワード」引数を暗号化する必要があります。
openCivilization

46

さらに別の解決策を提案したい:

- 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フィルターを使用できます。ただし、最初にログインする前に誰かがログインした場合、これはセキュリティ上の欠陥になる可能性があります。


3
他のソリューションがうまく機能しませんでした。しかし、あなたの答えはシンプルで効果的です。できれば5票をあげたいと思います。
leesei

パスワードをそのようにハードコード化したくない:(Ansible-Vaultからパスワードを取り出してここに挿入することは可能ですか?などのネストは"{{ '{{vaulted_password}}' | password_hash('sha512') }}"機能しないようです...
dokaspar

あなたは試してみました{{ vaulted_password | password_hash('sha512') }}ところ、vaulted_passwordボールト内の値の鍵はありますか?
マッドヘッド2018

update_password: on_createは機能していないようです(2017年からオープンバグがあります)。そのため、ユーザーの状態が変化するたびにパスワードが変更されます。
Diti、2019年

11

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

ボールトのパスワードで私のために働く唯一の解決策。本当にありがとうございました。
Denis Savenko

少なくとも最近のDebianベースのディストリビューションは、passwdバイナリへの長いGNUオプション "--stdin"をサポートしていないようです。
XXL 2018

10

このようにしてみてください

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"

2
スクリプトの実行時にパスワードを入力できるので、このソリューションが好きです。毎回実行するべきではないブートストラップスクリプトの優れたソリューション。Ubuntuの場合は「sha512_crypt」を使用しました。
Gunnar

6

この回答の役割の目的は、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"

3

これは簡単な方法です:

---
- 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

shell:常に変更が報告されます。
bbaassssiiee 2015年

真のオプション:あなたはNO_LOG追加でき@datasmid docs.ansible.com/ansible/...
フィルPafford

3

これは私にとってそれがどのように機能したかです

- 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

3

完全を期すために、そこにもキャッチがあるため、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

しかし、確認してください:

  1. コマンドは一重引用符で囲みます。二重にしないと、パスワードが機能しません。
  2. で実行する--sudoか、(useradd: cannot lock /etc/passwd; try again later)のようなエラーが発生します

おかげで、私は特別にアドホック版を探していましたが、あなたが述べたのと同じ引用問題がありました
alexakarpov


2

上記のいくつかのソリューションを組み合わせて、暗号化されたローカルの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を参照してください)。


2

passwordvarを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

$ 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/

1
これはmd5ハッシュ化パスワードを生成していませんか?それは安全ではありませんか?
マーク

2

プレイブックで秘密鍵を使用するために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はハッシュを期待しているためです。
texnic

2

ユーザーのランダムパスワードの生成

最初にユーザー変数を定義する必要があり、次に以下に従います

タスク:

- 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 }}'

1

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.'

1

どちらのソリューションも、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


1

パスワード認証を許可するLinuxアカウントを作成できるansible-playbookを作成しました。

CreateLinuxAccountWithAnsibleを参照してください

ハッシュ化されたパスワードは、mkpasswdコマンドを使用して生成されます。インストールする方法を提供しましたmkpasswdさまざまなオペレーティングシステム。

スクリプトを使用するために必要な手順は次のとおりです。

  1. 置き換え<your_user_name>および<your_password>内部run.shご希望のユーザー名とパスワードを使用して。

  2. で接続情報を変更しinventoryて、ansibleがマシンに接続してユーザーを作成できるようにします。

  3. 実行./run.shしてスクリプトを実行します。


1
ファイルはGitHubにありません。
Janus

0

これを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
}

0

パーティーに遅れるのはわかっていますが、使用している別の解決策があります。--stdinpasswdバイナリを持たないディストリビューションには便利かもしれません。

- 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で暗号化する必要があります。


0

私の解決策は、ルックアップを使用してパスワードを自動的に生成することです。

---
- 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') }}"

0

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"

-1

さて私はパーティーに完全に遅れています:)私はランダムなパスワードで複数のローカルユーザーを作成する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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.