{"record":{"id":"594f8ede76058557","repo":"kubernetes/kops","slug":"error-setting-gcs-bucket-acl-for-gs-s-for-s-as","errorCode":null,"errorMessage":"error setting GCS bucket ACL for gs://%s for %s as %s: %v","messagePattern":"error setting GCS bucket ACL for gs://(.+?) for (.+?) as (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gcetasks/storagebucketacl.go","lineNumber":114,"sourceCode":"\t\treturn fi.RequiredField(\"Entity\")\n\t}\n\treturn nil\n}\n\nfunc (_ *StorageBucketAcl) RenderGCE(t *gce.GCEAPITarget, a, e, changes *StorageBucketAcl) error {\n\tbucket := fi.ValueOf(e.Bucket)\n\tentity := fi.ValueOf(e.Entity)\n\trole := fi.ValueOf(e.Role)\n\n\tif a == nil {\n\t\tklog.V(2).Infof(\"Creating GCS bucket ACL for gs://%s for %s as %s\", bucket, entity, role)\n\t} else {\n\t\tklog.V(2).Infof(\"Updating GCS bucket ACL for gs://%s for %s as %s\", bucket, entity, role)\n\t}\n\n\terr := t.Cloud.Storage().Bucket(bucket).ACL().Set(context.TODO(), storage.ACLEntity(entity), storage.ACLRole(role))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting GCS bucket ACL for gs://%s for %s as %s: %v\", bucket, entity, role, err)\n\t}\n\n\treturn nil\n}\n\n// terraformStorageBucketAcl is the model for a terraform google_storage_bucket_acl rule\ntype terraformStorageBucketAcl struct {\n\tBucket     string   `cty:\"bucket\"`\n\tRoleEntity []string `cty:\"role_entity\"`\n}\n\nfunc (_ *StorageBucketAcl) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *StorageBucketAcl) error {\n\tvar roleEntities []string\n\troleEntities = append(roleEntities, fi.ValueOf(e.Role)+\":\"+fi.ValueOf(e.Entity))\n\ttf := &terraformStorageBucketAcl{\n\t\tBucket:     fi.ValueOf(e.Bucket),\n\t\tRoleEntity: roleEntities,\n\t}","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gcetasks/storagebucketacl.go#L96-L132","documentation":"StorageBucketAcl.RenderGCE wraps a failed cloud.google.com/go/storage ACL Set call. kOps calls Set to create or update an ACL rule (entity/role pair) on the GCS bucket; any API failure is wrapped with bucket, entity, and role.","triggerScenarios":"t.Cloud.Storage().Bucket(bucket).ACL().Set(ctx, entity, role) returns an error during RenderGCE of a StorageBucketAcl task (create or update path).","commonSituations":"kOps credentials lack storage.buckets.setIamPolicy / legacy bucket ACL write permission (roles/storage.legacyBucketOwner or storage.admin); the bucket was deleted or renamed between Find and apply; invalid entity string format (must be like `user-email`, `group-...`, `allAuthenticatedUsers`); bucket is public-access-prevention / org-policy restricted; transient 5xx.","solutions":["Read the wrapped error: 403 => grant roles/storage.admin (or storage.buckets.setIamPolicy + legacy ACL write) on the bucket; 404 => bucket missing, recreate it before the ACL task runs.","Validate the Entity format in the cluster spec (e.g. `user:email@domain` style values) — malformed entities are rejected.","Check bucket-level constraints (public access prevention for allUsers/allAuthenticatedUsers entities) and org policy restrictions.","Retry for transient 429/5xx; ensure the bucket task is ordered before the ACL task."],"exampleFix":"// before (invalid entity format)\nEntity: fi.String(\"jane@example.com\")\n// after\nEntity: fi.String(\"user-jane@example.com\")","handlingStrategy":"retry","validationCode":"validEntity := regexp.MustCompile(`^(allUsers|allAuthenticatedUsers|(user|group|domain|serviceAccount|project)-.+)`)\nif !validEntity.MatchString(fi.ValueOf(e.Entity)) {\n    return fmt.Errorf(\"invalid ACL entity %q (expected e.g. user-email@x or group-...)\", fi.ValueOf(e.Entity))\n}\n// also check write permission\nif !hasPerm(\"storage.buckets.setIamPolicy\") { return fmt.Errorf(\"missing storage.buckets.setIamPolicy\") }","typeGuard":"func validACLEntity(e string) bool {\n    return regexp.MustCompile(`^(allUsers|allAuthenticatedUsers|(user|group|domain|serviceAccount|project)-.+)`).MatchString(e)\n}","tryCatchPattern":"if err := kopsUpdate(); err != nil {\n    if strings.Contains(err.Error(), \"error setting GCS bucket ACL\") {\n        if strings.Contains(err.Error(), \"403\") {\n            log.Print(\"grant roles/storage.admin / storage.buckets.setIamPolicy\")\n        } else if strings.Contains(err.Error(), \"404\") {\n            log.Print(\"bucket missing; ensure bucket task runs before ACL task\")\n        }\n    }\n    return err\n}","preventionTips":["Use correct entity prefixes: user-, group-, domain-, serviceAccount-, project-.","Grant storage.buckets.setIamPolicy (roles/storage.admin) to the kOps identity.","Ensure the StorageBucket task creates the bucket before the ACL task applies.","Watch for public-access-prevention policies blocking allUsers entities."],"tags":["gcs","gcp","storage","acl","api-error"],"backgroundTag":"gcs-bucket-api-error","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}