使用Ansible创建新用户和密码

时间:2013-10-10 10:07:44

标签: bash shell ubuntu ansible

我有一个ansible任务,它在ubuntu 12.04上创建了一个新用户;

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

它按预期完成,但当我以该用户身份登录并尝试使用我设置的密码sudo时,它总是说它不正确。我做错了什么?

22 个答案:

答案 0 :(得分:133)

我可能来不及回复这个问题,但最近我发现jinja2过滤器有能力处理加密密码的生成。在我的import math def sumofSquares(n): f = 0 for b in range(n,4,-1): print(b) for a in range(b,4,-2): for C in range(math.ceil(b/2),n//2+1): if a+b>2*C: D = 2*(a**2+b**2-2*C**2) if (math.sqrt(D)/2).is_integer(): f += 1 return f a = int(input()) print(sumofSquares(a)) print('Done') 我生成加密密码为:

main.yml

" uusername"和" upassword"作为- 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 }}" 传递给剧本,并注意我在这里使用了jinja2过滤器来加密传递的密码。

我已将以下与此相关的教程添加到我的博客

答案 1 :(得分:86)

如果您阅读user module的Ansible手册,它会引导您访问Ansible示例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}}

如果您的playbook或ansible命令行以明文形式显示密码,则表示您的 shadow 文件中记录的密码哈希是错误的。这意味着当您尝试使用密码进行身份验证时,其哈希将永远不会匹配。

此外,请参阅Ansible FAQ,了解密码参数的一些细微差别以及如何正确使用密码参数。

答案 2 :(得分:39)

我想提出另一个解决方案:

- 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在user module中有update_password属性来解决此问题。将其与registered variables混合使用,只有在用户实际更新时,您才能使密码失效。

请注意,如果您手动更改用户的shell(假设您不喜欢邪恶管理员在其游戏中强制使用的shell),则会更新用户,因此他的密码将过期。

另请注意如何在播放中轻松使用纯文本初始密码。无需在其他地方对其进行编码并粘贴哈希值,您可以使用Jinja2 filter。但是,如果有人在您最初​​做之前登录,这可能是一个安全漏洞。

答案 3 :(得分:11)

Ansible'用户'模块以幂等方式管理用户。在下面的剧本中,第一个任务为用户声明 state = present 。请注意' 注册: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

答案 4 :(得分:9)

试试这个

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"

答案 5 :(得分:5)

此答案中角色的目的是为new_user_name生成随机密码并立即使密码失效。 new_user_name 需要在他/她第一次登录时更改密码。

create_user.yml:

---
# create_user playbook

- hosts: your_host_group
  become: True
  user: ansible

  roles:
    - create_user

角色/ create_user /任务/ 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"

答案 6 :(得分: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

答案 7 :(得分: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

答案 8 :(得分:3)

为了完整起见,我将使用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

但请确保:

  1. 该命令是单引号而不是双倍,否则您的密码将无法正常工作
  2. 您使用--sudo运行它,或者最终出现类似(useradd: cannot lock /etc/passwd; try again later
  3. 的错误

答案 9 :(得分:2)

user module的任务定义在最新的Ansible版本中应该有所不同。

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

答案 10 :(得分:2)

结合上面的一些解决方案,我创建了一个剧本,根据存储在加密的本地安全库文件中的明文密码自动生成正确的密码哈希值:

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

答案 11 :(得分:2)

您可以使用ansible-vault在playbooks中使用密钥。以yml定义密码。

离。传球:秘密 或

user:
  pass: secret
  name: fake

使用以下方法加密您的秘密文件:

ansible-vault encrypt /path/to/credential.yml

ansible将要求密码加密它。 (我将解释如何使用该通行证)

然后您可以根据需要使用变量。没有金库钥匙,任何人都无法阅读。

保险柜密钥用法:

在运行playbook时通过传递参数。

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

答案 12 :(得分:1)

Mxx的答案是正确的,但是当涉及不同的操作系统时,你的python crypt.crypt()方法是不安全的(与你系统上使用的glibc哈希算法有关。)

例如,如果您从MacOS生成哈希并在Linux上运行playbook,它将无法工作。在这种情况下,您可以使用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.'

答案 13 :(得分:1)

我创建了一个ansible-playbook,可让您创建一个允许密码认证的linux帐户。

请参见CreateLinuxAccountWithAnsible

使用mkpasswd命令生成哈希密码。我提供了在不同操作系统上安装mkpasswd的方法。

以下是使用我的脚本所需的步骤:

  1. 用所需的用户名和密码替换<your_user_name>中的<your_password>run.sh

  2. 更改inventory中的连接信息,以便ansible可以连接到计算机以创建用户。

  3. 运行./run.sh以执行脚本。

答案 14 :(得分:1)

为用户生成随机密码

首先需要定义用户变量,然后在下面进行操作

任务:

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

答案 15 :(得分: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的回答一样。

Better still ,使用SHA512代替MD5:

python3 -c 'from passlib.hash import sha512_crypt; \
      print(sha512_crypt.encrypt("This is my Password", salt="SomeSalt"))' 

结果:

  

$ 6 $轮= 656000 $ $ SomeSalt oYpmnpZahIsvn5FK8g4bDFEAmGpEN114Fe6Ko4HvinzFaz5Rq2UXQxoJZ9ZQyQoi9zaBo3gBH / FEAov3FHv48

答案 16 :(得分:1)

如何创建加密密码以传递给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的地址见herehere

的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 -e 'puts "password".crypt("$6$saltsalt$")'

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

答案 17 :(得分:0)

如果您想以Ansible ad-hoc命令完成此操作,可以执行以下操作:

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

答案 18 :(得分:0)

我知道我参加聚会迟到了,但是我正在使用另一种解决方案。对于在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 }}"
{p}中的

标签负责仅打印 用户名。整个剧本或仅用户变量(可以使用loop_control)都应使用ansible-vault进行加密。

答案 19 :(得分: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') }}"

答案 20 :(得分:0)

尝试了许多实用程序,包括mkpasswd,Python等。但是在读取其他工具生成的HASH值时,似乎与Ansible存在兼容性问题。因此,最终它通过ansible#值本身起作用。

可以全部使用-i localhost,-m调试-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"

答案 21 :(得分:-1)

好吧,我完全迟到了:)我需要玩一个有趣的游戏,用随机密码创建多个本地用户。我想出了这一点,从顶部使用了一些示例,并进行了一些更改。

创建带有密码的用户。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 /使用密码创建用户/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