Sectigo SaltStack integration

Overview

The Sectigo SaltStack integration provides a seamless solution for the enrollment, collection, renewal, replacement, and revocation of SSL/TLS and client (S/MIME) certificates issued by the Sectigo Certificate Manager (SCM). This integration is distributed as a SaltStack module. It provides the following features:

  • RSA 2048, 3072, and 4096-bit private key generation

  • Certificate signing request (CSR)

  • Enrollment, collection, renewal, replacement, and revocation of certificates issued by SCM

The Sectigo SaltStack integration supports both the generation of new SSL/client certificates and the detection of existing certificates stored in a location accessible to the module at runtime. The integration also checks the validity of existing certificates and allows the issuance of replacement certificates as required. There are various types of SSL and client certificates that can be requested by supplying the appropriate configuration options.

The types of SSL/TLS and client certificates available to you are based on your account setup.
SaltStack Sectigo integration

Prerequisites

The SaltStack integration has the following prerequisites:

  • SaltStack master and minions version 2018.3

  • Python version 2.7x

  • Sectigo Certificate Manager organization with Web API access enabled

  • A list of SSL and client certificate types with associated terms for the organization

  • Other Python libraries:

    • pip

    • requests

    • pyopenssl

    • pycrypto

    • pyyaml

The SaltStack module is supported for Linux master and Linux/Windows minions and has been tested on the following operating systems:

  • Linux CentOS 7.3 (master/minions)

  • Ubuntu 16.04 and 18.04

  • Windows 10

For further information, see Salt in 10 Minutes.

SaltStack master is not supported on Windows.

SaltStack integration package

The Sectigo SaltStack integration package contains the following:

  • pillar:

    • sectigo_ssl_certificate.sls: The configuration data for the SSL certificate

    • sectigo_client_certificate.sls: The configuration data for the client certificate

    • top.sls: A mandatory file which reads the configuration file(s)

    • env_vars.sls: This file is ONLY used if you are running Execution modules (as outlined in Generating certificates on minion nodes by using execution modules). This file contains Sectigo account credentials that you must configure for execution modules.

  • salt:

    • _runners:

      • sectigo_pycert.py: The utility library for the module

      • sectigo_saltstack_module.py: The Sectigo SaltStack module

    • _states:

      • apache_centos_ssl.sls: A sample State file for CentOS configurations for SSL

      • apache_debian_ssl.sls: A sample State file for Debian configurations for SSL

      • apache_windows_ssl.sls: A sample State file for Windows configurations for SSL

      • sectigo_configuration.sls: A sample Sectigo configuration that is included in all other state files. This file contains a specification that allows you to copy SSL certificates from a master node to minion nodes. You may modify it as per your needs.

    • files:

      • apache.conf: A sample Apache configuration file

      • httpd.conf: A sample httpd configuration file

      • index.html: A sample homepage

      • run.sh: A shell script that can be used in a cronjob to automate the execution of the module

      • windows_apache.conf: A sample Apache configuration file for Windows

Sectigo SaltStack integration components

Understanding the integration

The Sectigo SaltStack module hides the complexity of the SCM REST API by acting as an adapter between SaltStack and the Sectigo API. It enables you to request, renew, and revoke certificates on your master and minion nodes.

Components

The Sectigo SaltStack integration is based on the following components:

  • The Python client library for the Sectigo API which handles the communication with the Sectigo REST API. This library is delivered as a component of the SaltStack module. It is not designed or delivered as a general-purpose library for Sectigo customers. The intended use for the SaltStack module is to be the only software component that is interacting with this library.

  • The SaltStack module which mediates the interaction between you, the SaltStack master and minion nodes, and the Sectigo REST API. The module mainly consists of a standard Salt execution routine with minimum dependencies. It supports the enrollment, collection, replacement, renewal, and revocation of SSL and client certificates.

How the Sectigo SaltStack integration works

