Add option for CA certificate

The download of plugins during the init could fail, if the download
server used custom certificates, e.g. in a corporate intranet.

Now a CA-certificate can be configured that will be used for TLS
verification, if the default certificates fail to validate. This
way servers with custom certificate authorities and servers with
publicly signed certificates can be used.

The provided CA will also be used by other applications in the
deployment. Right now, this is only Promtail.

Change-Id: I8ea3ef15405a939e1ce4b92c6f85f71db1e38bce
diff --git a/container-images/gerrit-init/tools/download_plugins.py b/container-images/gerrit-init/tools/download_plugins.py
index e9fcc6c..9984dc1 100755
--- a/container-images/gerrit-init/tools/download_plugins.py
+++ b/container-images/gerrit-init/tools/download_plugins.py
@@ -114,7 +114,11 @@
 
     def _download_plugin(self, plugin, target):
         LOG.info("Downloading %s plugin to %s", plugin["name"], target)
-        response = requests.get(plugin["url"])
+        try:
+            response = requests.get(plugin["url"])
+        except requests.exceptions.SSLError:
+            response = requests.get(plugin["url"], verify=self.config.ca_cert_path)
+
         with open(target, "wb") as f:
             f.write(response.content)
 
diff --git a/container-images/gerrit-init/tools/init_config.py b/container-images/gerrit-init/tools/init_config.py
index f20c71b..13e7ef4 100644
--- a/container-images/gerrit-init/tools/init_config.py
+++ b/container-images/gerrit-init/tools/init_config.py
@@ -24,6 +24,8 @@
         self.packaged_plugins = set()
         self.plugin_cache_dir = None
 
+        self.ca_cert_path = True
+
     def parse(self, config_file):
         if not os.path.exists(config_file):
             raise FileNotFoundError("Could not find config file: %s" % config_file)
@@ -43,6 +45,9 @@
         if "pluginCacheDir" in config and config["pluginCacheDir"]:
             self.plugin_cache_dir = config["pluginCacheDir"]
 
+        if "caCertPath" in config:
+            self.ca_cert_path = config["caCertPath"]
+
         return self
 
     def get_all_configured_plugins(self):
diff --git a/helm-charts/gerrit-replica/README.md b/helm-charts/gerrit-replica/README.md
index e93b2af..99ca0ba 100644
--- a/helm-charts/gerrit-replica/README.md
+++ b/helm-charts/gerrit-replica/README.md
@@ -125,6 +125,16 @@
 | `storageClasses.shared.reclaimPolicy`  | Whether to `Retain` or `Delete` volumes, when they become unbound | `Delete`                                          |
 | `storageClasses.shared.parameters`     | Parameters for the provisioner                                    | `parameters.mountOptions: vers=4.1`               |
 
+### CA certificate
+
+Some application may require TLS verification. If the default CA built into the
+containers is not enough a custom CA certificate can be given to the deployment.
+Note, that Gerrit will require its CA in a JKS keytore, which is described below.
+
+| Parameter | Description                                                                | Default |
+|-----------|----------------------------------------------------------------------------|---------|
+| `caCert`  | CA certificate for TLS verification (if not set, the default will be used) | `None`  |
+
 ### Workaround for NFS
 
 Kubernetes will not be able to adapt the ownership of the files within NFS
diff --git a/helm-charts/gerrit-replica/templates/gerrit-replica.configmap.yaml b/helm-charts/gerrit-replica/templates/gerrit-replica.configmap.yaml
index 10962c1..9ba9e1b 100644
--- a/helm-charts/gerrit-replica/templates/gerrit-replica.configmap.yaml
+++ b/helm-charts/gerrit-replica/templates/gerrit-replica.configmap.yaml
@@ -33,6 +33,9 @@
     release: {{ .Release.Name }}
 data:
   gerrit-init.yaml: |-
+    {{ if .Values.caCert -}}
+    caCertPath: /var/mnt/etc/ca.crt
+    {{- end }}
     pluginCache: {{ .Values.gerritReplica.plugins.cache.enabled }}
     pluginCacheDir: /var/mnt/plugins
     {{- if .Values.gerritReplica.plugins.packaged }}
diff --git a/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml b/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml
index 163eb47..417813d 100644
--- a/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml
+++ b/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml
@@ -100,6 +100,11 @@
         - name: gerrit-init-config
           mountPath: "/var/config/gerrit-init.yaml"
           subPath: gerrit-init.yaml
