bash 使用 Ansible 创建新用户和密码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19292899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:17:39  来源:igfitidea点击:

Creating a new user and password with Ansible

bashshellubuntuansible

提问by raphael_turtle

I have an ansible task which creates a new user on ubuntu 12.04;

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

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

it completes as expected but when I login as that user and try to sudo with the password I set it always says it's incorrect. What am I doing wrong?

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

采纳答案by Mxx

If you read Ansible's manual for usermodule, it'll direct you to the Ansible-examples github repofor details how to use passwordparameter.

如果你阅读了 Ansible 的usermodule手册,它会引导你到 Ansible-examples github repo了解如何使用passwordparameter 的详细信息。

There you'll see that your password must be hashed.

在那里你会看到你的密码必须经过哈希处理。

- hosts: all
  user: root
  vars:
    # created with:
    # python -c 'import crypt; print crypt.crypt("This is my Password", "$SomeSalt$")'
    password: $SomeSalt$UqddPX3r4kH3UL5jq5/ZI.

  tasks:
    - user: name=tset password={{password}}

If your playbook or ansible command line has your password as-is in plain text, this means your password hash recorded in your shadowfile is wrong. That means when you try to authenticate with your password its hash will never match.

如果您的剧本或 ansible 命令行以纯文本形式提供密码,这意味着您的影子文件中记录的密码哈希是错误的。这意味着当您尝试使用密码进行身份验证时,其哈希值永远不会匹配。

Additionally, see Ansible FAQregarding some nuances of password parameter and how to correctly use it.

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

回答by thinkingmonster

I may be too late to reply this but recently I figured out that jinja2 filters have the capability to handle the generation of encrypted passwords. In my main.ymlI'm generating the encrypted password as:

我可能来不及回复这个问题,但最近我发现 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 " and "upassword " are passed as --extra-varsto the playbook and notice I have used jinja2 filter here to encrypt the passed password.

“uusername”和“upassword”作为--extra-vars剧本传递,请注意我在这里使用了jinja2过滤器来加密传递的密码。

I have added below tutorial related to this to my blog

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

回答by madhead

I want to propose yet another solution:

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

- 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

Why it is better? Like already has been noted here, Ansible plays should be idempotent. You should think of them not as a sequence of actions in imperative style, but like a desired state, declarative style. As a result you should be able to run it multiple times and get the same result, the same server state.

为什么更好?就像这里已经指出的那样,Ansible play 应该是幂等的。您不应将它们视为命令式风格的一系列操作,而应将它们视为一种期望状态、声明式风格。因此,您应该能够多次运行它并获得相同的结果和相同的服务器状态。

This all sounds great, but there are some nuances. One of them is managing users. "Desired state" means that every time you run a play that creates a user he will be updated to match exactly that state. By "updated" I mean that his password will be changed too. But most probably it is not what you need. Usually, you need to create user, set and expire his password only once, further play runs shouldn't update his password.

这一切听起来都很棒,但也有一些细微差别。其中之一是管理用户。“期望状态”意味着每次您运行创建用户的游戏时,他都会更新以完全匹配该状态。“更新”是指他的密码也将被更改。但很可能它不是你需要的。通常,您只需要创建用户,设置和过期他的密码一次,进一步的游戏运行不应该更新他的密码。

Fortunately, Ansible has update_passwordattribute in usermodulethat solves this issue. Mixing this with registered variablesyou can also expire his password only when the user is actually updated.

幸运的是,Ansibleupdate_passworduser模块中有解决这个问题的属性。将此与注册变量混合使用,您也可以仅在用户实际更新时使他的密码过期。

Note that if you change user's shell manually (suppose, you don't like the shell that evil admin forced in his play) the user will be updated, thus his password will be expired.

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

Also note how you can easily use plain text initial passwords in plays. No need to encode them somewhere else and paste hashes, you can use Jinja2 filterfor that. However, this can be a security flaw if someone happens to login before you initially do.

还要注意如何在播放中轻松使用纯文本初始密码。无需在其他地方对它们进行编码并粘贴哈希,您可以使用Jinja2 过滤器。但是,如果有人碰巧在您最初登录之前登录,这可能是一个安全漏洞。

回答by bbaassssiiee

The Ansible 'user' module manages users, in the idempotentway. In the playbook below the first task declares state=presentfor the user. Note that 'register: newuser' in the first action helps the second action to determine if the user is new (newuser.changed==True) or existing (newuser.changed==False), to only generate the password once.

Ansible“用户”模块以幂等方式管理用户。在下面的剧本中,第一个任务为用户声明state=present。请注意,第一个操作中的' register: newuser' 帮助第二个操作确定用户是新用户 (newuser.changed==True) 还是现有用户 ( newuser.changed==False),从而只生成一次密码。

The Ansible playbook has:

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

回答by Artem Feofanov

try like this

像这样尝试

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"

回答by McKelvin

The purpose of the role in this answer is to generate random password for new_user_name and expire the password immediately. The new_user_name is required to change the password on his/her first logon.

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

create_user.yml:

create_user.yml:

---
# create_user playbook

- hosts: your_host_group
  become: True
  user: ansible

  roles:
    - create_user

roles/create_user/tasks/main.yml:

角色/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

When you want to create a new user:

当您要创建新用户时:

ansible-playbook -i hosts.ini create_user.yml --extra-vars "new_user_name=kelvin"

回答by pgaref

Just for completeness I will post the ad-hoc command using ansible since there is a catch there as well.

为了完整起见,我将使用 ansible 发布临时命令,因为那里也有一个问题。

First try generating an encrypted password using the mkpasswd utility that is available on most Linux systems:

首先尝试使用大多数 Linux 系统上可用的 mkpasswd 实用程序生成加密密码:

mkpasswd --method=SHA-512

Then try the ansible ad-hock command:

然后尝试 ansible ad-hock 命令:

ansible all -m user -a 'name=testuser shell=/bin/bash \
     comment="Test User" password=$XXXX' -k -u admin --sudo

But make sure:

但请确保:

  1. The command is in single quotes and NOT double otherwise your password will never work
  2. You run it with --sudoor you end up with an error like (useradd: cannot lock /etc/passwd; try again later)
  1. 该命令是单引号而不是双引号,否则您的密码将永远无法使用
  2. 你用它运行它--sudo或者你最终得到一个像 ( useradd: cannot lock /etc/passwd; try again later)这样的错误

回答by Lightmed

This is the easy way:

这是简单的方法:

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

回答by hecbuma

This is how it worked for me

这就是它对我的工作方式

- 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: '$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

回答by Dmitriy

How to create encrypted password for passing to passwordvar to Ansible usertask (from @Brendan Wood's comment):

如何创建加密密码以传递给passwordvar 到 Ansibleuser任务(来自@Brendan Wood 的评论):

openssl passwd -salt 'some_plain_salt' -1 'some_plain_pass'

The result will look like:

结果将如下所示:

$some_pla$lmVKJwdV3Baf.o.F0OOy71

Example of usertask:

user任务示例:

- name: Create user
  user: name="my_user" password="$some_pla$lmVKJwdV3Baf.o.F0OOy71"

UPD: crypt using SHA-512 see hereand here:

UPD:使用 SHA-512 加密,请参见此处此处

Python

Python

$ python -c "import crypt, getpass, pwd; print crypt.crypt('password', '$6$saltsalt$')"

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

Perl

珀尔

$ perl -e 'print crypt("password","$6$saltsalt$") . "\n"'

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

Ruby

红宝石

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

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