The Sectigo SaltStack integration is designed to allow you to generate certificates on a master node and, in the case of SSL certificates, distribute them onto minion nodes as needed. This functionality is achieved by using Salt runners that are typically placed in the salt/_runners/ directory. Additionally, the Sectigo SaltStack integration allows you to generate certificates directly on minion nodes. This can be achieved by using Salt execution modules that are typically placed in the salt/_modules/ directory.

Understanding the configurations

This section describes the configuration parameters.

Customer specific parameters

The following parameters are required to establish connection with SCM.

Parameter Type Description

SECTIGO_CM_USER

Mandatory

Your Sectigo username

SECTIGO_CM_PASSWORD

Mandatory

Your Sectigo password

SECTIGO_CM_URI

Mandatory

Your specific Sectigo URI

sectigo_cm_org_id

Mandatory

Your organization ID (numeric)

sectigo_cm_base_url

Mandatory

The base URL of the Sectigo Certificate Authority

CSR parameters

The following parameters are required during the generation of the certificate signing request (CSR).

Parameter Type Description

sectigo_csr_domain

Conditional

A single value for a domain which is included in the certificate Common Name (CN) field.

sectigo_csr_country

Conditional

The country name which is included in the certificate Country (C) field.

sectigo_csr_state

Conditional

The state/province name which is included in the certificate State (ST) field.

sectigo_csr_location

Conditional

The location name which is included in the certificate Location (L) field.

sectigo_csr_organization

Conditional

The organization name which is included in the certificate Organization (O) field.

sectigo_csr_organization_unit

Conditional

The organization unit which is included in the certificate Organization Unit (OU) field.

sectigo_csr_email_address

Conditional

The email address which is included in the certificate emailAddress field.

sectigo_csr

Conditional

The full path of the certificate signing request file. If this is provided, then the subject parameters will be ignored.

sectigo_csr_key_algo

Optional

The private key algorithm to use to generate the private key. The default value is RSA.

sectigo_csr_key_size

Optional

The size of the TLS/SSL key to generate (numeric). The possible values are:

  • 2048: for 2048-bit (default)

  • 3072: for 3072-bit

  • 4096: for 4096-bit

Certificate issuance parameters

The following parameters are used for certificate issuance. This operation supports different scenarios that require different parameters.

Parameter Type Description

SSL certificates

sectigo_ssl_cert_file_path

Mandatory

The location where the certificate, CSR, private key, and enrollment IDs are stored.

sectigo_ssl_cert_file_name

Mandatory

The name of the certificate file. The same name is used for the private key, CSR, and enrollment IDs.

sectigo_ssl_cert_type

Mandatory

The type of the SSL certificate (numeric). This is the ID of the SSL certificate type.

sectigo_ssl_cert_validity

Mandatory

The certificate validity period in days (numeric). The available values are dependent on sectigo_ssl_cert_type.

sectigo_ssl_cert_format_type

Optional

The format type for the SSL certificate. The allowed values are:

  • x509: X509, Base64 encoded (default)

  • x509CO: X509 Certificate only, Base64 encoded

  • x509IO: X509 Intermediates/Root only, Base64 encoded

  • base64: PKCS#7, Base64 encoded

  • bin: PKCS#7, Bin encoded

  • x509IOR: X509 Intermediates/Root only reverse, Base64 encoded

sectigo_ssl_cert_comments

Optional

Comments for certificate enrollment

sectigo_ssl_cert_num_servers

Conditional

The number of server licenses (numeric)

sectigo_ssl_cert_custom_fields

Optional

The custom fields to be applied to the requested certificate. The expected format for custom fields is the following: [{"name":"custom_field_1","value":"value_1"},{"name":"custom_field_2","value":"value_2"}]. If you are providing this input in a JSON string, make sure that the internal double quotes are escaped properly using \.

sectigo_ssl_cert_server_type

Optional

The server type ID (numeric)

sectigo_ssl_cert_subject_alt_names

Optional

A comma-separated list of subject alternative names (SAN)

sectigo_ssl_cert_external_requester

Optional

A comma-separated list of emails

Client certificates

sectigo_client_cert_file_path

Mandatory

The location where the certificate, CSR, private key, and enrollment IDs are stored.

sectigo_client_cert_file_name

Mandatory

The name of the certificate file The same name is used for the private key, the CSR, and enrollment IDs.

sectigo_client_cert_first_name

Conditional

The user’s first name

sectigo_client_cert_middle_name

Conditional

The user’s middle name

sectigo_client_cert_last_name

Conditional

The user’s last name. The combined length of the first, middle, and last name fields cannot exceed 64 characters.

sectigo_client_cert_email

Mandatory

A valid user email that is less than 256 characters

sectigo_client_cert_type

Mandatory

The type of the certificate (numeric). This is the ID of the client certificate type.

sectigo_client_cert_validity

Mandatory

The certificate validity period in days (numeric). The available values depend on sectigo_client_cert_type.

sectigo_client_cert_subject_alt_names

Optional

A comma-separated list of subject alternative names (SAN)

sectigo_client_cert_custom_fields

Optional

The custom fields to be applied to the requested certificate. The expected format for custom fields is the following: [{"name":"custom_field_1","value":"value_1"},{"name":"custom_field_2","value":"value_2"}]. If you are providing this input in a JSON string, make sure that the internal double quotes are escaped properly using \.

sectigo_client_cert_revoke_on_replace

Mandatory

If True, previous certificates will be revoked when replaced. The default value is False.

Certificate autorenewal

sectigo_auto_renew

Optional

If True, the auto-renewal option is enabled. The default value is True.

sectigo_expiry_window

Optional

The period of days (numeric) prior to expiration that a new client certificate enrollment process will be initiated if a salt-run operation is started. The default expiry window is 7 days.

Certificate collection parameters

The collection operation may fail if the certificate is still being processed. In such cases, the Sectigo SaltStack integration will try several times before returning a failure. The following parameters are used to configure the frequency and maximum time for additional attempts at certificate collection.

Parameter Type Description

sectigo_loop_period

Optional

The interval (in seconds) between repeated attempts to collect a certificate (numeric). The default value is 30.

sectigo_max_timeout

Optional

The maximum time (in seconds) during which repeated attempts to collect a certificate will be made (numeric). The default value is 600.

Certificate revocation parameters

Certificates can be manually revoked. In order to revoke a certificate, the following parameters are needed:

Parameter Type Description

SSL certificates

sectigo_ssl_cert_revoke

Mandatory

If True, the existing certificate will be revoked. The default value is False.

Client certificates

sectigo_client_cert_revoke

Mandatory

If True, the existing certificate will be revoked. The default value is False.

It is suggested that you set sectigo_ssl_cert_revoke back to False following the revocation of a certificate. This will help prevent costs associated with unintended certificate revocations.

Other parameters

The following parameters are used to modify the behavior of the issuance operation.

Parameter Type Description

sectigo_force

Optional

Used to issue a new certificate even if there is already a certificate on the target server. The default value is False.

If True, the existing certificate will be backed up and any related information (Key, CSR, ID) will be deleted. This option is required if the certificate information (such as domain) has changed and a new certificate is required.

sectigo_minion_target_name

Mandatory

Set the target value. For example, if you want to deploy the certificate to a group of minions with similar hostname prefix (dev1, dev2 | prod1, prod2), you can use wildcards like dev* or prod*. If you wish to deploy to a single minion, use the exact hostname.

sectigo_reason

Mandatory

The reason why a certificate is to be revoked or replaced

SaltStack CLI parameters

The following parameters are used in the CLI commands directly.

Parameter Description

sectigo_saltstack_module.main

The filename.function_name that gets executed. Lowercase characters only.

cert_type

Can be either ssl or client

cert_config_file

The config file from the pillar folder that gets applied

target

