What Pub/Sub permissions do I need to create a subscription?

I have a Python 3.9 Cloud Function that is using the Cloud SDK to create Pub/Sub subscriptions. I'm having trouble determining what permissions I need to create a Pub/Sub subscription. The documentation shows the roles/pubsub.editor should be sufficient for creating subscriptions and attaching them to topics. However, when giving my service account being used by the Cloud Function the pubsub.editor role at the project level, I get this error when trying to create a subscription:

 

 

{
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "status": {
      "code": 7,
      "message": "User not authorized to perform this action."
    },
    "authenticationInfo": {
      "principalEmail": "person-api@<redacted>.iam.gserviceaccount.com",
      "serviceAccountDelegationInfo": [
        {
          "firstPartyPrincipal": {
            "principalEmail": "service-<redacted>@gcf-admin-robot.iam.gserviceaccount.com"
          }
        }
      ],
      "principalSubject": "serviceAccount:person-api@<redacted>.iam.gserviceaccount.com"
    },
    "requestMetadata": {
      "callerIp": "<redacted>",
      "callerSuppliedUserAgent": "grpc-python/1.50.0 grpc-c/28.0.0 (linux; chttp2),gzip(gfe)",
      "requestAttributes": {
        "time": "2022-10-31T22:24:28.743102902Z",
        "auth": {}
      },
      "destinationAttributes": {}
    },
    "serviceName": "pubsub.googleapis.com",
    "methodName": "google.pubsub.v1.Subscriber.CreateSubscription",
    "authorizationInfo": [
      {
        "resource": "projects/<redacted>",
        "permission": "pubsub.subscriptions.create",
        "granted": true,
        "resourceAttributes": {}
      }
    ],
    "resourceName": "projects/<redacted>/subscriptions/person-api-webhook-5a5e7a18-cd48-44e5-b241-d84b97484fda",
    "request": {
      "retainAckedMessages": true,
      "topic": "projects/<redacted>/topics/person-api-webhook-events",
      "ackDeadlineSeconds": 10,
      "name": "projects/<redacted>/subscriptions/person-api-webhook-5a5e7a18-cd48-44e5-b241-d84b97484fda",
      "@type": "type.googleapis.com/google.pubsub.v1.Subscription",
      "messageRetentionDuration": "604800s",
      "pushConfig": {
        "pushEndpoint": "<redacted>"
      }
    }
  },
  "insertId": "<redacted>",
  "resource": {
    "type": "pubsub_subscription",
    "labels": {
      "subscription_id": "projects/<redacted>/subscriptions/person-api-webhook-5a5e7a18-cd48-44e5-b241-d84b97484fda",
      "project_id": "<redacted>"
    }
  },
  "timestamp": "2022-10-31T22:24:28.735840698Z",
  "severity": "ERROR",
  "logName": "projects/<redacted>/logs/cloudaudit.googleapis.com%2Factivity",
  "receiveTimestamp": "2022-10-31T22:24:29.203119649Z"
}

 

 

I also tried giving the service account the pubsub.admin role and continued to get the same error. It wasn't until I assigned the service account the project editor role (don't worry, just for troubleshooting purposes) that I was able to successfully create a subscription from my cloud function.

Now for the extra weird part: I'm able to create a subscription from the command line while impersonating the service account when the service account only has the pubsub.editor role at the project level: gcloud pubsub subscriptions create my-subscription --impersonate-service-account=person-api@<redacted>.iam.gserviceaccount.com --topic=person-api-webhook-events

Additionally, if I login to the GCP console with a user that only has the pubsub.editor role, I'm also able to create a subscription. It seems like this issue is scoped to creating subscriptions from Cloud Functions.

Here is my python code in case it might be relevant to the issue. I hope it gives enough information to replicate the issue. google-cloud-pubsub version is 2.11.1

 

 

