Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [DBOPS-928]: SSL Connection issues with MongoDB Database DevOps #9646

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions docs/database-devops/use-database-devops/set-up-connectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@ The JDBC connector is used for connecting to your database instance.

#### URL Examples

| Database | JDBC URL Format |
|----------------|---------------------------------------------------------------------------------|
| **ORACLE** | `jdbc:oracle:thin:@//host:port/FREEPDB1` |
| **POSTGRES** | `jdbc:postgresql://host:port/dbName?sslmode=disable` |
| **SQLSERVER** | `jdbc:sqlserver://host:port;trustServerCertificate=true;databaseName=master` |
| **MongoAtlasSQL** | `jdbc:mongodb://host:port%s?ssl=true&authSource=admin` |
| **MYSQL** | `jdbc:mysql://host:port/db` |
| **MONGODB** | `mongodb://host:port/dbName/?authSource=admin` |
| **GOOGLE SPANNER** | `jdbc:cloudspanner:/projects/{project-id}/instances/{instance-id}/databases/{database-name}?lenient=true` |
| Database | JDBC URL Format |
|--------------------|----------------------------------------------------------------------------------------------------------------------------|
| **ORACLE** | `jdbc:oracle:thin:@//host:port/FREEPDB1` |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should review all connection string because {} are not added at correct places to know what customer needs to replace plus what is constant

| **POSTGRES** | `jdbc:postgresql://host:port/dbName?sslmode=disable` |
| **SQLSERVER** | `jdbc:sqlserver://host:port;trustServerCertificate=true;databaseName=master` |
| **MongoAtlasSQL** | `jdbc:mongodb://host:port%s?ssl=true&authSource=admin` |
| **MYSQL** | `jdbc:mysql://host:port/db` |
| **MONGODB** | `mongodb://host:port/dbName/?authSource=admin` |
| **GOOGLE SPANNER** | `jdbc:cloudspanner:/projects/{project-id}/instances/{instance-id}/databases/{database-name}?lenient=true` |
| **MongoDB SSL** | `mongodb://host:port/dbName/?tls=true&authSource=admin` |
| **POSTGRES SSL** | `jdbc:postgresql://host:port/dbName?ssl=true` |
| **SQLSERVER SSL** | `jdbc:sqlserver://host:port;databaseName=dbName;encrypt=true;trustServerCertificate=false;` |
| **MYSQL SSL** | `jdbc:mysql://host:port/dbName?useSSL=true` |
| **ORACLE SSL** | `jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=host)(PORT=port))(CONNECT_DATA=(SERVICE_NAME=servicename)))` |

---

Expand Down
139 changes: 139 additions & 0 deletions docs/database-devops/use-database-devops/ssl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
title: SSL
description: Learn More about How to set up Databases with SSL Connection with Harness DBDevops
sidebar_position: 11
---

# Introduction

This document provides a comprehensive guide to configuring databases with mTLS, including secret and delegate configurations, setting up for JDBC test connections, and pipeline permissions. It covers the necessary steps to set up and manage certificates for secure communication between database and other services.

## Pre-requisites
* `root_ca.crt` file is available
* To know more about generating CA certificates, [create_ca certificate](https://developer.harness.io/docs/platform/delegates/secure-delegates/delegate-mtls-support/#create-a-ca-certificate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add this root_ca.crt into the ca.bundle and give ref to ci docs

* `client.crt` and `client.key` is available
* To know more about generating client certificates, follow steps: 1 to 3 from [create_client certificate](https://developer.harness.io/docs/platform/delegates/secure-delegates/delegate-mtls-support/#create-a-client-certificate)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. in prequisites you can mention to use CI_MOUNT_VOLUMES only to copy cert (reason )as we need to different certs and key for mtls

after prequiisites you can add,
ssl for git clone

add steps, and add ref link

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

### Generating PKCS12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generating pkcs12 for client

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets remove pkcs for ci builds

Assuming that the `client.crt` and `client.key` files are available,

execute the below command to generate pkcs12 file

```shell
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name mongo-client -password pass:changeit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we say this is step1 and base64 encode is step2.
And below step2 you can add note blue color section why we are doing so

```

**IMPORTANT NOTE**:
If the .p12 file gets directly mounted as a Kubernetes Secret or ConfigMap, it might get encoded improperly, leading to corruption.

This is because:

* ConfigMaps store data as plain text and might not handle binary files properly.
* Secrets store data in Base64 encoding, which requires correct decoding when mounting.

**Hence, the `client.p12` file is stored as a base64 secret**

```shell
cat client.p12 | base64 > client_pkcs12.txt
```


### Secret Configuration

Create a secret using `root_ca.crt` and `client_pkcs12.txt`( base64 encoded value of the `client.p12` file )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this secret needs to be created on delegate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kubernetes secret used within the delegate and mounted onto the build pods later.


```shell
kubectl create secret -n namespace generic db-ops-ssl-secret --from-file root_ca.crt --from-file client_pkcs12.txt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we check why we cant use this directly?

kubectl create secret -n generic client-certificate
--from-file client.crt=client.crt
--from-file client.key=client.key

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't upload client crt and client key to the keystore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can only upload the pkcs12 file to the keystore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if we get both crt and key and create this pkcs on our side? then the steps remain same for customer?

```

### Delegate Configuration

Modify the delegate manifest file to include a volume mount.

1. Add the following YAML under `spec.template.spec.containers`

```shell
volumeMounts:
- mountPath: /opt/harness-delegate/ca-bundle/
name: custom-certs
readOnly: true
```

2. Add the following under `spec.template.spec`. Add the secret name with the value you used when you created the kubernetes secret.

```shell
volumes:
- name: custom-certs
secret:
secretName: db-ops-ssl-secret
defaultMode: 400
```

Within our delegate configuration **environment variables** mount the `root_ca.crt` file.

**This is done to ensure that the certificates are mounted onto the build pods.**

```shell
- name: ADDITIONAL_CERTS_PATH
value: "/opt/harness-delegate/ca-bundle/root_ca.crt"
Copy link
Contributor

@archit-harness archit-harness Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep this till bundle path

- name: CI_MOUNT_VOLUMES
value: "/opt/harness-delegate/ca-bundle/root_ca.crt:/etc/ssl/certs/dbops/root_ca.crt,/opt/harness-delegate/ca-bundle/client_pkcs12.txt:/etc/ssl/certs/dbops/client_pkcs12.txt"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy bundle into root_ca.crt

```

**IMPORTANT NOTE**:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

info note type


* The destination paths during mount in `CI_MOUNT_VOLUMES` has to be
* `/etc/ssl/certs/dbops/root_ca.crt`
* `/etc/ssl/certs/dbops/client_pkcs12.txt`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client and key

* `ADDITIONAL_CERTS_PATH` is a mandatory environment variable when `CI_MOUNT_VOLUMES` is provided

### JDBC Test Connection

In order for the JDBC test connection to work, using env variable `INIT_SCRIPT`,

the `root_ca.crt` file is imported into the java trustStore and `client.p12` to the java keyStore.

**This is done because the JDBC Test Connection runs within a delegate.**

Below is an example which imports

* crt file to the **default JVM trustStore** `$JAVA_HOME/lib/security/cacerts`
* pkcs12 file to the **default keyStore** `$JAVA_HOME/lib/security/jssecacerts`


```shell
- name: INIT_SCRIPT
value: |-
base64 --decode /opt/harness-delegate/ca-bundle/client_pkcs12.txt > client.p12
keytool -importkeystore -destkeystore $JAVA_HOME/lib/security/jssecacerts -srckeystore client.p12 -srcstoretype PKCS12 -alias mongo-client -storepass changeit -srcstorepass changeit -noprompt
keytool -importcert -file /opt/harness-delegate/ca-bundle/root_ca.crt -keystore $JAVA_HOME/lib/security/cacerts -alias "mongodb_ssl" -storepass changeit -noprompt
```

The trustStore and keyStore details are added as part of `JAVA_TOOL_OPTIONS` environment variable.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to use JAVA_OPTS


For default trustStore and keyStore

```shell
- name: JAVA_TOOL_OPTIONS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why will we need this? if we are using default truststore and keystore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because default keystore is not set by default in the system properties unlike trustStore

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we should mention this path is configurable, default values should be these if you are running jdk >= 17.0.0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

give ref to truststore override of delegate

value: "-Xms64M -Djavax.net.ssl.keyStore=/opt/java/openjdk/lib/security/jssecacerts -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.trustStore=/opt/java/openjdk/lib/security/cacerts -Djavax.net.ssl.trustStorePassword=changeit"
```

## Pipeline Permissions
The **DB step** needs to have access to the build pod to import keys to the default keyStores.

For example, if we want to run the ApplySchema as a root user, the step needs to be configured with **runAsUser** with value 0.

```shell
spec:
runAsUser: "0"
```

## Conclusion
By following this guide, you can securely configure Database with mTLS, ensuring encrypted communication and proper authentication between services.


## References
* [Using Self-Signed Certificates in Kubernetes Build Farm](https://developer.harness.io/docs/continuous-integration/use-ci/set-up-build-infrastructure/k8s-build-infrastructure/configure-a-kubernetes-build-farm-to-use-self-signed-certificates/)
* [Installing Delegates with Custom Certificates](https://developer.harness.io/docs/platform/delegates/secure-delegates/install-delegates-with-custom-certs/)
* [Delegate_MTLS_Support](https://developer.harness.io/docs/platform/delegates/secure-delegates/delegate-mtls-support/)