Use Google Secret Manager to Store MySQL Credentials

Learn how to use Google Secret Manager

Authors: John Shingler, Sergio del Amo

Micronaut Version: 4.3.7

1. Getting Started

In this guide, we will create a Micronaut application written in Java.

This guide will demonstrate how to use Google Secret Manager to store the configurations for a Micronaut Data JDBC application.

Instead of storing the database url, username and password in plan text or environment variables. A secret manager provides a convenient way to stores API keys, passwords, certificates, and other sensitive data while improving security.

2. What you will need

To complete this guide, you will need the following:

3. Costs

This guide uses paid services; you may need to enable Billing in Google Cloud to complete some steps in this guide.

4. Google Cloud Platform

Signup for the Google Cloud Platform

4.1. Cloud SDK

Install the Cloud SDK CLI for your operating system.

Cloud SDK includes the gcloud command-line tool. Run the init command in your terminal:

gcloud init

Log in to your Google Cloud Platform:

gcloud auth login

4.2. Google Cloud Platform Project

Create a new project with a unique name (replace xxxxxx with alphanumeric characters of your choice):

gcloud projects create micronaut-guides-xxxxxx
In GCP, project ids are globally unique, so the id you used above is the one you should use in the rest of this guide.

Change your project:

gcloud config set project micronaut-guides-xxxxxx

If you forget the project id, you can list all projects:

gcloud projects list

5. Creating the Application

Download the complete solution of the Access a database with Micronaut Data JDBC guide.

This guide is a companion to either the above guide or the Connect a Micronaut Data JDBC Application to a Google MySQL Database.

6. Dependencies

6.1. Update the Application to use Google’s Secret Manager

The micronaut-gcp subproject provides integration between Micronaut apps and the Google Cloud, including using Secret Manager as a distributed configuration source.

Add the following dependency to your build:

pom.xml
<dependency>
    <groupId>io.micronaut.gcp</groupId>
    <artifactId>micronaut-gcp-secret-manager</artifactId>
    <scope>compile</scope>
</dependency>
Native compile requires a supplemental library. See Micronaut GCP: Generating Native Executables for instructions on adding it to your build.

The Micronaut Framework reads distributed configurations, like secrets, at start-up, but needs to be instructed to do so.

7. Distributed Configuration

7.1. Enable Distributed Configuration

Create a bootstrap.properties file in the resources directory to enable distributed configuration. Add the following:

src/main/resources/bootstrap.properties
(1)
micronaut.application.name=micronautguide
(2)
micronaut.config-client.enabled=true
1 Set the application name in bootstrap.properties instead of application.properties so that it is available when reading configuration from distributed sources. properties
2 Set micronaut.config-client.enabled=true which is used to read and resolve configuration from distributed sources.

7.2. Clean up Application Configuration

If application.properties sets micronaut.application.name, remove it. You moved it to bootstrap.properties.

src/main/resources/application.properties
micronaut.application.name=micronautguide

7.3. Disable Distributed Configuration for Test

You can disable distributed configuration in a test by annotating a test with:

@Property(name = "micronaut.config-client.enabled", value = StringUtils.FALSE)
@MicronautTest

8. Google’s Secret Manager

8.1. Move JDBC URL, username and password from the Application Configurations

Create a file named datasource-info.yml in the project root directory, or elsewhere on your filesystem, to contain the JDBC connection information.

Do not add this file to source control, since it contains sensitive information.

Add the following:

datasource-info.yml
datasources:
  default:
    url: <JDBC_URL>
    username: <USER_NAME>
    password: <USER_PASSWORD>

8.1.1. Examples of datasource-info.yml:

Docker MySQL configurations example for Access a database with Micronaut Data JDBC
datasources:
  default:
    url: jdbc:mysql://localhost:3306/db
    username: root
    password: ''
Google Cloud MySQL configurations example for Connect a Micronaut Data JDBC Application to a Google MySQL Database
datasources:
  default:
    url: jdbc:mysql://34.xxx.xxx.65:3306/demo
    username: jdbcUser
    password: userSecretPassword

8.2. Clean up of the Application Configurations

Remove the following from the application.properties.

src/main/resources/application.properties
- micronaut.application.name=micronautguide
- datasources.default.url=${JDBC_URL:`jdbc:mysql://localhost:3306/db`}
- datasources.default.username=${JDBC_USER:root}
- datasources.default.password=${JDBC_PASSWORD:}
datasources.default.dialect=MYSQL
datasources.default.driver-class-name=${JDBC_DRIVER:com.mysql.cj.jdbc.Driver}
flyway.datasources.default.enabled=true