The host name of the minions (such as minion1, minion2, dev1, dev2, prod1, prod2, myhostname1, and myhostname2)

Note that you can also use wildcard if there is more than one minion with a similar prefix which needs to have the exact configuration. For example, if there are 3 minions with the names: dev1, dev2, and dev3 and all these 3 machines need to have the same certificate, then you pass dev* as the 'target' in the command.

The target is case sensitive and must match the minion hostname exactly.

Using the Sectigo SaltStack module

This section describes how to use the Sectigo SaltStack module.

Configuring the SaltStack work directory structure

The salt and pillar directories that are included in this integration’s package include all the files that are required by the Sectigo SaltStack module. These directories are generally placed inside the /srv/ directory on Linux systems. In order to use the Sectigo SaltStack module, the contents of the salt and pillar directories must be placed in the /srv/salt/ and /srv/pillar/ directories (or equivalent) on your master node, respectively.

Configuring the SaltStack master

Once you have a salt-master installed on your Linux system, you must configure the paths for the salt and pillar directories in the master configuration file. This configuration file is generally located by default at /etc/salt/master. You must set the following fields in the salt-master configuration file if they are not already set (you may uncomment the fields if they already exist but are commented).

file_roots:
  base:
    -/srv/salt (where "/srv/salt" is the path to the salt folder provided by Sectigo)

pillar_roots:
  base:
    -/srv/pillar (where "/srv/pillar" is the path to the pillar folder provided by Sectigo)

runner_dirs:
  -/srv/salt/_runners (where "/srv/_runners" is the path to the _runners folder provided by Sectigo)

Setting up environmental variables

There are three environmental variables that must be specified as part of this package. The variables for Linux are the following.

export SECTIGO_CM_USER='<your Sectigo username>'
export SECTIGO_CM_PASSWORD='<your Sectigo password>'
export SECTIGO_CM_URI='<your Sectigo URI>'
The Linux command to set these environment variables after adding them in ~/.bashrc is $ source ~/.bashrc.

Interacting with the module

This section describes how to interact with the SaltStack module.

This integration was designed and tested to work with a root user as the SaltStack default setup runs the master and minion as the root user. In order to use the integration with as a non-root user, you must configure the ownership and permissions of your work directories accordingly. For more information, see the SaltStack documentation.

Files synchronization between master and target minion nodes

You must ensure that the master and (target) minion nodes are synchronized by running the following command.

salt 'target' saltutil.sync_all

This command syncs all the files on the target minions. If there is more than one minion with a similar prefix you can also make use of wildcard. For example, if there are 3 target minions with the names dev1, dev2, and dev3, and all 3 machines need to have the same certificate, then you pass the following command.

salt 'dev*' saltutil.sync_all

To sync runners specifically, run the following command.

salt-run saltutil.sync_runners

Certificates issuance / collection

There are two techniques that can be used to generate certificates using the Sectigo SaltStack module:

  • Generating certificates on a master node using runners

  • Generating certificates on minion nodes using execution modules

If you have already issued a certificate, and would like to generate another one, either set the sectigo_force parameter to True, or select a new file name.

Generating certificates on a master node by using runners

In order to run the entire configuration and deploy the certificates and their necessary packages on the minions, run the following command on a master node.

salt-run sectigo_saltstack_module.main <cert_type> <cert_config_file>
If you added any new pillar config files, see File name requirements.

This command will call the Python modules and make respective API calls to SCM based on the current state.

Example SSL
salt-run sectigo_saltstack_module.main ssl sectigo_ssl_certificate
Example client
salt-run sectigo_saltstack_module.main client sectigo_client_certificate
You can only run the command above on a master node. All the certificate-related files that get generated are stored on the master from where they get transferred to the minions using a push or a pull mechanism.
  • Push Model (Run on Master): In the push mechanism, the master pushes the configuration and the certificate-related files to the minions. Since you are running the command on a master node, you must specify the target.

    salt 'target' state.apply "pillar={'cert_type': '<cert_type>', 'cert_config_file': '<pillar_file_name>'}"

    This command will set the necessary state of the minions according to the OS and the state file that is defined for that OS.

  • Pull Model (Run on Minions): In the pull mechanism, the minions can pull the state from the master and adjust their own configurations accordingly. Since you are directly running the command on a minion node, you do not have to specify the target.

    salt-call state.apply "pillar={'cert_type': '<cert_type>', 'cert_config_file': '<pillar_file_name>'}"