+        {{ if .Values.caCert -}}
+        - name: tls-ca
+          subPath: ca.crt
+          mountPath: "/var/config/ca.crt"
+        {{- end }}
       # If configured, run initialization taking the given Gerrit configuration
       # and persisted volumes into account.
       - name: gerrit-init
@@ -233,9 +238,11 @@
         - name: promtail-secret
           mountPath: /etc/promtail/promtail.secret
           subPath: promtail.secret
-        - name: promtail-secret
+        {{- if not .Values.promtailSidecar.tls.skipVerify }}
+        - name: tls-ca
           mountPath: /etc/promtail/promtail.ca.crt
-          subPath: promtail.ca.crt
+          subPath: ca.crt
+        {{- end }}
         - name: logs
           subPathExpr: "gerrit-replica/$(POD_NAME)"
           mountPath: "/var/gerrit/logs"
@@ -285,6 +292,11 @@
       - name: gerrit-replica-secure-config
         secret:
           secretName: {{ .Release.Name }}-gerrit-replica-secure-config
+      {{ if .Values.caCert -}}
+      - name: tls-ca
+        secret:
+          secretName: {{ .Release.Name }}-tls-ca
+      {{- end }}
       {{ if .Values.gerritReplica.service.ssh.enabled -}}
       - name: gerrit-replica-ssh
         secret:
diff --git a/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml b/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml
index 037cc3d..48ace53 100644
--- a/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml
+++ b/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml
@@ -86,6 +86,11 @@
         - name: gerrit-config
           mountPath: "/var/config/gerrit.config"
           subPath: gerrit.config
+        {{ if .Values.caCert -}}
+        - name: tls-ca
+          subPath: ca.crt
+          mountPath: "/var/config/ca.crt"
+        {{- end }}
       volumes:
       - name: gerrit-site
         emptyDir: {}
@@ -113,6 +118,9 @@
       - name: gerrit-config
         configMap:
           name: {{ .Release.Name }}-gerrit-replica-configmap
+      - name: tls-ca
+        secret:
+          secretName: {{ .Release.Name }}-tls-ca
       {{- if .Values.nfsWorkaround.enabled }}
       - name: nfs-config
         configMap:
diff --git a/helm-charts/gerrit-replica/templates/global.secrets.yaml b/helm-charts/gerrit-replica/templates/global.secrets.yaml
new file mode 100644
index 0000000..0afd2cd
--- /dev/null
+++ b/helm-charts/gerrit-replica/templates/global.secrets.yaml
@@ -0,0 +1,14 @@
+{{ if .Values.caCert -}}
+apiVersion: v1
+kind: Secret
+metadata:
+  name:  {{ .Release.Name }}-tls-ca
+  labels:
+    app: gerrit-replica
+    chart: {{ template "gerrit-replica.chart" . }}
+    heritage: {{ .Release.Service }}
+    release: {{ .Release.Name }}
+data:
+  ca.crt: {{ .Values.caCert | b64enc }}
+type: Opaque
+{{- end }}
diff --git a/helm-charts/gerrit-replica/templates/promtail.secret.yaml b/helm-charts/gerrit-replica/templates/promtail.secret.yaml
index ae05c2a..83d0221 100644
--- a/helm-charts/gerrit-replica/templates/promtail.secret.yaml
+++ b/helm-charts/gerrit-replica/templates/promtail.secret.yaml
@@ -11,7 +11,4 @@
 type: Opaque
 data:
   promtail.secret: {{ .Values.promtailSidecar.loki.password | b64enc }}
-  {{- if not .Values.promtailSidecar.tls.skipVerify }}
-  promtail.ca.crt: {{ .Values.promtailSidecar.tls.caCert | b64enc }}
-  {{- end }}
 {{- end }}
diff --git a/helm-charts/gerrit-replica/values.yaml b/helm-charts/gerrit-replica/values.yaml
index 8428373..952d645 100644
--- a/helm-charts/gerrit-replica/values.yaml
+++ b/helm-charts/gerrit-replica/values.yaml
@@ -94,6 +94,7 @@
   ssh:
     enabled: false
 
+caCert:
 
 promtailSidecar:
   enabled: false
@@ -108,10 +109,6 @@
       memory: 128Mi
   tls:
     skipVerify: true
