Quick links
| Ubuntu 22.04
- List of parameters used in application.yaml
- Parameters from mongo
- Good connect string:
mongodb+srv://<login>:<password>@<hostname>/<database-to-connect>?replicaSet=<name-of-replicaset>&readPreference=secondary&retryWrites=true&w=majority&authSource=admin&tls=true
- Repository with all files
Run mongodb inside Docker
1
2
3
4
|
docker run --rm --name mongodb -p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secret \
mongo
|
Connect to admin’s db and create a db with user (auth db will be the same db):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
mongosh "mongodb://admin:secret@localhost/admin?ssl=false"
admin> use mongo-test
mongo-test> db.createUser(
{
user: "admin",
pwd: "pass",
roles: [
{ role: "userAdmin", db: "mongo-test" },
{ role: "readWrite", db: "mongo-test" }
]
}
)
|
Check connection to db mongo-test and get collections (it will be empty):
1
2
3
4
5
|
mongosh "mongodb://admin:pass@localhost/mongo-test?ssl=false"
# Get collections from db mongo-test
mongo-test> db.getCollectionNames()
[]
|
SpringBoot application
Install SdkMan!
1
2
3
4
|
sdk version
SDKMAN!
script: 5.18.2
native: 0.4.6
|
Install Spring Boot, gradle and java
1
2
3
4
5
6
7
8
9
|
# Find
sdk list springboot
sdk list gradle
sdk list java
# Install
sdk install springboot 3.3.5
sdk install gradle 8.10.2
sdk install java 21.0.5-oracle
|
Generate Spring Boot application with MongoDB
List of supported dependencies:
1
2
|
spring init --list | grep -iE "mongo|web"
spring --help init
|
Initiate Spring Boot application:
1
2
3
4
5
6
7
|
spring init --build=gradle --type=gradle-project-kotlin \
--language=java --boot-version=3.3.5 \
--group-id="com.example" --artifact-id=demo --name=Demo \
--description="Demo project for Spring Boot" \
--packaging="jar" --java-version=21 \
--dependencies=web,data-mongodb /tmp/mongodb-demo
Project extracted to '/tmp/mongodb-demo'
|
Describe connection to MongoDB:
1
2
3
4
|
cd /tmp/mongodb-demo
cat src/main/resources/application.properties
spring.application.name=Demo
spring.data.mongodb.uri=mongodb://admin:pass@localhost/mongo-test?ssl=false
|
Using the example, we will prepare the source code:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
cd src/main/java/com/example/demo/
mkdir model
vi model/GroceryItem.java
mkdir repository
vi repository/CustomItemRepositoryImpl.java
vi repository/CustomItemRepository.java
vi repository/ItemRepository.java
vi DemoApplication.java
cd /tmp/mongodb-demo
|
Build the source code:
1
2
3
4
5
6
|
gradle tasks
gradle tasks --all
gradle build -x test
# Run the jar artifact
java -jar build/libs/demo-0.0.1-SNAPSHOT.jar
|
Check that collections and items were created:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
mongosh "mongodb://admin:pass@localhost/mongo-test?ssl=false"
mongo-test> db.getCollectionNames()
[ 'GroceryItem' ]
mongo-test> db.GroceryItem.find()
[
{
_id: 'Whole Wheat Biscuit',
name: 'Whole Wheat Biscuit',
quantity: 5,
category: 'munchies',
_class: 'com.example.demo.model.GroceryItem'
},
{
_id: 'Dried Red Chilli',
name: 'Dried Whole Red Chilli',
quantity: 2,
category: 'spices',
_class: 'com.example.demo.model.GroceryItem'
},
{
_id: 'Pearl Millet',
name: 'Healthy Pearl Millet',
quantity: 1,
category: 'millets',
_class: 'com.example.demo.model.GroceryItem'
},
{
_id: 'Cheese Crackers',
name: 'Bonny Cheese Crackers Plain',
quantity: 10,
category: 'munchies',
_class: 'com.example.demo.model.GroceryItem'
}
]
|
Now, add tls beetween MongoDB and our application:
Prepare certificates
1
2
|
ls ts
additional.info mongodb.crt mongodb.csr mongodb.jks mongodb.key mongodb.p12 mongodb.pem mytruststore.jks rootCA.key rootCA.pem rootCA.srl
|
Run MongoDB with tls
Read only owner:
1
|
chmod 0400 mongodb/ca.crt mongodb/mongodb.pem
|
Run MongoDB without tls and initiate user and password:
1
2
3
4
5
6
|
mkdir -pv ./mongodb/db
docker run --rm --name mongodb -p 27017:27017 \
-v "./mongodb/db:/data/db" \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secret \
mongo
|
Run MongoDB with tls:
1
2
3
4
5
6
7
|
docker run --rm --name mongodb -p 27017:27017 \
-v "./tls/rootCA.pem:/etc/ssl/ca.crt" \
-v "./tls/mongodb.pem:/etc/ssl/mongodb.pem" \
-v "./mongodb/db:/data/db" \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secret \
mongo sh -c "mongod --bind_ip_all --tlsMode requireTLS --tlsCAFile /etc/ssl/ca.crt --tlsCertificateKeyFile /etc/ssl/mongodb.pem"
|
Check connect with tls:
1
|
mongosh --tls --tlsCAFile ./tls/rootCA.pem --tlsCertificateKeyFile ./tls/mongodb.pem "mongodb://admin:secret@localhost/admin?tls=true"
|
Create database and user:
1
2
3
4
5
6
7
8
9
10
11
12
|
use mongo-test
db.createUser(
{
user: "admin",
pwd: "pass",
roles: [
{ role: "userAdmin", db: "mongo-test" },
{ role: "readWrite", db: "mongo-test" }
]
}
)
|
Check connection with created auth data:
1
|
mongosh --tls --tlsCAFile ./tls/rootCA.pem --tlsCertificateKeyFile ./tls/mongodb.pem "mongodb://admin:pass@localhost/mongo-test?tls=true"
|
Build and run spring application
1
2
3
4
5
6
7
|
cat src/main/resources/application.properties
spring.application.name=Demo
spring.data.mongodb.uri=mongodb://admin:pass@localhost/mongo-test?tls=true
gradle build -x test
export JAVA_TOOL_OPTIONS='-Djavax.net.ssl.trustStore=tls/mytruststore.jks -Djavax.net.ssl.trustStorePassword=thebattleforarrakis -Djavax.net.ssl.keyStore=tls/mongodb.jks -Djavax.net.ssl.keyStorePassword=thebattleforarrakis'
java -jar build/libs/demo-0.0.1-SNAPSHOT.jar
|
Communication between containers
Create network and run MongoDB there:
1
2
3
4
5
6
7
8
|
docker network create mongodb
docker run --rm --name mongodb -p 27017:27017 \
-v "./tls/rootCA.pem:/etc/ssl/ca.crt" \
-v "./tls/mongodb.pem:/etc/ssl/mongodb.pem" \
-v "./mongodb/db:/data/db" \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secret --network mongodb \
mongo sh -c "mongod --bind_ip_all --tlsMode requireTLS --tlsCAFile /etc/ssl/ca.crt --tlsCertificateKeyFile /etc/ssl/mongodb.pem"
|
Prepare Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
cat <<EOF> Dockerfile
FROM gradle:8.10-jdk21-alpine AS build
ENV GRADLE_OPTS="-Dorg.gradle.daemon=false"
WORKDIR /src
COPY . .
RUN gradle build -x test
FROM bellsoft/liberica-openjdk-alpine-musl:21
ARG APP_NAME=demo
ENV APP_NAME=\$APP_NAME
WORKDIR /opt
COPY --from=build ./src/build/libs /opt
RUN addgroup -S --gid 1001 "\$APP_NAME" \\
&& adduser -S "\$APP_NAME" --uid 1001 -G "\$APP_NAME" \\
&& chown -R "\$APP_NAME":"\$APP_NAME" /opt
USER \$APP_NAME
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/opt/demo-0.0.1-SNAPSHOT.jar"]
EOF
|
And .dockerignore
:
1
2
3
|
cat <<EOF> .dockerignore
mongodb/db/
EOF
|
Change connection string:
1
2
3
|
cat src/main/resources/application.properties
spring.application.name=Demo
spring.data.mongodb.uri=mongodb://admin:pass@mongo.mongo/mongo-test?tls=true
|
Build and run container with our demo application:
1
2
3
4
|
docker build -t demo:0.0.1 .
docker run --name demo -v $(pwd)/tls:/tls -it --network mongodb \
-e 'JAVA_TOOL_OPTIONS=-Djavax.net.ssl.trustStore=/tls/mytruststore.jks -Djavax.net.ssl.trustStorePassword=thebattleforarrakis -Djavax.net.ssl.keyStore=/tls/mongodb.jks -Djavax.net.ssl.keyStorePassword=thebattleforarrakis' \
demo:0.0.1
|
Kubernetes
Build image with tag and push into docker registry:
1
|
docker build --push -t tty8747/demo:0.0.1 .
|
Prepare secrets with passwords for truststore, keyStore and pkcs12:
1
2
3
4
5
|
kubectl --namespace default create secret generic jks-secret \
--from-literal=keystore-password=Oofiewe8uv1Gahriac \
--from-literal=truststore-password=Oofiewe8uv1Gahriac
kubectl --namespace default create secret generic pkcs12-secret --from-literal=pkcs12-password=ahwohraexi5eeN4Ahf
|
And create certificate and key with cert-manager:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
cat <<EOF | kubectl apply -f-
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: demo-internal
namespace: default
spec:
secretName: demo-internal-tls
secretTemplate:
labels:
demo: secret
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
keystores:
jks:
create: true
passwordSecretRef:
name: jks-secret
key: keystore-password
pkcs12:
create: true
passwordSecretRef:
name: pkcs12-secret
key: pkcs12-password
duration: 2160h # 90d
renewBefore: 360h # 15d
isCA: false
usages:
- server auth
- client auth
- digital signature
- key encipherment
subject:
organizations:
- cert-manager
commonName: demo-internal
dnsNames:
- "localhost"
- "mongodb-psmdb-db-rs01"
- "mongodb-psmdb-db-rs01.temp"
- "mongodb-psmdb-db-rs01.temp.svc.cluster.local"
- "*.mongodb-psmdb-db-rs01"
- "*.mongodb-psmdb-db-rs01.temp"
- "*.mongodb-psmdb-db-rs01.temp.svc.cluster.local"
- "mongodb-psmdb-db-rs01.temp.svc.clusterset.local"
- "*.mongodb-psmdb-db-rs01.temp.svc.clusterset.local"
- "*.temp.svc.clusterset.local"
- "mongodb-psmdb-db-mongos"
- "mongodb-psmdb-db-mongos.temp"
- "mongodb-psmdb-db-mongos.temp.svc.cluster.local"
- "*.mongodb-psmdb-db-mongos"
- "*.mongodb-psmdb-db-mongos.temp"
- "*.mongodb-psmdb-db-mongos.temp.svc.cluster.local"
- "mongodb-psmdb-db-cfg"
- "mongodb-psmdb-db-cfg.temp"
- "mongodb-psmdb-db-cfg.temp.svc.cluster.local"
- "*.mongodb-psmdb-db-cfg"
- "*.mongodb-psmdb-db-cfg.temp"
- "*.mongodb-psmdb-db-cfg.temp.svc.cluster.local"
- "mongodb-psmdb-db-mongos.temp.svc.clusterset.local"
- "*.mongodb-psmdb-db-mongos.temp.svc.clusterset.local"
- "mongodb-psmdb-db-cfg.temp.svc.clusterset.local"
- "*.mongodb-psmdb-db-cfg.temp.svc.clusterset.local"
issuerRef:
name: my-ca-issuer
kind: ClusterIssuer
group: cert-manager.io
EOF
|
Run pod of demo application and run
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
cat <<EOF pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: demo
name: demo
spec:
containers:
- image: tty8747/demo:0.0.1
name: demo
command:
- sh
- -c
- sleep 3600
volumeMounts:
- mountPath: /tls
name: tls
readOnly: true
volumes:
- name: tls
secret:
secretName: demo-internal-tls
dnsPolicy: ClusterFirst
restartPolicy: Never
EOF
|
Connect to demo pod and run:
1
2
|
export JAVA_TOOL_OPTIONS='-Djavax.net.ssl.trustStore=/tls/truststore.jks -Djavax.net.ssl.trustStorePassword=Oofiewe8uv1Gahriac -Djavax.net.ssl.keyStore=/tls/keystore.jks -Djavax.net.ssl.keyStorePassword=Oofiewe8uv1Gahriac -Dspring.data.mongodb.uri=mongodb+srv://admin:pass@mongodb-psmdb-db-rs01.temp.svc.csp.test.cluster/mongo-test?replicaSet=rs01&readPreference=secondary&retryWrites=true&w=majority&authSource=mongo-test&tls=true'
java -jar demo-0.0.1-SNAPSHOT.jar
|