Створення нового користувача та пароля за допомогою Ansible


103

У мене є відповідальне завдання, яке створює нового користувача на ubuntu 12.04;

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

він завершується так, як очікувалося, але коли я входжу в систему як цей користувач і намагаюся вступити з паролем, який я встановив, він завжди говорить, що це неправильно. Що я роблю неправильно?


1
Ви входите з одним і тим же паролем або ключами ssh? Ви перевірили ваш тіньовий файл, щоб переконатися, що його вміст очікується? Крім того, ваш passwordне повинен бути в простому тексті, а скоріше попередньо попередньо підготовлений.
Mxx

мій пароль зрозумілий, я не можу його використовувати таким чином? Я не розумію, як зробити це зашифрованим, або насправді це потрібно.
raphael_turtle

Відповіді:


101

Якщо ви прочитаєте посібник від Ansible для userмодуля , він переспрямує вас до github repo -прикладів Ansible для отримання детальної інформації про використання 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}}

Якщо у вашій програмі-програмі чи в командному рядку для запису пароля є звичайний текст, це означає, що хеш вашого пароля, записаний у вашому тіньовому файлі, неправильний. Це означає, що при спробі автентифікації зі своїм паролем хеш ніколи не збігатиметься.

Крім того, див анзібль довідки про деякі нюанси параметра пароля і як правильно його використовувати.


25
Дякую за пораду. Я просто хотів зазначити, що зв'язана вище документація про модуль користувача рекомендує використовувати openssl passwd -salt <salt> -1 <plaintext>для створення хешу паролів, а не однолінійного вкладиша Python, який у вас є вище. У мене виникли проблеми з правильним виведенням з Python, ймовірно, через мою власну некомпетентність і команда openssl працювала краще.
Брендан Вуд

6
Як ви синхронізуєте сіль для використання з ОС?
Breedly

5
@Breedly: немає потреби - сіль завжди зберігається як частина пароля ($ 1 $ thesalt $ thepasswordhash), тобто вона переноситься між ОС, використовуючи ту саму хеш-функцію
Бенджамін Дейл

3
Використання цієї команди python для створення хешу для мене не вийшло. Але я знайшов хеш, /etc/shadowвстановивши пароль вручну за допомогою passwd <user>.
докаспар

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у програму "playbook". Зауважте, що тут я використав фільтр jinja2 для шифрування пройденого пароля.

Я нижче додав підручник, пов’язаний із цим, до свого блогу


6
Щоб уникнути того, що елемент завжди "змінюється", ви можете додати секретну "сіль" як 2-й параметр до пароля_гаш.
Майкл Вайраз

11
Відповідно до пропозиції @ MichaelWyraz: додавання 2-го парами "солі" дозволяє уникнути "зміни". Ви можете встановити це за допомогою змінної, наприклад password={{upassword|password_hash('sha512', upassword_salt)}}. Це дозволяє помістити сіль у сховище змінних , як ви, мабуть, і з цим upassword, не виключаючи обох завдань.yml.
користувач85461

Я також застосував би @ bbaassssiiee перевірку стану та додаю update_password: on_createдо цього відповіді модуль користувача, щоб запобігти втраті паролів для вже створених користувачів.
озлоблений

Дякую за ваш чудовий приклад, що це привело мене до правильного шляху. Тим не менше, мені довелося зробити ще кілька речей, щоб змусити його працювати на Mac з відповідальною версією 2.8.2. Перш за все на mac не можна використовувати крипту, тому потрібно встановити бібліотеку passlib pip install passlib. Тоді , щоб мати можливість використовувати вбудовані сховище зашифрована рядки я повинен був переформатувати з таким доповненням: password: {{ upassword | string | password_hash('sha512') }}. Це дозволяє уникнути повідомлення про помилкуsecret must be unicode or bytes, not ansible.parsing.yaml.objects.AnsibleVaultEncryptedUnicode
Майкл

незважаючи на використання цього методу для встановлення пароля: "{{my_password | string | password_hash ('sha512')}}" Я все одно отримаю - [ПОПЕРЕДЖЕННЯ]: Здається, пароль введення не був прошитий. Аргумент 'пароль' повинен бути зашифрований, щоб цей модуль працював належним чином.
відкрита цивілізація

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 має update_passwordатрибут у userмодулі, який вирішує цю проблему. Змішуючи це з зареєстрованими змінними, ви можете також термін дії його пароля лише тоді, коли користувач фактично оновлений.

Зауважте, що якщо змінити оболонку користувача вручну (припустимо, вам не сподобається оболонка, яку злий адміністратор змусив у своїй грі), користувач буде оновлений, таким чином його термін дії буде втрачено.

Також зверніть увагу на те, як ви можете легко використовувати початкові паролі для простого тексту у п’єсах. Не потрібно кодувати їх деінде та вставляти хеші, ви можете використовувати для цього фільтр Jinja2 . Однак це може бути вадою безпеки, якщо хтось увійде в систему, перш ніж ви робите це.


