: ' MIT License Copyright (c) 2023 Roblox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ' !/bin/bash # Fail on any failed command set -eo pipefail # We expect to be executed within a container, hence use the docker DNS names. export VAULT_TOKEN=myroot ## Enable 'Consul Secrets Backend' in Vault setup_consul_secrets() { # Enable the 'consul secrets backend' in Vault vault secrets enable consul # Bootstrap the Consul ACL system to get the root ACL token which we'll give to Vault later on CONSUL_HTTP_TOKEN=$(consul acl bootstrap -format=json | jq --raw-output '.SecretID') export CONSUL_HTTP_TOKEN # Save the root ACL token into Consul itself - just in case that a human ever needs it. consul kv put consul_bootstrap_acl "$CONSUL_HTTP_TOKEN" # Configure the 'consul secrets backend' in Vault to use our local Consul vault write consul/config/access address=$CONSUL_HTTP_ADDR token="$CONSUL_HTTP_TOKEN" # TODO: @eyang to clean up. # Create the actual Consul policy used by the tests. This copies the 'consul_kv_entities' policy that exists in production. # https://github.com/Roblox/rblx_hashistack_terraform/blob/75ff7ad8ddf5321d6a8aa983be7fb4fa9419134b/vars/shared/production/vault.tfvars#L1035 vault write consul/roles/consul_kv_entities policy="$(base64 <<< 'node "" { policy = "read" } service "" { policy = "read" } key "teams/entities/" { policy = "write" } session "" { policy = "write"}')" vault policy write consul_kv_entities docker-utils/vault/policy_consul_kv_entities.hcl } ## Enable 'Nomad Secrets Backend' in Vault setup_nomad_secrets() { # Enable the 'nomad secrets backend' in Vault vault secrets enable nomad # Bootstrap the Consul Nomad system to get the root ACL token which we'll give to Vault later on # Nomad can be a bit slow to start up, hence we're retrying a few times. NOMAD_TOKEN=$(curl --retry 30 --retry-connrefused --retry-delay 1 --request POST $NOMAD_ADDR/v1/acl/bootstrap | jq -r '.SecretID') export NOMAD_TOKEN # Save the root ACL token into Consul - just in case that an human ever needs it. consul kv put nomad_bootstrap_acl "$NOMAD_TOKEN" # Configure the secrets backend using Nomad's vault token vault write nomad/config/access address=$NOMAD_ADDR token="$NOMAD_TOKEN" # Setup the policy given to our jobs in Nomad nomad acl policy apply entities-jobs docker-utils/nomad/policy_entities_jobs.hcl # Configure the default policy in Nomad to be wide-open (this differs from production) nomad acl policy apply anonymous docker-utils/nomad/policy_anonymous.hcl # Configure a role to Vault which can be used to define the policy that we just created vault write nomad/role/nomad_dbplat_entities policies=entities-jobs # Configure a policy (Vault concept) with access to the nomad role (Vault concept) that we created above vault policy write nomad_dbplat_entities docker-utils/vault/policy_nomad_dbplat_entities.hcl echo "Nomad ACL: $NOMAD_TOKEN"; } ## Load Vault policy to enable secrets storage setup_vault_storage() { # Switch from the V2 secrets engine to V1 since that's what production is using vault secrets disable secret vault secrets enable -path=secret kv # Write the Vault policy giving us access to our path in the secrets engine vault policy write secret_entities docker-utils/vault/policy_secret_entities.hcl } ## Enable PKI Engine for certificate management in Vault setup_pki_secrets() { # Enable the pki engine at the default path vault secrets enable pki # Generate the CA certificate in Vault vault write pki/root/generate/internal \ common_name=consul \ ttl=8760h > CA_cert.crt # Setup the URL configuration in Vault's PKI engine. vault write pki/config/urls \ issuing_certificates="$VAULT_ADDR/v1/pki/ca" \ crl_distribution_points="$VAULT_ADDR/v1/pki/crl" # Configure a role to generate certificates to use in vault vault write pki/roles/consul \ allowed_domains=consul \ allow_subdomains=true \ max_ttl=72h } echo "Setting up hashistack secrets engines for secondary hashistack containers" export NOMAD_ADDR=http://nomad-2:4646 export CONSUL_HTTP_ADDR=http://consul-2:8500 export VAULT_ADDR=http://vault-2:8200 echo "Enabling 'Consul Secrets Backend' in Vault" setup_consul_secrets echo "Enabling 'Nomad Secrets Backend' in Vault" setup_nomad_secrets echo "Loading Vault policy to enable secrets storage" setup_vault_storage echo "Enabling PKI Engine for certificate management in Vault" setup_pki_secrets echo "Adding auto scaler job for nomad dc2" nomad run docker-utils/nomad-auto-scaler2.nomad echo "Setting up hashistack secrets engines for main hashistack containers" export NOMAD_ADDR=http://nomad:4646 export CONSUL_HTTP_ADDR=http://consul:8500 export VAULT_ADDR=http://vault:8200 echo "Enabling 'Consul Secrets Backend' in Vault" setup_consul_secrets echo "Enabling 'Nomad Secrets Backend' in Vault" setup_nomad_secrets echo "Loading Vault policy to enable secrets storage" setup_vault_storage echo "Enabling PKI Engine for certificate management in Vault" setup_pki_secrets echo "Adding auto scaler job for nomad dc1" nomad run docker-utils/nomad-auto-scaler.nomad