Prompting for Secrets

This section describes how to add prompts for secrets to an existing cluster.conf file.

Overview

For security purposes, Apcera provides a syntax for adding secret prompts to cluster.conf. Secret prompts can be configured for both secrets that are stored in Vault and for secrets that are stored in the cluster configuration values file (named cluster.sec).

Syntax

This section describes the syntax and optional arguments for adding prompts to cluster.conf.erb.

Attribute Required Contains Notes
:prompt Yes Text string presented by orchestrator-cli. Orchestrator will prompt the user to enter some text. It will suffix the prompt with ':' or '[defaultValue]:'. The prompt string entered as part of the tag should be formulated accordingly. The :prompt field must be the first listed in the tag. The prompt text must be surrounded by single quotes; any single quotes or apostrophes within the prompt must be escaped with a double backslash, for example: Enter the user\\'s password.
:hide No Boolean true or false. Used to specify that the value being collected does not need to be hidden from the user, such as a username, for example. If not specified then :hide=true. The value must either be true or false, without quotes.
:default No Default value to use if no value already present. Typically only used when :hide=false. The default value must be surrounded by single quotes; any single quotes or apostrophes within the value must be escaped with a double backslash, for example: This is a \\'quoted\\' value.
:path No Location in Vault that the information will be stored. If not specified the path will be the path to the element's configuration in the cluster.conf file (equivalent to Apcera cfg dot-delimited notation but using slashes for delimiters). The path value must be surrounded by single quotes; any single quotes or apostrophes within the value must be escaped with a double backslash, for example: secret/with/a\\'quote\\'/in/its/path/.
:notstored No Boolean true or false. Indicates, when :path is not provided, that the value is not stored in vault. Instead it simply replaces the prompt tag in the configs used by the deploy runtime. Ignored if :path is provided since path is the storage location.
:optional No Boolean true or false. When true an empty value is permitted. Ignored if :default is provided since that value will be used when user provides no input.

Prompting examples

The following cluster.conf.erb snippet demonstrates how to enable prompts for Google Authentication.

chef: {
  "continuum": {
    ...
    "auth_server": {
      "identity": {
        "default_provider": "basic",
        "basic": {
          "enabled": true,
          "users": [
          {
            "name": "NAME",
            "password": "PASSWORD"
          }]
        },
        "google": {
          "users": [
            "user1@gmail.com",
            "user2@gmail.com",
            ],
          "enabled": false,
          "client_id": "<%% :prompt => 'Google Auth Client ID', :hide => false %>",
          "client_secret": "<%% :prompt => 'Google Auth Client Secret,' :hide => true %>",
          "web_client_id": "<%% :prompt => 'Google Auth Web Client ID' :hide => false %>",
        },
      "admins": [
        "user1@gmail.com",
        "user2@gmail.com",
      ],
    } # identity
  },  # auth_server
}

The following example cluster.conf.erb snippet shows prompting for secrets for LDAP authentication:

chef: {
    "continuum": {
      "auth_server": {
            "identity": {
                "ldap_basic": {
                    "enabled": true,
                    # -- Start Oracle LDAP config
                    "model_name": "basic",
                    "search_dn": "<%% :prompt => 'LDAP account used for searches', :default => 'Directory Manager', :path => 'identity/ldap_basic', :hide => false %>",
                    "search_passwd": "<%% :prompt => 'password for the LDAP account used for searches', :path => 'identity/ldap_basic' %>",
                    "base_dn": "ou=People,dc=example,dc=com",
                    "group_base_dn": "dc=example,dc=com",
                    "uri": "ldaps://172.27.0.152",
                    "port": "1636",
                    "tls_insecure_skip_verify": false,
                }
            }
        }
    }
}

When the resulting cluster.conf file is generated, the <%% … %> tags become <% … %> tags, resulting in the following in cluster.conf.

chef: {
    "continuum": {
        "auth_server": {
            "identity": {
                "ldap_basic": {
                      "enabled": true,
                      # -- Start Oracle LDAP config
                      "model_name": "basic",
                      "search_dn": "<% :prompt => 'LDAP account used for searches', :default => 'Directory Manager', :path => 'identity/ldap_basic', :hide => false %>",
                      "search_passwd": "<% :prompt => 'password for the LDAP account used for searches', :path => 'identity/ldap_basic' %>",
                      "base_dn": "ou=People,dc=example,dc=com",
                      "group_base_dn": "dc=example,dc=com",
                      "uri": "ldaps://172.27.0.152",
                      "port": "1636",
                      "tls_insecure_skip_verify": true,
                }
            }
        }
    }
}

Note that multiple tags can use the same :path, which results in one Vault secret holding a JSON object with one attribute for each configuration line. For example in the case of the ldap_basic configuration shown above, doing a read request on /v1/secret/identity/ldap_basic would return data:

    {
        "search_dn": "Directory Manager",
        "search_passwd": "pass@word1"
    }

The following example shows how to enable prompts for secrets that cannot be stored in Vault but can be stored in encrypted form in the secure configuration values file (cluster.sec). In this example the SSL/TLS cert and private key, as well as Zabbix credentials are configured for prompting and storage in cluster.sec.

chef: {
  "continuum": {
    "router": {
       "http_port": 80,
       "https_port": 443,
       "nginx_http_stub_status": true,
       "ssl": {
         "enable": true,
          "tlshosts": [
            {
              "server_names": [ "<%% :prompt => 'Enter server name(s), comma-separated if multiple', :hide => false, :notstored=>true %>"],
              "certificate_chain": (-----BEGIN CERTIFICATE-----"<%% :prompt => 'Enter certificate' :hide => false, :notstored=>true %>"-----END CERTIFICATE-----)
              "private_key": (-----BEGIN RSA PRIVATE KEY-----"<%% :prompt => 'Enter private key' :hide => false, :notstored=>true %>"-----END RSA PRIVATE KEY-----)
           },
         ]    # tlshosts
       }      # ssl
    },        # router
    "auth_server": {
      "identity": {
      ...
    } # identity
  },  # auth_server
  "apzabbix": {
    "disable_default_site": true,
    "web_hostnames": ["monitoring.my-cluster.apcera-platform.io"],
    "sslonly": true,
    "db": {
      "hostport": "localhost:5432",
      "master_user": "<%% :prompt => 'Zabbix DB master user (Already configured by Terraform)', :notstored=>true, :default=>"apcera_ops", :hide=>false %>",
      "master_pass": "<%% :prompt => 'Zabbix DB master password', :hide=>true, :notstored=>true %>",
      "zdb_user": "<%% :prompt => 'Zabbix DB user', :optional=>true, :notstored=>true %>",
      "zdb_pass": "<%% :prompt => 'Zabbix DB user password', :hide=>true, :optional=>true, :notstored=>true %>"
    }
    "users": {
      "guest": { "user": "<%% :prompt => 'Zabbix Guest User', :notstored=>true %>", "pass": "<%% :prompt => 'Zabbix Guest Password', :hide=>true, :notstored=>true %>" },
      "admin": "<%% :prompt => 'Zabbix Admin User',:default => 'admin', :notstored=>true %>", "pass": "<%% :prompt => 'Zabbix Admin Password', :notstored=>true, :hide=>true %>", "delete": false }
    },
  } # apzabbix
}