Automate nordix openvpn user config files 79/6179/15
authorsankar palanivel <sankar.palanivel@est.tech>
Tue, 6 Oct 2020 12:35:12 +0000 (13:35 +0100)
committersankar palanivel <sankar.palanivel@est.tech>
Wed, 14 Oct 2020 14:52:43 +0000 (15:52 +0100)
In this change,

- Generate *.ovpn file in project specific Openvpn/jump server
- Revoke user's Openvpn access from project specific Openvpn/jump server

Change-Id: Ifb692a8a467cf511de4cb95a291c9d9ca6010224

infra/openvpn_automation/README.md [new file with mode: 0644]
infra/openvpn_automation/generate-user-ovpn/files/make_config.sh [new file with mode: 0644]
infra/openvpn_automation/generate-user-ovpn/tasks/main.yaml [new file with mode: 0644]
infra/openvpn_automation/inventory/group_vars/all/vars.yaml [new file with mode: 0644]
infra/openvpn_automation/inventory/inventory.ini [new file with mode: 0644]
infra/openvpn_automation/openvpn_user_revoke.yaml [new file with mode: 0644]
infra/openvpn_automation/openvpn_user_setup.yaml [new file with mode: 0644]
infra/openvpn_automation/revoke-user-ovpn/tasks/main.yaml [new file with mode: 0644]

