HashiCorp Cloud Platform
Remediate leaked Google Cloud (GCP) secrets
HCP Vault Radar can scan for leaked Google Cloud Platform (GCP) secrets using dynamic secrets, for information on how to use statics secrets, go to the active secrets documentation.
Create an incident
Leaked secrets can lead to unauthorized access to your services. To prevent malicious activity, we recommend rotating and storing the secret in Vault.
- Follow your organization’s guidelines for emergency rotation of a secret.
- Contact your GCP account owner.
- Determine if your company already uses HashiCorp Vault.
Configure Vault's Google Cloud (GCP) secret engine
This example uses the GCP secrets engine and roleset. If your application is already configured to access secrets in Vault, use existing secrets engines and auth methods.
Note
Create a Google cloud service account with the permissions your app needs to access any Google Cloud services. For details on Google Cloud service accounts click here.
Set up a service account for the Google Cloud secret engine, the service account should have the following minimum scopes:
https://www.googleapis.com/auth/cloud-platform
Minimum required permissions
# Service account + key admin iam.serviceAccounts.create iam.serviceAccounts.delete iam.serviceAccounts.get iam.serviceAccounts.list iam.serviceAccounts.update iam.serviceAccountKeys.create iam.serviceAccountKeys.delete iam.serviceAccountKeys.get iam.serviceAccountKeys.list
When using rolesets or static accounts with bindings, Vault must have the following permissions:
<service>.<resource>.getIamPolicy <service>.<resource>.setIamPolicy
Where
service
andresource
correspond to permissions which will be granted, for example:# Projects resourcemanager.projects.getIamPolicy resourcemanager.projects.setIamPolicy # All compute compute.*.getIamPolicy compute.*.setIamPolicy # BigQuery datasets bigquery.datasets.get bigquery.datasets.update
Assign the set of roles required to get resource-specific
getIamPolicy/setIamPolicy
permissions. At a minimum you will need to assignroles/iam.serviceAccountAdmin
androles/iam.serviceAccountKeyAdmin
so Vault can manage service accounts and keys.For more information on IAM requirement, refer to this document.
Set the following environment variables in your local environment:
VAULT_TOKEN VAULT_ADDR VAULT_NAMESPACE GOOGLE_APPLICATION_CREDENTIALS
Enable the GCP secret engine in Vault.
$ vault secrets enable gcp
Note
This command will default to gcp/ as the path, you can specify any other path but make sure to change the path of the commands below.
Configure the secrets engine with account credentials, or leave blank or unwritten to use Application Default Credentials.
$ vault write gcp/config credentials=@my-credentials.json
Create a roleset in Vault.
$ vault write gcp/roleset/my-token-roleset \ project={my-project-id} \ secret_type="access_token" \ token_scopes="https://www.googleapis.com/auth/cloud-platform" \ bindings=-<<EOF resource "//cloudresourcemanager.googleapis.com/projects/{my-project-id}" { roles = ["roles/viewer"] } EOF
Note
Secrets created by Vault using GCP secret engine have a default lease of 60 minutes. Refer to the Vault documentation for more information on how to change the lease length.
Use the roleset to read credentials from GCP. For more information, refer to the Vault documentation.
$ vault read gcp/roleset/my-token-roleset/token Key Value --- ----- expires_at_seconds 1537402548 token ya29.c.ElodBmNLMNOPgcBpnXcE4ywG4w1k... token_ttl 3599
Note
Once the roleset has been created, you can use it to read credentials from GCP. For more information, please visit Vault documentation
Find more details on GCP roles here.
Remove the secret from code
Now that the GCP secret is available from Vault, remove the hardcoded secret from the source code. This example uses an environment variable to store the secret from Vault.
Create an environment variable with the secret from Vault.
$ export MY_SECRET=$($ curl \ --header "X-Vault-Token: ..." \ --request GET \ https://127.0.0.1:8200/v1/gcp/config)
Remove the secret from source and add a reference to the secret stored at the environment variable
MY_SECRET
.mySecret = getenv(“MY_SECRET”)
Start your local server and test.
Note
Dynamic secrets need to be refreshed. If you are using an environment variable to read the secret, your application needs a way to refresh the secret value when it expires. Here are some ways to keep the dynamic secret value updated within your running application.
- Create secrets with the Vault secrets operator for Kubernetes. (When using VSO and dynamic secrets, the application will need to rotate the secret value)
- Read and reload secrets in Spring.
- If you do not use environment variables, refer to the Vault API documentation
Revoke the secret
Revoke the secret to complete the remediation process.
- Validate the environment variable is populated from Vault.
- Deploy and test the application.
- Work with the GCP service owner to revoke the previous secret value.