8.3. Add Configurations to Google Secret Manager

Add the new datasource-info.yml configuration file to the secret manager.

gcloud secrets create application \
  --data-file=path/to/datasource-info.yml

You might be prompted to enable the Google SQL Admin API

API [secretmanager.googleapis.com] not enabled on project [<project-id>].

Would you like to enable and retry (this will take a few minutes)? (y/N)?

See Google Cloud Secret Manager Support’s "Configuration file resolution" section for other built-in and manual configured ways that configurations files can be named other than application as above.

8.4. Stand Alone Secret (Optional)

There are many cases where you might just need a secret (key and value) in your application. Helpful if something changes often or is different per environment.

With Google Secret Manager you can:

  1. Create a file that just contains the password, like above.

  2. Use the Google Cloud Console to add the secret.

  3. Add a secret directly on the command line, but this is discouraged because the plaintext will appear in your shell history.

For this example, let’s move the user’s password to its own secret, using option 3.

On Linux and Mac:

printf "<PASSWORD>" | gcloud secrets create jdbc_password --data-file=-

On Windows:

Write-Output "<PASSWORD>" | gcloud secrets create my-secret --data-file=-

All line breaks and leading and trailing whitespace are stripped from the secret at runtime.

Add the following to the bootstrap.properties

src/main/resources/bootstrap.properties
gcp.secret-manager.keys[0]=jdbc_password

This is needed, because Google’s Secret Manager does not offer a hierarchical approach. Therefor we need to tell the application which keys to read.

The secret jdbc_password will me mapped to the property sm.jdbc.password. And can be used like @Property(name="sm.jdbc.password") within the application.

Update the datasource-info.yml file to:

datasource-info.yml
datasources:
  default:
    url: <JDBC_URL>
    username: <USER_NAME>
    password: ${sm.jdbc.password}

Finally, update the secret.

gcloud secrets versions add application \
  --data-file=path/to/datasource-info.yml

8.5. Fix Test Configurations

Distributed configurations have a higher precedence (priority) than application configurations found in application_<env>.properties. Meaning if we tested the application now, the datasource configuration in Google’s Secret Manager would be used and not the Test Container configuration in application_test.properties.

With Secret Manager:

Add application-test.properties to secret manager:

gcloud secrets create application_test \
  --data-file=src/test/resources/application-test.properties
Without Secret Manager:

Create a bootstrap-test.properties file or rename application_test.properties to bootstrap-test.properties and add:

src/test/resources/bootstrap_test.properties
micronaut.config-client.enabled=true

9. Running the Application

To run the application, use the ./mvnw mn:run command, which starts the application on port 8080.

You might get this error message when running your application:
"Message: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information."

If you are developing locally you can do:

gcloud auth application-default login

However, it is strongly recommended that you set up a service account. Follow the instructions in the link above and Micronaut GCP setup instructions for creating and configuring the service account.

You can test the application in a web browser or with cURL.

Run from a terminal window to create a Genre:

curl -X "POST" "http://localhost:8080/genres" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{ "name": "music" }'

and run this to list the genres:

curl http://localhost:8080/genres/list

10. Cleaning Up

After you’ve finished this guide, you can clean up the resources you created on Google Cloud Platform so you won’t be billed for them in the future. The following sections describe how to delete or turn off these resources.

10.1. Deleting the project

The easiest way to eliminate billing is to delete the project you created for the tutorial.

Deleting a project has the following consequences:

  • If you used an existing project, you’ll also delete any other work you’ve done in the project.

  • You can’t reuse the project ID of a deleted project. If you created a custom project ID that you plan to use in the future, you should delete the resources inside the project instead. This ensures that URLs that use the project ID, such as an appspot.com URL, remain available.

  • If you are exploring multiple tutorials and quickstarts, reusing projects instead of deleting them prevents you from exceeding project quota limits.

10.1.1. Via the CLI

To delete the project using the Cloud SDK, run the following command, replacing YOUR_PROJECT_ID with the project ID:

gcloud projects delete YOUR_PROJECT_ID

10.1.2. Via the Cloud Platform Console

In the Cloud Platform Console, go to the Projects page.

In the project list, select the project you want to delete and click Delete project. After selecting the checkbox next to the project name, click Delete project

In the dialog, type the project ID, and then click Shut down to delete the project.

Deleting or turning off specific resources

You can individually delete or turn off some of the resources that you created during the tutorial.

11. Next Steps

Read more about Micronaut Data.

Read more about Micronaut GCP integration.

12. License

All guides are released with an Apache license 2.0 license for the code and a Creative Commons Attribution 4.0 license for the writing and media (images…​).