(apiserver) support key rotation
- Support key rotation for the etcd encryption key in the apiserver chart - Remove configmap annotations from the apiserver anchor pods as the pod is built to pickup changes in configmap contents without restart. - Also update the apiserver anchor DaemonSet to apps/v1 and make required updates to support that update. Change-Id: I2d18996bbe04bada9da2bce01a502550d3681c97
This commit is contained in:
parent
105fa608d7
commit
ad30aa7382
|
@ -0,0 +1,85 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Copyright 2019 AT&T Intellectual Property. All other rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
ANNOTATION_NAME="airshipit.org/encryption_key"
|
||||||
|
|
||||||
|
get_service_endpoints() {
|
||||||
|
ns="$1"
|
||||||
|
svc="$2"
|
||||||
|
kubectl -n $ns get endpoints -o json $svc | jq '.subsets[0].addresses' | jq '.[] | .targetRef.name' -r
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get_pod_annotation() {
|
||||||
|
ns="$1"
|
||||||
|
pod_name="$2"
|
||||||
|
kubectl -n $ns get pod "$pod_name" -o json | jq ".metadata.annotations.\"${ANNOTATION_NAME}\""
|
||||||
|
}
|
||||||
|
|
||||||
|
get_annotations_key() {
|
||||||
|
echo $ENCRYPTION_ANNOTATION | tr -d ' ' | awk -F':' '{print $1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
get_encryption_hash() {
|
||||||
|
echo $ENCRYPTION_ANNOTATION | tr -d ' ' | awk -F':' '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
apiserver_compare() {
|
||||||
|
echo "${apiservers[@]}" | sort | uniq > "${TEMP_DIR}/a.txt"
|
||||||
|
echo "${updated_apiservers[@]}" | sort | uniq > "${TEMP_DIR}/b.txt"
|
||||||
|
comm -3 "${TEMP_DIR}/a.txt" "${TEMP_DIR}/b.txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
{{- $envAll := . }}
|
||||||
|
|
||||||
|
|
||||||
|
{{- if and (.Values.conf) (hasKey .Values.conf "encryption_provider") }}
|
||||||
|
|
||||||
|
ENCRYPTION_ANNOTATION='{{ $envAll | include "kubernetes_apiserver.key_annotation" }}'
|
||||||
|
KUBE_SERVICE_NAMESPACE=${KUBE_SERVICE_NAMESPACE:-"kube-system"}
|
||||||
|
KUBE_SERVICE_NAME=${KUBE_SERVICE_NAME:-"kubernetes-apiserver"}
|
||||||
|
|
||||||
|
apiservers=( $(get_service_endpoints "$KUBE_SERVICE_NAMESPACE" "$KUBE_SERVICE_NAME"))
|
||||||
|
updated_apiservers=()
|
||||||
|
|
||||||
|
annotation="$(get_annotations_key)"
|
||||||
|
|
||||||
|
# TODO(sh8121att) add timeout logic
|
||||||
|
while [[ -n "$(apiserver_compare)" ]];
|
||||||
|
do
|
||||||
|
for pod_name in "${apiservers[@]}";
|
||||||
|
do
|
||||||
|
pod_key=$(get_pod_annotation "$KUBE_SERVICE_NAMESPACE" "$pod_name")
|
||||||
|
if [ "$pod_key" == "$(get_encryption_hash)" ];
|
||||||
|
then
|
||||||
|
updated_apiservers+=("$pod_name")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "All apiserver instances have an updated key."
|
||||||
|
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
kubectl get secrets --all-namespaces -o json | kubectl replace --validate=false -f -
|
||||||
|
if [[ $? -eq 0 ]]
|
||||||
|
then
|
||||||
|
echo "All secret resources re-encrypted."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
{{- end -}}
|
|
@ -27,4 +27,6 @@ data:
|
||||||
{{ tuple "bin/_anchor.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
{{ tuple "bin/_anchor.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
pre_stop: |+
|
pre_stop: |+
|
||||||
{{ tuple "bin/_pre_stop.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
{{ tuple "bin/_pre_stop.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
|
key-rotate.sh: |+
|
||||||
|
{{ tuple "bin/_key_rotate.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -33,15 +33,17 @@ spec:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{ $labels | indent 6 }}
|
{{ $labels | indent 6 }}
|
||||||
{{ tuple $envAll "kubernetes-apiserver-anchor" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}
|
{{ tuple $envAll "kubernetes-apiserver-anchor" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{ $labels | indent 6 }}
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
{{ $labels | indent 8 }}
|
{{ $labels | indent 8 }}
|
||||||
annotations:
|
annotations:
|
||||||
|
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
|
||||||
scheduler.alpha.kubernetes.io/critical-pod: ''
|
scheduler.alpha.kubernetes.io/critical-pod: ''
|
||||||
configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
|
configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
|
||||||
configmap-certs-hash: {{ tuple "configmap-certs.yaml" . | include "helm-toolkit.utils.hash" }}
|
|
||||||
configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
|
|
||||||
spec:
|
spec:
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
{{ .Values.labels.kubernetes_apiserver.node_selector_key }}: {{ .Values.labels.kubernetes_apiserver.node_selector_value }}
|
{{ .Values.labels.kubernetes_apiserver.node_selector_key }}: {{ .Values.labels.kubernetes_apiserver.node_selector_value }}
|
||||||
|
@ -63,8 +65,8 @@ spec:
|
||||||
value: /host{{ .Values.anchor.kubelet.manifest_path }}/{{ .Values.service.name }}.yaml
|
value: /host{{ .Values.anchor.kubelet.manifest_path }}/{{ .Values.service.name }}.yaml
|
||||||
- name: PKI_PATH
|
- name: PKI_PATH
|
||||||
value: /host{{ .Values.apiserver.host_etc_path }}/pki
|
value: /host{{ .Values.apiserver.host_etc_path }}/pki
|
||||||
command:
|
command: ["/bin/sh","-c"]
|
||||||
- /tmp/bin/anchor
|
args: ["/tmp/bin/anchor"]
|
||||||
lifecycle:
|
lifecycle:
|
||||||
preStop:
|
preStop:
|
||||||
exec:
|
exec:
|
||||||
|
|
|
@ -12,6 +12,29 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
{{- define "kubernetes_apiserver.key_concat" -}}
|
||||||
|
{{- range $encProv := .Values.conf.encryption_provider.content.resources -}}
|
||||||
|
{{- if hasKey (index $encProv "providers" 0) "identity" -}}
|
||||||
|
{{- printf "%s" (index $encProv "providers" 0 "identity") -}}
|
||||||
|
{{- else if hasKey (index $encProv "providers" 0) "secretbox" -}}
|
||||||
|
{{- printf "%s" (index $encProv "providers" 0 "secretbox" "keys" 0 "secret") -}}
|
||||||
|
{{- else if hasKey (index $encProv "providers" 0) "aescbc" -}}
|
||||||
|
{{- printf "%s" (index $encProv "providers" 0 "aescbc" "keys" 0 "secret") -}}
|
||||||
|
{{- else if hasKey (index $encProv "providers" 0) "aesgcm" -}}
|
||||||
|
{{- printf "%s" (index $encProv "providers" 0 "aesgcm" "keys" 0 "secret") -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
{{- define "kubernetes_apiserver.key_annotation" -}}
|
||||||
|
{{- if and (.Values.conf) (hasKey .Values.conf "encryption_provider") -}}
|
||||||
|
{{- $encKey := ( . | include "kubernetes_apiserver.key_concat") -}}
|
||||||
|
{{ .Values.const.encryption_annotation | quote }}: {{ sha256sum $encKey | quote }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
{{- $envAll := . }}
|
{{- $envAll := . }}
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -23,6 +46,7 @@ metadata:
|
||||||
{{ .Values.service.name }}-service: enabled
|
{{ .Values.service.name }}-service: enabled
|
||||||
{{ tuple $envAll "kubernetes" "apiserver" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
|
{{ tuple $envAll "kubernetes" "apiserver" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
|
||||||
annotations:
|
annotations:
|
||||||
|
{{ $envAll | include "kubernetes_apiserver.key_annotation" }}
|
||||||
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
|
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
|
||||||
spec:
|
spec:
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
{{/*
|
||||||
|
Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/}}
|
||||||
|
|
||||||
|
{{- if .Values.manifests.job_key_rotate }}
|
||||||
|
{{- $envAll := . }}
|
||||||
|
{{ $serviceAccountName := "apiserver-key-rotate" }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ $serviceAccountName }}
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: {{ $serviceAccountName }}-cluster
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- delete
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ $serviceAccountName }}-cluster
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: {{ $serviceAccountName }}-cluster
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ $serviceAccountName }}
|
||||||
|
namespace: {{ $envAll.Release.Namespace }}
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ $serviceAccountName }}-{{ $envAll.Release.Namespace }}
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- endpoints
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ $serviceAccountName }}-{{ $envAll.Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
namespace: {{ $envAll.Release.Namespace }}
|
||||||
|
name: {{ $serviceAccountName }}-{{ $envAll.Release.Namespace }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ $serviceAccountName }}
|
||||||
|
namespace: {{ $envAll.Release.Namespace }}
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: apiserver-key-rotate
|
||||||
|
annotations:
|
||||||
|
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
|
||||||
|
labels:
|
||||||
|
{{ tuple $envAll "kube-apiserver" "key-rotate" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
|
||||||
|
spec:
|
||||||
|
serviceAccountName: {{ $serviceAccountName }}
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
nodeSelector:
|
||||||
|
{{ .Values.labels.job.node_selector_key }}: {{ .Values.labels.job.node_selector_value }}
|
||||||
|
initContainers:
|
||||||
|
{{ tuple $envAll "key_rotate" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: apiserver-key-rotate
|
||||||
|
image: {{ .Values.images.tags.key_rotate | quote }}
|
||||||
|
imagePullPolicy: {{ .Values.images.pull_policy | quote }}
|
||||||
|
{{ tuple $envAll $envAll.Values.pod.resources.key_rotate | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
|
||||||
|
env:
|
||||||
|
- name: "ANNOTATION_NAME"
|
||||||
|
value: {{ .Values.const.encryption_annotation | quote }}
|
||||||
|
command:
|
||||||
|
- /tmp/key-rotate.sh
|
||||||
|
volumeMounts:
|
||||||
|
- name: apiserver-bin
|
||||||
|
mountPath: /tmp/key-rotate.sh
|
||||||
|
subPath: key-rotate.sh
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: apiserver-bin
|
||||||
|
configMap:
|
||||||
|
name: {{ .Values.service.name }}-bin
|
||||||
|
defaultMode: 0555
|
||||||
|
...
|
||||||
|
{{- end }}
|
|
@ -17,6 +17,7 @@ release_group: null
|
||||||
# NOTE(mark-burnett): These values are not really configurable -- they live
|
# NOTE(mark-burnett): These values are not really configurable -- they live
|
||||||
# here to keep the templates cleaner.
|
# here to keep the templates cleaner.
|
||||||
const:
|
const:
|
||||||
|
encryption_annotation: "airshipit.org/encryption_key"
|
||||||
command_prefix:
|
command_prefix:
|
||||||
- /apiserver
|
- /apiserver
|
||||||
- --advertise-address=$(POD_IP)
|
- --advertise-address=$(POD_IP)
|
||||||
|
@ -55,14 +56,24 @@ const:
|
||||||
|
|
||||||
images:
|
images:
|
||||||
tags:
|
tags:
|
||||||
|
dep_check: quay.io/stackanetes/kubernetes-entrypoint:v0.3.1
|
||||||
anchor: gcr.io/google_containers/hyperkube-amd64:v1.11.6
|
anchor: gcr.io/google_containers/hyperkube-amd64:v1.11.6
|
||||||
apiserver: gcr.io/google_containers/hyperkube-amd64:v1.11.6
|
apiserver: gcr.io/google_containers/hyperkube-amd64:v1.11.6
|
||||||
|
key_rotate: gcr.io/google_containers/hyperkube-amd64:v1.11.6
|
||||||
pull_policy: "IfNotPresent"
|
pull_policy: "IfNotPresent"
|
||||||
|
local_registry:
|
||||||
|
active: false
|
||||||
|
exclude:
|
||||||
|
- dep_check
|
||||||
|
- image_repo_sync
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
kubernetes_apiserver:
|
kubernetes_apiserver:
|
||||||
node_selector_key: kubernetes-apiserver
|
node_selector_key: kubernetes-apiserver
|
||||||
node_selector_value: enabled
|
node_selector_value: enabled
|
||||||
|
job:
|
||||||
|
node_selector_key: kubernetes-apiserver
|
||||||
|
node_selector_value: enabled
|
||||||
|
|
||||||
anchor:
|
anchor:
|
||||||
dns_policy: Default
|
dns_policy: Default
|
||||||
|
@ -85,7 +96,17 @@ conf:
|
||||||
# plugins:
|
# plugins:
|
||||||
# - name: EventRateLimit
|
# - name: EventRateLimit
|
||||||
# path: eventconfig.yaml
|
# path: eventconfig.yaml
|
||||||
#
|
# eventconfig:
|
||||||
|
# file: eventconfig.yaml
|
||||||
|
# command_options: []
|
||||||
|
# content:
|
||||||
|
# kind: Configuration
|
||||||
|
# apiVersion: eventratelimit.admission.k8s.io/v1alpha1
|
||||||
|
# limits:
|
||||||
|
# - type: Server
|
||||||
|
# qps: 1000
|
||||||
|
# burst: 10000
|
||||||
|
|
||||||
# Uncomment any of the below to enable enhanced Audit Logging command line options.
|
# Uncomment any of the below to enable enhanced Audit Logging command line options.
|
||||||
#
|
#
|
||||||
# auditpolicy:
|
# auditpolicy:
|
||||||
|
@ -98,28 +119,22 @@ conf:
|
||||||
# rules:
|
# rules:
|
||||||
# - level: Metadata
|
# - level: Metadata
|
||||||
#
|
#
|
||||||
# eventconfig:
|
encryption_provider:
|
||||||
# file: eventconfig.yaml
|
file: encryption_provider.yaml
|
||||||
# command_options:
|
command_options:
|
||||||
# - '--experimental-encryption-provider-config=/etc/kubernetes/apiserver/encryption_provider.yaml'
|
- '--experimental-encryption-provider-config=/etc/kubernetes/apiserver/encryption_provider.yaml'
|
||||||
# content:
|
content:
|
||||||
# kind: Configuration
|
kind: EncryptionConfig
|
||||||
# apiVersion: eventratelimit.admission.k8s.io/v1alpha1
|
apiVersion: v1
|
||||||
# limits:
|
resources:
|
||||||
# - type: Server
|
- resources:
|
||||||
# qps: 1000
|
- 'secrets'
|
||||||
# burst: 10000
|
providers:
|
||||||
# encryption_provider:
|
- secretbox:
|
||||||
# file: encryption_provider.yaml
|
keys:
|
||||||
# command_option: ''
|
- name: key1
|
||||||
# content:
|
secret: Xw2UcbjILTJM6QiFZ0WPSbUvjtoT8OJC/Nl8qqYWjGk=
|
||||||
# kind: EncryptionConfig
|
- identity: {}
|
||||||
# apiVersion: v1
|
|
||||||
# resources:
|
|
||||||
# - resources:
|
|
||||||
# - 'secrets'
|
|
||||||
# providers:
|
|
||||||
# - identity: {}
|
|
||||||
|
|
||||||
apiserver:
|
apiserver:
|
||||||
arguments:
|
arguments:
|
||||||
|
@ -181,6 +196,18 @@ secrets:
|
||||||
cert: null
|
cert: null
|
||||||
key: null
|
key: null
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
dynamic:
|
||||||
|
common:
|
||||||
|
local_image_registry:
|
||||||
|
jobs:
|
||||||
|
- apiserver-image-repo-sync
|
||||||
|
services:
|
||||||
|
- endpoint: node
|
||||||
|
service: local_image_registry
|
||||||
|
static:
|
||||||
|
key_rotate: {}
|
||||||
|
|
||||||
# typically overriden by environmental
|
# typically overriden by environmental
|
||||||
# values, but should include all endpoints
|
# values, but should include all endpoints
|
||||||
# required by this chart
|
# required by this chart
|
||||||
|
@ -236,6 +263,13 @@ pod:
|
||||||
limits:
|
limits:
|
||||||
memory: "1024Mi"
|
memory: "1024Mi"
|
||||||
cpu: "2000m"
|
cpu: "2000m"
|
||||||
|
key_rotate:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "1024Mi"
|
||||||
|
cpu: "2000m"
|
||||||
kubernetes_apiserver:
|
kubernetes_apiserver:
|
||||||
requests:
|
requests:
|
||||||
memory: "128Mi"
|
memory: "128Mi"
|
||||||
|
@ -254,3 +288,4 @@ manifests:
|
||||||
secret_ingress_tls: false
|
secret_ingress_tls: false
|
||||||
service: true
|
service: true
|
||||||
service_ingress: false
|
service_ingress: false
|
||||||
|
job_key_rotate: true
|
||||||
|
|
Loading…
Reference in New Issue