Bootiful GCP: To Production!
Want to learn more about how to use the Spring Cloud Google Cloud Platform? Check out this post where we look at implementing authorization with service accounts.
Join the DZone community and get the full member experience.Join For Free
Hi, Spring fans! In this series, we have looked at the Spring Cloud integration for the Google Cloud Platform, called Spring Cloud GCP. Spring Cloud GCP represents a joint effort between Google and Pivotal that endeavors to provide a first-class experience for Spring Cloud developers when using the Google Cloud Platform. Pivotal Cloud Foundry users will enjoy an even easier integration with the GCP service broker. I wrote these installments with input from Google Cloud Developer Advocate, and my buddy, Ray Tsang. You can also catch a walkthrough of Spring Cloud GCP in our Google Next 2018 session, Bootiful Google Cloud Platform. Thanks, buddy! As always, I’d love to hear from you if you have feedback.
As we’ve worked through these examples, we’ve relied on the default authentication of the Google Cloud SDKs and Spring Cloud GCP, working with a local installation of the Google Cloud SDK and the
gcloud CLI. Spring Cloud GCP’s auto-configuration configures a
DefaultCredentialsProvider that looks for some way to authenticate. Everything’s worked fine on our local machine so far, because we ran the interactive authentication prompt and confirmed on the Google Cloud website the linking of our authorities to this application. But, what if you want to run tests in a CI environment or deploy the application to a cloud platform?
We need a way to convey our authorization when running in these environments. We can do this on Google Cloud using service accounts. The process is explained here. The gist is that you will need to describe, as narrowly as possible, the privileges your application can have using a Google Cloud service account and then render those credentials into a file that we will feed to the application. First, consider the following:
- The name is arbitrary. You might use a name that reflects the nature of your application.
- Create the service account giving it a name
- Add a role —
roles/owner— to our service binding. You would do well to be more granular in the assignment of your roles.
- Generate a file,
gcp-service-app.json, that contains the key.
The result of this process should be a
gcp-service-app.json, on your local machine.
.jsonfile is a secret! Do not share or lose track of it!
You need to tell the Spring Cloud application where to find this credential. You can pass it to Spring Cloud GCP as a file location or a Base 64-encoded
String. Let’s do the latter. We can use the
spring.cloud.gcp.credentials.encoded-key to convey the Base64-encoded contents of the file we just generated.
This is a secret value, and it will differ from one environment to another. We don’t want it checked into version control, in
src/main/resources/application.properties, and even if we did we’d still need to maintain different environment-specific values. Spring Boot lets us provide overrides when running the application. We could use
application.yml files. We could stash them in the environment-specific Runtime Config. We could provide them as
-D arguments or environment variables when running the application. So, you could easily say
java -Dspring.cloud.gcp.credentials.encoded-key=… -jar .. to provide a value that either contributes a new value to the application or overrides the existing value in
Environment variables are a more natural fit for platforms like Cloud Foundry or Heroku where we don’t necessarily want to have control over how an application is run over its
java incantation. The platform Buildpack does that for us. Let’s look at how we could run the application locally.
#!/bin/bash export SPRING_CLOUD_GCP_CREDENTIALS_ENCODED_KEY=$( cat $GCP_SERVICE_ACCOUNT_KEY_FILE | base64 -w0 ) export SPRING_CLOUD_GCP_PROJECT_ID=$(gcloud config list --format 'value(core.project)') mvn clean spring-boot:run
When you run this script, set the environment variable
SPRING_CLOUD_GCP_CREDENTIALS_ENCODED_KEY before running the application to point to the location of your service account
On my machine, I was able to run that script like this:
GCP_SERVICE_ACCOUNT_KEY_FILE=/home/jlong/keys/gcp-service-account.json ./run.sh. Your local path for the
.json file will most likely vary.
You can translate those environment variables as needed for your particular CI environment. Once your application has been tested and integrated, it’s off to production! For me, production is Cloud Foundry (running on top of Google Cloud, no less). Here’s a script that deploys the application to the Cloud Foundry instance in which I’m authenticated.
#!/usr/bin/env bash mvn -DskipTests=true clean package cf d -f $APP_NAME cf push --no-start --random-route -p $JAR $APP_NAME cf set-env $APP_NAME SPRING_CLOUD_GCP_CREDENTIALS_ENCODED_KEY "$( cat $GCP_SERVICE_ACCOUNT_KEY_FILE | base64 -w0 )" cf set-env $APP_NAME SPRING_CLOUD_GCP_PROJECT_ID $(gcloud config list --format 'value(core.project)') cf restart $APP_NAME
Warning — this script deletes the existing application. You don’t need to, but it ensures things are cleanly reset.
Here, we push the application, giving it a random route and tell Cloud Foundry to not start it. Then, we specify environment variables for the application.
Finally, we start the application now that we’re done securing it:
Tip: In both
deploy.sh, we used
base64 -w0to encode the
.jsonservice account file in Base64. One of us is running on Linux and the other on OS X. The
-w0operand ensures that the Base64 encoded file isn’t hard-wrapped and that it is one contiguous line of text when running on Linux against the
Published at DZone with permission of Josh Long, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.