Skip to content

Commit

Permalink
Update import additional CA certificates chapter (#1719)
Browse files Browse the repository at this point in the history
Update import additional CA certificates chapter

Signed-off-by: Mykola Morhun <mmorhun@redhat.com>
  • Loading branch information
mmorhun committed Dec 15, 2020
1 parent 715faa6 commit b309a50
Show file tree
Hide file tree
Showing 3 changed files with 378 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[id="importing-untrusted-tls-certificates-old"]
// = Importing untrusted TLS certificates
:navtitle: Importing untrusted TLS certificates to {prod-short}
:keywords: installation-guide, tls, certificate
:page-aliases: .:importing-untrusted-tls-certificates-old

include::partial$proc_importing-untrusted-tls-certificates-old.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@

[id="importing-untrusted-tls-certificates_{context}"]
= Importing untrusted TLS certificates to {prod-short}

====
NOTE: Starting from {prod-short} version
ifeval::["{project-context}" == "che"]
v7.23.0
endif::[]
ifeval::["{project-context}" != "che"]
2.5.1
endif::[]
there is xref:importing-untrusted-tls-certificates.adoc[newer way] to apply additional TLS certificates.
This method is kept for backward compatibility.
====

Internal communications between {prod-short} components are, by default, encrypted with TLS. Communications of {prod-short} components with external services such as proxies, source code repositories, identity providers may require TLS tool. Those communications require the use of TLS certificates signed by trusted Certificate Authorities.

When the certificates used by {prod-short} components or by an external service are signed by an untrusted CA it can be necessary to import the CA certificate in the {prod-short} installation, so that every {prod-short} component will consider them as signed by a trusted CA.

Typical cases that may require this addition are:

* when the underlying Kubernetes cluster uses TLS certificates signed by a CA that is not trusted,
* when {prod-short} server or workspace components connect to external services such as {identity-provider} or a Git server that use TLS certificates signed by an untrusted CA.

To store those certificates, {prod-short} uses a dedicated ConfigMap. Its default name is `ca-certs` but {prod-short} allows configuring its name.

[NOTE]
====
ifeval::["{project-context}" == "che"]
On OpenShift, when
endif::[]
ifeval::["{project-context}" != "che"]
When
endif::[]
the cluster contains cluster-wide trusted CA certificates added through the link:https://docs.openshift.com/container-platform/4.4/networking/configuring-a-custom-pki.html#nw-proxy-configure-object_configuring-a-custom-pki[cluster-wide-proxy configuration], {prod-short} Operator detects them and automatically injects them into this ConfigMap:
- {prod-short} automatically labels the ConfigMap with the `config.openshift.io/inject-trusted-cabundle="true"` label.
- Based on this annotation, OpenShift automatically injects the cluster-wide trusted CA certificates inside the `ca-bundle.crt` key of ConfigMap
====

== At {prod-short} installation time

.Prerequisites

* The `{orch-cli}` tool is available.
* You are ready to create `CheCluster` custom resource.

.Procedure

include::example$snip_importing-untrusted-tls-certificates_1.adoc[]

. Create a new ConfigMap with the required TLS certificates:
+
[subs="+attributes,+quotes"]
----
$ {orch-cli} create configmap ca-certs --from-file=__<certificate-file-path>__ -n=__<{project-context}-namespace-name>__
----
+
To apply more than one certificate, add another `--from-file=_<certificate-file-path>_` option to the above command.

. During the installation process, when creating the `CheCluster` custom resource, take care of configuring the right name for the created ConfigMap.
+
====
For a {prod-short} link:https://docs.openshift.com/container-platform/latest/operators/olm-what-operators-are.html[Operator] deployment,
ensure you add the `spec.server.ServerTrustStoreConfigMapName` field with the name of the ConfigMap, to the `CheCluster` Custom Resource you will create during the installation:
[source,yaml,subs="+quotes",options="nowrap",role=white-space-pre]
----
spec:
server:
...
spec.server.ServerTrustStoreConfigMapName: ca-certs
----
====
ifeval::["{project-context}" == "che"]
+
====
For a {prod-short} link:https://helm.sh/[Helm Chart] deployment, ensure you override the `global.tls.serverTrustStoreConfigMapName` Helm Chart property with the name of the ConfigMap when installing the {prod-short} Helm Chart. For this you should add the following arguments to the Helm command line:
[subs="+quotes",options="nowrap",role=white-space-pre]
----
--set global.tls.serverTrustStoreConfigMapName=ca-certs
----
====
endif::[]

== On already-running {prod-short} installations

.Prerequisites

* The `{orch-cli}` tool is available.

* You should first gather the name of the ConfigMap used to import certificates:
+
====
On instances of {prod-short} deployed with the {prod-short} link:https://docs.openshift.com/container-platform/latest/operators/olm-what-operators-are.html[Operator],
retrieve the name of the ConfigMap by reading the `spec.server.ServerTrustStoreConfigMapName` `CheCluster` Custom Resource property:
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get checluster {prod-checluster} -n __<{project-context}-namespace-name>__ -o jsonpath={.spec.server.serverTrustStoreConfigMapName}
----
====
ifeval::["{project-context}" == "che"]
+
====
On instances of {prod-short} deployed with the {prod-short} link:https://helm.sh/[Helm Chart] deployment, retrieve the name of the ConfigMap by reading the `global.tls.serverTrustStoreConfigMapName` property from the Helm Chart:
[subs="+quotes",options="nowrap",role=white-space-pre]
----
$ helm get values che --all --output json | jq -r '.global.tls.serverTrustStoreConfigMapName'
----
====
endif::[]
+
[NOTE]
====
If the existing installation did not define any name for the ConfigMap, just use `ca-certs`.
====

.Procedure

include::example$snip_importing-untrusted-tls-certificates_1.adoc[]

. Add the required TLS certificates in the ConfigMap:
+
[subs="+attributes,+quotes"]
----
$ {orch-cli} create configmap __<config-map-name>__ --from-file=__<certificate-file-path>__ -n=__<{project-context}-namespace-name>__ -o yaml --dry-run | {orch-cli} apply -f -
----
+
To apply more than one certificate, add another `--from-file=_<certificate-file-path>_` option to the above command.

. Configure the {prod-short} installation to use the ConfigMap:
+
====
For a {prod-short} link:https://docs.openshift.com/container-platform/latest/operators/olm-what-operators-are.html[Operators] deployment:
. Edit the `spec.server.ServerTrustStoreConfigMapName` `CheCluster` Custom Resource property to match the name of the ConfigMap:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} patch checluster {prod-checluster} -n __<{project-context}-namespace-name>__ --type=json -p '[{"op": "replace", "path": "/spec/server/serverTrustStoreConfigMapName", "value": "<config-map-name>"}]'
----
+
====
ifeval::["{project-context}" == "che"]
+
====
For a {prod-short} link:https://helm.sh/[Helm Chart] deployment:
. Clone the https://github.com/eclipse/che[che] project.
. Go to the `deploy/kubernetes/helm/che` directory.
. Update the name of the configMap {prod-short} will use, by editing the `global.tls.serverTrustStoreConfigMapName` Helm Chart property to match the created or updated ConfigMap:
+
[subs="+quotes",options="nowrap",role=white-space-pre]
----
$ helm upgrade che -n che --set global.tls.serverTrustStoreConfigMapName=<config-map-name> \
--set global.ingressDomain=__<kubernetes-cluster-domain>__ .
----
+
When using Minikube to run {prod-short}, substitute _<kubernetes-cluster-domain>_ with `$(minikube ip).nip.io`.
====
endif::[]

