Skip to content

Commit 9b4512c

Browse files
authored
Merge pull request #207 from iankko/KEYCLOAK-15633
[KEYCLOAK-15633] Add support for "${prefix}_CONNECTION_PROPERTY_*" for non-XA datasources too
2 parents e8a5375 + 654231a commit 9b4512c

File tree

6 files changed

+315
-55
lines changed

6 files changed

+315
-55
lines changed

modules/eap/setup/eap/modules/added/launch/datasource-common.sh

Lines changed: 137 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,16 @@ function clearDatasourceEnv() {
4949
unset ${prefix}_BACKGROUND_VALIDATION
5050
unset ${prefix}_BACKGROUND_VALIDATION_MILLIS
5151

52-
for xa_prop in $(compgen -v | grep -s "${prefix}_XA_CONNECTION_PROPERTY_"); do
53-
unset ${xa_prop}
52+
### Start of RH-SSO add-on -- KEYCLOAK-15633:
53+
### -----------------------------------------
54+
### Remove / undefine also "${prefix}_CONNECTION_PROPERTY_*" env vars when
55+
### removing / undefining "${prefix}_XA_CONNECTION_PROPERTY_*" env vars
56+
for property in $(compgen -v | grep -oPs "${prefix}(|_XA)_CONNECTION_PROPERTY_"); do
57+
unset "${property}"
5458
done
5559
}
60+
### End of RH-SSO add-on
61+
### --------------------
5662

