How to upload ssh public key to as authorized_key using Ansible


Step 1: Create hosts inventory file

You need to tell Ansible which hosts you are going to use:
$ cat my_ssh_hosts
Sample outputs:


Step 2: Create playbook

Create a file called upload_ssh_keys.yml as follows:

- hosts: all
  remote_user: vivek
          # upload ssh key                
          - authorized_key:
                  user: vivek
                  state: present
                  manage_dir: yes
                  key: "{{ lookup('file', '/path/to/your/www_id_rsa.pub') }}"
# vim:ft=ansible:

The above will place public key file (/path/to/your/www_id_rsa.pub) to all server listed my_ssh_hosts file. Make sure you setup ssh keys for root account.

Step 3: Run playbook

The syntax is:
$ ansible-playbook -i my_ssh_hosts upload_ssh_keys.yml

Another example

In this example, a new user named vivek is created. Next ssh key added for user vivek and ssh server configured to drop password based login using ssh-setup.j2 template.

File: ssh-setup.yml

- hosts: cluster
          # create users for us
          # note user vivek added to sudo group 
          # on many system you may need to use wheel 
          # user in sudo or wheel group can sudo
          - user:
                  name: vivek
                  comment: "Vivek Gite"
                  shell: /bin/bash
                  groups: sudo
                  append: yes
                  generate_ssh_key: yes
                  ## run command 'mkpasswd --method=sha-512' to create your own encrypted password ##
                  password: $6$gF1EHgeUSSwDT3$xgw22QBdZfNe3OUjJkwXZOlEsL645TpacwiYwTwlUyah03.Zh1aUTTfh7iC7Uu5WfmHBkv5fxdbJ2OkzMAPkm/
                  ssh_key_type: ed25519
          # upload ssh key                
          - authorized_key:
                  user: vivek
                  state: present
                  manage_dir: yes
                  key: "{{ lookup('file', '/home/vivek/.ssh/id_ed25519.pub') }}"
          # configure ssh server
          - template:
                  src: ssh-setup.j2
                  dest: /etc/ssh/sshd_config
                  owner: root
                  mode: '0600'
                  validate: /usr/sbin/sshd -t -f %s
                  backup: yes
          # restart sshd
          - service:
                  name: sshd
                  state: restarted

File: ssh-setup.j2

The following will disable root login and password login. Only user named vivek may be login over ssh using public key (you need to issue sudo -i command to gain root shell):

Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
UsePrivilegeSeparation sandbox
KeyRegenerationInterval 3600
ServerKeyBits 1024
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin {{ sshd_permitroot_login }}
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM {{ sshd_use_pam }}
PasswordAuthentication {{ sshd_password_authentication }}
ChallengeResponseAuthentication {{ sshd_challenge_response_authentication }}
{% for nip in ansible_all_ipv4_addresses  %}
ListenAddress {{ nip }}
{% endfor %}

File: my-inventory.hosts


You run it as follows:
$ ansible-playbook -i my-inventory.hosts ssh-setup.yml
You can also use loops as follows to upload file for each user:

- hosts: all
  user: root
# ....
  - name: vivek
    key: "{{ lookup('file', 'vivek.pub') }}"
  - name: tom
    key: "{{ lookup('file', 'tom.pub') }}"
  - name: wendy
    key: "{{ lookup('file', 'wendy.pub') }}"
  - name: jerry
    key: "{{ lookup('file', 'jerry.pub') }}"
# ...
- name: Add ssh pub keys
  authorized_key: user={{ item.name }} key="{{ item.key }}"
  with_items: my_ssh_users

See authorized_key module doc for more info.

Свежие комментарии


Лучшие статьи

Fatal error: Uncaught Error: Call to a member function have_posts() on null in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php:380 Stack trace: #0 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/widget.php(257): fox56_blog_grid(NULL, Array) #1 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/register.php(33): include('/home/host18670...') #2 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/class-wp-widget.php(394): Wi_Widget_Latest_Posts->widget(Array, Array) #3 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/widgets.php(837): WP_Widget->display_callback(Array, Array) #4 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(417): dynamic_sidebar('sidebar') #5 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(136): fox56_single_sidebar() #6 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(7): fox56_single_inner() #7 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/single.php(23): fox56_single() #8 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/template-loader.php(106): include('/home/host18670...') #9 /home/host1867038/the-devops.ru/htdocs/www/wp-blog-header.php(19): require_once('/home/host18670...') #10 /home/host1867038/the-devops.ru/htdocs/www/index.php(17): require('/home/host18670...') #11 {main} thrown in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php on line 380