Simplification of TLS config

This commit is contained in:
sttlab
2026-05-03 12:48:42 +00:00
parent 5a48150820
commit 4f1c251ff8
4 changed files with 97 additions and 75 deletions
+36 -11
View File
@@ -50,10 +50,13 @@ gravitee-selfsigned-bootstrap (Issuer, self-signed)
### cert-manager keystores ### cert-manager keystores
Two secrets include PKCS12 keystores automatically generated by cert-manager: Three secrets include PKCS12 keystores automatically generated by cert-manager:
- `api-internal-tls``keystore.p12` (used by Jetty) - `api-internal-tls``keystore.p12` (Jetty server cert) + `truststore.p12` (CA trust for JVM)
- `gateway-internal-tls``keystore.p12` (used by Vert.x) - `gateway-internal-tls``keystore.p12` (Vert.x server cert) + `truststore.p12` (CA trust for JVM)
- `elasticsearch-tls``truststore.jks` (used by the JVM to trust the ES certificate) - `elasticsearch-tls``keystore.p12` + `truststore.p12` (ES server cert — keystore unused by Gravitee)
Each component mounts only its own internal TLS secret at `/run/secrets/tls/`, providing both
the server keystore and the JVM truststore from a single volume.
Keystore password is stored in the `gravitee-jks-password` secret. Keystore password is stored in the `gravitee-jks-password` secret.
@@ -86,7 +89,9 @@ All secrets are created by `secrets-create.sh` before the first deployment.
| `gravitee-admin` | `admin-password-plain`, `admin-password-bcrypt` | api (env) | | `gravitee-admin` | `admin-password-plain`, `admin-password-bcrypt` | api (env) |
| `gravitee-es-master-credentials` | ES `username`, `password` | api, gateway (env) | | `gravitee-es-master-credentials` | ES `username`, `password` | api, gateway (env) |
| `gravitee-jks-password` | keystore password | api, gateway (env) + cert-manager | | `gravitee-jks-password` | keystore password | api, gateway (env) + cert-manager |
| `gravitee-ca-trust` | `ca.crt` only — no tls.crt/key | nginx ingress proxy-ssl-secret | | `gravitee-ca-trust` | `ca.crt` only — no tls.crt/key | nginx ingress `proxy-ssl-secret` |
> `gravitee-ca-trust` is created by `secrets-create.sh` after the certificates are ready (it reads `ca.crt` from `gravitee-ca-tls`). It must contain **only** `ca.crt` — if `tls.crt`/`tls.key` were present, nginx would present them as a client certificate, triggering unintended mTLS toward backends.
> `gravitee-ca-trust` is a dedicated secret containing only `ca.crt`. The `proxy-ssl-secret` nginx annotation presents `tls.crt`/`tls.key` as a client certificate if they exist, which would unintentionally trigger mTLS toward backends. > `gravitee-ca-trust` is a dedicated secret containing only `ca.crt`. The `proxy-ssl-secret` nginx annotation presents `tls.crt`/`tls.key` as a client certificate if they exist, which would unintentionally trigger mTLS toward backends.
@@ -116,10 +121,11 @@ env:
TLS enabled via `tls=true` in the connection URI. Server certificate validation is handled by the JVM truststore: TLS enabled via `tls=true` in the connection URI. Server certificate validation is handled by the JVM truststore:
``` ```
JAVA_OPTS: -Djavax.net.ssl.trustStore=/run/secrets/truststore/truststore.jks JAVA_OPTS: -Djavax.net.ssl.trustStoreType=PKCS12
-Djavax.net.ssl.trustStore=/run/secrets/tls/truststore.p12
-Djavax.net.ssl.trustStorePassword=${JKS_PASSWORD} -Djavax.net.ssl.trustStorePassword=${JKS_PASSWORD}
``` ```
The `truststore.jks` is sourced from the `elasticsearch-tls` secret (contains the Gravitee CA). The `truststore.p12` is sourced from the component's own internal TLS secret (`api-internal-tls` or `gateway-internal-tls`), which cert-manager populates with the issuing CA chain.
MongoDB runs with `--tlsAllowConnectionsWithoutCertificates` (no client mTLS) but requires server TLS (`--tlsMode=requireTLS`). MongoDB runs with `--tlsAllowConnectionsWithoutCertificates` (no client mTLS) but requires server TLS (`--tlsMode=requireTLS`).
@@ -173,17 +179,34 @@ annotations:
### First install ### First install
```bash ```bash
# 1. Create secrets ./deploy.sh
```
Or step by step:
```bash
# 1. Create credential secrets
./secrets-create.sh ./secrets-create.sh
# 2. Deploy PKI # 2. Deploy PKI and wait for certificates
kubectl apply -f certificates.yml kubectl apply -f certificates.yml
kubectl -n gravitee-apim wait --for=condition=Ready certificate --all --timeout=180s
# 3. Deploy backends # 3. Create CA trust secret for nginx (requires certificates to be ready first)
kubectl -n gravitee-apim get secret gravitee-ca-tls -o jsonpath='{.data.ca\.crt}' | base64 -d | \
kubectl -n gravitee-apim create secret generic gravitee-ca-trust --from-file=ca.crt=/dev/stdin \
--dry-run=client -o yaml | kubectl apply -f -
# 4. Enable nginx ingress snippets
kubectl patch configmap ingress-nginx-controller -n ingress-nginx \
--type merge -p '{"data":{"allow-snippet-annotations":"true","annotations-risk-level":"Critical"}}'
kubectl rollout restart deployment/ingress-nginx-controller -n ingress-nginx
# 5. Deploy backends
helm upgrade --install mongodb bitnami/mongodb -n gravitee-apim -f mongo-values.yml helm upgrade --install mongodb bitnami/mongodb -n gravitee-apim -f mongo-values.yml
helm upgrade --install elasticsearch elastic/elasticsearch -n gravitee-apim -f elastic-values.yml helm upgrade --install elasticsearch elastic/elasticsearch -n gravitee-apim -f elastic-values.yml
# 4. Deploy Gravitee # 6. Deploy Gravitee
helm upgrade --install graviteeio-apim graviteeio/apim -n gravitee-apim -f apim-values.yml helm upgrade --install graviteeio-apim graviteeio/apim -n gravitee-apim -f apim-values.yml
``` ```
@@ -198,6 +221,8 @@ helm upgrade --install elasticsearch elastic/elasticsearch -n gravitee-apim -f e
helm upgrade --install graviteeio-apim graviteeio/apim -n gravitee-apim -f apim-values.yml helm upgrade --install graviteeio-apim graviteeio/apim -n gravitee-apim -f apim-values.yml
``` ```
> Secrets, certs, PVs and the `gravitee-ca-trust` secret are preserved across workload rebuilds.
### /etc/hosts ### /etc/hosts
``` ```
+10 -37
View File
@@ -14,33 +14,19 @@ gateway:
enabled: true enabled: true
replicaCount: 2 replicaCount: 2
# Mount CA bundle and internal server cert
extraVolumes: | extraVolumes: |
- name: gravitee-ca
secret:
secretName: gravitee-ca-tls
items:
- key: ca.crt
path: ca.crt
- name: gateway-internal-tls - name: gateway-internal-tls
secret: secret:
secretName: gateway-internal-tls secretName: gateway-internal-tls
- name: es-truststore
secret:
secretName: elasticsearch-tls
items: items:
- key: truststore.jks - key: keystore.p12
path: truststore.jks path: keystore.p12
- key: truststore.p12
path: truststore.p12
extraVolumeMounts: | extraVolumeMounts: |
- name: gravitee-ca
mountPath: /run/secrets/ca
readOnly: true
- name: gateway-internal-tls - name: gateway-internal-tls
mountPath: /run/secrets/tls mountPath: /run/secrets/tls
readOnly: true readOnly: true
- name: es-truststore
mountPath: /run/secrets/truststore
readOnly: true
env: env:
- name: GRAVITEE_MANAGEMENT_MONGODB_URI - name: GRAVITEE_MANAGEMENT_MONGODB_URI
@@ -73,7 +59,7 @@ gateway:
name: gravitee-jks-password name: gravitee-jks-password
key: password key: password
- name: JAVA_OPTS - name: JAVA_OPTS
value: "-Djavax.net.ssl.trustStore=/run/secrets/truststore/truststore.jks -Djavax.net.ssl.trustStorePassword=$(JKS_PASSWORD)" value: "-Djavax.net.ssl.trustStoreType=PKCS12 -Djavax.net.ssl.trustStore=/run/secrets/tls/truststore.p12 -Djavax.net.ssl.trustStorePassword=$(JKS_PASSWORD)"
# Enable HTTPS on the gateway listener (port 8082) # Enable HTTPS on the gateway listener (port 8082)
ssl: ssl:
@@ -125,31 +111,18 @@ api:
replicaCount: 1 replicaCount: 1
extraVolumes: | extraVolumes: |
- name: gravitee-ca
secret:
secretName: gravitee-ca-tls
items:
- key: ca.crt
path: ca.crt
- name: api-internal-tls - name: api-internal-tls
secret: secret:
secretName: api-internal-tls secretName: api-internal-tls
- name: es-truststore
secret:
secretName: elasticsearch-tls
items: items:
- key: truststore.jks - key: keystore.p12
path: truststore.jks path: keystore.p12
- key: truststore.p12
path: truststore.p12
extraVolumeMounts: | extraVolumeMounts: |
- name: gravitee-ca
mountPath: /run/secrets/ca
readOnly: true
- name: api-internal-tls - name: api-internal-tls
mountPath: /run/secrets/tls mountPath: /run/secrets/tls
readOnly: true readOnly: true
- name: es-truststore
mountPath: /run/secrets/truststore
readOnly: true
env: env:
- name: GRAVITEE_MANAGEMENT_MONGODB_URI - name: GRAVITEE_MANAGEMENT_MONGODB_URI
@@ -192,7 +165,7 @@ api:
name: gravitee-jks-password name: gravitee-jks-password
key: password key: password
- name: JAVA_OPTS - name: JAVA_OPTS
value: "-Djavax.net.ssl.trustStore=/run/secrets/truststore/truststore.jks -Djavax.net.ssl.trustStorePassword=$(JKS_PASSWORD)" value: "-Djavax.net.ssl.trustStoreType=PKCS12 -Djavax.net.ssl.trustStore=/run/secrets/tls/truststore.p12 -Djavax.net.ssl.trustStorePassword=$(JKS_PASSWORD)"
# Enable HTTPS on Management API + Portal API listeners # Enable HTTPS on Management API + Portal API listeners
http: http:
+43 -26
View File
@@ -1,9 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Deploy Gravitee APIM OSS on a single-node k3s cluster # Deploy Gravitee APIM OSS on a single-node k3s cluster.
# - Domain: *.gravitee.sttlab.pc # - Domain: *.gravitee.sttlab.pc
# - Ingress: nginx # - Ingress: nginx
# - TLS: cert-manager with namespace-scoped self-signed CA Issuer # - TLS: cert-manager with namespace-scoped self-signed CA Issuer
# - Secrets: pre-created (run create-secrets.sh first) # - Secrets: pre-created by secrets-create.sh
set -euo pipefail set -euo pipefail
@@ -12,7 +12,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "==> Checking prerequisites" echo "==> Checking prerequisites"
command -v kubectl >/dev/null || { echo "kubectl not found"; exit 1; } command -v kubectl >/dev/null || { echo "kubectl not found"; exit 1; }
command -v helm >/dev/null || { echo "helm not found"; exit 1; } command -v helm >/dev/null || { echo "helm not found"; exit 1; }
command -v htpasswd >/dev/null || { echo "htpasswd not found (required for admin BCrypt hash)"; exit 1; }
echo "==> Verifying cluster reachable" echo "==> Verifying cluster reachable"
kubectl cluster-info kubectl cluster-info
@@ -28,14 +29,14 @@ kubectl get ingressclass nginx >/dev/null 2>&1 || {
echo "WARNING: 'nginx' IngressClass not found. Ensure nginx-ingress is installed." echo "WARNING: 'nginx' IngressClass not found. Ensure nginx-ingress is installed."
} }
echo "==> Step 1/5 : Create namespace" echo "==> Step 1/6 : Create namespace"
kubectl create namespace "${NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f - kubectl create namespace "${NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
echo "==> Step 2/5 : Create credential secrets (idempotent)" echo "==> Step 2/6 : Create credential secrets (idempotent)"
"${SCRIPT_DIR}/create-secrets.sh" "${SCRIPT_DIR}/secrets-create.sh"
echo "==> Step 3/5 : Apply cert-manager Issuer + Certificates" echo "==> Step 3/6 : Apply cert-manager Issuers + Certificates"
kubectl apply -f "${SCRIPT_DIR}/manifests/cert-manager.yaml" kubectl apply -f "${SCRIPT_DIR}/certificates.yml"
echo "==> Waiting for CA Issuer to be Ready" echo "==> Waiting for CA Issuer to be Ready"
kubectl -n "${NAMESPACE}" wait --for=condition=Ready issuer/gravitee-ca-issuer --timeout=120s kubectl -n "${NAMESPACE}" wait --for=condition=Ready issuer/gravitee-ca-issuer --timeout=120s
@@ -47,28 +48,41 @@ for cert in gravitee-ca console-tls portal-tls api-tls gateway-tls \
kubectl -n "${NAMESPACE}" wait --for=condition=Ready "certificate/${cert}" --timeout=180s kubectl -n "${NAMESPACE}" wait --for=condition=Ready "certificate/${cert}" --timeout=180s
done done
echo "==> Step 4/5 : Add Helm repos" echo "==> Creating gravitee-ca-trust secret (CA only, for nginx proxy-ssl-secret)"
helm repo add bitnami https://charts.bitnami.com/bitnami kubectl -n "${NAMESPACE}" get secret gravitee-ca-tls -o jsonpath='{.data.ca\.crt}' | base64 -d | \
helm repo add elastic https://helm.elastic.co kubectl -n "${NAMESPACE}" create secret generic gravitee-ca-trust \
helm repo add graviteeio https://helm.gravitee.io --from-file=ca.crt=/dev/stdin \
--dry-run=client -o yaml | kubectl apply -f -
echo "==> Step 4/6 : Configure nginx ingress controller (enable snippets)"
kubectl patch configmap ingress-nginx-controller -n ingress-nginx \
--type merge \
-p '{"data":{"allow-snippet-annotations":"true","annotations-risk-level":"Critical"}}'
kubectl rollout restart deployment/ingress-nginx-controller -n ingress-nginx
kubectl rollout status deployment/ingress-nginx-controller -n ingress-nginx --timeout=60s
echo "==> Step 5/6 : Add Helm repos"
helm repo add bitnami https://charts.bitnami.com/bitnami 2>/dev/null || true
helm repo add elastic https://helm.elastic.co 2>/dev/null || true
helm repo add graviteeio https://helm.gravitee.io 2>/dev/null || true
helm repo update helm repo update
echo "==> Installing MongoDB" echo "==> Installing MongoDB"
helm upgrade --install mongodb bitnami/mongodb \ helm upgrade --install mongodb bitnami/mongodb \
--namespace "${NAMESPACE}" \ --namespace "${NAMESPACE}" \
--values "${SCRIPT_DIR}/values-mongodb.yaml" \ --values "${SCRIPT_DIR}/mongo-values.yml" \
--wait --timeout 10m --wait --timeout 10m
echo "==> Installing Elasticsearch" echo "==> Installing Elasticsearch"
helm upgrade --install elasticsearch elastic/elasticsearch \ helm upgrade --install elasticsearch elastic/elasticsearch \
--namespace "${NAMESPACE}" \ --namespace "${NAMESPACE}" \
--values "${SCRIPT_DIR}/values-elasticsearch.yaml" \ --values "${SCRIPT_DIR}/elastic-values.yml" \
--wait --timeout 10m --wait --timeout 10m
echo "==> Step 5/5 : Installing Gravitee APIM" echo "==> Step 6/6 : Installing Gravitee APIM"
helm upgrade --install graviteeio-apim graviteeio/apim \ helm upgrade --install graviteeio-apim graviteeio/apim \
--namespace "${NAMESPACE}" \ --namespace "${NAMESPACE}" \
--values "${SCRIPT_DIR}/values-apim.yaml" \ --values "${SCRIPT_DIR}/apim-values.yml" \
--wait --timeout 15m --wait --timeout 15m
echo "" echo ""
@@ -76,15 +90,18 @@ echo "==> Deployment complete"
echo "" echo ""
kubectl get pods -n "${NAMESPACE}" kubectl get pods -n "${NAMESPACE}"
echo "" echo ""
echo "Add to /etc/hosts (replace <NODE_IP>):" echo "Add to /etc/hosts (replace <NODE_IP> with your node IP):"
echo " <NODE_IP> gateway.gravitee.sttlab.pc console.gravitee.sttlab.pc portal.gravitee.sttlab.pc api.gravitee.sttlab.pc" echo " <NODE_IP> console.gravitee.sttlab.pc portal.gravitee.sttlab.pc api.gravitee.sttlab.pc gateway.gravitee.sttlab.pc"
echo "" echo ""
echo "URLs (HTTPS, self-signed CA - trust gravitee-ca-tls/ca.crt in your browser):" echo "Import the CA into your browser:"
echo " - Console : https://console.gravitee.sttlab.pc"
echo " - Portal : https://portal.gravitee.sttlab.pc"
echo " - API : https://api.gravitee.sttlab.pc/management"
echo " - Gateway : https://gateway.gravitee.sttlab.pc"
echo ""
echo "To export the CA cert for your trust store:"
echo " kubectl -n ${NAMESPACE} get secret gravitee-ca-tls -o jsonpath='{.data.ca\\.crt}' | base64 -d > gravitee-ca.crt" echo " kubectl -n ${NAMESPACE} get secret gravitee-ca-tls -o jsonpath='{.data.ca\\.crt}' | base64 -d > gravitee-ca.crt"
echo ""
echo "Admin credentials:"
echo " Username: admin"
echo " Password: $(kubectl -n ${NAMESPACE} get secret gravitee-admin -o jsonpath='{.data.admin-password-plain}' | base64 -d)"
echo ""
echo "URLs:"
echo " Console : https://console.gravitee.sttlab.pc"
echo " Portal : https://portal.gravitee.sttlab.pc"
echo " API : https://api.gravitee.sttlab.pc/management"
echo " Gateway : https://gateway.gravitee.sttlab.pc"
+8 -1
View File
@@ -50,8 +50,15 @@ kubectl -n "${NS}" create secret generic gravitee-jwt \
--from-literal=GRAVITEE_JWT_SECRET="${JWT_SECRET}" \ --from-literal=GRAVITEE_JWT_SECRET="${JWT_SECRET}" \
--dry-run=client -o yaml | kubectl apply -f - --dry-run=client -o yaml | kubectl apply -f -
echo "==> Creating CA trust secret for nginx ingress proxy-ssl-secret"
# Contains only ca.crt (no tls.crt/key) to avoid nginx presenting the CA as a client cert.
kubectl -n "${NS}" get secret gravitee-ca-tls -o jsonpath='{.data.ca\.crt}' | base64 -d | \
kubectl -n "${NS}" create secret generic gravitee-ca-trust \
--from-file=ca.crt=/dev/stdin \
--dry-run=client -o yaml | kubectl apply -f -
echo "" echo ""
echo "==> Done. Secrets created in namespace ${NS}:" echo "==> Done. Secrets created in namespace ${NS}:"
kubectl -n "${NS}" get secrets | grep -E 'mongodb-credentials|gravitee-mongodb-uri|gravitee-admin|gravitee-jwt' kubectl -n "${NS}" get secrets | grep -E 'mongodb-credentials|gravitee-mongodb-uri|gravitee-admin|gravitee-jwt|gravitee-jks-password|gravitee-ca-trust'
echo "" echo ""