. Restart the {prod-short} Operator, the {prod-short} server and {identity-provider} to load the new certificates:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ kubectl rollout restart -n __<{project-context}-namespace-name>__ deployment/{prod-id-short}-operator
$ kubectl rollout restart -n __<{project-context}-namespace-name>__ deployment/keycloak
$ kubectl rollout restart -n __<{project-context}-namespace-name>__ deployment/{prod-id-short}
----
+
[NOTE]
====
Restarting the {prod-short} components is not required anymore on {prod-short}
ifeval::["{project-context}" == "che"]
v7.20.0
endif::[]
ifeval::["{project-context}" != "che"]
2.5.0
endif::[]
and higher.
====

== Verification at the {prod-short} installation level

If you added the certificates without error, the {prod-short} server starts and obtains {identity-provider} configuration over https. Otherwise here is a list of things to verify:

. In case of a {prod-short} link:https://docs.openshift.com/container-platform/latest/operators/olm-what-operators-are.html[Operator] deployment, the `CheCluster` attribute `serverTrustStoreConfigMapName` value matches the name of the ConfigMap. Get the value using the following command :
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get -o json checluster/{prod-checluster} -n __<{project-context}-namespace-name>__ | jq .spec.server.serverTrustStoreConfigMapName
----
+
. {prod-short} Pod Volumes list contains one Volume that uses the ConfigMap as data-source. To get the list of Volumes of the {prod-short} Pod:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get pod -o json __<{prod-id-short}-pod-name>__ -n __<{project-context}-namespace-name>__ | jq .spec.volumes
----
+
. {prod-short} mounts certificates in folder `/public-certs/` of the {prod-short} server container. This command returns the list of files in that folder:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} exec -t __<{prod-id-short}-pod-name>__ -n __<{project-context}-namespace-name>__ -- ls /public-certs/
----
+
. In the {prod-short} server logs there is a line for every certificate added to the Java truststore, including configured {prod-short} certificates.
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} logs __<{prod-id-short}-pod-name>__ -n __<{project-context}-namespace-name>__
(...)
Found a custom cert. Adding it to java trust store based on /usr/lib/jvm/java-1.8.0/jre/lib/security/cacerts
(...)
----
+
. {prod-short} server Java truststore contains the certificates. The certificates SHA1 fingerprints are among the list of the SHA1 of the certificates included in the truststore returned by the following command:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} exec -t __<{prod-id-short}-pod-name>__ -n {prod-namespace} -- keytool -list -keystore {prod-home}/cacerts
Your keystore contains 141 entries
(...)
----
+
To get the SHA1 hash of a certificate on the local filesystem:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ openssl x509 -in __<certificate-file-path>__ -fingerprint -noout
SHA1 Fingerprint=3F:DA:BF:E7:A7:A7:90:62:CA:CF:C7:55:0E:1D:7D:05:16:7D:45:60
----

