Configuring access to a cloud provider

Security problem

When using tools for automating infrastructure build process in a cloud, an access credentials to a cloud resource provider are needed. The credentials should be available to the tools only during infrastructure build or update process. Ideally the credentials will be provided automatically and without any human interaction.

Security control proposal

  • Store credentials in a trusted backend as close as possible to automation tools.

  • Add credentials to environment only during build process (don’t hardcode them into source files).

  • Use static checkers for your automation tool to make sure your code doesn’t contain any secrets.

Reference implementation

Following 2 options are recommended way of safely storing secrets needed by

  1. Set environment variables in your CI/CD toolchain. Make them available to the automation tools only during pipeline run.

  2. Read environment variables from safe remote storage such as Hashicorp Vault or AWS Secrets Manager.

Following tabs show different automation tools configurations without secret/sensitive variables present.

# Configure the OpenStack Provider
provider "openstack" {
  tenant_name = "admin"
  auth_url    = "https://myauthurl.example.com:5000/v2.0"
  region      = "RegionOne"
}
# Configure the PowerDNS provider
provider "powerdns" {
  api_key = "${var.pdns_api_key}"
  server_url = "https://powernds-api-url.example.com"
}

Terraform Openstack provider

The example above shows configuration as it should be, i.e. only showing non-secret variables. The secret variables will be picked up from the environment. Their corresponding environment variables names can be found in the configuration reference

Full Terraform Openstack provider configuration reference can be found here

Terraform PowerDNS provider

The PowerDNS provider example above shows secure configuration. api_key is mandatory argument and the value in example above is var.pdns_api_key, which is variable declared in terraform files. However, the value is either set by exporting TF_VAR_pdns_api_key or by exporting PDNS_API_KEY. Argument reference of the PowerDNS provider discusses variable name.

Full Terraform PowerDNS provider configuration reference can be found here

Practical implementation

Setting environment variables

Following screenshot shows where to locate and set environment variables in the settings in Gitlab.

In Gitlab, we set and locate environment variables in the Settings -> CI/CD page.

Reading secrets from secure backend

Following gitlab-ci shows how to read Openstack username and password into OS_USERNAME and OS_PASSWORD. The values are read from Hashicorp’s Vault instance running at https://api.secrets.sec.in.pan-net.eu. The authentication mechanism used in this example is using JWT that is unique per Gitlab CI job.

image: vault:latest
stages:
   - vault
variables:
      VAULT_ADDR: https://api.secrets.sec.in.pan-net.eu
      # VAULT_TOKEN is obtained from https://safes.security.in.pan-net.eu/ and set as CICD secret variable
read_secrets:
  stage: vault
  script:
      - export OS_USERNAME="$(vault kv get -field=username my_project/dc1/os_username)"
      - export OS_PASSWORD="$(vault kv get -field=password my_project/dc1/os_password)"
  only:
      - master