All _state sample files provided in this package are for SSL certificates. If you need to use the push or pull mechanisms for client certificates you will need to create your own _client.sls files and modify the sectigo_configuration file for client certificates. More information on creating state files can be found here.

Generating certificates on minion nodes by using execution modules

It is possible to execute the Python files directly on minions instead of running them on the master node. For this, you need to use execution modules instead of runners and copy the contents from the salt/_runners/ folder into the salt/_modules/ folder. You must make sure all the Python related prerequisites are configured on the minions. Additionally, if you have made any configuration changes on the master, you must re-synchronize the files by re-running the salt 'target' saltutil.sync_all command.

For execution modules, it is not necessary to set the environment variables on minions. However, you need to update the env_vars.sls file in the salt/pillar folder with your Sectigo account related credentials.

This file is only necessary in the case of execution modules, and not runner modules.

The following command can then be executed.

salt 'target' sectigo_saltstack_module.main <cert_type> <cert_config_file>
Example SSL
salt 'target' sectigo_saltstack_module.main ssl sectigo_ssl_certificate
Example client
salt 'target' sectigo_saltstack_module.main client sectigo_client_certificate
This will execute the script on all the target minions and might cause the operations like Enroll and Renew to be executed separately on each minion.
SaltStack certificate issuance diagram

Certificate auto renewal / validity check

If the existing certificate is expired or is about to expire (within the specified sectigo_expiry_window), the Sectigo SaltStack module will try and enroll a new certificate.

The module makes use of the existing .key and .csr files if they are available.

The existing certificates related files are not deleted and only renamed with a timestamp.

Certificate replacement

In order to replace a certificate, one of the following conditions must be met:

  • A CSR value is provided using sectigo_csr, and a value of any sectigo_csr, domain, or SANs parameters has been modified.

  • A value of any individual CSR, domain, or SANs parameters has been modified.

If either of the two conditions are satisfied, you can replace your certificate by running the following command.

salt-run sectigo_saltstack_module.main <cert_type> <cert_config_file>

The certificate replacement behavior is shown in the following diagram.

Sectigo SaltStack certificate replacement

Certificate revocation

In order to revoke an existing certificate, you must change the value of the revoke parameter (sectigo_ssl_cert_revoke for SSL certs or sectigo_client_cert_revoke for client certs) to True in your pillar configuration file, and run the following command.

salt-run sectigo_saltstack_module.main <cert_type> <cert_config_file>

Output

There are different forms of output that you may get when attempting to issue a certificate using the Sectigo SaltStack module. The output depends on how you interact with the plugin.

Output from generating certificates on a master node using runners

When working directly on the master node, the Sectigo SaltStack module initially stores the issued certificate, key, and CSR files on the master node’s file system. The file path that’s used for this storage is set dynamically, and it follows the following pattern.

salt/files/certs/<minion_name>/<sectigo_ssl_cert_file_path>

The salt/files path already exists on the master node; the certs directory and its content get dynamically generated when you execute the following command.

salt-run sectigo_saltstack_module.main <cert_type> <cert_config_file>

In the case of a single minion, <minion_name> consists of the minion’s hostname (for example, Minion1). In the case of a wildcard, the <minion_name> consists of the common prefix element in the wildcard, along with _allMinions as a suffix. For example, suppose that you have three minions, APP1-Minion1, APP1-Minion2, and APP1-Minion3, if you use APP1* as your target wildcard, the <minion_name> will be APP1_allMinions.

