From abafe10f2daea8b6047f7ba807eb412038518bd3 Mon Sep 17 00:00:00 2001 From: decentral1se Date: Tue, 15 Mar 2022 11:39:22 +0100 Subject: [PATCH] init --- .ansible-lint.yml | 13 +++++++ .drone.yml | 14 +++++++ .envrc.sample | 18 +++++++++ .gitignore | 3 ++ .yamllint.yml | 16 ++++++++ README.md | 3 ++ defaults/main.yml | 4 ++ handlers/main.yml | 6 +++ molecule/default/converge.yml | 29 +++++++++++++++ molecule/default/files/members.yml | 6 +++ molecule/default/molecule.yml | 19 ++++++++++ requirements.txt | 4 ++ tasks/main.yml | 18 +++++++++ tasks/users.yml | 60 ++++++++++++++++++++++++++++++ 14 files changed, 213 insertions(+) create mode 100644 .ansible-lint.yml create mode 100644 .drone.yml create mode 100644 .envrc.sample create mode 100644 .gitignore create mode 100755 .yamllint.yml create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 molecule/default/converge.yml create mode 100644 molecule/default/files/members.yml create mode 100644 molecule/default/molecule.yml create mode 100644 requirements.txt create mode 100644 tasks/main.yml create mode 100644 tasks/users.yml diff --git a/.ansible-lint.yml b/.ansible-lint.yml new file mode 100644 index 0000000..0cf684d --- /dev/null +++ b/.ansible-lint.yml @@ -0,0 +1,13 @@ +--- +skip_list: + - "106" + - "204" + - "207" + - "208" + - "301" + - "305" + - "503" + - "602" + - "no-log-password" + - yaml + - "risky-shell-pipe" diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..fc2e1b4 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,14 @@ +---- +kind: pipeline +name: default +steps: + - name: integration test + image: python:3.9-buster + environment: + REMOTE_USER: molecule + HCLOUD_TOKEN: + from_secret: HCLOUD_TOKEN + commands: + - pip install -r requirements.txt + - export INSTANCE_UUID=$(pwgen 8 1) + - molecule test diff --git a/.envrc.sample b/.envrc.sample new file mode 100644 index 0000000..8a266bf --- /dev/null +++ b/.envrc.sample @@ -0,0 +1,18 @@ +# Your username that you use for accounts on our machines. +export REMOTE_USER= +export ANSIBLE_USER=$REMOTE_USER + +# The path to our pass credentials store +export PASSWORD_STORE_DIR= + +# The Hetzner Cloud API token for managing our instances +# Uncomment the prod/test line below depending on what you're doing +# export HCLOUD_TOKEN=$(pass show logins/hetzner/prod/api_key) +# export HCLOUD_TOKEN=$(pass show logins/hetzner/test/api_key) +export HCLOUD_TOKEN=$(pass show logins/hetzner/cicd/api_key) + +# For molecule role testing +export INSTANCE_UUID=$RANDOM + +# So molecule will show credentials in the logs +export MOLECULE_NO_LOG=False diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e88fc0b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +.envrc +/.venv/ diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100755 index 0000000..456c99c --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,16 @@ +--- +extends: default + +yaml-files: + - "*.yaml" + - "*.yml" + +ignore: | + .venv + .drone.yml + +rules: + line-length: disable + braces: + max-spaces-inside: 1 + level: error diff --git a/README.md b/README.md new file mode 100644 index 0000000..be4841f --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# autonomic.add-users + +[![Build Status](https://drone.autonomic.zone/api/badges/autonomic-cooperative/autonomic.add-users/status.svg?ref=refs/heads/main)](https://drone.autonomic.zone/autonomic-cooperative/autonomic.add-users) diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..d0ac058 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,4 @@ +--- +pass_length: 30 +user_groups: + - sudo diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..1135e07 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart SSH + become: true + service: + name: ssh + state: restarted diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml new file mode 100644 index 0000000..65be367 --- /dev/null +++ b/molecule/default/converge.yml @@ -0,0 +1,29 @@ +--- +- name: Converge + hosts: all + vars: + members: files/members.yml + pre_tasks: + - name: Wait for Hetzner VPS networking to come up + pause: + seconds: 10 + echo: false + + - name: Include resource variables + include_vars: "{{ members }}" + + # Note(decentral1se): We create the accounts before the role since we do + # not make molecule test this part of the role under test because we do not + # setup the password store. So, instead, we ensure the other parts are + # working. + - name: Prepare user accounts for the new role + user: + name: "{{ item.username }}" + shell: /bin/bash + password: "$apr1$GILkREir$r2zDF8rr9Bl8We9UVXnZl1" + groups: "{{ user_groups }}" + append: true + update_password: always + with_items: "{{ members }}" + roles: + - role: autonomic.add-users diff --git a/molecule/default/files/members.yml b/molecule/default/files/members.yml new file mode 100644 index 0000000..9f1aa65 --- /dev/null +++ b/molecule/default/files/members.yml @@ -0,0 +1,6 @@ +--- +members: + - username: foobar + email: barfoo + ssh_key: "ssh-rsa foo bar@nowhere.com" + uid: 1100 diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..19ee81a --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,19 @@ +--- +dependency: + name: galaxy + +driver: + name: hetznercloud + +platforms: + - name: "autonomic.add-users-${INSTANCE_UUID}" + server_type: cx11 + image: debian-10 + +provisioner: + name: ansible + +lint: | + set -e + yamllint -c .yamllint.yml . + ansible-lint --exclude .drone.yml -c .ansible-lint.yml . diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7d6c96a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +ansible-lint==6.0.0 +ansible==5.4.0 +molecule-hetznercloud==1.3.0 +molecule==3.6.1 diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..a1a4738 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,18 @@ +--- +- name: Ensure mandatory variables are configured + assert: + that: "{{ item }} is defined" + fail_msg: "You must define the '{{ item }}' variable" + with_items: + - members + +- name: Include resource variables + include_vars: "{{ members }}" + tags: + # Note(d1): we already load in converge.yml so skip here + - molecule-notest + +# Note(d1): Done in this way because https://stackoverflow.com/a/39041069 +- name: Include user addition tasks + include: users.yml user={{ item }} + with_items: "{{ members }}" diff --git a/tasks/users.yml b/tasks/users.yml new file mode 100644 index 0000000..23675ba --- /dev/null +++ b/tasks/users.yml @@ -0,0 +1,60 @@ +--- +- name: "Create new user account" + block: + - name: Show which user account is being handled + debug: + msg: "Attempting to create account for {{ user.username }}..." + + - name: Check if the user accounts already exists + getent: + database: passwd + key: "{{ user.username }}" + register: user_exists + ignore_errors: true + + - name: Prepare password store entry + become: false + delegate_to: localhost + command: "pass init -p users/{{ user.username }}/sudo/ {{ item.email }}" + when: user_exists is failed + tags: + - molecule-notest + + - name: Create a new user account with a new password + user: + name: "{{ user.username }}" + uid: "{{ user.uid }}" + shell: /bin/bash + password: "{{ lookup('passwordstore', 'users/{{ user.username }}/sudo/{{ inventory_hostname }} create=true length={{ pass_length }}') | password_hash('sha512') }}" + groups: "{{ user_groups }}" + append: true + update_password: always + when: user_exists is failed + tags: + - molecule-notest + + - name: Make sure the user's .ssh directory exists + file: + path: "/home/{{ user.username }}/.ssh" + state: directory + owner: "{{ user.username }}" + group: "{{ user.username }}" + mode: "0700" + + - name: Add new member's SSH key to authorized_keys file + blockinfile: + path: "/home/{{ user.username }}/.ssh/authorized_keys" + block: "{{ user.ssh_key }}" + state: present + create: true + mode: "0600" + owner: "{{ user.username }}" + group: "{{ user.username }}" + + - name: "Add username to the SSH AllowUsers configuration" + replace: + backup: true + dest: /etc/ssh/sshd_config + regexp: '^(AllowUsers(?!.*\b{{ user.username }}\b).*)$' + replace: '\1 {{ user.username }}' + notify: Restart SSH