web-dev-qa-db-ja.com

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

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

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

期待どおりに完了しますが、そのユーザーとしてログインし、パスワードを使用してSudoを試行すると、常に間違っていると表示されます。何が間違っていますか?

86
raphael_turtle

user module のAnsibleのマニュアルを読むと、Ansible-examples github repo の詳細な使用方法 password parameter にアクセスできます。

ここで、パスワードをハッシュする必要があることがわかります。

- 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コマンドラインにパスワードがプレーンテキストのままである場合、これはshadowファイルに記録されたパスワードハッシュが間違っていることを意味します。つまり、パスワードで認証しようとすると、そのハッシュは一致しません。

また、パスワードパラメータの微妙な違いとその正しい使用方法については、Ansible FAQ を参照してください。

87
Mxx

返信するには遅すぎるかもしれませんが、最近、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フィルターを使用したことに注意してください。

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

135
thinkingmonster

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

- 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の user module にはupdate_password属性があり、この問題を解決します。これを 登録済み変数 と混合すると、ユーザーが実際に更新されたときにのみパスワードを失効させることもできます。

ユーザーのシェルを手動で変更すると(悪の管理者がプレイで強制したシェルが気に入らない場合)、ユーザーが更新されるため、パスワードが期限切れになることに注意してください。

また、プレイでプレーンテキストの初期パスワードを簡単に使用する方法にも注意してください。他の場所にエンコードしてハッシュを貼り付ける必要はありません。そのために Jinja2 filter を使用できます。ただし、最初にログインする前に誰かがログインした場合、これはセキュリティ上の欠陥になる可能性があります。

39
madhead

Ansible 'user'モジュールはidempotentの方法でユーザーを管理します。以下のプレイブックでは、最初のタスクがユーザーに対してstate = presentを宣言しています。最初のアクションの「register: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
11
bbaassssiiee

このようにしてみて

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"
9
Artem Feofanov

この回答のロールの目的は、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"
5
McKelvin

これは簡単な方法です:

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

これは私のために働いた方法です

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

完全を期すために、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)のようなエラーが発生します
3
pgaref

プレイブックで秘密鍵を使用するために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}}
2
pmoksuz

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

ser module のタスク定義は、最新のAnsibleバージョンで異なる必要があります。

tasks:
  - user: name=test password={{ password }} state=present
2

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

CreateLinuxAccountWithAnsible を参照してください。

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

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

  1. <your_user_name><your_password>内のrun.shを希望のユーザー名とパスワードに置き換えます。

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

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

1
Brian

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

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

結果は、Mxxの答えのように$1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.になります。

より良い、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
texnic

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

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

タスク:

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

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を使用した暗号化 here および hereを参照

Python

$ 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

$ Ruby -e 'puts "password".crypt("$6$saltsalt$")'

$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
1
Dmitriy

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"
0
DjangoChained

私はパーティーに遅れていることを知っていますが、私が使用している別のソリューションがあります。 passwdバイナリに--stdinを持たないディストリビューションに便利かもしれません。

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

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

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

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