diff --git a/infra/openvpn_automation/README.md b/infra/openvpn_automation/README.md
new file mode 100644 (file)
index 0000000..ba44e08
--- /dev/null
@@ -0,0 +1,119 @@
+# Creating OpenVPN files for users
+
+## Prerequisites
+
+In order to follow the steps documented here, few things must be prepared
+in advance.
+
+* Access to required below Nordix OpenVPN/Jump servers with sudo access to infra user,
+  +----------------+---------------+--------------------------------------+
+  | Nordix OpenVPN |   IP ADDRESS  |              SSH ACCESS              |
+  +================+===============+======================================+
+  | ONAP-CityCloud |  77.81.6.42   | ssh <USER_ID>@77.81.6.42 -p 52413    |
+  +----------------+---------------+--------------------------------------+
+  | ONAP-Xerces    | 129.192.70.24 | ssh <USER_ID>@129.192.70.24 -p 52413 |
+  +----------------+---------------+--------------------------------------+
+  | Acumos         | 91.106.193.58 | ssh <USER_ID>@91.106.193.58 -p 52413 |
+  +----------------+---------------+--------------------------------------+
+
+* Ensure SSH key based authentication enabled between Openvpn server and CA
+
+* Login to required Nordix OpenVPN/Jump server from your machine
+
+* 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
+```
+* Install Ansible 2.9.6
+```
+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 "ssh://<USERNAME>@gerrit.nordix.org:29418/infra/tools" && scp -p -P 29418 <USERNAME>@gerrit.nordix.org:hooks/commit-msg "tools/.git/hooks/"
+```
+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 <YOUR_HOME_DIR>/tools/infra/openvpn_automation
+source <YOUR_HOME_DIR>/.venv/bin/activate
+ansible-playbook -i inventory/inventory.ini openvpn_user_setup.yaml -e "client_name=<USERNAME_TO_CREATE_OVPN_CERT>"
+```
+
+NOTE:
+* 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,
+  +----------------+---------------+---------------------------+
+  | Nordix OpenVPN |     CIDR      |    Client_name            |
+  +================+===============+===========================+
+  | ONAP-CityCloud | 10.1.0.0/24   | client_userid.onap        |
+  |                | 10.2.0.0/24   |                           |
+  +----------------+---------------+---------------------------+
+  | ONAP-Xerces    | 10.10.10.0/24 | client_userid.xerces.onap |
+  |                | 172.16.0.0/16 |                           |
+  +----------------+---------------+---------------------------+
+  | Acumos         | 10.1.0.0/24   | client_userid.acumos      |
+  +----------------+---------------+---------------------------+
+
+* Once user specific ovpn file is generated, this file should be shared with user's email with below instructions,
+
+  * Please install the openvpn on your laptop. Assuming you using Ubuntu:
+    $ sudo apt install openvpn
+  * Then you need to open the VPN connection using the .ovpn file which contain all the required certificates:
+    $ sudo openvpn --config {{ client_name }}.ovpn
+  * Now, you should have access to all the VMs directly from your laptop
+    $ nmap -n -sP <CIDR>/24
+  * 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
+
+
+## Revoke User ovpn file
+
+* Login to required Nordix OpenVPN/Jump server from your machine
+
+* Clone infra/tools repository from Nordix Gerrit
+
+```bash
+git clone "ssh://<USERNAME>@gerrit.nordix.org:29418/infra/tools && scp -p -P 29418 <USERNAME>@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 to you home directory from where repo cloned
+```bash
+cd <YOUR_HOME_DIR>/tools/infra/openvpn_automation
+source <YOUR_HOME_DIR>/.venv/bin/activate
+ansible-playbook -i inventory/inventory.ini openvpn_user_revoke.yaml -e "client_name=<USERNAME_TO_REVOKE_ACCESS>"
+```
+NOTE:
+* 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,
+  +----------------+---------------+---------------------------+
+  | Nordix OpenVPN |     CIDR      |    Client_name            |
+  +================+===============+===========================+
+  | ONAP-CityCloud | 10.1.0.0/24   | client_userid.onap        |
+  |                | 10.2.0.0/24   |                           |
+  +----------------+---------------+---------------------------+
+  | ONAP-Xerces    | 10.10.10.0/24 | client_userid.xerces.onap |
+  |                | 172.16.0.0/16 |                           |
+  +----------------+---------------+---------------------------+
+  | Acumos         | 10.1.0.0/24   | client_userid.acumos      |
+  +----------------+---------------+---------------------------+
+
+You are done!
diff --git a/infra/openvpn_automation/generate-user-ovpn/files/make_config.sh b/infra/openvpn_automation/generate-user-ovpn/files/make_config.sh
new file mode 100644 (file)
index 0000000..24ba4b5
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# First argument: Client identifier
+if [ -z "$1" ]
+  then
+    echo "Please provide the client identifier."
+    echo "   example: $0 jsmith.xerces.onap"
+    exit 1
+fi
+
+KEY_DIR=~/OpenVPN/client-configs/keys
+OUTPUT_DIR=~/OpenVPN/client-configs/files
+BASE_CONFIG=~/OpenVPN/client-configs/base.conf
+
+cat ${BASE_CONFIG} \
+    <(echo -e '<ca>') \
+    ${KEY_DIR}/ca.crt \
+    <(echo -e '</ca>\n<cert>') \
+    ${KEY_DIR}/${1}.crt \
+    <(echo -e '</cert>\n<key>') \
+    ${KEY_DIR}/${1}.key \
+    <(echo -e '</key>\n<tls-auth>') \
+    ${KEY_DIR}/ta.key \
+    <(echo -e '</tls-auth>') \
+    > ${OUTPUT_DIR}/${1}.ovpn
+
diff --git a/infra/openvpn_automation/generate-user-ovpn/tasks/main.yaml b/infra/openvpn_automation/generate-user-ovpn/tasks/main.yaml
new file mode 100644 (file)
index 0000000..fcf8bdf
--- /dev/null
@@ -0,0 +1,81 @@
+---
+- 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"
+    dest: /tmp
+  changed_when: true
+
+- name: Check {{ client_name }} csr existence in CA
+  stat:
+    path: "{{ nordix_ca_easyrsa_path }}/pki/reqs/{{ client_name }}.req"
+  register: client_csr
+
+- name: Import client csr
+  command: ./easyrsa --batch import-req /tmp/{{ client_name }}.req {{ client_name }}
+  args:
+    chdir: "{{ nordix_ca_easyrsa_path }}"
+  when: client_csr.stat.exists == false
+  changed_when: true
+
+- name: Check {{ client_name }} crt existence in CA
+  stat:
+    path: "{{ nordix_ca_easyrsa_path }}/pki/issued/{{ client_name }}.crt"
+  register: client_crt
+
+- name: Sign client csr
+  command: ./easyrsa --batch sign-req client {{ client_name }}
+  args:
+    chdir: "{{ nordix_ca_easyrsa_path }}"
+  when: client_crt.stat.exists == false
+  changed_when: true
+
+- 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/"
+    flat: true
+  changed_when: true
+
+- name: Generate Client .ovpn file
+  script: make_config.sh "{{ client_name }}"
+  args:
+    chdir: "{{ nordix_openvpn_clientconfig }}/"
+    executable: /bin/bash
+  delegate_to: localhost
+
+- 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,"
+      - "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 &"
+      - "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"
+      - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+      - ''
+  delegate_to: localhost
diff --git a/infra/openvpn_automation/inventory/group_vars/all/vars.yaml b/infra/openvpn_automation/inventory/group_vars/all/vars.yaml
new file mode 100644 (file)
index 0000000..0f31ca2
--- /dev/null
@@ -0,0 +1,6 @@
+# common: vars
+---
+nordix_remote_user_name: "infra"
+nordix_ca_easyrsa_path: "/home/infra/EasyRSA-v3.0.6"
+nordix_openvpn_easyrsa_path: "/home/infra/OpenVPN/EasyRSA-v3.0.6"
+nordix_openvpn_clientconfig: "/home/infra/OpenVPN/client-configs"
diff --git a/infra/openvpn_automation/inventory/inventory.ini b/infra/openvpn_automation/inventory/inventory.ini
new file mode 100644 (file)
index 0000000..624a86b
--- /dev/null
@@ -0,0 +1,8 @@
+[all:vars]
+ansible_ssh_extra_args=' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
+
+[localhost]
+127.0.0.1 ansible_connection=local ansible_user=infra
+
+# Nordix CA server used to sign CSR's generated for user ovpn files
+nordix_ca ansible_connection=ssh ansible_host=77.81.6.250 ansible_user=infra ansible_port=52413 ansible_python_interpreter=/usr/bin/python
diff --git a/infra/openvpn_automation/openvpn_user_revoke.yaml b/infra/openvpn_automation/openvpn_user_revoke.yaml
new file mode 100644 (file)
index 0000000..60d3a6f
--- /dev/null
@@ -0,0 +1,21 @@
+---
+- name: Revoke user Openvpn 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 not 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 == 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
new file mode 100644 (file)
index 0000000..3c7fe49
--- /dev/null
@@ -0,0 +1,21 @@
+---
+- 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/revoke-user-ovpn/tasks/main.yaml b/infra/openvpn_automation/revoke-user-ovpn/tasks/main.yaml
new file mode 100644 (file)
index 0000000..bcb8bf2
--- /dev/null
@@ -0,0 +1,71 @@
+---
+- name: Check {{ client_name }} cert existence in CA
+  stat:
+    path: "{{ nordix_ca_easyrsa_path }}/pki/issued//{{ client_name }}.crt"
+  register: client_cert
+
+- name: Revoke {{ client_name }} cert in CA
+  command: ./easyrsa --batch revoke {{ client_name }}
+  args:
+    chdir: "{{ nordix_ca_easyrsa_path }}"
+  when: client_cert.stat.exists == true
+  register: revoke_result
+
+- name: Run gen-crl in CA
+  command: ./easyrsa gen-crl
+  args:
+    chdir: "{{ nordix_ca_easyrsa_path }}"
+  when: revoke_result.rc == 0
+
+- name: Check updated crl file existence in CA
+  stat:
+    path: "{{ nordix_ca_easyrsa_path }}/pki/crl.pem"
+  register: crl_existence
+
+- name: Fetch updated crl from CA to Openvpn /tmp dir
+  fetch:
+    src: "{{ nordix_ca_easyrsa_path }}/pki/crl.pem"
+    dest: "/tmp/"
+    flat: true
+  when: crl_existence.stat.exists == true
+  changed_when: true
+
+- name: Move updated crl to /etc/openvpn/ dir
+  command: mv /tmp/crl.pem /etc/openvpn/
+  delegate_to: localhost
+  register: updated_crl
+  changed_when: true
+  become: true
+
+- name: Restart Openvpn Service
+  systemd:
+    name: openvpn@server
+    state: restarted
+    daemon_reload: true
+    enabled: true
+  delegate_to: localhost
+  when: updated_crl.rc == 0
+  become: true
+
+- name: Remove {{ client_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
+  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 }}"
+      - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+      - ''
+  when: '"All items completed" in user_files_removal.msg'
+  delegate_to: localhost