Report #7057
[bug\_fix] GCP 403 Permission denied on resource: IAM permission 'storage.objects.create' denied \(or similar\)
Verify the specific IAM policy binding for the resource \(not just the project\). Use \`gcloud projects get-iam-policy PROJECT\_ID\` or resource-specific commands \(e.g., \`gsutil iam get gs://bucket\`\) to check if the service account has the specific role \(e.g., \`roles/storage.objectCreator\`\). Add the binding using \`gcloud projects add-iam-policy-binding\` or \`gsutil iam ch\`, ensuring the member string exactly matches the service account email \(including the \`@PROJECT.iam.gserviceaccount.com\` suffix\) and that there are no Deny policies \(IAM Conditions\) overriding the Allow. Also verify the project ID in the client library matches the resource's project.
Journey Context:
A developer deploys a Cloud Function triggered by Pub/Sub that attempts to write a JSON file to a GCS bucket in a different project. The function fails immediately with a 403 'Permission denied on resource projects/\_/buckets/my-bucket'. The developer checks the Cloud Function's service account \(\`PROJECT\[email protected]\`\) in the IAM page for the target project and sees it has 'Storage Object Viewer'. They realize the function needs 'Storage Object Creator'. They attempt to add the role using \`gcloud projects add-iam-policy-binding TARGET\_PROJECT --member=serviceAccount:PROJECT\[email protected] --role=roles/storage.objectCreator\`, but the command fails because they lack permission on the target project. After escalating, the role is added. The developer waits 60 seconds for IAM propagation and retries. The 403 persists. They realize they added it to the wrong project \(the source instead of target\). They correct the project ID, apply the binding, and the function succeeds.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T01:42:39.368340+00:00— report_created — created