Create a Simple CA Server using Ansible

Learn how to establish a basic Certificate Authority (CA) server with Ansible, facilitating certificate and Java Keystore/Truststore management.

Projects: c2platform/rws/ansible-gis, c2platform.core, c2platform.wincore,


Overview

This document details the RWS approach to manage certificates and Java Keystores/Truststores via Ansible, utilizing the c2platform.core.cacerts2 role. This setup, involving Vagrant and Ansible, accomplishes the following:

  1. Vagrant sets up three VMs using VirtualBox, preparing each for its role: a file share, a CA server, and a Tomcat server.
  2. Ansible automates the configuration across these VMs, establishing a file share, initializing the CA server, and deploying a Tomcat server configured with CA-issued certificates.
NodeOSProviderPurpose
gsd-ansible-file-share1Windows 2022 ServerVirtualBoxFile share for certificates
gsd-ca-serverRed Hat 9VirtualBoxSimple Ansible based CA Server
gsd-ca-server-clientWindows 2022 ServerVirtualBoxTomcat server with HTTPS / Java Keystores

Prerequisites

  • Ensure your RWS Development Environment is set up on Ubuntu 22, as detailed here.
  • Ensure the proxy node gsd-rproxy1 is active for Windows node internet access:
    vagrant up gsd-rproxy1
    

Setup

To prepare the complete environment, execute vagrant up for the specified VMs. On a high-performance development workstation, this setup should take approximately 25 minutes.

vagrant up gsd-ansible-file-share1 gsd-ca-server gsd-ca-server-client

Verification

  1. SSH into the CA server and inspect the certificates directory:

    vagrant ssh gsd-ca-server
    
    tree /mnt/ansible-certificates/
    

    Expect to see the CA’s root certificate (c2.crt), key (c2.key), and the Tomcat server’s certificate and Java KeyStore.

    Show me

    [vagrant@gsd-ca-server ~]$ tree /mnt/ansible-certificates/
    /mnt/ansible-certificates/
    └── c2
        ├── c2.crt
        ├── c2.csr
        ├── c2.key
        ├── downloads
        │   └── c2-ca.crt
        └── tomcat
            ├── gsd-ca-server-client-gsd-ca-server-client.crt
            ├── gsd-ca-server-client-gsd-ca-server-client.csr
            ├── gsd-ca-server-client-gsd-ca-server-client.key
            ├── gsd-ca-server-client-gsd-ca-server-client.keystore
            ├── gsd-ca-server-client-gsd-ca-server-client.p12
            ├── gsd-ca-server-client-gsd-ca-server-client.pem
            └── gsd-ca-server-client-gsd-ca-server-client.truststore
    
    3 directories, 11 files
    [vagrant@gsd-ca-server ~]$
    

  2. Access gsd-ca-server-client via Remmina or VirtualBox Manager as the vagrant user (password: vagrant).

    On the destop there is a shortcut to https://gsd-ca-server-client:8443/helloworld/ 

    This will show a warning about potential security risk because the certificate is not trusted by FireFox. At this point, you can import the root certificate \\gsd-ansible-file-share1\ansible-certs\c2\c2.crt to establish a trust relationship and this warning will not be shown.

  3. Confirm the server.xml in D:\Apps\tomcat\conf reflects the correct SSL/TLS configuration, indicating the successful installation of the Java Keystore by Ansible.

    <Connector port="8443" URIEncoding="ISO-8859-1" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https"
        secure="True" clientAuth="False" sslProtocol="TLSv1.2" SSLCipherSuite="ECDHE-RSA-AES128-GCM-SHA256"
        keystoreFile="conf/gsd-ca-server-client-gsd-ca-server-client.keystore"
        keystorePass="secret"
        keyAlias="gsd-ca-server-client"
        SSLHonorCipherOrder="true"
        server="server"  />
    

    The Java Keystore gsd-ca-server-client-gsd-ca-server-client.keystore was created on the CA Server by Ansible and then installed by Ansible using the c2platform.cacerts2 role.

Certificate Management on CIFS Share

To reproduce this issue:

  1. Navigate to group_vars/cacerts_server_client/certs.yml, modify a certificate property (e.g., subject_alt_name).
  2. Provision gsd-ca-server-client again:
    vagrant provision gsd-ca-server-client
    

This will fail with the message below, because of Ansible’s incompatibility with file attribute management on CIFS shares.

Error while setting attributes: Usage: /bin/chattr [-pRVf] [-+=aAcCdDeijPsStTuFx]

Show me

