blob: 7782b111ad56e37faa577061e51ae8ca6267dd52 [file] [log] [blame]
== GCP Secrets Manager Vault Example with PostgreSQL
In this sample you'll use the GCP Secrets Manager Vault Properties Source
=== Install JBang
First install JBang according to https://www.jbang.dev
When JBang is installed then you should be able to run from a shell:
[source,sh]
----
$ jbang --version
----
This will output the version of JBang.
To run this example you can either install Camel on JBang via:
[source,sh]
----
$ jbang app install camel@apache/camel
----
Which allows to run CamelJBang with `camel` as shown below.
=== Setup the GCP Secret Manager
First of all you'll need to install the gcloud cli from https://cloud.google.com/sdk/docs/install
Once the Cli has been installed we can proceed to login and to setup the project with the following commands:
[source,sh]
----
gcloud auth login
----
and
[source,sh]
----
gcloud projects create gcp-sec-refresh --name="GCP Secret Manager Refresh"
----
The project will need a service identity for using secret manager service and we'll be able to have that through the command:
[source,sh]
----
gcloud beta services identity create --service "secretmanager.googleapis.com" --project "gcp-sec-refresh"
----
The latter command will provide a service account name that we need to export
[source,sh]
----
export SM_SERVICE_ACCOUNT="service-...."
----
Since we want to have notifications about event related to a specific secret through a Google Pubsub topic we'll need to create a topic for this purpose with the following command:
[source,sh]
----
gcloud pubsub topics create "projects/gcp-sec-refresh/topics/pubsub-gcp-sec-refresh"
----
The service account will need Secret Manager authorization to publish messages on the topic just created, so we'll need to add an iam policy binding with the following command:
[source,sh]
----
gcloud pubsub topics add-iam-policy-binding pubsub-gcp-sec-refresh --member "serviceAccount:${SM_SERVICE_ACCOUNT}" --role "roles/pubsub.publisher" --project gcp-sec-refresh
----
We now need to create a subscription to the pubsub-gcp-sec-refresh just created and we're going to call it sub-gcp-sec-refresh with the following command:
[source,sh]
----
gcloud pubsub subscriptions create "projects/gcp-sec-refresh/subscriptions/sub-gcp-sec-refresh" --topic "projects/gcp-sec-refresh/topics/pubsub-gcp-sec-refresh"
----
Now we need to create a service account for running our application:
[source,sh]
----
gcloud iam service-accounts create gcp-sec-refresh-sa --description="GCP Sec Refresh SA" --project gcp-sec-refresh
----
Let's give the SA an owner role:
[source,sh]
----
gcloud projects add-iam-policy-binding gcp-sec-refresh --member="serviceAccount:gcp-sec-refresh-sa@gcp-sec-refresh.iam.gserviceaccount.com" --role="roles/owner"
----
Now we should create a Service account key file for the just create SA:
[source,sh]
----
gcloud iam service-accounts keys create gcp-sec-refresh.json --iam-account=gcp-sec-refresh-sa@gcp-sec-refresh.iam.gserviceaccount.com
----
Modify the application.properties file to point to serviceAccountKey property to the just create gcp-sec-refresh.json file.
Let's enable the Secret Manager API for our project
[source,sh]
----
gcloud services enable secretmanager.googleapis.com --project gcp-sec-refresh
----
If needed enable also the Billing API.
Now it's time to create our hello secret, with topic notification:
[source,sh]
----
gcloud secrets create database --topics=projects/gcp-sec-refresh/topics/pubsub-gcp-sec-refresh --project=gcp-sec-refresh
----
Let's add a value to the secret:
[source,sh]
----
echo -n '{"username":"postgres","password":"mysecretpassword"}' | gcloud secrets versions add database --data-file=- --project=gcp-sec-refresh
----
=== Setup the PostgreSQL container
First of all let's run the container
[source,sh]
----
docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
----
Now look at the container IP address:
[source,sh]
----
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' some-postgres
> 172.17.0.2
----
Use this address into the postgresql-log.yaml file as serverName
Now let's connect to the database and populate it with a table and 3 columns:
[source]
----
CREATE TABLE accounts (
user_id serial PRIMARY KEY,
username VARCHAR ( 50 ) UNIQUE NOT NULL,
city VARCHAR ( 50 ) NOT NULL
);
----
[source,sh]
----
docker exec -it some-postgres psql -h some-postgres -U postgres
psql (15.1 (Debian 15.1-1.pgdg110+1))
Type "help" for help.
postgres=# CREATE TABLE accounts (
user_id serial PRIMARY KEY,
username VARCHAR ( 50 ) UNIQUE NOT NULL,
city VARCHAR ( 50 ) NOT NULL
);
CREATE TABLE
postgres=# INSERT into accounts (username,city) VALUES ('andrea', 'Roma');
INSERT 0 1
postgres=# INSERT into accounts (username,city) VALUES ('John', 'New York');
INSERT 0 1
postgres=# select * from accounts;
user_id | username | city
---------+----------+----------
1 | andrea | Roma
2 | John | New York
(2 rows)
----
=== Setting up the GCP Service account key
In the application.properties you'll need to provide all the needed bits and the path to the just created service account key file. So you should have something like this:
[source,sh]
----
camel.vault.gcp.projectId=gcp-sec-refresh
camel.vault.gcp.serviceAccountKey = file:////gcp-sec-refresh.json
camel.vault.gcp.refreshEnabled=true
camel.vault.gcp.refreshPeriod=60000
camel.vault.gcp.secrets=database*
camel.vault.gcp.subscriptionName=sub-gcp-sec-refresh
camel.main.context-reload-enabled = true
----
=== How to run
Then you can run this example using:
[source,sh]
----
$ camel run postgresql-log.yaml
----
Or run it even shorter:
[source,sh]
----
$ camel run *
----
This will give the following log:
[source,bash]
----
2023-07-06 13:51:47.793 INFO 24893 --- [ main] org.apache.camel.main.MainSupport : Apache Camel (JBang) 3.21.0 is starting
2023-07-06 13:51:48.024 INFO 24893 --- [ main] org.apache.camel.main.MainSupport : Using Java 11.0.16.1 with PID 24893. Started by oscerd in /home/oscerd/workspace/apache-camel/camel-kamelets-examples/jbang/postgresql-gcp-secret-refresh
2023-07-06 13:51:48.036 INFO 24893 --- [ main] mel.cli.connector.LocalCliConnector : Camel CLI enabled (local)
2023-07-06 13:51:51.418 INFO 24893 --- [ main] main.MainAutowiredLifecycleStrategy : Autowired property: dataSource on component: sql as exactly one instance of type: javax.sql.DataSource (org.apache.commons.dbcp2.BasicDataSource) found in the registry
2023-07-06 13:51:51.500 INFO 24893 --- [ main] el.impl.engine.AbstractCamelContext : Apache Camel 3.21.0 (GCPExample) is starting
2023-07-06 13:51:51.724 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : Property-placeholders summary
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] query=select * from accounts;
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] dsBean=dsBean-1
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] delay=90000
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] password=xxxxxx
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] serverName=172.17.0.2
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] databaseName=postgres
2023-07-06 13:51:51.725 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [stgresql-source.kamelet.yaml] username=xxxxxx
2023-07-06 13:51:51.726 INFO 24893 --- [ main] g.apache.camel.main.BaseMainSupport : [log-sink.kamelet.yaml] showStreams=true
2023-07-06 13:51:51.742 INFO 24893 --- [ main] el.impl.engine.AbstractCamelContext : Routes startup (started:3)
2023-07-06 13:51:51.742 INFO 24893 --- [ main] el.impl.engine.AbstractCamelContext : Started route1 (kamelet://postgresql-source)
2023-07-06 13:51:51.742 INFO 24893 --- [ main] el.impl.engine.AbstractCamelContext : Started postgresql-source-1 (sql://select%20*%20from%20accounts;)
2023-07-06 13:51:51.743 INFO 24893 --- [ main] el.impl.engine.AbstractCamelContext : Started log-sink-2 (kamelet://source)
2023-07-06 13:51:51.743 INFO 24893 --- [ main] el.impl.engine.AbstractCamelContext : Apache Camel 3.21.0 (GCPExample) started in 1s992ms (build:119ms init:1s631ms start:242ms JVM-uptime:4s)
2023-07-06 13:51:52.950 INFO 24893 --- [rom%20accounts;] log-sink : Exchange[ExchangePattern: InOnly, BodyType: org.apache.camel.converter.stream.InputStreamCache, Body: {"user_id":1,"username":"andrea","city":"Roma"}]
2023-07-06 13:51:52.955 INFO 24893 --- [rom%20accounts;] log-sink : Exchange[ExchangePattern: InOnly, BodyType: org.apache.camel.converter.stream.InputStreamCache, Body: {"user_id":2,"username":"John","city":"New York"}]
----
=== Modify the secret
You can list the secrets in use from the GCP secret manager service:
[source,sh]
----
camel get vault
----
While the integration is running you could modify the secret and the integration will reload automatically
In our example we want to change the password for postgres user and to do that we can do:
[source,sh]
----
cat alter-user.sql | docker exec -i some-postgres psql -U postgres
----
and at the same time modify the secret in GCP:
[source,sh]
----
echo -n '{"username":"postgres","password":"password123"}' | gcloud secrets versions add database --data-file=- --project=gcp-sec-refresh
----
Now, get back, to the running Camel application and wait for the reloading.
You should see something like:
[source,sh]
----
.
.
.
.
2023-07-06 14:01:05.185 INFO 25531 --- [ Gax-8] nager.vault.PubsubReloadTriggerTask : Update for GCP secret: projects/119110008178/secrets/database detected, triggering CamelContext reload
2023-07-06 14:01:05.185 INFO 25531 --- [ Gax-8] upport.DefaultContextReloadStrategy : Reloading CamelContext (GCPExample) triggered by: org.apache.camel.component.google.secret.manager.vault.PubsubReloadTriggerTask$FilteringEventMessageReceiver@46d2a059
2023-07-06 14:01:06.549 INFO 25531 --- [rom%20accounts;] log-sink : Exchange[ExchangePattern: InOnly, BodyType: org.apache.camel.converter.stream.InputStreamCache, Body: {"user_id":1,"username":"andrea","city":"Roma"}]
2023-07-06 14:01:06.550 INFO 25531 --- [rom%20accounts;] log-sink : Exchange[ExchangePattern: InOnly, BodyType: org.apache.camel.converter.stream.InputStreamCache, Body: {"user_id":2,"username":"John","city":"New York"}]
.
.
.
.
----
And the secret should also now be listed as updated from the get vault command:
[source,sh]
----
camel get vault
----
=== Developer Web Console
You can enable the developer console via `--console` flag as show:
[source,sh]
----
$ camel run postgresql-log.camel.yaml --console
----
Then you can browse: http://localhost:8080/q/dev to introspect the running Camel Application.
=== Help and contributions
If you hit any problem using Camel or have some feedback, then please
https://camel.apache.org/community/support/[let us know].
We also love contributors, so
https://camel.apache.org/community/contributing/[get involved] :-)
The Camel riders!