diff --git a/testapp/certman-istio-controller/Dockerfile b/testapp/certman-istio-controller/Dockerfile new file mode 100644 index 0000000..c20afa7 --- /dev/null +++ b/testapp/certman-istio-controller/Dockerfile @@ -0,0 +1,3 @@ +FROM flant/shell-operator:latest +ADD hooks /hooks +ADD cleanup.sh / diff --git a/testapp/certman-istio-controller/Makefile b/testapp/certman-istio-controller/Makefile new file mode 100644 index 0000000..9f76335 --- /dev/null +++ b/testapp/certman-istio-controller/Makefile @@ -0,0 +1,13 @@ +CC=docker +APP=certman-istio-controller +TAG=127.0.0.1:5000/cert/$(APP):$(VERSION) + +all: build push + +build: + $(CC) build --build-arg VERSION=$(VERSION) -t $(TAG) . + +push: + $(CC) push $(TAG) + +.PHONY: build push diff --git a/testapp/certman-istio-controller/README.md b/testapp/certman-istio-controller/README.md new file mode 100644 index 0000000..f4c07db --- /dev/null +++ b/testapp/certman-istio-controller/README.md @@ -0,0 +1,32 @@ +# Istio Cert Manager + +The Istio Cert Manager is an addon controller to support Cert-Manager's `ACME HTTP01` Issuer with Istio `Gateway` and `VirtualService` intgration. + +## Install + +Create the Custom Resource Definition: + +``` +kubectl apply -f crd.yaml +``` + +Grant permissions for the new controller: + +``` +kubectl apply -f rbac.yaml +``` + +Create the controller pod: + +``` +kubectl apply -f pod.yaml +``` + +## Cleanup + +``` +kubectl -n cert-manager exec certman-istio-controller /cleanup.sh +kubectl delete -f pod.yaml +kubectl delete -f rbac.yaml +kubectl delete -f crd.yaml +``` diff --git a/testapp/certman-istio-controller/cleanup.sh b/testapp/certman-istio-controller/cleanup.sh new file mode 100755 index 0000000..fdc0552 --- /dev/null +++ b/testapp/certman-istio-controller/cleanup.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +source /hooks/common/functions.sh + +for refmap in $(kubectl get refmap -ojson | jq -r '.items[] | .metadata.name'); do + delete "${refmap}" +done diff --git a/testapp/certman-istio-controller/crd.yaml b/testapp/certman-istio-controller/crd.yaml new file mode 100644 index 0000000..c30698a --- /dev/null +++ b/testapp/certman-istio-controller/crd.yaml @@ -0,0 +1,43 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: refmaps.cic.giftfish.de +spec: + group: cic.giftfish.de + versions: + - name: v1alpha1 + served: true + storage: true + scope: Cluster + names: + plural: refmaps + singular: refmap + kind: RefMap + shortNames: + - rm + preserveUnknownFields: false + validation: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + namespace: + type: string + gateway: + type: object + properties: + ref: + type: string + action: + type: string + pattern: '^(none|delete)$' + virtualService: + type: object + properties: + ref: + type: string + action: + type: string + pattern: '^(clear|delete)$' diff --git a/testapp/certman-istio-controller/hooks/common/functions.sh b/testapp/certman-istio-controller/hooks/common/functions.sh new file mode 100644 index 0000000..7f2ea6c --- /dev/null +++ b/testapp/certman-istio-controller/hooks/common/functions.sh @@ -0,0 +1,188 @@ +config() { + cat <${tmp} || return 0 + ns=$(jq -r '.spec.namespace' ${tmp}) + gwName=$(jq -r '.spec.gateway.ref' ${tmp}) + gwAction=$(jq -r '.spec.gateway.action' ${tmp}) + vsName=$(jq -r '.spec.virtualService.ref' ${tmp}) + vsAction=$(jq -r '.spec.virtualService.action' ${tmp}) + rm -f ${tmp} + if [[ "${gwName}" != "" ]]; then + case ${gwAction} in + delete) delgw "${gwName}" "${ns}" ;; + none|*) ;; + esac + fi + if [[ "${vsName}" != "" ]]; then + case ${vsAction} in + delete) delvs "${vsName}" "${ns}" ;; + clear) clearvs "${vsName}" "${ns}" ;; + esac + fi + deldr "$1" "${ns}" + delmap "$1" +} + +add() { + res=$1 + ns=$2 + tmp=$(mktemp) + kubectl -n ${ns} get ingress ${res} -ojson >${tmp} || return 0 + host=$(jq -r '.spec.rules[0].host' ${tmp}) + svcName=$(jq -r '.spec.rules[0].http.paths[0].backend.serviceName' ${tmp}) + svcPort=$(jq -r '.spec.rules[0].http.paths[0].backend.servicePort' ${tmp}) + path=$(jq -r '.spec.rules[0].http.paths[0].path' ${tmp}) + rm -f ${tmp} + gwName= + for gw in $(kubectl -n ${ns} get gateway -ojson | jq -r '.items[] | .metadata.name'); do + contains=$(kubectl -n ${ns} get gateway ${gw} -ojson | jq -r ".spec.servers[0].hosts | contains([\"${host}\"])") + [[ "${contains}" == "true" ]] && { gwName=${gw}; break; } + done + if [[ "${gwName}" == "" ]]; then + gwName=${res} + mkgw "${gwName}" "${ns}" "${host}" + gwAction=delete + else + gwAction=none + fi + vsName= + vsAction= + for vs in $(kubectl -n ${ns} get virtualservice -ojson | jq -r '.items[] | .metadata.name'); do + contains=$(kubectl -n ${ns} get virtualservice ${vs} -ojson | jq -r ".spec.hosts | contains([\"${host}\"])") + [[ "${contains}" == "true" ]] && { vsName=${vs}; break; } + done + if [[ "${vsName}" == "" ]]; then + vsName=${res} + mkvs "${vsName}" "${ns}" "${host}" "${path}" "${svcName}" "${svcPort}" + vsAction=delete + else + addvs "${vsName}" "${ns}" "${path}" "${svcName}" "${svcPort}" + vsAction=clear + fi + mkdr "${res}" "${ns}" "${svcName}" + mkmap "${res}" "${ns}" "${gwName}" "${gwAction}" "${vsName}" "${vsAction}" +} diff --git a/testapp/certman-istio-controller/hooks/ingress-add.sh b/testapp/certman-istio-controller/hooks/ingress-add.sh new file mode 100755 index 0000000..10f87d1 --- /dev/null +++ b/testapp/certman-istio-controller/hooks/ingress-add.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +source /hooks/common/functions.sh + +if [[ $1 == "--config" ]]; then + config add +else + json=${BINDING_CONTEXT_PATH} + ns=$(jq -r '.[0].resourceNamespace' ${json}) + res=$(jq -r '.[0].resourceName' ${json}) + add "${res}" "${ns}" +fi diff --git a/testapp/certman-istio-controller/hooks/ingress-delete.sh b/testapp/certman-istio-controller/hooks/ingress-delete.sh new file mode 100755 index 0000000..e443178 --- /dev/null +++ b/testapp/certman-istio-controller/hooks/ingress-delete.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +source /hooks/common/functions.sh + +if [[ $1 == "--config" ]]; then + config delete +else + delete "$(jq -r '.[0].resourceName' ${BINDING_CONTEXT_PATH})" +fi diff --git a/testapp/certman-istio-controller/pod.yaml b/testapp/certman-istio-controller/pod.yaml new file mode 100644 index 0000000..b6ffc71 --- /dev/null +++ b/testapp/certman-istio-controller/pod.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: certman-istio-controller + namespace: cert-manager + labels: + app: certman-istio-controller + version: v1 +spec: + containers: + - name: certman-istio-controller + image: 127.0.0.1:5000/cert/certman-istio-controller:v1 + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + imagePullPolicy: Always + serviceAccountName: certman-istio-controller diff --git a/testapp/certman-istio-controller/rbac.yaml b/testapp/certman-istio-controller/rbac.yaml new file mode 100644 index 0000000..636cfad --- /dev/null +++ b/testapp/certman-istio-controller/rbac.yaml @@ -0,0 +1,45 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: certman-istio-controller + namespace: cert-manager +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: certman-istio-controller +rules: +- apiGroups: + - extensions + resources: + - ingresses + verbs: ["get", "list", "watch"] +- apiGroups: + - networking.istio.io + resources: + - gateways + - virtualservices + verbs: ["*"] +- apiGroups: + - networking.istio.io + resources: + - destinationrules + verbs: ["get", "create", "delete"] +- apiGroups: + - cic.giftfish.de + resources: + - refmaps + verbs: ["get", "list", "create", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: certman-istio-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: certman-istio-controller +subjects: +- kind: ServiceAccount + name: certman-istio-controller + namespace: cert-manager