Search code examples
spring-bootgoogle-cloud-platformgoogle-cloud-rungoogle-secret-manager

GCP Secret Manager: Environment variables and secrets not resolved in Spring Boot Application


Following this guide and this code example, I have this in my application-deploy.yaml:

spring:following
  cloud:
    gcp:
      project-id: ${PROJECT_ID}  # Set during build-process (Docker)
      sql:
        enabled: true
        database-name: xxxxxxxxxx
        instance-connection-name: ${sm://CLOUD_SQL_INSTANCE_CONNECTION_NAME}

  datasource:
    driver-class-name: org.postgresql.Driver
    username: ${sm://JDBC_DATABASE_USERNAME}
    password: ${sm://JDBC_DATABASE_PASSWORD}
    name: postgres

and the following dependencies in my pom.xml:

<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter</artifactId>
</dependency>

<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-sql-postgresql</artifactId>
</dependency>

<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-secretmanager</artifactId>
</dependency>

However, after running gcloud run deploy for the service, it immediatelly crahes because the environment variables are not properly resolved:

Caused by: java.lang.IllegalArgumentException: [//CLOUD_SQL_INSTANCE_CONNECTION_NAME] Cloud SQL connection name is invalid, expected string in the form of "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>".
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:145) ~[guava-31.1-jre.jar!/:na]
    at com.google.cloud.sql.core.CloudSqlInstance.<init>(CloudSqlInstance.java:135) ~[jdbc-socket-factory-core-1.11.0.jar!/:na]
    at com.google.cloud.sql.core.CoreSocketFactory.lambda$getCloudSqlInstance$0(CoreSocketFactory.java:165) ~[jdbc-socket-factory-core-1.11.0.jar!/:na]
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]
    ...

The following is in my bootstrap.yaml

spring:
  cloud:
    gcp:
      project-id: ${PROJECT_ID}
      secretmanager:
        project-id: ${PROJECT_ID}

For good measure, and according to another source, I'm throwing in some additional dependency-management in order to make sure `` is available:

<!-- ... -->

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

<!-- ... -->

<dependencyManagement>
    <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring.cloud-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

    </dependencies>
</dependencyManagement>

I have added Secret Manager Admin roles to the SA principals:

enter image description here

What am I missing here?


Solution

  • It turned out to be a simple issue: I wasn't aware that we have to "import" the sm:// prefix in the application.yaml (do yourself a favor and use .yaml instead or .properties):

    spring:
      config:
        import: "sm://"
    

    You can find a full example here: spring-boot-gcp-secret-manager