Managing secrets securely is crucial for any application, especially in cloud environments. Google Cloud Secret Manager provides a centralized and secure way to store and manage sensitive information like API keys, passwords, and certificates. This post will guide you through creating and managing secrets using Python and the Google Cloud Secret Manager API.
Prerequisites
Before you start, ensure you have the following:
- A Google Cloud Platform (GCP) project.
- The Google Cloud SDK (gcloud) installed and configured.
- Python 3.6 or higher.
-
The Google Cloud Secret Manager Python library installed. You can install it using pip:
pip install google-cloud-secret-manager
- Ensure you have enabled the Secret Manager API for your project in the Google Cloud Console.
Setting Up Authentication
You need to authenticate your Python script with Google Cloud to access the Secret Manager API. The recommended approach is to use a service account.
- Create a Service Account: In the Google Cloud Console, navigate to “IAM & Admin” -> “Service Accounts” and create a new service account.
- Grant Permissions: Grant the service account the necessary permissions. At a minimum, it needs the “Secret Manager Secret Accessor” (
roles/secretmanager.secretAccessor
) and “Secret Manager Admin” (roles/secretmanager.admin
) roles. The Secret Manager Admin role is required to create, update and delete secrets. The Secret Manager Secret Accessor is required to read secret values. For production environments, it is recommended to create custom roles with only the minimal required permissions. - Download the Key File: Download the JSON key file for the service account.
-
Set the Environment Variable: Set the
GOOGLE_APPLICATION_CREDENTIALS
environment variable to the path of the key file:export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"
Python Code Examples
Here’s how to perform common Secret Manager operations using Python.
Creating a Secret
from google.cloud import secretmanager
def create_secret(project_id, secret_id):
"""
Creates a new secret in Google Cloud Secret Manager.
"""
client = secretmanager.SecretManagerServiceClient()
parent = f"projects/{project_id}"
try:
secret = client.create_secret(
request={
"parent": parent,
"secret_id": secret_id,
"secret": {"replication": {"automatic": {}}},
}
)
print(f"Successfully created secret: {secret.name}")
return secret.name
except Exception as e:
print(f"Error creating secret: {e}")
return None
# Example usage:
project_id = "your-gcp-project-id" # Replace with your GCP project ID
secret_id = "my-super-secret"
secret_name = create_secret(project_id, secret_id)
Replace "your-gcp-project-id"
with your actual Google Cloud project ID. The replication policy {"replication": {"automatic": {}}}
configures the secret to be replicated automatically across Google’s global network.
Adding a Secret Version
from google.cloud import secretmanager
def add_secret_version(project_id, secret_id, payload):
"""
Adds a new version to an existing secret.
"""
client = secretmanager.SecretManagerServiceClient()
parent = f"projects/{project_id}/secrets/{secret_id}"
payload_bytes = payload.encode("UTF-8")
try:
version = client.add_secret_version(
request={"parent": parent, "payload": {"data": payload_bytes}}
)
print(f"Successfully added secret version: {version.name}")
return version.name
except Exception as e:
print(f"Error adding secret version: {e}")
return None
# Example usage:
project_id = "your-gcp-project-id" # Replace with your GCP project ID
secret_id = "my-super-secret"
payload = "This is my secret value!"
version_name = add_secret_version(project_id, secret_id, payload)
This function adds a new version of the secret with the provided payload. The payload is encoded as UTF-8 before being sent to the API.
Accessing a Secret Version
from google.cloud import secretmanager
def access_secret_version(project_id, secret_id, version="latest"):
"""
Accesses the payload of a specific secret version.
"""
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version}"
try:
response = client.access_secret_version(request={"name": name})
payload = response.payload.data.decode("UTF-8")
print(f"Secret value: {payload}")
return payload
except Exception as e:
print(f"Error accessing secret version: {e}")
return None
# Example usage:
project_id = "your-gcp-project-id" # Replace with your GCP project ID
secret_id = "my-super-secret"
secret_value = access_secret_version(project_id, secret_id)
This function retrieves the payload of a specific secret version. By default, it accesses the “latest” version.
Disabling a Secret Version
from google.cloud import secretmanager
def disable_secret_version(project_id, secret_id, version_id):
"""Disables a secret version."""
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
try:
response = client.destroy_secret_version(request={"name": name})
print(f"Disabled secret version: {name}")
return True
except Exception as e:
print(f"Error disabling secret version: {e}")
return False
# Example Usage
project_id = "your-gcp-project-id"
secret_id = "my-super-secret"
version_id = "1" # Replace with the version to disable
disable_secret_version(project_id, secret_id, version_id)
This disables a secret version. Disabled versions cannot be accessed.
Deleting a Secret
from google.cloud import secretmanager
def delete_secret(project_id, secret_id):
"""Deletes a secret."""
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/{secret_id}"
try:
client.delete_secret(request={"name": name})
print(f"Deleted secret: {name}")
return True
except Exception as e:
print(f"Error deleting secret: {e}")
return False
# Example Usage
project_id = "your-gcp-project-id"
secret_id = "my-super-secret"
delete_secret(project_id, secret_id)
This deletes an entire secret and all its versions. Use with caution!
IAM Permissions
The following IAM roles are relevant to Secret Manager:
- roles/secretmanager.secretAccessor: Allows access to secret values. This is the minimum permission required to read secrets.
- roles/secretmanager.secretVersionManager: Allows managing secret versions (adding, disabling, destroying).
- roles/secretmanager.admin: Provides full administrative access to Secret Manager, including creating, deleting, and managing secrets and their versions, as well as setting IAM policies.
Remember to grant the least privilege necessary to service accounts and users. Avoid granting broad roles like roles/owner
when more restrictive roles are sufficient.
Best Practices
- Use Service Accounts: Authenticate your applications using service accounts with the necessary permissions.
- Principle of Least Privilege: Grant only the minimum required permissions to service accounts and users.
- Secret Rotation: Implement a secret rotation policy to regularly update your secrets.
- Monitoring and Auditing: Monitor Secret Manager access and audit logs to detect any suspicious activity.
- Avoid Storing Secrets in Code: Never hardcode secrets directly in your code or configuration files.
Conclusion
Google Cloud Secret Manager provides a robust and secure way to manage your application’s secrets. By using the Python client library and following best practices, you can ensure that your sensitive information is protected and properly managed. Remember to carefully configure IAM permissions and implement a secret rotation policy for enhanced security.