3
Я не міг змусити іншого рішення працювати на мене. І все ж ви відповідаєте просто і справно. Я хотів би дати вам 5 результатів, якщо б міг.
leesei

Я не хочу, щоб мій пароль був так зашифрований так :( Чи можна дістати його з ангіозного сховища та ввести його сюди? Вкладене начебто "{{ '{{vaulted_password}}' | password_hash('sha512') }}"не працює ...
dokaspar

Ви спробували {{ vaulted_password | password_hash('sha512') }}, де vaulted_passwordключ до значення в сховищі?
madhead

update_password: on_createСхоже, не працює ( про це відкрита помилка з 2017 року), тому паролі змінюватимуться кожного разу, коли у користувача буде зміна стану.
Діті

11

Модуль Ansible 'user' керує користувачами безвідмовно . У ігровій книзі нижче першого завдання оголошує стан = присутній для користувача. Зауважте, що " register: newuser " у першій дії допомагає другій дії визначити, користувач новий (newuser.changed == True) чи існуючий ( newuser.changed==False), щоб генерувати пароль лише один раз.

Книга "Відповідальні" має:

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

Лише одне рішення працює для мене з паролем Vault. Дуже дякую.
Денис Савенко

принаймні останні дистрибутиви на базі Debian, схоже, не підтримують довгий варіант GNU "--stdin" до бінарного файлу passwd.
XXL

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".
Гуннар

6

Мета ролі в цій відповіді - генерувати випадковий пароль для імені 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"

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

оболонка: завжди буде викликати повідомлення про зміни.
bbaassssiiee

@datasmid ви можете додати no_log: Справжній варіант docs.ansible.com/ansible/…
Phill 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, оскільки там також є улов.

Спочатку спробуйте створити зашифрований пароль за допомогою утиліти mkpasswd, яка доступна в більшості систем Linux:

mkpasswd --method=SHA-512

Потім спробуйте команду adible-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)

дякую товаришу, я спеціально шукав версію adhoc, і у мене була ця сама проблема з цитатами, яку ви згадали
alexakarpov


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", щоб розшифрувати файл vault (див. Ansible-treult для інформації про те, як керувати зашифрованим сховищем).


2

Як створити зашифрований пароль для переходу до passwordvar до userзавдання Ansible (з коментаря @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-treult для використання секретних ключів у ігрових книгах. Визначте свій пароль у 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 очікує, що хеш там.
текстовий

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 правильна, але ви, crypt.crypt()метод python , не безпечний, коли задіяні різні операційні системи (пов'язані з алгоритмом хеш-файлу glibc, який використовується у вашій системі.)

Наприклад, це не буде працювати, якщо ви генеруєте свій хеш із MacOS і запустите програму playbook на 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

Жодне з рішень не працювало безпосередньо на моєму Mac, що контролює Ubuntu. Тож заради інших, поєднуючи відповіді 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.

А ще краще використовувати 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


1

Я створив ansible-playbook, який дозволяє вам створити обліковий запис linux, який дозволяє перевірити пароль.

Див. Розділ CreateLinuxAccountWithAnsible .

Хешований пароль генерується за допомогою mkpasswdкоманди. Я запропонував способи встановлення mkpasswdна різних операційних системах.

Ось такі кроки, необхідні для використання мого сценарію:

  1. Замініть <your_user_name>і <your_password>всередині run.shпотрібне ім’я користувача та пароль.

  2. Змініть інформацію про з'єднання inventoryтак, щоб відповідальний міг підключитися до машини, щоб створити користувача.

  3. Запустіть ./run.shдля виконання сценарію.


1
Файл більше не знаходиться на GitHub.
Янус

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

Я знаю, що я спізнююсь на вечірку, але є ще одне рішення, яке я використовую. Це може бути зручно для дистрибутивів, які не мають --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 }}"

Label in loop_controlвідповідає за друк лише імені користувача. Вся книжка чи просто змінні користувача (ви можете використовувати vars_files:) повинна бути зашифрована за допомогою ansible-treult.


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 тощо. Але, схоже, існує проблема сумісності з Ansible при читанні значень HASH, створених іншими інструментами. Отже, нарешті, це спрацювало саме ansible # value.

ansible all -i localhost, -m debug -a "msg = {{'yourpasswd' | password_hash ('sha512', 'mysecretsalt')}}"

Playbook -

- name: User creation
  user: 
    name: username  
    uid: UID
    group: grpname
    shell: /bin/bash
    comment: "test user"
    password: "$6$mysecretsalt$1SMjoVXjYf.3sJR3a1WUxlDCmdJwC613.SUD4DOf40ASDFASJHASDFCDDDWERWEYbs8G00NHmOg29E0"

-1

Ну, я зовсім спізнився на вечірку :) У мене виникла потреба у програванні ansible, яка створює декількох місцевих користувачів із паролями Randoms. Це те, що я придумав, використав декілька прикладів зверху і склав їх разом із деякими змінами.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.