from google.cloud import pubsub_v1
from google.cloud.pubsub_v1.types import Subscription, PushConfig, ExpirationPolicy, RetryPolicy, Duration, DeleteSubscriptionRequest
project_id = "<redacted>"
subscriber = pubsub_v1.SubscriberClient()
subscription_name = subscriber.subscription_path(project_id, "person-api-webhook-5a5e7a18-cd48-44e5-b241-d84b97484fda")
oidc_token = PushConfig.OidcToken(audience="https://<redacted>.cloudfunctions.net/webhook_proxy", service_account_email="person-api-webhook-subscriber@<redacted>.iam.gserviceaccount.com")
topic_id = "projects/<redacted>/topics/person-api-webhook-events"
subscription_request = Subscription(
    name=subscription_name,
    topic=topic_id,
    push_config=PushConfig(push_endpoint="https://<redacted>.cloudfunctions.net/webhook_proxy/5a5e7a18-cd48-44e5-b241-d84b97484fda", oidc_token=oidc_token),
    message_retention_duration=Duration(seconds=604800),
    retain_acked_messages=True,
    expiration_policy=ExpirationPolicy(ttl=Duration(seconds=2678400)),
    ack_deadline_seconds=10,
    filter=None,
    enable_exactly_once_delivery=False,
    enable_message_ordering=False,
    dead_letter_policy=None,
    retry_policy=RetryPolicy(
        minimum_backoff=Duration(seconds=10),
        maximum_backoff=Duration(seconds=600)
    )
)
with subscriber:
    subscriber.create_subscription(request=subscription_request)

 

 

 

Solved Solved
2 9 5,959
1 ACCEPTED SOLUTION

Just to close the loop on this, the issue was that the service account we were using to create the pubsub subscription did not have the `iam.serviceAccounts.actAs` permission. This is documented here: 

View solution in original post

9 REPLIES 9

Make sure that the client you are using is authorized to publish to Pub/Sub. See details here.

If your client belongs to the same project as the topic, typically it won't require additional access control configuration. Make sure that your client is authenticated properly.

To rule out any error, add the pubsub.editor role to said Service Account at both projects.

Thank you for the reply. We have a custom service account used with the cloud function, and we apply roles directly to that service account.

All of this is taking place in the same project (i.e. no cross-project interactions).

What's odd to me is that the logs seem to show that the service account has permission (granted=true), but the action of creating a subscription is ultimately denied. Do you know why this is?

"authorizationInfo": [
      {
        "resource": "projects/<redacted>",
        "permission": "pubsub.subscriptions.create",
        "granted": true,
        "resourceAttributes": {}
      }
    ],

Hi, Jared,


I have noticed you are using Python 3.9 for your Cloud Function. You are also using grpc-python/1.50.0, which supports Python up to 3.11, see.

Could you downgrade your Python version to 3.11, or upgrade your grpc and try again?

I will be waiting for your response.

I'm not sure I understand your suggestion. GCF does not support 3.11. https://cloud.google.com/functions/docs/concepts/python-runtime

Sorry for the inconvenience, Jared.

I meant Python 3.10 (recommended).

I tried using Python 3.10 and ran into the same error.

It seems like I am able to create the subscription if I remove the pushConfig (line 11 in my original example). The service account that this Cloud Function is using seems to be lacking permissions to create a subscription if  the subscription contains a pushConfig.

I can create a subscription from the cloud function if the service account has a project editor role, but not if it has the pubsub admin role. It seems like the default pubsub IAM roles do not contain a permission needed to create the subscription (but only from Cloud Functions?), but the project Editor role does.

I'd prefer not to have to brute force test every permission, but I'm not sure what else to do at this point. Any suggestions?

Hi, Jared,

I think we’ve found substantial information about the roles. See.

If your project was created on or before April 8, 2021, you must grant the roles/iam.serviceAccountTokenCreator role to the Google-managed service account service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com on the project in order to allow Pub/Sub to create tokens. However, if your project was created after that date, you don't need to grant this role because the service account has the roles/pubsub.serviceAgent role with identical permissions.

If this does not resolve the issue, your project would need to be inspected by support.

This can be done over a support case.

If not, I suggest you create a Public Issue Tracker.

Just to close the loop on this, the issue was that the service account we were using to create the pubsub subscription did not have the `iam.serviceAccounts.actAs` permission. This is documented here: 

Thanks for closing the loop! Glad you found the solution you were seeking. 🤞