It is also possible to issue different certificates for different wildcards, for more information see Issuing certificates using runners for multiple minion wildcards.

Output from generating certificates on minion nodes using execution modules

When using the execution modules to issue certificates directly on minion nodes, the certificates are stored directly under the path specified in the sectigo_ssl_cert_file_path parameter.

In other words, if you set sectigo_ssl_cert_file_path to be /etc/ssl/, then when you run the following command, the resulting certificate, key, and CSR files will be stored directly inside /etc/ssl/.

salt 'target' sectigo_saltstack_module.main <cert_type> <cert_config_file>

Logs

If you are running the commands manually, the entire trace is shown on the screen and is also stored in the sectigo_saltstack.log file present in the location from where the command is executed.

You can also enable SaltStack logging as per your needs by referring to the SaltStack documentation.

If you are working with the runner module, and you execute commands manually on the master, the log files will be generated in your current work directory. If you use the run.sh file provided with the package, the logs will be generated by default on minions in the /<filename>.log directory. If you are running the execution module using the salt-call command on a minion, since it’s a manual step, the logs will be generated in your current work directory.

Salt master logs and Salt minion logs are typically located at /var/log/salt/master and /var/log/salt/minion, respectively.

How to use existing CSRs

If you want to provide the existing CSR, you can do that by enabling the sectigo_csr parameter in the pillar file and giving the exact full path of the .csr file, also making sure the file exists. If the .csr file is provided, the module will use it instead of creating a new one. The certificate enrollment, renewal, replacement, or collection uses the content from the provided .csr files.

The system assumes that you already have the KEY file and will NOT generate a KEY. You can provide the existing CSR by passing the full file path in the sectigo_csr parameter (for example, /etc/ssl/sectigo_ssl.csr). All the other files will be present in the sectigo_ssl_cert_file_path (for SSL) and sectigo_client_cert_file_path (for client) folders.

For more details on how the files are stored, see the Output section.

Automating the execution

The run.sh script included in the integration’s package can be used as a cronjob. It will be executed at the defined time interval, and run all the commands defined in the Interacting with the module section. For information about setting the cronjobs, see Crontab.guru. The script requires 3 arguments to be passed: <cert_type>, <cert_config_file>, <target>. Make sure to add executable permissions to the run.sh file with the chmod +x /srv/run.sh command. The script considers the default salt root path as /srv/.

The following sample cronjob command will execute the script for SSL every two hours.

0 */2 * * * /srv/run.sh ssl sectigo_ssl_certificate minion*

Additional notes

The following are additional notes for the Sectigo SaltStack integration.

File name requirements

The integration package contains sample pillar config files for SSL and client certificates: sectigo_ssl_certificate.sls and sectigo_client_certificate.sls, respectively. You must configure all your SCM and certificate-related parameters in the applicable .sls file prior to running the preceding command. If a new pillar config file is added, make sure that the new file names and the YAML header inside the new file are the same (see the screenshot). You must also make sure to add the new file names into the /srv/pillar/top.sls file.

SaltStack Sectigo file name requirements

Issuing certificates using runners for multiple minion wildcards

It is possible to execute the salt-run command several times for different target wildcards. For instance, suppose that you are using the same master to generate certificates for two different set of minions (APP1-Minion1, APP1-Minion2, APP1-Minion3) and (APP2-Minion1, APP2- Minion2, APP2-Minion3) with the sectigo_ssl_cert_file_path parameter set to /etc/ssl/.

If you execute the salt-run command for the APP1* and APP2* wildcards, the first execution will issue a certificate and store it at /srv/salt/files/certs/APP1_allMinions/etc/ssl/. The second execution will issue a certificate and store it at /srv/salt/files/certs/APP2_allMinions/etc/ssl/. After that, you can use the PUSH or PULL mechanisms to transfer the generated certificates to your applicable minion nodes. This behavior is illustrated in the following diagram.

SaltStack Sectigo using runners