Skip to content

Instantly share code, notes, and snippets.

@riveraja
Last active January 26, 2024 08:27
Show Gist options
  • Save riveraja/f9e3ed84b54fddb935baf4742a8febe9 to your computer and use it in GitHub Desktop.
Save riveraja/f9e3ed84b54fddb935baf4742a8febe9 to your computer and use it in GitHub Desktop.
Create SSL certificates using Terraform

This post will guide you in creating TLS keys for Vault with Terraform using terraform-google-vault private-tls-cert submodule [https://registry.terraform.io/modules/hashicorp/vault/google/0.0.4/submodules/private-tls-cert].

We will need to download Hashicorp Terraform tool from https://www.terraform.io/downloads.html and then unzip the compressed file:

# wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
--2018-06-18 12:19:33--  https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
Resolving releases.hashicorp.com (releases.hashicorp.com)... 151.101.1.183, 151.101.65.183, 151.101.129.183, ...
Connecting to releases.hashicorp.com (releases.hashicorp.com)|151.101.1.183|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16490308 (16M) [application/zip]
Saving to: 'terraform_0.11.7_linux_amd64.zip'

100%[============================================================================================================================================================>]
 16,490,308  5.29MB/s   in 3.0s

2018-06-18 12:19:36 (5.29 MB/s) - 'terraform_0.11.7_linux_amd64.zip' saved [16490308/16490308]

# unzip terraform_0.11.7_linux_amd64.zip
Archive:  terraform_0.11.7_linux_amd64.zip
  inflating: terraform
# cp terraform /usr/local/sbin
# terraform --version
Terraform v0.11.7

Then create a terraform configuration file in a named folder similar to the one below, notice that in this example I will be creating self-signed certificates and SSL CA for Vault however you may use these steps to create certificates for any other applications that require them:

# cat main.tf
module "vault_private-tls-cert" {
  source  = "hashicorp/vault/google//modules/private-tls-cert"
  version = "0.0.4"

#------------------------------------#
#  Edit variables below accordingly  #
#------------------------------------#

ca_public_key_file_path = "/etc/sslkeys/ca.crt.pem"
public_key_file_path = "/etc/sslkeys/vault.crt.pem"
private_key_file_path = "/etc/sslkeys/vault.key.pem"
owner = "root"
organization_name = "Percona"
ca_common_name = "percona_ca"
common_name = "percona_cn"
dns_names = [ "*", "*.*", ]
ip_addresses = [ "192.168.0.108", ]
validity_period_hours = 8760

}

A quick rundown of the description of the editable variables above can be found here: https://registry.terraform.io/modules/hashicorp/vault/google/0.0.4/submodules/private-tls-cert?tab=inputs

Let's now start by running terraform init to initialize the working directory. For more details on this specific command please refer to this page: https://www.terraform.io/docs/commands/init.html

# terraform init
Initializing modules...
- module.vault_private-tls-cert
  Found version 0.0.4 of hashicorp/vault/google on registry.terraform.io
  Getting source "hashicorp/vault/google//modules/private-tls-cert"

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "tls" (1.1.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.tls: version = "~> 1.1"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Optionally, you would want to run terraform plan command to create an execution plan in the working directory:

# terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + module.vault_private-tls-cert.tls_cert_request.cert
      id:                     
      cert_request_pem:       
      dns_names.#:            "2"
      dns_names.0:            "*"
      dns_names.1:            "*.*"
      ip_addresses.#:         "1"
      ip_addresses.0:         "192.168.0.108"
      key_algorithm:          "RSA"
      private_key_pem:        "8f34ea7a4e6d6c5992dc7b9e202e47cad2b38995"
      subject.#:              "1"
      subject.0.common_name:  "percona_cn"
      subject.0.organization: "Percona"

  + module.vault_private-tls-cert.tls_locally_signed_cert.cert
      id:                     
      allowed_uses.#:         "2"
      allowed_uses.0:         "key_encipherment"
      allowed_uses.1:         "digital_signature"
      ca_cert_pem:            "67c5245fc6ca7f0c9c84221a0286253194dbb985"
      ca_key_algorithm:       "RSA"
      ca_private_key_pem:     "6c435a4a25d847452106d0271104a386d269ae6b"
      cert_pem:               
      cert_request_pem:       "452edd219852555f5ee00cbcde664dc5950bbe93"
      early_renewal_hours:    "0"
      validity_end_time:      
      validity_period_hours:  "8760"
      validity_start_time:    

  + module.vault_private-tls-cert.tls_private_key.ca
      id:                     
      algorithm:              "RSA"
      ecdsa_curve:            "P256"
      private_key_pem:        
      public_key_openssh:     
      public_key_pem:         
      rsa_bits:               "2048"

  + module.vault_private-tls-cert.tls_private_key.cert
      id:                     
      algorithm:              "RSA"
      ecdsa_curve:            "P256"
      private_key_pem:        
      public_key_openssh:     
      public_key_pem:         
      rsa_bits:               "2048"

  + module.vault_private-tls-cert.tls_self_signed_cert.ca
      id:                     
      allowed_uses.#:         "3"
      allowed_uses.0:         "cert_signing"
      allowed_uses.1:         "key_encipherment"
      allowed_uses.2:         "digital_signature"
      cert_pem:               
      early_renewal_hours:    "0"
      is_ca_certificate:      "true"
      key_algorithm:          "RSA"
      private_key_pem:        "6c435a4a25d847452106d0271104a386d269ae6b"
      subject.#:              "1"
      subject.0.common_name:  "percona_ca"
      subject.0.organization: "Percona"
      validity_end_time:      
      validity_period_hours:  "8760"
      validity_start_time:    


Plan: 5 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Then run terraform apply to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a terraform plan execution plan.


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + module.vault_private-tls-cert.tls_cert_request.cert
      id:                     
      cert_request_pem:       
      dns_names.#:            "2"
      dns_names.0:            "*"
      dns_names.1:            "*.*"
      ip_addresses.#:         "1"
      ip_addresses.0:         "192.168.0.108"
      key_algorithm:          "RSA"
      private_key_pem:        "8f34ea7a4e6d6c5992dc7b9e202e47cad2b38995"
      subject.#:              "1"
      subject.0.common_name:  "percona_cn"
      subject.0.organization: "Percona"

  + module.vault_private-tls-cert.tls_locally_signed_cert.cert
      id:                     
      allowed_uses.#:         "2"
      allowed_uses.0:         "key_encipherment"
      allowed_uses.1:         "digital_signature"
      ca_cert_pem:            "67c5245fc6ca7f0c9c84221a0286253194dbb985"
      ca_key_algorithm:       "RSA"
      ca_private_key_pem:     "6c435a4a25d847452106d0271104a386d269ae6b"
      cert_pem:               
      cert_request_pem:       "452edd219852555f5ee00cbcde664dc5950bbe93"
      early_renewal_hours:    "0"
      validity_end_time:      
      validity_period_hours:  "8760"
      validity_start_time:    

  + module.vault_private-tls-cert.tls_private_key.ca
      id:                     
      algorithm:              "RSA"
      ecdsa_curve:            "P256"
      private_key_pem:        
      public_key_openssh:     
      public_key_pem:         
      rsa_bits:               "2048"

  + module.vault_private-tls-cert.tls_private_key.cert
      id:                     
      algorithm:              "RSA"
      ecdsa_curve:            "P256"
      private_key_pem:        
      public_key_openssh:     
      public_key_pem:         
      rsa_bits:               "2048"

  + module.vault_private-tls-cert.tls_self_signed_cert.ca
      id:                     
      allowed_uses.#:         "3"
      allowed_uses.0:         "cert_signing"
      allowed_uses.1:         "key_encipherment"
      allowed_uses.2:         "digital_signature"
      cert_pem:               
      early_renewal_hours:    "0"
      is_ca_certificate:      "true"
      key_algorithm:          "RSA"
      private_key_pem:        "6c435a4a25d847452106d0271104a386d269ae6b"
      subject.#:              "1"
      subject.0.common_name:  "percona_ca"
      subject.0.organization: "Percona"
      validity_end_time:      
      validity_period_hours:  "8760"
      validity_start_time:    


Plan: 5 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.vault_private-tls-cert.tls_private_key.cert: Creating...
  algorithm:          "" => "RSA"
  ecdsa_curve:        "" => "P256"
  private_key_pem:    "" => ""
  public_key_openssh: "" => ""
  public_key_pem:     "" => ""
  rsa_bits:           "" => "2048"
module.vault_private-tls-cert.tls_private_key.ca: Creating...
  algorithm:          "" => "RSA"
  ecdsa_curve:        "" => "P256"
  private_key_pem:    "" => ""
  public_key_openssh: "" => ""
  public_key_pem:     "" => ""
  rsa_bits:           "" => "2048"
module.vault_private-tls-cert.tls_private_key.ca: Creation complete after 0s (ID: 39fd447410d9a6bff105b362f66b0df4ec14776c)
module.vault_private-tls-cert.tls_self_signed_cert.ca: Creating...
  allowed_uses.#:         "" => "3"
  allowed_uses.0:         "" => "cert_signing"
  allowed_uses.1:         "" => "key_encipherment"
  allowed_uses.2:         "" => "digital_signature"
  cert_pem:               "" => ""
  early_renewal_hours:    "" => "0"
  is_ca_certificate:      "" => "true"
  key_algorithm:          "" => "RSA"
  private_key_pem:        "" => "91cb977a9a683390691b25a399c0df98b5d6c0fe"
  subject.#:              "" => "1"
  subject.0.common_name:  "" => "percona_ca"
  subject.0.organization: "" => "Percona"
  validity_end_time:      "" => ""
  validity_period_hours:  "" => "8760"
  validity_start_time:    "" => ""
module.vault_private-tls-cert.tls_self_signed_cert.ca: Provisioning with 'local-exec'...
module.vault_private-tls-cert.tls_self_signed_cert.ca (local-exec): Executing: ["/bin/sh" "-c" "echo '-----BEGIN CERTIFICATE-----\nMIIDGzCCAgOgAwIBAgIRALAbmcHnUNp6GWpiWgHdzYQwDQYJKoZIhvcNAQELBQAw\nJzEQMA4GA1UEChMHUGVyY29uYTETMBEGA1UEAwwKcGVyY29uYV9jYTAeFw0xODA2\nMTgxMjQyMDZaFw0xOTA2MTgxMjQyMDZaMCcxEDAOBgNVBAoTB1BlcmNvbmExEzAR\nBgNVBAMMCnBlcmNvbmFfY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDltgNgdPlt3fkVSxH1GakvHvaS6NhqQ2zbayWddC/TcpFAoN0DfYRkF6LmDQIC\n77XfCJuENSgztU3z//sLb1yhvG/sMrm3V06OsZNCV7wfPJQXpnkps9teT3Y/VKkU\nBvSNuxDNSv2ss8DIusB9uBtUjf790D3ziXJRLMNRjRvqHXdrZPQt8fLYpXGdB+Nb\njZi7LCqw/7DFzb8HB3es2S21AOJx5yndaC34RGZV3iL47YQOKJOP2zluvYogQsHV\n6EaPFGZ+7ebOBJWC1L7H1kIOlJctMb2E50R0XKYSgF2+KKHCP1M9HaovjGPYt5dS\n91G+V3hFD+s1O2Vkpn/UblfJAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwICpDAPBgNV\nHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQTLcRqMYupKLaOxHJtEl3aYBzaLDANBgkq\nhkiG9w0BAQsFAAOCAQEAzNOnV02EP7r1YypZU9lTfo57pfBlanAo5HEji3IsId+J\n/h7+Q581BFeOgEQuK3ol3mIVGxNILVB60mivu/VkFWK+l9RtlV+AgfnIB5Tb9ywr\nMwyVOW4lcMdEYcEdK9qZsyZTjurm+XU/kO5RsM22DqfENhp7gf0VIgfmTdO7K07g\nWVosRmbon6WBSnM60BtsuyQq1D6kKDyw2wanuDgWKIJl/uKr3gz7BDbwiu7b9O1L\np+11HGSTJgWX5AX0xrBlsPR6K8CT0FNG/QkomJ8az2YB0wLeWc5KbtL7NjFMTu3T\n7pI4O6XmtWi5ing49cU7k5W1OmRefKggAkm2DluZdg==\n-----END CERTIFICATE-----\n' > '/etc/sslkeys/ca.crt.pem' && chmod 0600 '/etc/sslkeys/ca.crt.pem' && chown root '/etc/sslkeys/ca.crt.pem'"]
module.vault_private-tls-cert.tls_self_signed_cert.ca: Creation complete after 0s (ID: 234087437844619140998159693615478984068)
module.vault_private-tls-cert.tls_private_key.cert: Provisioning with 'local-exec'...
module.vault_private-tls-cert.tls_private_key.cert (local-exec): Executing: ["/bin/sh" "-c" "echo '-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvc8V2oy3uQ149jVPUkpfKTdyJQr2lu5itZpvVTWOhaiRsB+y\n2SW1+lmAtKZob5bG4lhRKnHGkjykoIKokEZw5jvWQYe6W4i+OFhP4L3nOt+PENSA\n1wSdd7yqFys3pvQJoOX+Rbn+rHS7v+KdzNU0NRpYkY+VdBBrJLKTfllB9ZFbcB7u\nhGF8FoADmDnvHx0i/+qbWZDgFPr/HVWWgWe3w+ixQoymLhX87FigQwcNvsLwuSpU\nLBIQwsayJlaGJRTDafM1ua9I7Ija/rXyLFJFrzOE71GQOi/6DHzHob9/yGEFyD6a\npUkWrm6Sw4i39OmTQVFl89pJapRiZSQe+sHCHQIDAQABAoIBAHpUgyMt2iL8Gd+k\nkBDbOeWYhIp3PGIeFaQxeluSft6JvAulAmGNOnG1SYwkS97PcDLk9LrERVRunTON\nwhHqNE1Od1IYpfTkdqRd1m1kNyjseIpCSx9JLCvFfmIcSmvhkGsQkAZkT0zalz6e\nUVF4f4NSDY8S2SHKiyNFrGWcJTScc1Cf9LAoyrO7bV/9aNnyLjd3qM9tKImGXwxm\niQZ7iORGaE6lxjvaSVUYU/HI/h3xW3vZ55KeU0lb+OGReSVC5gjJ1H2VWvmR38Q0\npz8sxko25SF5+YeZoaczcZgTTqTn8+y7bepIof1itsgoz1EhYJ0pO6U8av3u098O\npxdcQckCgYEA7NnOae3BYgJ767ZLgsLSLcReOKh0bPfoXmr70dgNvmpJGCpFe+a2\nixzukiNPGeR56+ECisntfLOZA9nVUL6+zhagihBB1Tv+u4Saz1s7xlrGsuX+pARD\nB7NCyrs51yzRnF56ZBTGSEH7rgG6ZnApodqJ4k2qyYxuoZ332Jjx7VcCgYEAzSei\nicBmdSJFOqOlFNU/9mX/54o/tlAG+ade74GA9iOTnkCYNMEYvj3oCu9oVlYmGXr9\ntyYnHMVM9znul10TD/uyA0T/3hnln0niC7OYbx3xTa0nwDxCG1PG9Z5COIQmQA/E\nH9Z/s5X8Y9YpL79kCYIp1ESwi/BeG8CyXX+M76sCgYAViwYcWnTRflpZKT6bCS9m\n3EqZqrDUTIRFOkPnZVhyrmYxnX6uc2C9LIeCoVWLjF2Ol+vMReulAQz07bZaXs8q\nHaLCjBIA3DEiS0BtheXc99rE4OiVcJHMPIDhwb/UE46JQ4qsWbtjTSUgQaX7tU4E\nG8WY4Omc5XoWlzC48chnhwKBgQC6g3Q0BGWhzFxgKXLl89JI8waqvHecCjmtM0sO\nOBDEtid40oUOQRd7rdCOUIXtKDlPJRAROHCKqZ2FjnepyQaRm2SFsG9mvuiR3pvR\nw5+sNe6xjeD71kzLh2j02MKfmxUjXLITt/E1lgB1y7h6HmiWdG4O+7v+HbORS6ld\nc57wLQKBgQCBU0XugkyaE3hpJeCkt3PzHsCVpxAxFfxP4FOzFu7tWAHAO8uNO2Ib\n9kWyJzVHNdNTXq1U4x0re5d9+f8jFMKV30LS9cS9edU3Bh0xlLsejAxVh0+CINyG\n69Js7opiAr+r0AGpYaPps03T/v53gLwmZq8/0/mGXkeFSaw1axjegw==\n-----END RSA PRIVATE KEY-----\n' > '/etc/sslkeys/vault.key.pem' && chmod 0600 '/etc/sslkeys/vault.key.pem' && chown root '/etc/sslkeys/vault.key.pem'"]
module.vault_private-tls-cert.tls_private_key.cert: Creation complete after 1s (ID: 11ec94d21172ac94f99ad05f93e7313fe9e36bb4)
module.vault_private-tls-cert.tls_cert_request.cert: Creating...
  cert_request_pem:       "" => ""
  dns_names.#:            "" => "2"
  dns_names.0:            "" => "*"
  dns_names.1:            "" => "*.*"
  ip_addresses.#:         "" => "1"
  ip_addresses.0:         "" => "192.168.0.108"
  key_algorithm:          "" => "RSA"
  private_key_pem:        "" => "8774f0515375706931dbc36d1371d2934c57798d"
  subject.#:              "" => "1"
  subject.0.common_name:  "" => "percona_cn"
  subject.0.organization: "" => "Percona"
module.vault_private-tls-cert.tls_cert_request.cert: Creation complete after 0s (ID: 4d6e3f6696c67c996ccc59053cb513345bcf1c4f)
module.vault_private-tls-cert.tls_locally_signed_cert.cert: Creating...
  allowed_uses.#:        "" => "2"
  allowed_uses.0:        "" => "key_encipherment"
  allowed_uses.1:        "" => "digital_signature"
  ca_cert_pem:           "" => "ab4790a1694d9e5a18134e87bcd73cee92ca7406"
  ca_key_algorithm:      "" => "RSA"
  ca_private_key_pem:    "" => "91cb977a9a683390691b25a399c0df98b5d6c0fe"
  cert_pem:              "" => ""
  cert_request_pem:      "" => "2ff49081dce7c6a7270e912e484ad6a82833134a"
  early_renewal_hours:   "" => "0"
  validity_end_time:     "" => ""
  validity_period_hours: "" => "8760"
  validity_start_time:   "" => ""
module.vault_private-tls-cert.tls_locally_signed_cert.cert: Provisioning with 'local-exec'...
module.vault_private-tls-cert.tls_locally_signed_cert.cert (local-exec): Executing: ["/bin/sh" "-c" "echo '-----BEGIN CERTIFICATE-----\nMIIDMjCCAhqgAwIBAgIQJBdu0na9FjkLCNqoqHZDlTANBgkqhkiG9w0BAQsFADAn\nMRAwDgYDVQQKEwdQZXJjb25hMRMwEQYDVQQDDApwZXJjb25hX2NhMB4XDTE4MDYx\nODEyNDIwN1oXDTE5MDYxODEyNDIwN1owJzEQMA4GA1UEChMHUGVyY29uYTETMBEG\nA1UEAwwKcGVyY29uYV9jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAL3PFdqMt7kNePY1T1JKXyk3ciUK9pbuYrWab1U1joWokbAfstkltfpZgLSmaG+W\nxuJYUSpxxpI8pKCCqJBGcOY71kGHuluIvjhYT+C95zrfjxDUgNcEnXe8qhcrN6b0\nCaDl/kW5/qx0u7/inczVNDUaWJGPlXQQaySyk35ZQfWRW3Ae7oRhfBaAA5g57x8d\nIv/qm1mQ4BT6/x1VloFnt8PosUKMpi4V/OxYoEMHDb7C8LkqVCwSEMLGsiZWhiUU\nw2nzNbmvSOyI2v618ixSRa8zhO9RkDov+gx8x6G/f8hhBcg+mqVJFq5uksOIt/Tp\nk0FRZfPaSWqUYmUkHvrBwh0CAwEAAaNaMFgwDgYDVR0PAQH/BAQDAgWgMAwGA1Ud\nEwEB/wQCMAAwHwYDVR0jBBgwFoAUEy3EajGLqSi2jsRybRJd2mAc2iwwFwYDVR0R\nBBAwDoIBKoIDKi4qhwTAqABsMA0GCSqGSIb3DQEBCwUAA4IBAQDDTe5KVnVYH3DM\nTQkcGWOjU+yCmJDPFvAbcFkU+Rsru/7c0nVas5cl4evUGQjmVk7HWZPiPdzfCstI\nsbh2WwRqjsTrm9uku9BmKEBmT5+m/kxOpOWdnT+yUtFIjwvGhmwmtUOuVisVPbod\nP3//5aXX+lhMcIj+LUdKAvL+s5+7dMzQnHZd9IQoc2+TPF8gKkZP0jV+gLy2XRhu\nj3Fe28DquGkJQiUHHyJDeJ+bajzceSsdistoGVgvaToszZDXfWw7qpIwhFr0Ebt2\nRm8u+BT88vugsYU2tzqPv3KUjPoey9wy542X0IDYosPfQB4HM9SKb2SX7r9cxs7M\neBysm7cl\n-----END CERTIFICATE-----\n' > '/etc/sslkeys/vault.crt.pem' && chmod 0600 '/etc/sslkeys/vault.crt.pem' && chown root '/etc/sslkeys/vault.crt.pem'"]
module.vault_private-tls-cert.tls_locally_signed_cert.cert: Creation complete after 0s (ID: 47973878415721625222398828536864850837)

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

The last command will create a new file in the working directory and the SSL CA and self-signed certificates in the /etc/sslkeys directory as defined in your terraform configuration file.

# ls -l
total 40
-rw-r--r-- 1 root root   475 Jun 18 12:41 main.tf
-rw-r--r-- 1 root root 16623 Jun 18 12:42 terraform.tfstate
# ls -l /etc/sslkeys/
total 36
-rw------- 1 root root 1140 Jun 18 12:42 ca.crt.pem
-rw------- 1 root root 1169 Jun 18 12:42 vault.crt.pem
-rw------- 1 root root 1680 Jun 18 12:42 vault.key.pem

It is recommended to delete the terraform.tfstate file as it contains information related to the SSL CA and self-signed certificate key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment