AS3 w/ certificates and renewals..
So, I found myself in a little bit of a quandary with the use AS3 declarations to deploy our F5 configurations for our services.
So to create a virtual server with SSL certificate and profiles, and the nine-yards, you need to have as part of your AS3 declaration: SSL certificate (key and cert), that populate the profile, that then populates the profile section within the virtual server.
So far so good...
Now, the certificate has a TTL (if you will), and needs to be renewed.
In the past, I had a Python script that goes through the F5 using REST API to find expiring certificates and get new certs and updates the configuration. That worked just fine, and I have adapted that to be used on our new F5s using partitions/tenants, and it works.
Unfortunately is also breaks the one source of truth (AS3), so if I go make a change to an AS3 declaration to make pool member or other configuration changes, and I then redeploy the AS3 declaration, then the OLD certificate if put back into play (which could be expired) and the service goes down. Has not happened yet, because this FUBAR situation popped into my head.
..and that is my quandary...
How do I redeploy configurations and have it ignore the certificate and profile stanzas in AS3 declaration - so it does not redeploy an old and possibly expired certificate?
One may think .. well update the declaration with the updated certificate. Not as easy as one may think. I would have to do this for any declaration that I want to modify, not a easy task.. log-into the F5, fetch the new PEMdata for the certificate and key, update the declaration, and then deploy it. In some AS3 declarations, I am defining multiple environments for a service, and there might be up to 5 different certificate/key pairs that I would need to update prior to redeploying .. ugh!
I am in a pickle. Thoughts?
The only solution that I have been able to conjure up in my head is additional automation and scripting that would automatically update the AS3 declarations when a certificate is renewed, which makes sense .. just have no idea how to go about this just yet.
Hoping there are other alternatives?!
I appreciate the response. We have already made an extensive investment in AS3, so we are not backing out of that. For the new setup, we are forgoing the Python script that we used in the past to renew certificates - due to it breaking the source of truth of AS3.
So I have some ideas, and we do have the Ansible Automation Platform (AAP), so I think we will be writing a playbook that will basically do the following:- Use a home-made python based AAP plugin that will scan all the files in our GitHub repository. It will return a list of files that have expired certificates within, based on a threshold date.
- Read in each file into a JSON variable, this would be the entire declaration. I am doing this, so it will be easy to literally pull out the certificate(s) into a separate variable using JSON/YAML references.
- Pull out the Common Name and any SANs from the existing certificate.
- Generate a new CSR / private key based on info above.
- Using ACME, generate a new certificate.
- Insert the certificate and new key into the JSON/YAML structure (again using the references, using an assignment).
- Write out the JSON/YAML structure to a file, and upload up to Github, replace what exists (new version, and all).
- Do a push and pull request (all automated).
- Then run the two plays I have that fetch the declaration from GitHub and deploy it (thus renewing the certificate) -- all using the source of truth.
I am sure you saw that I am uploading the certificate and key to the GitHub repository. Right now -- yes -- probably a bad practice, but one we are following until we get everything migrated. The GitHub repository is private to myself and the service owners (white list access only), which is a stopgap. During and after migration -- I will be working on pulling the private keys out, and putting references there instead, that I would read and fetch the appropriate private key from a safer storage location, and then insert it into a read in declaration -- then deploy it, all from memory, and the private key is purged from memory once the playbook ends.