5763
function clearDatasourcesEnv() {
5864
IFS=',' read -a db_backends <<< $DB_SERVICE_PREFIX_MAPPING
@@ -372,42 +378,99 @@ function generate_external_datasource() {
372378
fi
373379
}
374380

381+
### Start of RH-SSO add-on -- KEYCLOAK-15633:
382+
### -----------------------------------------
383+
### Allow specification of datasource connection properties for:
384+
### 1) XA datasources via the DB_XA_CONNECTION_PROPERTY_<property_name> and
385+
### 2) Non-XA datasources via the DB_CONNECTION_PROPERTY_<property_name>
386+
###
387+
### environment variable(s) defined on the container image. The <property_name>
388+
### in the above expressions is the actual name of the connection property to
389+
### be set on the underlying datasource.
390+
###
391+
function inject_connection_properties_to_datasource_xml() {
392+
local ds="${1}"
393+
394+
local failed="false"
395+
local is_xa_ds="false"
396+
397+
if [[ "${ds}" =~ \<datasource[[:space:]].*$ ]]; then
398+
local conn_prop_env_var="${prefix}_CONNECTION_PROPERTY_"
399+
local conn_prop_xml_elem_name="connection-property"
400+
elif [[ "${ds}" =~ \<xa-datasource[[:space:]].*$ ]]; then
401+
local conn_prop_env_var="${prefix}_XA_CONNECTION_PROPERTY_"
402+
local conn_prop_xml_elem_name="xa-datasource-property"
403+
is_xa_ds="true"
404+
else
405+
log_warning "Unable to determine if '${ds}' datasource is a non-XA or XA one."
406+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
407+
failed="true"
408+
fi
409+
410+
declare -ra conn_props=($(compgen -v | grep -s "${conn_prop_env_var}"))
411+
if [ "${is_xa_ds}" == "true" ] && [ -z "${conn_props}" ]; then
412+
log_warning "At least one ${prefix}_XA_CONNECTION_PROPERTY_property for datasource ${service_name} is required."
413+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
414+
failed="true"
415+
fi
416+
417+
if [ "${failed}" != "true" ]; then
418+
for property in "${conn_props[@]}"; do
419+
prop_name=$(sed -e "s/${conn_prop_env_var}//g" <<< "${property}")
420+
prop_value=$(find_env "${property}")
421+
if [ ! -z "${prop_value}" ]; then
422+
ds="${ds}
423+
<${conn_prop_xml_elem_name} name=\"${prop_name}\">${prop_value}</${conn_prop_xml_elem_name}>"
424+
fi
425+
done
426+
fi
427+
428+
# 'ds' value of empty string indicates an error occurred earlier
429+
if [ "${failed}" == "true" ]; then
430+
echo ""
431+
else
432+
echo "${ds}"
433+
fi
434+
}
435+
### End of RH-SSO add-on
436+
### --------------------
437+
375438
function generate_external_datasource_xml() {
439+
440+
### Start of RH-SSO add-on -- KEYCLOAK-15633:
441+
### -----------------------------------------
442+
### Modify the 'generate_external_datasource_xml()' method to
443+
### allow specification of connection properties also for non-XA datasources
444+
376445
local failed="false"
446+
local ds_universal_attrs="jndi-name=\"${jndi_name}\" pool-name=\"${pool_name}\" enabled=\"true\" use-java-context=\"true\" statistics-enabled=\"\${wildfly.datasources.statistics-enabled:\${wildfly.statistics-enabled:false}}\""
377447

378448
if [ -n "$NON_XA_DATASOURCE" ] && [ "$NON_XA_DATASOURCE" = "true" ]; then
379-
ds="<datasource jta=\"${jta}\" jndi-name=\"${jndi_name}\" pool-name=\"${pool_name}\" enabled=\"true\" use-java-context=\"true\" statistics-enabled=\"\${wildfly.datasources.statistics-enabled:\${wildfly.statistics-enabled:false}}\">
380-
<connection-url>${url}</connection-url>
381-
<driver>$driver</driver>"
449+
ds="<datasource jta=\"${jta}\" ${ds_universal_attrs}>
450+
<connection-url>${url}</connection-url>"
382451
else
383-
ds=" <xa-datasource jndi-name=\"${jndi_name}\" pool-name=\"${pool_name}\" enabled=\"true\" use-java-context=\"true\" statistics-enabled=\"\${wildfly.datasources.statistics-enabled:\${wildfly.statistics-enabled:false}}\">"
384-
local xa_props=$(compgen -v | grep -s "${prefix}_XA_CONNECTION_PROPERTY_")
385-
if [ -z "$xa_props" ]; then
386-
log_warning "At least one ${prefix}_XA_CONNECTION_PROPERTY_property for datasource ${service_name} is required. Datasource will not be configured."
387-
failed="true"
388-
else
389-
390-
for xa_prop in $(echo $xa_props); do
391-
prop_name=$(echo "${xa_prop}" | sed -e "s/${prefix}_XA_CONNECTION_PROPERTY_//g")
392-
prop_val=$(find_env $xa_prop)
393-
if [ ! -z ${prop_val} ]; then
394-
ds="$ds <xa-datasource-property name=\"${prop_name}\">${prop_val}</xa-datasource-property>"
395-
fi
396-
done
452+
ds="<xa-datasource ${ds_universal_attrs}>"
453+
fi
397454

398-
ds="$ds
399-
<driver>${driver}</driver>"
400-
fi
455+
ds=$(inject_connection_properties_to_datasource_xml "${ds}")
456+
# 'ds' value of empty string indicates an error occurred earlier
457+
if [ "${ds}" == "" ]; then
458+
failed="true"
401459
fi
402460

461+
ds="$ds
462+
<driver>${driver}</driver>"
463+
### End of RH-SSO add-on
464+
### --------------------
465+
403466
if [ -n "$tx_isolation" ]; then
404467
ds="$ds
405-
<transaction-isolation>$tx_isolation</transaction-isolation>"
468+
<transaction-isolation>$tx_isolation</transaction-isolation>"
406469
fi
407470

408471
if [ -n "$min_pool_size" ] || [ -n "$max_pool_size" ]; then
409472
if [ -n "$NON_XA_DATASOURCE" ] && [ "$NON_XA_DATASOURCE" = "true" ]; then
410-
ds="$ds
473+
ds="$ds
411474
<pool>"
412475
else
413476
ds="$ds
@@ -473,9 +536,19 @@ function generate_external_datasource_xml() {
473536
fi
474537
}
475538

539+
### Start of RH-SSO add-on -- KEYCLOAK-15633:
540+
### -----------------------------------------
541+
### Allow specification of datasource connection properties for:
542+
### 1) XA datasources via the DB_XA_CONNECTION_PROPERTY_<property_name> and
543+
### 2) Non-XA datasources via the DB_CONNECTION_PROPERTY_<property_name>
544+
###
545+
### environment variable(s) defined on the container image. The <property_name>
546+
### in the above expressions is the actual name of the connection property to
547+
### be set on the underlying datasource.
548+
###
476549
function generate_external_datasource_cli() {
477550
local failed="false"
478-
551+
local is_xa_ds="false"
479552
local subsystem_addr="/subsystem=datasources"
480553
local ds_resource="${subsystem_addr}"
481554
local other_ds_resource
@@ -487,32 +560,41 @@ function generate_external_datasource_cli() {
487560
ds_tmp_key_values["statistics-enabled"]="\${wildfly.datasources.statistics-enabled:\${wildfly.statistics-enabled:false}}"
488561
ds_tmp_key_values["driver-name"]="${driver}"
489562

490-
local -A ds_tmp_xa_connection_properties
563+
local -A ds_tmp_connection_properties
491564

492565
if [ -n "$NON_XA_DATASOURCE" ] && [ "$NON_XA_DATASOURCE" = "true" ]; then
493566
ds_resource="${subsystem_addr}/data-source=${pool_name}"
494567
other_ds_resource="${subsystem_addr}/xa-data-source=${pool_name}"
495568

569+
local conn_prop_env_var="${prefix}_CONNECTION_PROPERTY_"
570+
local conn_prop_cli_elem_name="connection-properties"
571+
496572
ds_tmp_key_values["jta"]="${jta}"
497573
ds_tmp_key_values['connection-url']="${url}"
498574

499575
else
500576
ds_resource="${subsystem_addr}/xa-data-source=${pool_name}"
501577
other_ds_resource="${subsystem_addr}/data-source=${pool_name}"
502578

503-
local xa_props=$(compgen -v | grep -s "${prefix}_XA_CONNECTION_PROPERTY_")
504-
if [ -z "$xa_props" ] && [ "$driver" != "postgresql" ] && [ "$driver" != "mysql" ]; then
505-
log_warning "At least one ${prefix}_XA_CONNECTION_PROPERTY_property for datasource ${service_name} is required. Datasource will not be configured."
579+
local conn_prop_env_var="${prefix}_XA_CONNECTION_PROPERTY_"
580+
local conn_prop_cli_elem_name="xa-datasource-properties"
581+
is_xa_ds="true"
582+
583+
declare -ra conn_props=($(compgen -v | grep -s "${conn_prop_env_var}"))
584+
if [ "${is_xa_ds}" == "true" ] && [ -z "${conn_props}" ]; then
585+
log_warning "At least one ${prefix}_XA_CONNECTION_PROPERTY_property for datasource ${service_name} is required."
586+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
506587
failed="true"
507588
else
508-
509-
for xa_prop in $(echo $xa_props); do
510-
prop_name=$(echo "${xa_prop}" | sed -e "s/${prefix}_XA_CONNECTION_PROPERTY_//g")
511-
prop_val=$(find_env $xa_prop)
512-
if [ ! -z ${prop_val} ]; then
513-
ds_tmp_xa_connection_properties["$prop_name"]="$prop_val"
514-
fi
515-
done
589+
if [ "${failed}" != "true" ]; then
590+
for property in "${conn_props[@]}"; do
591+
prop_name=$(sed -e "s/${conn_prop_env_var}//g" <<< "${property}")
592+
prop_value=$(find_env "${property}")
593+
if [ ! -z "${prop_value}" ]; then
594+
ds_tmp_connection_properties["${prop_name}"]="${prop_value}"
595+
fi
596+
done
597+
fi
516598
fi
517599
fi
518600

@@ -559,11 +641,11 @@ function generate_external_datasource_cli() {
559641
done
560642
ds_tmp_add="${ds_tmp_add})"
561643

562-
# Add the xa-ds properties
563-
local ds_tmp_xa_properties
564-
for key in "${!ds_tmp_xa_connection_properties[@]}"; do
565-
ds_tmp_xa_properties="${ds_tmp_xa_properties}
566-
$ds_resource/xa-datasource-properties=${key}:add(value=\"${ds_tmp_xa_connection_properties[$key]}\")
644+
# Add the connection properties to both XA & non-XA datasource
645+
local ds_tmp_conn_props_add
646+
for key in "${!ds_tmp_connection_properties[@]}"; do
647+
ds_tmp_conn_props_add="${ds_tmp_conn_props_add}
648+
$ds_resource/${conn_prop_cli_elem_name}=${key}:add(value=\"${ds_tmp_connection_properties[$key]}\")
567649
"
568650
done
569651

@@ -589,9 +671,12 @@ function generate_external_datasource_cli() {
589671
590672
batch
591673
${ds_tmp_add}
592-
${ds_tmp_xa_properties}
674+
${ds_tmp_conn_props_add}
593675
run-batch
594676
"
677+
### End of RH-SSO add-on
678+
### --------------------
679+
595680
if [ "$failed" == "true" ]; then
596681
echo ""
597682
else
@@ -810,10 +895,12 @@ function map_properties() {
810895
if [ -z "$(eval echo \$${prefix}_XA_CONNECTION_PROPERTY_URL)" ]; then
811896
if [ -z "${!serverNameVar}" ] || [ -z "${!portVar}" ] || [ -z "${!databaseNameVar}" ]; then
812897
if [ "$prefix" != "$service" ]; then
813-
log_warning "Missing configuration for datasource $prefix. ${service}_SERVICE_HOST, ${service}_SERVICE_PORT, and/or ${prefix}_DATABASE is missing. Datasource will not be configured."
898+
log_warning "Missing configuration for datasource $prefix. ${service}_SERVICE_HOST, ${service}_SERVICE_PORT, and/or ${prefix}_DATABASE is missing."
899+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
814900
eval ${invalidVar}="true"
815901
else
816-
log_warning "Missing configuration for XA datasource $prefix. Either ${prefix}_XA_CONNECTION_PROPERTY_URL or $serverNameVar, and $portVar, and $databaseNameVar is required. Datasource will not be configured."
902+
log_warning "Missing configuration for XA datasource $prefix. Either ${prefix}_XA_CONNECTION_PROPERTY_URL or $serverNameVar, and $portVar, and $databaseNameVar is required."
903+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
817904
eval ${invalidVar}="true"
818905
fi
819906
else
@@ -823,7 +910,8 @@ function map_properties() {
823910
fi
824911
fi
825912
else
826-
log_warning "Missing configuration for datasource $prefix. ${service}_SERVICE_HOST, ${service}_SERVICE_PORT, and/or ${prefix}_DATABASE is missing. Datasource will not be configured."
913+
log_warning "Missing configuration for datasource $prefix. ${service}_SERVICE_HOST, ${service}_SERVICE_PORT, and/or ${prefix}_DATABASE is missing."
914+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
827915
eval ${invalidVar}="true"
828916
fi
829917

@@ -950,7 +1038,8 @@ function inject_datasource() {
9501038
fi
9511039

9521040
if [ -z "$driver" ]; then
953-
log_warning "DRIVER not set for datasource ${service_name}. Datasource will not be configured."
1041+
log_warning "DRIVER not set for datasource ${service_name}."
1042+
log_warning "Datasource '$(basename ${jndi_name})' will not be configured."
9541043
else
9551044
datasource=$(generate_datasource "${service,,}-${prefix}" "$jndi" "$username" "$password" "$host" "$port" "$database" "$checker" "$sorter" "$driver" "$service_name" "$jta" "$validate" "$url")
9561045

@@ -1054,4 +1143,4 @@ function inject_job_repository() {
10541143
echo "${cli}" >> "${DEFAULT_JOB_REPOSITORY_FILE}"
10551144
fi
10561145

1057-
}
1146+
}

s2i/postgresql/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SSL/TLS support for PostgreSQL SQL database server container image
2+
3+
The [PostgreSQL 10 SQL database server](https://catalog.redhat.com/software/containers/rhscl/postgresql-10-rhel7/5aa63541ac3db95f196086f1)
4+
doesn't support SSL/TLS encryption by default. In order to enable the
5+
SSL/TLS encryption, the PostgreSQL server container image needs to be
6+
extended using the [source-to-image](https://github.com/openshift/source-to-image)
7+
method. Refer to [_*Extending image*_](https://catalog.redhat.com/software/containers/rhscl/postgresql-10-rhel7/5aa63541ac3db95f196086f1)
8+
and primarily to [the available example](https://github.com/sclorg/postgresql-container/tree/master/examples/enable-ssl)
9+
for additional details.
10+
11+
This (sub)directory contains all the information needed to enable SSL/TLS
12+
support for the [PostgreSQL 10 SQL database server](https://catalog.redhat.com/software/containers/rhscl/postgresql-10-rhel7/5aa63541ac3db95f196086f1)
13+
used in the available PostgreSQL [templates](https://github.com/jboss-container-images/redhat-sso-7-openshift-image/tree/sso75-dev/templates)
14+
for [Red Hat Single Sign-On 7.5 for OpenJDK / OpenJ9 on OpenShift container images](https://github.com/jboss-container-images/redhat-sso-7-openshift-image/tree/sso75-dev).
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Example to enable SSL/TLS for the PostgreSQL SQL database server container image
2+
3+
Inspired by the ["enable-ssl"](https://github.com/sclorg/postgresql-container/tree/master/examples/enable-ssl)
4+
example from the Red Hat Software Collections PostgreSQL container images repository.
5+
6+
Compared to the original, this example does NOT store the TLS certificate & private
7+
key files directly in the repository. Instead of that, those files are generated
8+
on the fly by the PostgreSQL OpenShift service using the OpenShift's service serving
9+
certificate secrets mechanism based on the corresponding annotation applied to the
10+
definition of the PostgreSQL service.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
ssl = on
2+
# The TLS certificate & key are generated using the OpenShift's service serving
3+
# certificate secrets via corresponding annotation of the PostgreSQL service
4+
# and stored into a read-only persistent volume, corresponding to the OpenShift
5+
# secret.
6+
#
7+
# Later the 'postgresql-pre-start/enable_ssl.sh' script, present in this
8+
# repository, copies the generated TLS certificate & key to by current UID
9+
# writable "/var/run/postgresql/pki" directory, so it's possible to correct
10+
# the permissions of the TLS private key to mode required by PostgreSQL server
11+
ssl_cert_file = '/var/run/postgresql/pki/tls.crt' # PostgreSQL server certificate
12+
ssl_key_file = '/var/run/postgresql/pki/tls.key' # PostgreSQL server private key
13+
ssl_ca_file = '/run/secrets/kubernetes.io/serviceaccount/ca.crt' # OpenShift CA
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
set -eu
4+
5+
# Copy the TLS certificate & key generated by the OpenShift's service serving
6+
# certificate secrets from "/etc/pki/postgresql" (which is mounted read-only,
7+
# since coming from secret) to "/var/run/postgresql/pki", so it's possible to
8+
# correct the permissions of the TLS private key as required below
9+
SOURCE_DIR="/etc/pki/postgresql"
10+
DESTINATION_DIR="/var/run/postgresql/pki"
11+
if [ ! -d "${DESTINATION_DIR}" ]; then
12+
mkdir -p "${DESTINATION_DIR}"
13+
fi
14+
cp "${SOURCE_DIR}"/tls.{crt,key} "${DESTINATION_DIR}"
15+
16+
# PostgreSQL will fail to start and throw an error like:
17+
#
18+
# FATAL: private key file "/path/to/key" has group or world access
19+
# File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.
20+
#
21+
# if the permissions of the TLS private key are incorrect.
22+
#
23+
# Thus correct the permissions so PostgreSQL server can start successfully
24+
chmod 0600 "${DESTINATION_DIR}/tls.key"

0 commit comments

Comments
 (0)