<p>I have a GKE Autopilot cluster with one service to publish a message to GCP Pub/Sub topic for testing.</p>
<p>I have created a KSA for the deployment, have used GCP Workload Identity Management to authorize the KSA to act as a GCP Service Account (GSA). Then I gave the GSA the Pub/Sub editor role.</p>
<h3>The following commands are what I used:</h3>
<pre><code>kubectl create serviceaccount KSA_NAME
</code></pre>
<pre><code>gcloud iam service-accounts add-iam-policy-binding GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member &quot;serviceAccount:PROJECT_ID.svc.id.goog[KSA_NAME]&quot;
</code></pre>
<p>But even after doing all of this, I receive the following error when I try to publish a message to the topic.</p>
<pre class="lang-bash prettyprint-override"><code>ERROR:google.cloud.pubsub_v1.publisher._batch.thread:Failed to publish 1 messages.
Traceback (most recent call last):
  File &quot;/usr/local/lib/python3.7/site-packages/google/api_core/grpc_helpers.py&quot;, line 65, in error_remapped_callable
    return callable_(*args, **kwargs)
  File &quot;/usr/local/lib/python3.7/site-packages/grpc/_channel.py&quot;, line 946, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File &quot;/usr/local/lib/python3.7/site-packages/grpc/_channel.py&quot;, line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: &lt;_InactiveRpcError of RPC that terminated with:
        status = StatusCode.PERMISSION_DENIED
        details = &quot;User not authorized to perform this action.&quot;
        debug_error_string = &quot;UNKNOWN:Error received from peer ipv4:142.250.192.42:443 {grpc_message:&quot;User not authorized to perform this action.&quot;, grpc_status:7, created_time:&quot;2022-11-01T10:27:21.972013149+00:00&quot;}&quot;
&gt;

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File &quot;/usr/local/lib/python3.7/site-packages/google/cloud/pubsub_v1/publisher/_batch/thread.py&quot;, line 272, in _commit
    timeout=self._commit_timeout,
  File &quot;/usr/local/lib/python3.7/site-packages/google/pubsub_v1/services/publisher/client.py&quot;, line 613, in publish
    response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
  File &quot;/usr/local/lib/python3.7/site-packages/google/api_core/gapic_v1/method.py&quot;, line 154, in __call__
    return wrapped_func(*args, **kwargs)
  File &quot;/usr/local/lib/python3.7/site-packages/google/api_core/retry.py&quot;, line 288, in retry_wrapped_func
    on_error=on_error,
  File &quot;/usr/local/lib/python3.7/site-packages/google/api_core/retry.py&quot;, line 190, in retry_target
    return target()
  File &quot;/usr/local/lib/python3.7/site-packages/google/api_core/timeout.py&quot;, line 99, in func_with_timeout
    return func(*args, **kwargs)
  File &quot;/usr/local/lib/python3.7/site-packages/google/api_core/grpc_helpers.py&quot;, line 67, in error_remapped_callable
    raise exceptions.from_grpc_error(exc) from exc
google.api_core.exceptions.PermissionDenied: 403 User not authorized to perform this action.
</code></pre>
<h3>Here is the concerned code:</h3>
<pre class="lang-py prettyprint-override"><code>
from flask import Flask, request, jsonify
app = Flask(__name__)

@app.route('/new_pub/&lt;pages&gt;')
def new_pubsub(pages: int):
    publish_message(pages)
    return json.dumps({'success': True}), 200, {
        'ContentType': 'application/json'}



from google.cloud import pubsub_v1
import json
def publish_message(data):
    d = {&quot;message&quot;: data}
    publisher = pubsub_v1.PublisherClient()
    topic_path = publisher.topic_path(&quot;MY_PROJECT&quot;, &quot;TOPIC_NAME&quot;)
    publisher.publish(topic_path, json.dumps(d).encode('utf-8'))

</code></pre>

<p>Found the issue.</p>
<p>I missed to annotate the KSA with the email address of the IAM service account.</p>
<p>After these two commands,</p>
<pre class="lang-bash prettyprint-override"><code>kubectl create serviceaccount KSA_NAME

gcloud iam service-accounts add-iam-policy-binding GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member &quot;GSA_NAME:PROJECT_ID.svc.id.goog[KSA_NAME]&quot;

</code></pre>
<p>I had to run this command:</p>
<pre class="lang-bash prettyprint-override"><code>kubectl annotate serviceaccount KSA_NAME \
    --namespace default \
    iam.gke.io/gcp-service-account=GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
</code></pre>