== Verification at the workspace level

. Start a workspace, get the Kubernetes namespace in which it has been created, and wait for it to be started

. Get the name of the workspace Pod with the following command:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get pods -o=jsonpath='{.items[0].metadata.name}' -n __<workspace namespace>__ | grep '^workspace.*'
----

. Get the name of the Theia IDE container in the workspace Pod with the following command:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get -o json pod __<workspace pod name>__ -n __<workspace namespace>__ | \
jq -r '.spec.containers[] | select(.name | startswith("theia-ide")).name'
----

. Look for a `ca-certs` ConfigMap that should have been created inside the workspace namespace:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get cm ca-certs __<workspace namespace>__
----

. Check that the entries in the `ca-certs` ConfigMap contain all the additional entries you added in the certificate ConfigMap at the {prod-short} installation level, in addition to the `ca-bundl.crt` entry which is a reserved one:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get cm ca-certs -n __<workspace namespace>__ -o json | jq -r '.data | keys[]'
ca-bundle.crt
manually-added-certificate.crt
----

. Make sure that the `ca-certs` ConfigMap has been added as a volume in the workspace Pod:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get -o json pod __<workspace pod name>__ -n __<workspace namespace>__ | \
jq '.spec.volumes[] | select(.configMap.name == "ca-certs")'
{
"configMap": {
"defaultMode": 420,
"name": "ca-certs"
},
"name": "che-self-signed-certs"
}
----

. Confirm that the volume has been mounted into containers, especially in the Theia IDE container:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} get -o json pod __<workspace pod name>__ -n __<workspace namespace>__ | \
jq '.spec.containers[] | select(.name == "__<theia ide container name>__").volumeMounts[] | select(.name == "che-self-signed-certs")'
{
"mountPath": "/public-certs",
"name": "che-self-signed-certs",
"readOnly": true
}
----

. Inspect `/public-certs` folder on the Theia IDE container and check that its contents match the list of entries in the `ca-certs` ConfigMap:
+
[subs="+attributes,+quotes",options="nowrap",role=white-space-pre]
----
$ {orch-cli} exec __<workspace pod name>__ -c __<theia ide container name>__ -n __<workspace namespace>__ -- ls /public-certs
ca-bundle.crt
manually-added-certificate.crt
----
Loading

0 comments on commit b309a50

Please sign in to comment.