Google Cloud has recently added Custom Domain support, including managed SSL certificates, to their Cloud Run fully managed serverless-with-containers offering.

Another new feature is Secret Manager which allows for secure storage, retrieval and versioning of sensitive information such as passwords and API keys.

In this blog post I will explore both of these new features. I will first add a custom domain to the Cloud Run service that was set up in a previous blog post, then proceed to move secrets to Secret Manager.

 

1. Adding a custom domain to the Cloud Run service

Prerequisites:

  • All the steps in .NET Core on Google Cloud must be completed, in a region that supports mapping custom domains to Cloud Run, such as us-central1europe-west1, or asia-northeast1Importantly, australia-southeast1, which was used in that post, does not support it yet (as of September 2020).
  • Also, you will need to purchase (or already own) an Internet domain name.

1. Open Cloud Run.

Cloud Run screen

2 .Click “Manage custom domains”.

Domain mappings page

3. On the “Domain mappings” page, click "Add mapping".

Service to map to: ehop-on-web (us-central1)

Verified domain: Select "Verify a new domain".

Base domain to verify: example.com (replace with your own domain)

Add mapping screen

Select a verified domain dropdown

Base domain to verify page

4. Click “Verify in Webmaster Central” and follow the instructions in order to verify your domain. The instructions will likely require you to log in to your domain registrar's administration interface.

  • From my experience, verifying a domain using the default method (“DNS TXT record”) with namecheap.com as the domain registrar was quite easy and it took only a minute or so for the domain to show up as verified in Google Cloud.
  • Alternatively, buy a domain from Google Domains (Google’s Internet domain name registration service), as it will then be pre-verified.

Webmaster Central domain name provider selection page

Webmaster Central domain verification page

5. Once the domain is verified, back in the “Add mapping” form, the last step is to Update DNS record:

  • Still logged in to your domain registrar's administration interface, add the records listed here to your domain. Since we are mapping the root domain (the “naked” domain, e.g. example.com as opposed to www.example.com) the records will be A records and AAAA records.
  • If mapping a subdomain (www or other), a CNAME record will be required instead.

Add mapping page

6. Once done updating the records at your domain registrar, click the Done button.

7. After a while, usually less than an hour, the domain mapping should be complete and your Cloud Run service will now be available at your own domain, e.g. https://example.com.

8. Navigate to your own domain using Firefox and the Modify Header Value (HTTP Headers) add-on as outlined in the previous blog post .NET Core on Google Cloud, but this time adding the Authorization header to your own domain, e.g. https://example.com using the Modify Header Value (HTTP Headers) add-on. As before, generate a token using gcloud auth print-identity-token.

 

2. Secret Manager

Prerequisites:

We will now extend the previous ASP.NET Core Web application with SQL Server setup, where the database connection strings were stored as an insecure manner.

We will use Google Secret Manager to improve the security of this setup.

1. Open Secret Manager

Secret Manager introduction page

2. Click Enable

3. Click Create Secret

Secret Manager page

4. Enter the secret details:

Name: ConnectionStrings__CatalogConnection

Secret value: Server=PRIVATE_IP_ADDRESS_OF_SQL_SERVER_INSTANCE;User Id=sqlserver;Password=PASSWORD_FROM_CREATE_SQL_SERVER_INSTANCE_STEP;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;

Create secret page

5. Click "Create secret"

Secret details page

6. Repeat the above for the second connection string. Use the following secret details:

Name: ConnectionStrings__IdentityConnection

Secret value: Server=PRIVATE_IP_ADDRESS_OF_SQL_SERVER_INSTANCE;User Id=sqlserver;Password=PASSWORD_FROM_CREATE_SQL_SERVER_INSTANCE_STEP;Initial Catalog=Microsoft.eShopOnWeb.Identity;

7. Next we need to grant the Cloud Build Service Account access to read the secrets in Secret Manager. Open IAM.

IAM page

8. Click the edit permissions icon at the right side of the Cloud Build Service Account IAM entry

Cloud Build Service Account IAM entry

9. Click "Add another role"


Edit permissions page

10. In the role selector, search for "secret" and select the role "Secret Manager Secret Accessor"

Role selection

Secret Manager Secret Accessor role selected

11. Click Save

Cloud Build Service Account IAM entry, now with Secret Manager Secret Accessor role added

12. In the list of IAM entries, verify that the Cloud Build Service Account now has the new role "Secret Manager Secret Accessor"

13. Next, we need to use the new secrets in Cloud Build as part of the deploy process for Cloud Run

The preferred approach would be to store the connection strings in Google Secret Manager only, but unfortunately as of now there is no support for populating environment variables on the container instance directly from Secret Manager.

As a temporary measure until such a feature becomes available (Google is reportedly looking into it), we will follow the indirect approach of populating the environment variable definitions in the Cloud Run service deployment settings from Secret Manager.

We will need to update the cloudbuild.yaml file, specifically, the gcr.io/google.com/cloudsdktool/cloud-sdk step will need to be updated

from

  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    args:
      - run
      - deploy
      - $_SERVICE_NAME
      - "--platform=managed"
      - "--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"
      - >-
        --labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS
      - "--region=$_DEPLOY_REGION"
      - "--quiet"
    id: Deploy
    entrypoint: gcloud

to

  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    args:
      - "-c"
      - |
        gcloud run deploy $_SERVICE_NAME \
        --platform=managed \
        --image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA \
        --labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS \
        --region=$_DEPLOY_REGION \
        --set-env-vars="ASPNETCORE_URLS=http://*:8080,ConnectionStrings__CatalogConnection=$(gcloud secrets versions access --secret=ConnectionStrings__CatalogConnection latest),ConnectionStrings__IdentityConnection=$(gcloud secrets versions access --secret=ConnectionStrings__IdentityConnection latest)" \
        --quiet
    id: Deploy
    entrypoint: bash

14. Push the updated cloudbuild.yaml file to the master branch, and a Cloud Build will automatically trigger and yield a new Cloud Run deployment automatically after 5-10 minutes. There will be no functional differences, but the secrets will now have been populated from Secret Manager as part of the build process.

 

Conclusion

Building on the setup from a previous post, we now have a custom domain configured for our ASP.NET web application running on Google Cloud.

Also, Google Cloud automatically configured a managed SSL certificate under the hood when we configured a custom domain, so the website can be securely accessed using https.

We have also reconfigured the setup so that a secret manager is used to store secrets in a more secure manner.