I use an Ansible role based approach to deploying service configurations on my testing infrastructure; most of these services that run on VMs (rather than part of my Kubernetes infrasturcture) are deployed as Docker containers, and then an Nginx proxy configuration is generated. I have two roles, one that simply creates a self-signed certificate for the service, and other that uses an internal CA to sign the certificates. I'm going to demonstrate the use of the latter in this piece.
In the top-level playbook that invokes this role, you might have a host group like this:
- hosts:
- cicd
become: true
vars:
ca_cert_name: "rootCA"
ca_key_path: "/etc/ssl/private/rootCA.key"
roles:
- { role: ca-signed-cert-service, common_name: "build.krebstar.internal", backend_addr: "http://127.0.0.1:8900" }
Where under (amongst whatever other roles) roles
for that host group, would be the ca-signed-cert-service role, and the common_name for the certificate and the backend_addr that will wind up in the Nginx proxy configuration.
The structure of the roles/ca-signed-service
directory is:
files handlers tasks templates
So, in templates
, we'll start with nginx.conf.j2
:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ common_name }};
ssl_certificate /etc/ssl/cert/{{ common_name }}.crt;
ssl_certificate_key /etc/ssl/private/{{ common_name }}.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
location / {
proxy_pass {{ backend_addr }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
port_in_redirect off;
proxy_connect_timeout 300;
}
}
server {
listen 80;
listen [::]:80;
server_name {{ common_name }};
return 301 https://$host$request_uri;
}
which Ansible, when the tasks run, will populate the template with the common_name and backend_addr you specified earlier.
In tasks/main.yml
:
---
- name: Creates directory for Certificate Signing Requests, Keys, and Certfiles
file:
path: "/etc/ssl/{{ item }}"
state: directory
owner: root
group: root
mode: 0775
recurse: yes
with_items:
- csr
- private
- cert
- certs
- name: Install CA
file:
src: "{{ ca_cert_name }}.pem"
dest: "/etc/ssl/certs/{{ ca_cert_name }}.pem"
notify: Update ca-certificates
we create the expected directories for storing the rootCA and the new csrs, keys, and certs, and then install the new CA.
We then proceed to generate a new cert signed by the new CA:
- name: Generate an OpenSSL private key for {{ common_name }}
openssl_privatekey:
path: /etc/ssl/private/{{ common_name }}.pem
size: 1024
- name: Generate a Certificate Signing Request for {{common_name}}
openssl_csr:
path: /etc/ssl/csr/{{ common_name }}.csr
privatekey_path: /etc/ssl/private/{{ common_name }}.pem
common_name: "{{ common_name }}"
- name: Generate an OpenSSL certificate signed with your own CA certificate
openssl_certificate:
path: /etc/ssl/cert/{{ common_name }}.crt
csr_path: /etc/ssl/csr/{{ common_name }}.csr
ownca_path: "/etc/ssl/certs/{{ ca_cert_name }}.pem"
ownca_privatekey_path: "{{ca_key_path}}"
provider: ownca
and install Nginx and template the service configuration:
- name: Install nginx Package
apt:
update_cache: yes
name: nginx
state: present
notify: Start nginx
- name: Nginx Configuration
file:
src: nginx.conf
dest: /etc/nginx/nginx.conf
- name: Nginx Config for {{ common_name }}
template:
src: nginx_conf.j2
dest: "/etc/nginx/sites-enabled/{{ common_name }}.conf"
notify: Reload nginx
You'll notice in the above there are a few instances of a notify
directive, meaning that when that step runs, another command should be triggered, and this is done by notifying a handler, so for the notifications in our tasks, we'll have the following in handlers/main.yml
:
---
- name: Reload nginx
service:
name: "nginx"
state: reloaded
- name: Start nginx
service:
name: "nginx"
state: started
- name: Kill pid
shell: 'kill -HUP $(cat /var/run/nginx.pid)'
- name: Update ca-certificates
shell: update-ca-certificates
So, for example, after we install the CA cert, we would use notify: Update ca-certificates
to run that update-ca-certificates
command, or notify: Start nginx
or Reload nginx
to use the service command in Ansible to attempt to have that service state becoming started or reloaded.
Top comments (0)