Introduction

In my experience, the hard part of an IT professional’s job when it comes to standing up a server isn’t the physical task of getting a server certificate. It’s getting bulk certificates where they need to go when you’re standing up more servers than you would have known what to do with 10 years ago. And it’s refreshing an existing certificate without downtime. Or maybe waiting for that one person to get into the office because they’re the only ones who can receive domain approval emails or update your DNS. You know how it is when that responsibility was given to a different department even though you’re the one on call when that water pipe bursts a floor above your server room.

That’s where automation tools such as Ansible shine, and where there’s a lot of value – and a lot less headache – in having a robust API that can help you request new certificates or update existing certificates. In this blog article, I’m going to be focusing on the new integrations we added between Ansible and our Entrust Certificate Services (ECS) API. Even if you aren’t currently using or don’t plan on using Ansible, our ECS API was written to an Open API 2.0 specification, which means there are a number of third-party and open-source tools that can consume that specification to generate client code stubs, making it easier to integrate with whatever tools or codebases you are using.

Brief Introduction to Ansible and ECS

I’m not going to go over all the functionality of our ECS API in depth, or walk you through an entire Ansible architecture. But here are some of the basics of what you need to know in order for the rest of this blog article to make sense:

  • The ECS API has authentication requirements of client certificate authentication  and a username/password combination.
  • With the ECS API, you can request approval of domains and organizations separate from the actual submission of a Certificate Signing Request (CSR). There are also things like different clients that can be defined, which have different organizations, all sorts of custom tracking information … but that’s outside the scope of this blog. The important bit is that you don’t need to validate your domain or organization when you request a certificate. That makes a big difference when you want to automate.
  • With Ansible, you write playbooks that consist of (among other things) tasks that perform actions on targeted servers, defined by an inventory file.
  • Keep in mind that I’m just writing individual Ansible tasks to demonstrate workflow; this is not a full plug-and-play tutorial.
  • Ansible best practices would involve using “Ansible Vault” or another means to protect and/or encrypt your sensitive data like credential information. But to keep things simple, I’m not doing that for this walkthrough.

Getting a Certificate

1. Generate a key pair using the openssl_privatekey module.

  • This has nothing to do with the Entrust integration. Maybe you’re using Ansible’s “command” module to generate a key in an Entrust HSM, for instance. But generating a key pair somehow is the first step, so consider this a placeholder for whatever your secure process is (which Ansible can likely support).
- name: Generate a 2048 bit RSA private key
openssl_privatekey:
path: '/tmp/entrust_test/testcert.key'
passphrase: 'pleaseUseYourOwnPasswordDoNotCopyAndPasteFromDemo'
cipher: auto
type: RSA
size: 2048

2. Generate a Certificate Signing Request (CSR) using the openssl_csr module.

  • Again, you can create the CSR however you want.
  • The domain in the Subject Distinguished Name (DN=) and all domains in the Subject Alternate Name (SAN) list must be validated domains tied to your ECS account.
  • If specified, the organization (O=) must be a validated organization for your account.
  • The various locality fields in the certificate must be valid for any specified organization.
- name: Generate a certificate signing request using the generated key
openssl_csr:
path: '/tmp/entrust_test/certificate_request.csr'
privatekey_path: '/tmp/entrust_test/testcert.key'
privatekey_passphrase: 'pleaseUseYourOwnPasswordDoNotCopyAndPasteFromDemo'
common_name: entrustdatacard.com'
organization_name: 'Validated Organization, Inc.'
organizational_unit_name: 'Blog Department'
country_name: 'US'
state_or_province_name: 'MA'
digest: sha256

3. Submit the CSR using the openssl_certificate module to get a self-signed certificate.

  • We added ECS support as a new provider to the openssl_certificate module.
  • In this example that demonstrates the scenario if you were already integrated with openssl_certificate, you can switch the provider over, add Entrust Datacard-specific parameters and leverage your existing playbooks.
  • If you aren’t already using openssl_certificate, you can jump straight to the next step. Or perhaps you have some environments where it’s useful to be able to deploy self-signed certificates, then switch over to real certificates using the same playbook. You can use variables to switch gears without changing your workflow, because it’s the same module.
- name: Generate a self signed certificate using openssl_certificate
openssl_certificate:
path: '/tmp/entrust_test/self_signed_certificate.cer'
privatekey_path: '/tmp/entrust_test/testcert.key'
privatekey_passphrase: 'pleaseUseYourOwnPasswordDoNotCopyAndPasteFromDemo'
csr_path: '/tmp/entrust_test/certificate_request.csr'
provider: selfsigned

4. Add the Entrust parameters, and the same module will request an Entrust certificate.

  • If there’s already a valid certificate in the specified path (“/tmp/entrust_test/certificate”), it will not request a new one unless “force: true” is added as a task parameter.
  • If this task submits the CSR and gets a certificate, the return value will have a “changed” of True, and the certificate will be in the specified path (“/tmp/entrust_test/certificate.cer”).
- name: Have ECS generate a signed certificate for us using a local file path for the specification
openssl_certificate:
path: '/tmp/entrust_test/entrust_certificate.cer'
csr_path: '/tmp/entrust_test/certificate_request.csr'
provider: entrust
entrust_requester_name: 'Chris Trufan'
entrust_requester_email: '[email protected]'
entrust_requester_phone: '555-867-5309'
entrust_cert_type: 'UC_SSL'
entrust_api_user: 'abc284329a-559391'
entrust_api_key: 'FJ33SV#13116DSL90'
entrust_api_client_cert_path: '/tmp/entrust_test/api_files/client_cert.pem'
entrust_api_client_cert_key_path: '/tmp/entrust_test/api_files/client_key.pem'
entrust_api_specification_path: '/tmp/entrust_test/api_files/cms-api-2.1.0.yaml'

5. Create a PKCS12 file containing your certificate and key.

  • Again not an Entrust-specific thing, but now you’ve got a certificate in the previously specified “path,” so you can put it wherever you need it.
- name: Create a PKCS#12 containing the certificate and private key
openssl_pkcs12:
action: export
certificate_path: '/tmp/entrust_test/entrust_certificate.cer'
privatekey_path: '/tmp/entrust_test/testcert.key'
privatekey_passphrase: 'pleaseUseYourOwnPasswordDoNotCopyAndPasteFromDemo'
friendly_name: entrustcert
path: '/tmp/entrust_test/entrust_certificate.p12'
passphrase: 'pkcs12Passphrase'

Now that you have your certificate and key, you can import it into a server keystore, hardware security module, or wherever else you need it. By incorporating a call to the ECS API into the workflow of your Ansible playbook, you can automate the process of providing your deployed servers with new or refreshed certificates. Similarly, you can see how you might leverage the ECS API in other automation tools and threads, any time you need a certificate.

Where Can I Get the Module?

The addition of the Entrust provider to the openssl_certificate module is planned for Ansible Release 2.9, which currently has a target release date of 2019-10-16. In the interim, your ECS Sales representative can provide you with the module.

What’s Next?

In the meantime, watch our latest webinar, where I do a demonstration for the Ansible Module and answer common questions during a live Q&A. Watch recording >