Skip to main content
The External Secrets Inc. Audit & Compliance product suite is a premium product. It requires a specific subscription. Contact us for more information.

GCP Secret Manager Provider

The Audit Listener can be configured to receive audit logs from GCP Secret Manager by utilizing a Pub/Sub Subscription and a Cloud Audit Logging Router. The illustration below demonstrates the setup: Architecture Light

Required Permissions

To set up the Listener, the following roles must be assigned:
  • roles/secretmanager.secretAccessor - on the GCP project level.
  • roles/secretmanager.viewer - on the GCP project level.
  • roles/pubsub.subscriber - on the designated Pub/Sub Subscription.
The Secret Accessor and Secret Viewer permissions are necessary for the listener to calculate duplicate entries.

Configuring the Provider

Setting up the provider may require configuration of the authentication methods during the listener installation process.

Supported Authentication Methods

The Audit Listener supports the following Google Application Credentials authentication methods:
  • Using a Service Account Key defined in the runtime.
  • Leveraging the GCE Metadata Server.
  • Utilizing the GKE Metadata Server and Workload Identity.
Create a patch file named gce-patch.yaml with the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: audit-listener
spec:
  template:
    spec:
      containers:
      - name: audit-listener
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS_JSON
          valueFrom:
            secretKeyRef:
              name: secret-name
              key: key-name
Add the following values to the helm install:
extraEnv:
  - name: GOOGLE_APPLICATION_CREDENTIALS_JSON
    valueFrom:
      secretKeyRef:
        name: secret-name
        key: key-name
Execute the following command using an account with appropriate privileges:systemd edit audit-listener.serviceThen, edit the file to include the necessary environment variables:
[Service]
Environment="GOOGLE_APPLICATION_CREDENTIALS_JSON=secret-token"
  • This method is incompatible with Kubernetes installations.
  • This method is incompatible with Kubernetes installations.
  • No additional setup is required for authentication through the GCE Metadata Server. Proceed with configuring your GCP setup
Add the following gke-sa-patch.yaml to the kustomization file:
apiVersion: apps/v1
kind: ServiceAccount
metadata:
name: audit-listener
annotations:
iam.gke.io/gcp-service-account: <sa_name>@<project_id>.iam.gserviceaccount.com
Add the following values to the helm install:
serviceAccount:
  annotations:
    "iam.gke.io/gcp-service-account": <sa_name>@<project_id>.iam.gserviceaccount.com
  • This authentication method is not supported for standalone installations.

Creating a new Provider

After completing the listener setup, you can create a new provider.
  1. Navigate to the Dashboard.
  2. Add a new provider:
  • Select GCP as the provider type.
  • Specify the fields based on your installation:
  • ProjectId: GCP Project ID.
  • Topic: Name of the Pub/Sub Topic.
  • Subscription: Name of the Pub/Sub Subscription.

Setting Up GCP

The final step is to configure GCP:
  • Enable Cloud Audit Logs for all Secret Manager events.
  • Create a Pub/Sub Topic and Subscription.
  • Set up a log router to route audit logs to the Topic.
  • Create a Service Account and assign the necessary permissions.
  • Add the necessary configuration based on your installation method.

Configure the project Cloud Audit Logs to send information on all SecretManager events

Enabling Audit Logging for Secret Manager

# Enable audit logging for Secret Manager
resource "google_project_service" "secretmanager" {
  service = "secretmanager.googleapis.com"
}

resource "google_project_iam_audit_config" "secret_manager_audit" {
  project = var.project_id
  service = "secretmanager.googleapis.com"

  audit_log_config {
    log_type = "DATA_READ"
  }
}

Creating a Pub/Sub Topic and Subscription

resource "google_pubsub_topic" "topic" {
  name = var.topic_name
}

resource "google_pubsub_subscription" "subscription" {
  name  = var.subscription_name
  topic = google_pubsub_topic.topic.name
}

Creating a Log Router

resource "google_logging_log_sink" "sink" {
  name = var.sink_name
  destination = "pubsub.googleapis.com/projects/${var.project_id}/topics/${var.topic_name}"
  ## Filter to all secretManager events
  filter = "protoPayload.methodName=~\"google.cloud.secretmanager.v1.SecretManagerService\""
}

resource "google_pubsub_topic_iam_member" "topic" {
  topic = google_pubsub_topic.topic.name
  role         = "roles/pubsub.publisher"
  member       = google_logging_project_sink.log_sink.writer_identity
}

Create a Service account and grant it the needed permissions

resource "google_service_account" "service_account" {
  account_id   = var.service_account_id
  display_name = var.service_account_display_name
}
resource "google_project_iam_member" "secret_accessor" {
  project = var.project_id
  role    = "roles/secretmanager.secretAccessor"
  member  = "serviceAccount:${google_service_account.service_account.email}"
}
resource "google_project_iam_member"  "secret_viewer" {
  project = var.project_id
  role    = "roles/secretmanager.viewer"
  member  = "serviceAccount:${google_service_account.service_account.email}"
}
resource "google_pubsub_subscription_iam_member" "subscriber" {
  project = var.project_id
  subscription = google_pubsub_subscription.subscription.name
  role         = "roles/pubsub.subscriber"
  member       = "serviceAccount:${google_service_account.service_account.email}"
}

Add the needed configuration according to the installation method

resource "google_service_account_key" "key" {
  service_account_id = google_service_account.service_account.name
}
resource "google_service_account_iam_member" "workload_identity_binding" {
  service_account_id = google_service_account.service_account.name
  role    = "roles/iam.workloadIdentityUser"
  member  = "serviceAccount:${var.project_id}.svc.id.goog[${var.k8s_namespace}/${var.k8s_service_account_name}]"}"
}
resource "google_compute_instance" "listener-vm" {
  name         = "listener-vm"
  # omited for simplicity ...
  service_account {
    email  = google_service_account.service_account.email
    scopes = ["userinfo-email", "compute-ro", "storage-ro"]
  }
}

GCP Events Format

Coming Soon.