TASK [c2platform.core.cacerts2 : Generate an OpenSSL certificate] **************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Exception: Error while setting attributes: Usage: /bin/chattr [-pRVf] [-+=aAcCdDeijPsStTuFx] [-v version] files...
fatal: [rws-ipvw-fme201 -> rws-iavl-gjb201(rws-iavl-gjb201.workload.rws.local)]: FAILED! => {"changed": false, "details": "Error while setting attributes: Usage: /bin/chattr [-pRVf] [-+=aAcCdDeijPsStTuFx] [-v version] files...\\n", "gid": 0, "group": "root", "mode": "0755", "msg": "chattr failed", "owner": "root", "path": "/mnt/tbgeo/Certificates/gs/tomcat/rws-ipvw-fme201-rws-ipvw-fme201.crt.1781900.2024-03-19@13:50:05~", "secontext": "system_u:object_r:cifs_t:s0", "size": 2037, "state": "file", "uid": 0}

This is caused by the lack of MS Windows support in Ansible core utility modules. Specifically these modules do not support managing files on CIFS shares. In this case, because we are updating certificates, Ansible tries to use the method backup_local in lib/ansible/module_utils/basic.py  to make a copy of the certificate before it is overwritten. This fails, it is not supported.

To fix this and update the certificate and keystore:

  1. Access gsd-ca-server-client via Remmina or VirtualBox Manager as the vagrant user (password: vagrant).
  2. Op Windows Explorer and go to \\gsd-ansible-file-share1\ansible-certs\c2\tomcat
  3. Delete all the files in that folder except the private key.
  4. Provision gsd-ca-server-client again:
    vagrant provision gsd-ca-server-client
    

Note that the new certificate and Java Keystore is created, deployed and then Tomcat is restarted to effectuate the change.

Integrating External Certificates

The c2platform.core.cacerts2 role supports replacing certificates with official certificates issued by a dedicated unit such as is the case for RWS, as detailed in Implementing PKI for RWS GIS with Ansible This we can simulate with the following steps:

  1. Access gsd-ca-server-client via Remmina or VirtualBox Manager as the vagrant user (password: vagrant).
  2. Op Windows Explorer and go to \\gsd-ansible-file-share1\ansible-certs\c2\tomcat.
  3. Copy gsd-ca-server-client-gsd-ca-server-client.crt and gsd-ca-server-client-gsd-ca-server-client.csr to the desktop. This CSR and certificate simuliate respectively the CSR we send to unit and the certificate we received in response. Rename the certificate gsd-ca-server-client-gsd-ca-server-client.rws-csp.crt. This now is for the purpose of the test the official RWS certificate.
  4. Remove the files with extension crt, keystore, p12, pem, truststore.
  5. Provision gsd-ca-server-client again:
    vagrant provision gsd-ca-server-client
    
    We now have new crt file that is different from gsd-ca-server-client-gsd-ca-server-client.rws-csp.crt.

So we have now reached the step where we are going to use Ansible role c2platform.core.cacerts2 to replace our temporary certificates with RWS certificates.

  1. Go to the folder \\gsd-ansible-file-share1\ansible-certs\c2\tomcat
  2. Remove the files with extension keystore, p12, pem.
  3. Copy the certificate gsd-ca-server-client-gsd-ca-server-client.rws-csp.crt from the desktop to the folder \\gsd-ansible-file-share1\ansible-certs\c2\tomcat
  4. Provision gsd-ca-server-client again:
    vagrant provision gsd-ca-server-client
    
  5. Using the shortcut on the desktop for KeyStore Explorer verify using thumbprint that the certificate in the KeyStore is gsd-ca-server-client-gsd-ca-server-client.rws-csp.crt.

Review

To understand the VM setup and configuration, review the Ansible Inventory and Vagrant project files, and the Ansible collections.

Ansible Inventory

Review the following files in the Ansible inventory / Vagrant project c2platform/rws/ansible-gis:

File(s)Description
plays/mgmt/cacerts_server_rhel.ymlThe primary Ansible playbook to provision the three VM’s
group_vars/ansible_file_share/*Configuration for the file share node gsd-ansible-file-share1
group_vars/cacerts_server_client/*Configuration for the Tomcat server gsd-ca-server-client

See Ansible Inventory Project for more information on Ansible inventory projects.

Ansible Collections / Roles

CollectionDescription
c2platform.wincoreIncludes essential roles for Windows hosts, such as win
c2platform.coreProvides role for Linux targets linux and cacerts2.
c2platform.gisCollection with roles for GIS Platform e.g. tomcat and java.

See Ansible Collection Project for more information on Ansible collection projects.

Additional Information

For additional insights and guidance: