Skip to content

Commit

Permalink
Separate truststore and keystore config
Browse files Browse the repository at this point in the history
Configure the JVM truststore using the JDK_JAVA_OPTION env var. HTTP server keystore configuration is stored in the spring app env var.
  • Loading branch information
Josh Hunziker committed Jun 14, 2024
1 parent e2ccb09 commit d3fc553
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 169 deletions.
5 changes: 4 additions & 1 deletion operator/crd/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ spec:
- key
- type
keystore:
description: "Configure server TLS connections using a JKS keystore. The keystore password should be stored in a secret and referenced in the route Custom Resource as a secretSource. The format of the secret should be `server.ssl.key-store-password=password`."
description: "Configure HTTP server TLS connections using a JKS or PKCS12 keystore. The keystore password should be stored in a secret and referenced in the route Custom Resource. The format of the secret should be `password=<password>`."
type: object
properties:
secretName:
Expand All @@ -122,10 +122,13 @@ spec:
enum:
- jks
- pkcs12
passwordSecretRef:
type: string
required:
- secretName
- key
- type
- passwordSecretRef
required:
- routeConfigMap
required:
Expand Down
6 changes: 6 additions & 0 deletions operator/example/testroute.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ spec:
# group: abc
secretSources:
- testroute-secret
tls:
keystore:
secretName: test-keystore
type: jks
key: keystore.jks
passwordSecretRef: jks-password
123 changes: 62 additions & 61 deletions operator/webhook/introute/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,36 @@ def _spring_cloud_k8s_config(parent) -> Optional[Mapping]:
}


def _spring_app_config_env_var(parent) -> Mapping[str, str]:
def _get_server_ssl_config(parent) -> Optional[Mapping]:
tls_config = parent["spec"].get("tls")
if not tls_config:
return None

keystore = tls_config.get("keystore")

if not keystore:
return None

return {
"ssl": {
"key-alias": "certificate",
"key-store": str(Path(KEYSTORE_PATH, keystore["key"])),
"key-store-type": keystore["type"].upper()
},
"port": 8443
}


def _spring_app_config_env_var(parent) -> Optional[Mapping]:
metadata = parent["metadata"]
app_config = {
"spring": {
"application": {"name": metadata["name"]},
}
}
app_config["management"] = {
"server": {
"port": 80,
"ssl": {
"enabled": False
}
}
}

if tls_config := _get_server_ssl_config(parent):
app_config["server"] = tls_config

if cloud_config := _spring_cloud_k8s_config(parent):
app_config["spring"]["config.import"] = "kubernetes:"
Expand All @@ -200,69 +215,53 @@ def _spring_app_config_env_var(parent) -> Mapping[str, str]:
}


def _get_tls_options(parent) -> Optional[List[Mapping[str, str]]]:
tls_config = parent["spec"].get("tls")
def _get_keystore_password_env(tls) -> Mapping[str, str]:

if not tls_config:
keystore = tls.get("keystore")

if not keystore:
return None

tls_env_vars = []
if 'truststore' in tls_config:
tls_type = tls_config['truststore']['type']
_validate_tls_type(tls_type)
truststore_password = "changeit" if tls_type == "jks" else ""
truststore_vars = [
{
"name": "SERVER_SSL_TRUSTSTORE",
"value": str(Path(TRUSTSTORE_PATH, tls_config['truststore']['key']))
},
{
"name": "SERVER_SSL_TRUSTSTOREPASSWORD",
"value": truststore_password
},
{
"name": "SERVER_SSL_TRUSTSTORETYPE",
"value": tls_type.upper()
return {
"name": "SERVER_SSL_KEYSTOREPASSWORD",
"valueFrom": {
"secretKeyRef": {
"name": keystore["passwordSecretRef"],
"key": "password"
}
]
tls_env_vars.extend(truststore_vars)
}
}

if 'keystore' in tls_config:
tls_type = tls_config['keystore']['type']
_validate_tls_type(tls_type)
keystore_vars = [
{
"name": "SERVER_PORT",
"value": 443
},
{
"name": "SERVER_SSL_KEYSTORE",
"value": str(Path(KEYSTORE_PATH, tls_config['keystore']['key']))
},
{
"name": "SERVER_SSL_KEYSTORETYPE",
"value": tls_type.upper()
},
{
"name": "SERVER_SSL_KEYALIAS",
"value": "certificate"
}
]
tls_env_vars.extend(keystore_vars)
return tls_env_vars

def _validate_tls_type(tls_type):
assert tls_type in ["jks", "pkcs12"], \
f"({tls_type}) is not a supported TLS type. Supported types: ('jks', 'pkcs12')"
def _get_java_jdk_options(tls) -> Optional[Mapping[str, str]]:

truststore = tls.get("truststore")

if not truststore:
return None

tls_type = truststore["type"]
truststore_password = "changeit" if tls_type == "jks" else ""

return {
"name": "JDK_JAVA_OPTIONS",
"value": f"-Djavax.net.ssl.trustStore={str(Path(TRUSTSTORE_PATH, truststore['key']))} -Djavax.net.ssl.trustStorePassword={truststore_password} -Djavax.net.ssl.trustStoreType={tls_type.upper()}"
}


def _generate_container_env_vars(parent) -> List[Mapping[str, str]]:
env_vars = []

if spring_app_config := _spring_app_config_env_var(parent):
env_vars.append(spring_app_config)

if tls_options := _get_tls_options(parent):
env_vars.extend(tls_options)
if tls := parent["spec"].get("tls"):
if jdk_options := _get_java_jdk_options(tls):
env_vars.append(jdk_options)

if keystore_password_env := _get_keystore_password_env(tls):
env_vars.append(keystore_password_env)


return env_vars

Expand All @@ -284,14 +283,16 @@ def _create_pod_template(parent, labels, integration_image):
"livenessProbe": {
"httpGet": {
"path": "/actuator/health/liveness",
"port": 80,
"port": 8443,
"scheme": "HTTPS"
},
"initialDelaySeconds": 10,
},
"readinessProbe": {
"httpGet": {
"path": "/actuator/health/readiness",
"port": 80,
"port": 8443,
"scheme": "HTTPS"
},
"initialDelaySeconds": 10,
},
Expand Down
3 changes: 2 additions & 1 deletion operator/webhook/test/json/full-iroute-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"keystore": {
"secretName": "test-tls-secret",
"key": "test-keystore.jks",
"type": "jks"
"type": "jks",
"passwordSecretRef": "keystore-password-ref"
},
"truststore": {
"configMapName": "test-tls-cm",
Expand Down
43 changes: 15 additions & 28 deletions operator/webhook/test/json/full-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,49 +79,36 @@
"livenessProbe": {
"httpGet": {
"path": "/actuator/health/liveness",
"port": 80
"port": 8443,
"scheme": "HTTPS"
},
"initialDelaySeconds": 10
},
"readinessProbe": {
"httpGet": {
"path": "/actuator/health/readiness",
"port": 80
"port": 8443,
"scheme": "HTTPS"
},
"initialDelaySeconds": 10
},
"env": [
{
"name": "SPRING_APPLICATION_JSON",
"value": "{\"spring\": {\"application\": {\"name\": \"testroute\"}, \"config.import\": \"kubernetes:\", \"cloud\": {\"kubernetes\": {\"config\": {\"fail-fast\": true, \"namespace\": \"testspace\", \"sources\": [{\"name\": \"testroute-props\"}, {\"labels\": {\"group\": \"ir-common\"}}]}, \"secrets\": {\"paths\": \"/etc/secrets\"}}}}, \"management\": {\"server\": {\"port\": 80, \"ssl\": {\"enabled\": false}}}}"
"value": "{\"spring\": {\"application\": {\"name\": \"testroute\"}, \"config.import\": \"kubernetes:\", \"cloud\": {\"kubernetes\": {\"config\": {\"fail-fast\": true, \"namespace\": \"testspace\", \"sources\": [{\"name\": \"testroute-props\"}, {\"labels\": {\"group\": \"ir-common\"}}]}, \"secrets\": {\"paths\": \"/etc/secrets\"}}}}, \"server\": {\"ssl\": {\"key-alias\": \"certificate\", \"key-store\": \"/etc/keystore/test-keystore.jks\", \"key-store-type\": \"JKS\"}, \"port\": 8443}}"
},
{
"name": "SERVER_SSL_TRUSTSTORE",
"value": "/etc/cabundle/test-truststore.p12"
"name": "JDK_JAVA_OPTIONS",
"value": "-Djavax.net.ssl.trustStore=/etc/cabundle/test-truststore.p12 -Djavax.net.ssl.trustStorePassword= -Djavax.net.ssl.trustStoreType=PKCS12"
},
{
"name": "SERVER_SSL_TRUSTSTOREPASSWORD",
"value": ""
},
{
"name": "SERVER_SSL_TRUSTSTORETYPE",
"value": "PKCS12"
},
{
"name": "SERVER_PORT",
"value": 443
},
{
"name": "SERVER_SSL_KEYSTORE",
"value": "/etc/keystore/test-keystore.jks"
},
{
"name": "SERVER_SSL_KEYSTORETYPE",
"value": "JKS"
},
{
"name": "SERVER_SSL_KEYALIAS",
"value": "certificate"
"name": "SERVER_SSL_KEYSTOREPASSWORD",
"valueFrom": {
"secretKeyRef": {
"name": "keystore-password-ref",
"key": "password"
}
}
}
]
}
Expand Down Expand Up @@ -187,4 +174,4 @@
}
}
]
}
}
Loading

0 comments on commit d3fc553

Please sign in to comment.