-    caCert: |-
-      -----BEGIN CERTIFICATE-----
-
-      -----END CERTIFICATE-----
   loki:
     url: loki.example.com
     user: admin
diff --git a/helm-charts/gerrit/README.md b/helm-charts/gerrit/README.md
index b4c40a6..5e691dd 100644
--- a/helm-charts/gerrit/README.md
+++ b/helm-charts/gerrit/README.md
@@ -174,6 +174,16 @@
 the external PVC, set `gitRepositoryStorage.externalPVC.enabled` to `true` and
 give the name of the PVC under `gitRepositoryStorage.externalPVC.name`.
 
+### CA certificate
+
+Some application may require TLS verification. If the default CA built into the
+containers is not enough a custom CA certificate can be given to the deployment.
+Note, that Gerrit will require its CA in a JKS keytore, which is described below.
+
+| Parameter | Description                                                                | Default |
+|-----------|----------------------------------------------------------------------------|---------|
+| `caCert`  | CA certificate for TLS verification (if not set, the default will be used) | `None`  |
+
 ### Git garbage collection
 
 | Parameter                           | Description                                                      | Default                  |
diff --git a/helm-charts/gerrit/templates/gerrit.configmap.yaml b/helm-charts/gerrit/templates/gerrit.configmap.yaml
index 4048d50..1e6b744 100644
--- a/helm-charts/gerrit/templates/gerrit.configmap.yaml
+++ b/helm-charts/gerrit/templates/gerrit.configmap.yaml
@@ -33,6 +33,9 @@
     release: {{ .Release.Name }}
 data:
   gerrit-init.yaml: |-
+    {{ if .Values.caCert -}}
+    caCertPath: /var/config/ca.crt
+    {{- end }}
     pluginCache: {{ .Values.gerrit.plugins.cache.enabled }}
     pluginCacheDir: /var/mnt/plugins
     {{- if .Values.gerrit.plugins.packaged }}
diff --git a/helm-charts/gerrit/templates/gerrit.stateful-set.yaml b/helm-charts/gerrit/templates/gerrit.stateful-set.yaml
index bdef9c3..5a6684a 100644
--- a/helm-charts/gerrit/templates/gerrit.stateful-set.yaml
+++ b/helm-charts/gerrit/templates/gerrit.stateful-set.yaml
@@ -101,6 +101,11 @@
           mountPath: "/var/mnt/etc/config"
         - name: gerrit-secure-config
           mountPath: "/var/mnt/etc/secret"
+        {{ if .Values.caCert -}}
+        - name: tls-ca
+          subPath: ca.crt
+          mountPath: "/var/mnt/etc/ca.crt"
+        {{- end }}
       containers:
       - name: gerrit
         image: {{ template "registry" . }}{{ .Values.gerrit.images.gerrit }}:{{ .Values.images.version }}
@@ -155,6 +160,11 @@
       - name: gerrit-secure-config
         secret:
           secretName: {{ .Release.Name }}-gerrit-secure-config
+      {{ if .Values.caCert -}}
+      - name: tls-ca
+        secret:
+          secretName: {{ .Release.Name }}-tls-ca
+      {{- end }}
   volumeClaimTemplates:
   {{ if .Values.gerrit.persistence.enabled -}}
   - metadata:
diff --git a/helm-charts/gerrit/templates/global.secrets.yaml b/helm-charts/gerrit/templates/global.secrets.yaml
new file mode 100644
index 0000000..cf3c4c5
--- /dev/null
+++ b/helm-charts/gerrit/templates/global.secrets.yaml
@@ -0,0 +1,14 @@
+{{ if .Values.caCert -}}
+apiVersion: v1
+kind: Secret
+metadata:
+  name:  {{ .Release.Name }}-tls-ca
+  labels:
+    app: gerrit
+    chart: {{ template "gerrit.chart" . }}
+    heritage: {{ .Release.Service }}
+    release: {{ .Release.Name }}
+data:
+  ca.crt: {{ .Values.caCert | b64enc }}
+type: Opaque
+{{- end }}
diff --git a/helm-charts/gerrit/values.yaml b/helm-charts/gerrit/values.yaml
index 2d196ab..635d407 100644
--- a/helm-charts/gerrit/values.yaml
+++ b/helm-charts/gerrit/values.yaml
@@ -55,6 +55,7 @@
     name: git-repositories-pvc
   size: 5Gi
 
+caCert:
 
 gitGC:
   image: k8sgerrit/git-gc