IAM Component
The IAM component creates service accounts and assigns roles for secure access to GCP resources.
Service Accounts
| Service Account | Purpose |
|---|---|
app@project.iam | Application workloads in GKE |
gke-nodes@project.iam | GKE node pool identity |
cicd@project.iam | CI/CD pipeline deployments |
langfuse@project.iam | Observability service |
Architecture
Role Assignments
Application Service Account (app)
Used by backend pods via Workload Identity:
| Role | Purpose |
|---|---|
secretmanager.secretAccessor | Read secrets |
storage.objectAdmin | Access app data buckets |
cloudsql.client | Connect to databases |
GKE Nodes Service Account (gke-nodes)
Used by GKE node pools:
| Role | Purpose |
|---|---|
artifactregistry.reader | Pull container images |
logging.logWriter | Write logs to Cloud Logging |
monitoring.metricWriter | Write metrics |
CI/CD Service Account (cicd)
Used by deployment pipelines:
| Role | Purpose |
|---|---|
artifactregistry.writer | Push container images |
container.developer | Deploy to GKE |
storage.objectAdmin | Upload static assets |
Langfuse Service Account (langfuse)
Used by observability service:
| Role | Purpose |
|---|---|
storage.objectAdmin | Write to langfuse bucket |
Workload Identity
Workload Identity federates Kubernetes and GCP identities:
Configuration
- Kubernetes ServiceAccount with annotation:
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend
namespace: default
annotations:
iam.gke.io/gcp-service-account: app@PROJECT_ID.iam.gserviceaccount.com
- IAM Binding for Workload Identity:
new gcp.serviceaccount.IAMMember('workload-identity-binding', {
serviceAccountId: appServiceAccount.name,
role: 'roles/iam.workloadIdentityUser',
member: pulumi.interpolate`serviceAccount:${projectId}.svc.id.goog[NAMESPACE/KSA_NAME]`,
});
Outputs
interface IamOutputs {
appServiceAccountEmail: string;
gkeNodesServiceAccountEmail: string;
cicdServiceAccountEmail: string;
langfuseServiceAccountEmail?: string;
}
Security Best Practices
Principle of Least Privilege
Each service account has only the roles required for its function:
- App SA cannot push images
- CI/CD SA cannot read secrets
- Node SA can only read images
No Key Export
Service accounts use:
- Workload Identity for GKE pods
- Attached Service Account for CI/CD
- No long-lived JSON keys in production
Audit Logging
All service account actions are logged in Cloud Audit Logs for compliance and security monitoring.