Secrets like passwords, API keys, are sensitive information should be stored in a secure, encrypted storage, access controlled, and auditable. Some systems opt to use Vault to store these secrets. On Google Cloud Platform, you can use Secret Manager, a managed service, to securely store the secrets, and control access to individual secrets using IAM.
In Spring Boot, you can use Spring Cloud GCP to easily access these secrets by referring to them as any other Spring properties.
In this codelab, you will store a secret in Secret Manager, then build simple Spring Boot microservices and retrieve the secret.
If you see a "request account button" at the top of the main Codelabs window, click it to obtain a temporary account. Otherwise ask one of the staff for a coupon with username/password.
These temporary accounts have existing projects that are set up with billing so that there are no costs associated for you with running this codelab.
Note that all these accounts will be disabled soon after the codelab is over.
Use these credentials to log into the machine or to open a new Google Cloud Console window https://console.cloud.google.com/. Accept the new account Terms of Service and any updates to Terms of Service.
Here's what you should see once logged in:
When presented with this console landing page, please select the only project available. Alternatively, from the console home page, click on "Select a Project" :
While Google Cloud services can be operated remotely from your laptop, in this codelab we will be using Google Cloud Shell, a command line environment running in the Cloud.
If you've never started Cloud Shell before, you'll be presented with an intermediate screen (below the fold) describing what it is. If that's the case, click Continue (and you won't ever see it again). Here's what that one-time screen looks like:
It should only take a few moments to provision and connect to Cloud Shell.
This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory and runs in Google Cloud, greatly enhancing network performance and authentication. Much, if not all, of your work in this codelab can be done with simply a browser or your Chromebook.
Once connected to Cloud Shell, you should see that you are already authenticated and that the project is already set to your project ID.
gcloud auth list
Command output
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
Command output
[core] project = <PROJECT_ID>
If it is not, you can set it with this command:
gcloud config set project <PROJECT_ID>
Command output
Updated property [core/project].
To use Secret Manager, first enable the API:
$ gcloud services enable secretmanager.googleapis.com
Then, create a secret named greeting
, with value of Hello
:
$ echo "Hello" | \
gcloud secrets create greeting \
--data-file=- --replication-policy=automatic
This command uses STDIN
to provide the value to the command line. However, you can also simply put the secret value in a file, an specify the filename for the --data-file
argument.
You can list all the secrets using the gcloud CLI:
$ gcloud secrets list
After Cloud Shell launches, you can use the command line to generate a new Spring Boot application with Spring Initializr:
$ curl https://start.spring.io/starter.tgz -d packaging=jar \
-d dependencies=web,cloud-gcp \
-d bootVersion=2.3.1.RELEASE \
-d baseDir=hello-secret-manager | tar -xzvf - \
&& cd hello-secret-manager
In the pom.xml
, add the Spring Cloud GCP starter dependency:
pom.xml
<project>
...
<dependencies>
...
<!-- Add Secret Manager Starter -->
<dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-secretmanager</artifactId>
</dependency>
</dependency>
</dependencies>
...
</project>
This will automatically configure a Spring Property Source, so that you can simply refer to secrets using a property value, with the prefix of sm://
, for example, sm://greeting
. See Spring Cloud GCP Secret Manager documentation for more detail on the format of the property.
Create a new REST controller by adding a new class:
src/main/java/com/example/demo/HelloSecretController.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloSecretController {
String greeting = "Hi";
@GetMapping("/")
public String hello() {
return greeting + " World!";
}
}
You can start the Spring Boot application normally with the Spring Boot plugin. Let's skip tests for this lab:
$ ./mvnw -DskipTests spring-boot:run
Once the application started, click on the Web Preview icon in the Cloud Shell toolbar and choose preview on port 8080.
After a short wait you should see the result:
You can use the @Value
annotation to refer to the secret property using the sm://
prefix. In the HelloSecretController class, inject the greeting
value using the annotation,
src/main/java/com/example/demo/HelloSecretController.java
package com.example.demo;
...
@RestController
public class HelloSecretController {
@Value("${sm://greeting}")
String greeting;
...
}
You can start the Spring Boot application normally with the Spring Boot plugin. Let's skip tests for this lab:
$ ./mvnw -DskipTests spring-boot:run
Once the application started, click on the Web Preview icon in the Cloud Shell toolbar and choose preview on port 8080.
After a short wait you should see the result:
You can also map the value to a property in application.properties
:
src/main/resources/application.properties
greeting=${sm://greeting}
In HelloSecretController, you can reference to this more generic property name as opposed to a Secret Manager name:
src/main/java/com/example/demo/HelloSecretController.java
package com.example.demo;
...
@RestController
public class HelloSecretController {
@Value("${greeting}")
String greeting;
...
}
You can start the Spring Boot application normally with the Spring Boot plugin. Let's skip tests for this lab:
$ ./mvnw -DskipTests spring-boot:run
Once the application started, click on the Web Preview icon in the Cloud Shell toolbar and choose preview on port 8080.
This technique is useful especially if you use different Spring Boot application profiles. For example, you can create secrets such as greeting-dev
, greeting-staging
, greeting-prod
. And in each of the profile, map to the right greetings.
Create a greeting-prod
secret:
$ echo "Hola" | \
gcloud secrets create greeting-prod \
--data-file=- --replication-policy=automatic
Create an application-prod.properties
file.
src/main/resources/application-prod.properties
greeting=${sm://greeting-prod}
You can start the Spring Boot application normally with the Spring Boot plugin, but with the prod
profile. Let's skip tests for this lab:
$ ./mvnw -DskipTests spring-boot:run -Dspring-boot.run.profiles=prod
Once the application started, click on the Web Preview icon in the Cloud Shell toolbar and choose preview on port 8080.
After a short wait you should see the result:
In this lab, you've created a service that can be configured using secrets stored in Secret Manager by using Spring's property names prefixed with sm://
and injecting the value from applications.properties
file and @Value
annotations..
You learned how to write your first App Engine web application!
This work is licensed under a Creative Commons Attribution 2.0 Generic License.