I have a spring boot application that would run on a local server (not on a google cloud server). I plan to use a service account to allow the application to use Google Cloud Storage and Logging. I created a service account and an api key and downloaded the json file which looks like this:
{
"type": "service_account",
"project_id": "...",
"private_key_id": "....",
"private_key": "-----BEGIN PRIVATE KEY-----\n....\n-----END PRIVATE KEY-----\n",
"client_email": ".....iam.gserviceaccount.com",
"client_id": ".....",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/....."
}
If I start the app in a development environment and set an environment variable that point to the json file, the app works as expected (GOOGLE_APPLICATION_CREDENTIALS).
However, I need to run the application as an init.d service in ubuntu (the application is configured to run as an executable jar). I install my jar file as a service like this:
sudo ln -s /home/<user>/<jarname>.jar /etc/init.d/<service-name>
sudo chmod +x /etc/init.d/<service-name>
sudo update-rc.d <service-name> defaults
sudo service <service-name> start
The init.d service won't see the environment variable I set, so I need to authenticate in another way.
I installed gcloud
and setup the service account like this:
gcloud auth activate-service-account service-account-name@project-name.iam.gserviceaccount.com --key-file=credentials.json
gcloud config set project <projectId>
I also ran gclout init
and it shows the service account I added.
When I run the application, I get a multiple errors: com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: The request is missing a valid API key.
. Looks like something is missing, but I don't know what.
My logback-spring.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/cloud/gcp/autoconfigure/logging/logback-appender.xml" />
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
<!-- Optional : filter logs at or above a level -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<log>application.log</log> <!-- Optional : default java.log -->
<!--resourceType>gae_app</resourceType--> <!-- Optional : default: auto-detected, fallback: global -->
<loggingEventEnhancer>....LoggingEventEnhancer</loggingEventEnhancer>
<flushLevel>INFO</flushLevel> <!-- Optional : default ERROR -->
</appender>
<root level="INFO">
<!-- If running in GCP, remove the CONSOLE appender otherwise logs will be duplicated. -->
<appender-ref ref="CONSOLE"/>
<appender-ref ref="CLOUD"/>
</root>
</configuration>
Running gcloud logging sinks list
works fine on the server, so the permissions should be right.
I know about spring.cloud.gcp.credentials.location=file:/..
, but it doesn't work for me. (Also, this: https://github.com/spring-cloud/spring-cloud-gcp/issues/315#issuecomment-359077878)
I used systemd, it allows me to set any environment variable on service start.
/opt/<name>
or /home/<user>/<name>
/etc/systemd/system/<name>.service
[Unit]
Description=Description text...etc
Wants=network-online.target
After=network.target network-online.target
[Service]
Environment="LOGPATH=/var/<name>/logs"
Environment="GOOGLE_APPLICATION_CREDENTIALS=/path-to-google-json/google/credentials.json"
ExecStartPre=/bin/mkdir -pm 0755 ${LOGPATH}
ExecStart=/opt/<name>/<jar-name>.jar
PIDFile=/run/<name>/<name>%i.pid
Restart=on-abort
RuntimeDirectory=<name>
RuntimeDirectoryMode=755
WorkingDirectory=/opt/<name>
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable <name>.service
sudo systemctl start <name>.service
Status: sudo systemctl status <name>.service
Follow the stdout: sudo journalctl -u <name>.service --follow