From eafbaed304c6ae925fb84b6d4ecc9a6beda31531 Mon Sep 17 00:00:00 2001 From: sankar palanivel Date: Tue, 26 Oct 2021 12:16:59 +0100 Subject: [PATCH] Update ansible roles to automate nordix openvpn user management In this change, - Update ansible roles to automate the nordix openvpn user access management from the self-service portal - Update README file to include steps to manually create/revoke openvpn access for users Change-Id: I2db874045923f14553d11872c96f5b2e332baaf7 --- infra/openvpn_automation/README.md | 90 ++++++++++++------- .../delete_openvpn_client.sh | 42 +++++++++ .../generate_openvpn_client.sh | 42 +++++++++ .../inventory/group_vars/all/vars.yaml | 3 + .../inventory/inventory.ini | 1 + .../openvpn_user_revoke.yaml | 21 ----- .../openvpn_user_setup.yaml | 21 ----- .../playbooks/openvpn_user_revoke.yaml | 8 ++ .../playbooks/openvpn_user_setup.yaml | 29 ++++++ .../generate-user-ovpn/files/make_config.sh | 0 .../roles}/generate-user-ovpn/tasks/main.yaml | 69 +++++++------- .../roles}/revoke-user-ovpn/tasks/main.yaml | 33 +++---- .../roles/vpn-client-certs/tasks/main.yml | 30 +++++++ .../vpn-client-preflight/tasks/main.yaml | 23 +++++ 14 files changed, 289 insertions(+), 123 deletions(-) create mode 100755 infra/openvpn_automation/delete_openvpn_client.sh create mode 100755 infra/openvpn_automation/generate_openvpn_client.sh delete mode 100644 infra/openvpn_automation/openvpn_user_revoke.yaml delete mode 100644 infra/openvpn_automation/openvpn_user_setup.yaml create mode 100644 infra/openvpn_automation/playbooks/openvpn_user_revoke.yaml create mode 100644 infra/openvpn_automation/playbooks/openvpn_user_setup.yaml rename infra/openvpn_automation/{ => playbooks/roles}/generate-user-ovpn/files/make_config.sh (100%) rename infra/openvpn_automation/{ => playbooks/roles}/generate-user-ovpn/tasks/main.yaml (50%) rename infra/openvpn_automation/{ => playbooks/roles}/revoke-user-ovpn/tasks/main.yaml (60%) create mode 100644 infra/openvpn_automation/playbooks/roles/vpn-client-certs/tasks/main.yml create mode 100644 infra/openvpn_automation/playbooks/roles/vpn-client-preflight/tasks/main.yaml diff --git a/infra/openvpn_automation/README.md b/infra/openvpn_automation/README.md index feb89c9..d62d14a 100644 --- a/infra/openvpn_automation/README.md +++ b/infra/openvpn_automation/README.md @@ -1,13 +1,14 @@ -# Creating OpenVPN files for users +# Manually Creating & Removing OpenVPN access for users ## Prerequisites -In order to follow the steps documented here, few things must be prepared -in advance. +In order to manually create/remove OpenVPN access for users, there are pre-requisites +steps which should be fulfilled. -* Access to required below Nordix OpenVPN/Jump servers with sudo access to infra user, +* Access to below Nordix OpenVPN/Jump and CA servers with sudo access to infra user + from your local machine, +----------------+---------------+--------------------------------------+ - | Nordix OpenVPN | IP ADDRESS | SSH ACCESS | + | Nordix OpenVPN | IP ADDRESS | SSH ACCESS | +================+===============+======================================+ | ONAP-CityCloud | 77.81.6.42 | ssh @77.81.6.42 -p 52413 | +----------------+---------------+--------------------------------------+ @@ -17,20 +18,18 @@ in advance. +----------------+---------------+--------------------------------------+ | CCD | 188.212.109.53| ssh @188.212.109.53 -p 52413| +----------------+---------------+--------------------------------------+ - -* Ensure SSH key based authentication enabled between Openvpn server and CA - -* Login to required Nordix OpenVPN/Jump server from your machine + | CA Server | 77.81.6.250 | ssh @77.81.6.250 -p 52413 | + +----------------+---------------+--------------------------------------+ * Install virtualenv, python3-minimal, python3-dev, and python3-pip -```bash +``` sudo apt update sudo apt install -y virtualenv python3-minimal python3-dev python3-pip ``` * Create and set virtualenv -```bash +``` virtualenv -p python3 .venv -source .venv/bin/activate +source ~/.venv/bin/activate ``` * Install Ansible 2.9.6 ``` @@ -39,25 +38,25 @@ pip install ansible==2.9.6 ## Generate User ovpn file -* Login to OpenVPN/Jump server with your credentials - * Clone infra/tools repository from Nordix Gerrit -```bash +``` git clone "https://gerrit.nordix.org/infra/tools" ``` You are now ready to create ovpn files for users in project specific OpenVPN server, -* Switch to infra user in OpenVPN/Jump server - -* Change directory to you home directory from where repo cloned -```bash -cd /tools/infra/openvpn_automation -source /.venv/bin/activate -ansible-playbook -i inventory/inventory.ini openvpn_user_setup.yaml -e "client_name=" +* Change directory in your computer where the repo cloned, +``` +cd tools/infra/openvpn_automation ``` +* Export the `user_name` and `vpn_server_public_ip` as environment variable +``` +export user_name= +export vpn_server_public_ip= +``` NOTE: +* OpenVPN server public IP's can be taken from the table in the top of this file * Client user ID should be user's username (first character of user firstname + lastname) * {{ client_name }} should be given as per specific OpenvVPN servers listed below, +----------------+---------------+---------------------------+ @@ -74,6 +73,20 @@ NOTE: | CCD | 10.4.0.0/24 | client_userid.ccd | +----------------+---------------+---------------------------+ +* Update the invetory file to proceed, +``` +cat >> inventory/inventory.ini <@gerrit.nordix.org:29418/infra/tools && scp -p -P 29418 @gerrit.nordix.org:hooks/commit-msg "tools/.git/hooks/" ``` You are now ready to revoke Openvpn access for users in project specific OpenVPN server, -* Switch to infra user in OpenVPN/Jump server +* Change directory in your computer where the repo cloned, +``` +cd tools/infra/openvpn_automation +``` -* Change directory to you home directory from where repo cloned -```bash -cd /tools/infra/openvpn_automation -source /.venv/bin/activate -ansible-playbook -i inventory/inventory.ini openvpn_user_revoke.yaml -e "client_name=" +* Export the `user_name` and `vpn_server_public_ip` as environment variable +``` +export user_name= +export vpn_server_public_ip= ``` NOTE: +* OpenVPN server public IP's can be taken from the table in the top of this file * Client user ID should be user's username (first character of user firstname + lastname) * {{ client_name }} should be given as per specific OpenvVPN servers listed below, +----------------+---------------+---------------------------+ @@ -122,4 +136,18 @@ NOTE: | CCD | 10.4.0.0/24 | client_userid.ccd | +----------------+---------------+---------------------------+ +* Update the invetory file to proceed, +``` +cat >> inventory/inventory.ini < 0 or user_ovpn_file.stat.exists == false - - roles: - - {role: revoke-user-ovpn, when: client_name is defined and client_name | length > 0} diff --git a/infra/openvpn_automation/openvpn_user_setup.yaml b/infra/openvpn_automation/openvpn_user_setup.yaml deleted file mode 100644 index 3c7fe49..0000000 --- a/infra/openvpn_automation/openvpn_user_setup.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -- name: Generate user vpn config files - hosts: nordix_ca - become: false - gather_facts: false - - pre_tasks: - - name: Check user ovpn file existence - stat: - path: "{{ nordix_openvpn_clientconfig }}/files/{{ client_name }}.ovpn" - register: user_ovpn_file - delegate_to: localhost - - - name: Fail the deployment - fail: - msg: - - "{{ client_name }}.ovpn file already exist under '{{ nordix_openvpn_clientconfig }}/files/{{ client_name }}.ovpn' or Client name is not defined" - when: client_name is not defined and client_name | length > 0 or user_ovpn_file.stat.exists - - roles: - - {role: generate-user-ovpn, when: client_name is defined and client_name | length > 0} diff --git a/infra/openvpn_automation/playbooks/openvpn_user_revoke.yaml b/infra/openvpn_automation/playbooks/openvpn_user_revoke.yaml new file mode 100644 index 0000000..8419d9d --- /dev/null +++ b/infra/openvpn_automation/playbooks/openvpn_user_revoke.yaml @@ -0,0 +1,8 @@ +--- +- name: Revoke user Openvpn config files + hosts: nordix_ca + become: false + gather_facts: false + + roles: + - {role: revoke-user-ovpn} \ No newline at end of file diff --git a/infra/openvpn_automation/playbooks/openvpn_user_setup.yaml b/infra/openvpn_automation/playbooks/openvpn_user_setup.yaml new file mode 100644 index 0000000..5e9ddf7 --- /dev/null +++ b/infra/openvpn_automation/playbooks/openvpn_user_setup.yaml @@ -0,0 +1,29 @@ +--- +- name: Prepare to create user ovpn file in OpenVPN server + hosts: localhost + gather_facts: false + vars_files: + - "{{ playbook_dir }}/../inventory/group_vars/all/vars.yaml" + + roles: + - {role: vpn-client-preflight} + +- name: Generate Certificates for vpn users + hosts: jumphost + become: false + gather_facts: false + vars_files: + - "{{ playbook_dir }}/../inventory/group_vars/all/vars.yaml" + + roles: + - {role: vpn-client-certs} + +- name: Generate user vpn config files + hosts: nordix_ca + become: false + gather_facts: false + vars_files: + - "{{ playbook_dir }}/../inventory/group_vars/all/vars.yaml" + + roles: + - {role: generate-user-ovpn} \ No newline at end of file diff --git a/infra/openvpn_automation/generate-user-ovpn/files/make_config.sh b/infra/openvpn_automation/playbooks/roles/generate-user-ovpn/files/make_config.sh similarity index 100% rename from infra/openvpn_automation/generate-user-ovpn/files/make_config.sh rename to infra/openvpn_automation/playbooks/roles/generate-user-ovpn/files/make_config.sh diff --git a/infra/openvpn_automation/generate-user-ovpn/tasks/main.yaml b/infra/openvpn_automation/playbooks/roles/generate-user-ovpn/tasks/main.yaml similarity index 50% rename from infra/openvpn_automation/generate-user-ovpn/tasks/main.yaml rename to infra/openvpn_automation/playbooks/roles/generate-user-ovpn/tasks/main.yaml index fcf8bdf..6fbcaa6 100644 --- a/infra/openvpn_automation/generate-user-ovpn/tasks/main.yaml +++ b/infra/openvpn_automation/playbooks/roles/generate-user-ovpn/tasks/main.yaml @@ -1,49 +1,32 @@ --- -- name: Check {{ client_name }} key existence - stat: - path: "{{ nordix_openvpn_easyrsa_path }}/pki/private/{{ client_name }}.key" - register: client_privatekey - delegate_to: localhost - -- name: Create client cert and csr - command: ./easyrsa --batch --req-cn={{ client_name }} gen-req {{ client_name }} nopass - args: - chdir: "{{ nordix_openvpn_easyrsa_path }}" - when: client_privatekey.stat.exists == false - delegate_to: localhost - -- name: Copy client key to client_config directory - copy: - src: "{{ nordix_openvpn_easyrsa_path }}/pki/private/{{ client_name }}.key" - dest: "{{ nordix_openvpn_clientconfig }}/keys/" - changed_when: true - delegate_to: localhost - - name: Copy client csr to nordix CA copy: - src: "{{ nordix_openvpn_easyrsa_path }}/pki/reqs/{{ client_name }}.req" + src: "{{ hostvars['localhost']['vpn_user_files_location'] }}/{{ user_name }}.req" dest: /tmp + owner: "infra" + group: "infra" changed_when: true + become: true -- name: Check {{ client_name }} csr existence in CA +- name: Check {{ user_name }} csr existence in CA stat: - path: "{{ nordix_ca_easyrsa_path }}/pki/reqs/{{ client_name }}.req" + path: "{{ nordix_ca_easyrsa_path }}/pki/reqs/{{ user_name }}.req" register: client_csr - name: Import client csr - command: ./easyrsa --batch import-req /tmp/{{ client_name }}.req {{ client_name }} + command: ./easyrsa --batch import-req /tmp/{{ user_name }}.req {{ user_name }} args: chdir: "{{ nordix_ca_easyrsa_path }}" when: client_csr.stat.exists == false changed_when: true -- name: Check {{ client_name }} crt existence in CA +- name: Check {{ user_name }} crt existence in CA stat: - path: "{{ nordix_ca_easyrsa_path }}/pki/issued/{{ client_name }}.crt" + path: "{{ nordix_ca_easyrsa_path }}/pki/issued/{{ user_name }}.crt" register: client_crt - name: Sign client csr - command: ./easyrsa --batch sign-req client {{ client_name }} + command: ./easyrsa --batch sign-req client {{ user_name }} args: chdir: "{{ nordix_ca_easyrsa_path }}" when: client_crt.stat.exists == false @@ -51,28 +34,46 @@ - name: Fetch client cert to client-configs/keys/ dir fetch: - src: "{{ nordix_ca_easyrsa_path }}/pki/issued/{{ client_name }}.crt" - dest: "{{ nordix_openvpn_clientconfig }}/keys/" + src: "{{ nordix_ca_easyrsa_path }}/pki/issued/{{ user_name }}.crt" + dest: "{{ hostvars['localhost']['vpn_user_files_location'] }}/" flat: true changed_when: true +- name: Copy client cert file to OpenVPN server + copy: + src: "{{ hostvars['localhost']['vpn_user_files_location'] }}/{{ user_name }}.crt" + dest: "{{ nordix_openvpn_clientconfig }}/keys/" + changed_when: true + delegate_to: jumphost + - name: Generate Client .ovpn file - script: make_config.sh "{{ client_name }}" + script: make_config.sh "{{ user_name }}" args: chdir: "{{ nordix_openvpn_clientconfig }}/" executable: /bin/bash - delegate_to: localhost + delegate_to: jumphost + become: false + +- name: Fetch Client .ovpn file + fetch: + src: "{{ nordix_openvpn_clientconfig }}/files/{{ item|basename }}" + dest: "{{ hostvars['localhost']['vpn_user_files_location'] }}/" + flat: true + with_items: + - "{{ user_name }}.ovpn" + delegate_to: jumphost + become: false - name: Log user specific ovpn files location on the console debug: msg: - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - "The ovpn file {{ client_name }}.ovpn is located in {{ nordix_openvpn_clientconfig }}/files/{{ client_name }}.ovpn" - - "Please share the newly generated {{ client_name }}.ovpn file with user over email with below instructions," + - "The ovpn file {{ user_name }}.ovpn is located in {{ nordix_openvpn_clientconfig }}/files/{{ user_name }}.ovpn" + - "Please share the newly generated {{ user_name }}.ovpn file with user over email with below instructions," - "1. Please install the openvpn on your laptop. Assuming you using Ubuntu:" - "#sudo apt install openvpn" - "2. Then you need to open the VPN connection using the .ovpn file which contain all the required certificates:" - - "#sudo openvpn --config {{ client_name }}.ovpn &" + - "#sudo openvpn --config {{ user_name }}.ovpn &" - "3. Now, user should have access to all the VMs directly from your laptop" - "4. In case you use Windows 10 OS, please use the community version of OpenVPN client:" - "https://swupdate.openvpn.org/community/releases/openvpn-install-2.4.8-I602-Win10.exe" diff --git a/infra/openvpn_automation/revoke-user-ovpn/tasks/main.yaml b/infra/openvpn_automation/playbooks/roles/revoke-user-ovpn/tasks/main.yaml similarity index 60% rename from infra/openvpn_automation/revoke-user-ovpn/tasks/main.yaml rename to infra/openvpn_automation/playbooks/roles/revoke-user-ovpn/tasks/main.yaml index bcb8bf2..7a3f716 100644 --- a/infra/openvpn_automation/revoke-user-ovpn/tasks/main.yaml +++ b/infra/openvpn_automation/playbooks/roles/revoke-user-ovpn/tasks/main.yaml @@ -1,11 +1,11 @@ --- -- name: Check {{ client_name }} cert existence in CA +- name: Check {{ user_name }} cert existence in CA stat: - path: "{{ nordix_ca_easyrsa_path }}/pki/issued//{{ client_name }}.crt" + path: "{{ nordix_ca_easyrsa_path }}/pki/issued//{{ user_name }}.crt" register: client_cert -- name: Revoke {{ client_name }} cert in CA - command: ./easyrsa --batch revoke {{ client_name }} +- name: Revoke {{ user_name }} cert in CA + command: ./easyrsa --batch revoke {{ user_name }} args: chdir: "{{ nordix_ca_easyrsa_path }}" when: client_cert.stat.exists == true @@ -31,8 +31,10 @@ changed_when: true - name: Move updated crl to /etc/openvpn/ dir - command: mv /tmp/crl.pem /etc/openvpn/ - delegate_to: localhost + copy: + src: /tmp/crl.pem + dest: /etc/openvpn/ + delegate_to: jumphost register: updated_crl changed_when: true become: true @@ -43,28 +45,27 @@ state: restarted daemon_reload: true enabled: true - delegate_to: localhost - when: updated_crl.rc == 0 + delegate_to: jumphost become: true -- name: Remove {{ client_name }} files from OpenVPN server +- name: Remove {{ user_name }} files from OpenVPN server file: path: "{{ item }}" state: absent with_items: - - "{{ nordix_openvpn_easyrsa_path }}/pki/private/{{ client_name }}.key" - - "{{ nordix_openvpn_easyrsa_path }}/pki/reqs/{{ client_name }}.req" - - "{{ nordix_openvpn_clientconfig }}/keys/{{ client_name }}.crt" - - "{{ nordix_openvpn_clientconfig }}/keys/{{ client_name }}.key" - - "{{ nordix_openvpn_clientconfig }}/files/{{ client_name }}.ovpn" - delegate_to: localhost + - "{{ nordix_openvpn_easyrsa_path }}/pki/private/{{ user_name }}.key" + - "{{ nordix_openvpn_easyrsa_path }}/pki/reqs/{{ user_name }}.req" + - "{{ nordix_openvpn_clientconfig }}/keys/{{ user_name }}.crt" + - "{{ nordix_openvpn_clientconfig }}/keys/{{ user_name }}.key" + - "{{ nordix_openvpn_clientconfig }}/files/{{ user_name }}.ovpn" + delegate_to: jumphost register: user_files_removal - name: Log user specific ovpn files location on the console debug: msg: - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - "The OpenVPN access has been revoked for the user {{ client_name }}" + - "The OpenVPN access has been revoked for the user {{ user_name }}" - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - '' when: '"All items completed" in user_files_removal.msg' diff --git a/infra/openvpn_automation/playbooks/roles/vpn-client-certs/tasks/main.yml b/infra/openvpn_automation/playbooks/roles/vpn-client-certs/tasks/main.yml new file mode 100644 index 0000000..dbe4e54 --- /dev/null +++ b/infra/openvpn_automation/playbooks/roles/vpn-client-certs/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Check {{ user_name }} key existence + stat: + path: "{{ nordix_openvpn_easyrsa_path }}/pki/private/{{ user_name }}.key" + register: client_privatekey + +- name: Create client cert and csr + command: ./easyrsa --batch --req-cn={{ user_name }} gen-req {{ user_name }} nopass + args: + chdir: "{{ nordix_openvpn_easyrsa_path }}" + when: client_privatekey.stat.exists == false + +- name: Copy client key to client_config directory + copy: + src: "{{ nordix_openvpn_easyrsa_path }}/pki/private/{{ user_name }}.key" + dest: "{{ nordix_openvpn_clientconfig }}/keys/" + remote_src: true + owner: "infra" + group: "infra" + changed_when: true + become: true + +- name: Fetch the CA, user {{ user_name }} cert and key + fetch: + src: "{{ nordix_openvpn_easyrsa_path }}/pki/reqs/{{ user_name }}.req" + dest: "{{ hostvars['localhost']['vpn_user_files_location'] }}/" + flat: true + remote_src: true + force: true + become: true diff --git a/infra/openvpn_automation/playbooks/roles/vpn-client-preflight/tasks/main.yaml b/infra/openvpn_automation/playbooks/roles/vpn-client-preflight/tasks/main.yaml new file mode 100644 index 0000000..3f2e110 --- /dev/null +++ b/infra/openvpn_automation/playbooks/roles/vpn-client-preflight/tasks/main.yaml @@ -0,0 +1,23 @@ +--- +# tasks file for preflight +- name: Check user vpn directory existence + stat: + path: "{{ lookup('env','HOME') }}/{{ user_name }}" + register: uservpn_dir + +- name: Log user vpn directory status on console + debug: + msg: "The user vpn directory {{ lookup('env','HOME') }}/{{ user_name }} is already exist" + when: uservpn_dir.stat.exists + +- name: Create directory to user vpn files + file: + path: "{{ lookup('env','HOME') }}/{{ user_name }}" + state: directory + mode: "0700" + recurse: true + when: not uservpn_dir.stat.exists + +- name: Set fact for user vpn files directory + set_fact: + vpn_user_files_location: "{{ lookup('env','HOME') }}/{{ user_name }}" \ No newline at end of file -- 2.25.1