Skip to content

Permissions in Google Cloud Platform

Identity & Access Mangement (IAM) lets you create and manage permissions for Google Cloud resources on the Google Cloud Platform (GCP).

Info

Please read through the Google Cloud IAM documentation for a more thorough introduction to IAM and related concepts.

Most services (e.g. PostgreSQL, Cloud Storage / Buckets, BigQuery) offered by NAIS on GCP will automatically be configured with any needed permissions that allows your application to access them.

In cases where you wish to use other services in the Google Cloud Platform not officially supported by NAIS, you will also have to set up permissions that allows your application to access these resources.

Concepts

Permissions

See https://cloud.google.com/iam/docs/overview#permissions.

Roles

See https://cloud.google.com/iam/docs/overview#roles.

See also Google Cloud Predefined Roles for a list of predefined roles.

Policy Granularity

Google Cloud resources are organized hierarchically. A policy that grants a principal (a user or a service account) any permissions to a resource will thus also apply to any children of said resource. This allows for fine-grained access control.

For example, you may grant the roles/pubsub.subscriber role for your application at the project-level. This means that the application will have the role for any PubSub subscription for the entire project. If you instead grant the same role at the subscription-level, the application would only have access to a specific PubSub subscription.

See https://cloud.google.com/iam/docs/overview#resource-hierarchy.

Service Accounts

Applications running on Kubernetes (which is the runtime platform at the core of NAIS) each have an associated Kubernetes Service Account (KSA). This account provides an identity for the individual applications running on the platform.

To access the various Google Cloud resources, a Google Service Account (GSA) is required. For simplicity's sake, NAIS automatically provisions Google Service Accounts for each application that is deployed to the GCP clusters. The Google Service Account is uniquely identified by its email address:

<service-account-name>@<project-id>.iam.gserviceaccount.com

You can find this email for your application's GSA by querying the clusters. Ensure that you have set up access to the Kubernetes clusters first, then run the following command:

kubectl get sa <app> \
  -ojsonpath="{.metadata.annotations.\iam\.gke\.io/gcp-service-account}" \
  -n <namespace>

Authentication

In order to authenticate using the identity of the Google Service Account, we need a set of credentials. The documentation on Google Cloud Platform mention several best practices for managing such credentials. One of these practices is to use workload identity.

Workload identity works by essentially creating a mapping between a Kubernetes Service Account and a Google Service Account. In other words, your application can authenticate itself with the Kubernetes Service Account credentials, and access Google Cloud APIs with the identity of the Google Service Account.

If your application uses the official Google Client Libraries, the library will automatically discover and handle authentication.

For local development, you can acquire credentials for your own user account by using Application Default Credentials. Your application will then automatically discover and use these when running locally. Ensure that your user has the required permissions or roles to access the Google Cloud resources and APIs used by your application.

Granting permissions

There are multiple ways of granting your application access to Google Cloud resources.

Declaratively

The NAIS application manifest allows for basic configuration to grant roles to your application roles. This can either apply for a specific resource or for the entire project. To do so, you need the following information:

Field Description Example value
Kind The Config Connector Resource Name. See the list of supported resources. KMSCryptoKey
APIVersion The apiVersion associated with the above kind. See the list of resources, find the matching kind and see the sample YAMLs to find the correct apiVersion value. kms.cnrm.cloud.google.com/v1beta1 (source)
Role See predefined roles for a list of available predefined roles for each resource. cloudkms.cryptoKeyEncrypterDecrypter
Name The resource name or reference in Google Cloud. Not needed for project-wide access. See the table for external reference formats. projects/<project-ID>/locations/<location>/keyRings/<key-ring-ID>/cryptoKeys/<key-name>

See also the resource reference table below for some common combinations.

For example:

spec:
  gcp:
    permissions:
      - resource:
          apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
          kind: Project
        role: roles/cloudkms.cryptoKeyEncrypterDecrypter

The above example grants your application the role roles/cloudkms.cryptoKeyEncrypterDecrypter at the project level. This means that your application will have this role for any Cloud KMS resource in your project.

Note that the name field is omitted as it is automatically inferred.

If you only want your application to be able to access a specific key in Cloud KMS, the example would look like this:

spec:
  gcp:
    permissions:
      - resource:
          apiVersion: kms.cnrm.cloud.google.com/v1beta1
          kind: KMSCryptoKey
          name: locations/europe-north1/keyRings/<some-key-ring>/cryptoKeys/<some-key>
        role: roles/cloudkms.cryptoKeyEncrypterDecrypter

Note that you can omit the project/<project ID>/-prefix from the name value, as shown in the example. The prefix is automatically inferred by the NAIS platform.

Resource Reference

The table below summarizes the combinations of apiVersion, kind and name formats for a few of the most commonly used resources:

Kind APIVersion Name
Project resourcemanager.cnrm.cloud.google.com/v1beta1 <empty>
KMSCryptoKey kms.cnrm.cloud.google.com/v1beta1 locations/{{location}}/keyRings/{{key_ring_id}}/cryptoKeys/{{key_name}}
KMSKeyRing kms.cnrm.cloud.google.com/v1beta1 locations/{{location}}/keyRings/{{key_ring_id}}
PubSubSubscription pubsub.cnrm.cloud.google.com/v1beta1 subscriptions/{{subscription_name}}
PubSubTopic pubsub.cnrm.cloud.google.com/v1beta1 topics/{{topic_name}}
SecretManagerSecret secretmanager.cnrm.cloud.google.com/v1beta1 secrets/{{secret_id}}

Debugging

List the IAMPolicyMembers created for your application and check for any errors:

kubectl get iampolicymember -l app=my-app
NAME                               AGE     READY   STATUS               STATUS AGE
my-app-17135ea6bddbfb87-0c3df6d4   47h     True    UpToDate             47h
my-app-2c73ffe043d5bdfb-3afabf2b   46h     False   DependencyNotReady   46h
my-app-5807c739790a971a-65560940   4d12h   True    UpToDate             4d12h

Inspect the failing IAMPolicyMember resource by describing the resource and looking for the events:

kubectl describe iampolicymember my-app-2c73ffe043d5bdfb-3afabf2b
Name:         my-app-2c73ffe043d5bdfb-3afabf2b
Kind:         IAMPolicyMember
...
Events:
  Type     Reason              Age                    From                        Message
  ----     ------              ----                   ----                        -------
  Warning  DependencyNotReady  2m27s (x2911 over 4d)  iampolicymember-controller  reference StorageBucket my-namespace/my-app-bucket is not ready

Cloud Console

See the Google Cloud documentation for granting access to either projects or lower level resources.


Last update: 2022-07-11
Created: 2022-07-07