google-cloud-platformgoogle-cloud-rungoogle-iamgoogle-cloud-iamspring-cloud-gcp

Cloud Run Requires Authentication (Across GCP projects and in Same GCP project)


I am facing these issues, When I try to make my Cloud Run Instances to allow only authenticated invocations (Requires Authentication)

I have multiple GCP Projects and many Cloud Run Instances in each project, Sometimes they have to communicate like this Project A's Cloud Run Instance (CR-A1) has to communicate with Project B's Cloud Run Instance (CR-B1) and also sometimes, Cloud Run Instances present in Project A/B has to communicates other Cloud Run Instances present in the same Project like CR-A1 communicates CR-A2

For Cross Project Communication:

I have created a Service Account (SA-Project A) and used it in Security Service Account for CR-A1 instance while deploying, this Service Account has all required IAM permissions such as Editor, Service Account Token Creator, Sql Admin. And the same Service Account (SA-Project A) has been added in Project B with **Cloud Run Invoker ** IAM Permission

Now when I try to make a Rest call from CR-A1 Instance to CR-B1 . I am getting "Client Not Authorized 401 Error"

I even have created Service Account keys and generated its access token from using default credentials of SA-Project A, and used that access token as Bearer token sent it Http Headers, Still same error,

Can anyone help here Please,

Question may be little complex of typical, Please take some time to understand.

Note : All Cloud Run Instances Requires Authentication.

Thank you

Requirement

Successful Authentication among Cross Project CR API Invocations and also CR API Invocations in Same Project.

Kindly note that, all Cloud Run(CR) Instances requires authentication


Solution

  • Cloud Run Service to Service

    1. Create a service account in 1st GCP Project with IAM permission as Service Account Token Creator, and use this Service Account in Cloud Run Instance 1.
    2. Add the Service Account(Step 1) in 2nd GCP Project IAM, with Cloud Run Invoker.
    3. Create Service Account Keys for Service Account in 1st GCP Project(Step 1),
    4. Store these Servicee Account Keys in GCP Secret Manager for security, and use these keys whenever you want to generate OIDC Token.
    5. Now we can use OIDC Tokens in HttpHeaders with Authorization as "Bearer "

    These OIDC token will authenticate your Rest Call from Cloud Run Instance 1 of 1st GCP Project to Cloud Run Instance 2 of 2nd GCP Project.

    Check below code to generate OIDC token in Java Code

    public String getOIDCTOken(){
         Credentials creds= GoogleCredentials.fromStream(new ByteArrayInputStream(getSAKeysFromSecretManager(<ProjectId>, <secretName>, <version>).getBytes()));
    
         IdTokenCredentials idTokenCredentials = IdTokenCredentials.newBuilder()
                    .setIdTokenProvider((IdTokenProvider) credentials)
                    .setTargetAudience(https://<instance-name>-ID-region.run.app) // Cloud Run Instance 2nd Url 
                    .build();
          AccessToken token = idTokenCredentials.refreshAccessToken();
          return token.getTokenValue();
    } 
    
    //To get secrets from Secret Manager 
    public String getSAKeysFromSecretManager(projectId, secretName, version){
           AccessSecretVersionResponse response;
           try(SecretManagerServiceClient client = create()){
           SecretVersionName secretVersionName= SecretVersionName.of(projectId,secretName,version);
           response = client.accessSecretVersion(secretVersionName)
           }
          return response.getPayload().getData().toStringUtf8();
    }