diff --git a/charts/ingress-controller/README.md b/charts/ingress-controller/README.md index 3715c0e..b9c8513 100644 --- a/charts/ingress-controller/README.md +++ b/charts/ingress-controller/README.md @@ -59,4 +59,9 @@ Ingress Controller for API7 | podDisruptionBudget.enabled | bool | `false` | Enable or disable podDisruptionBudget | | podDisruptionBudget.maxUnavailable | int | `1` | Set the maxUnavailable of podDisruptionBudget | | podDisruptionBudget.minAvailable | string | `"90%"` | Set the `minAvailable` of podDisruptionBudget. You can specify only one of `maxUnavailable` and `minAvailable` in a single PodDisruptionBudget. See [Specifying a Disruption Budget for your Application](https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget) for more details | +| webhook.certificate.provided | bool | `false` | Set to true if you want to provide your own certificate | +| webhook.enabled | bool | `true` | Enable or disable admission webhook | +| webhook.failurePolicy | string | `"Fail"` | Failure policy for the webhook (Fail or Ignore) | +| webhook.port | int | `9443` | The port for the webhook server to listen on | +| webhook.timeoutSeconds | int | `10` | Timeout in seconds for the webhook | diff --git a/charts/ingress-controller/templates/_helpers.tpl b/charts/ingress-controller/templates/_helpers.tpl index 164dac5..e669001 100644 --- a/charts/ingress-controller/templates/_helpers.tpl +++ b/charts/ingress-controller/templates/_helpers.tpl @@ -50,3 +50,23 @@ app.kubernetes.io/name: {{ include "api7-ingress-controller-manager.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{- end }} + +{{/* +Webhook service name - ensure it stays within 63 character limit +*/}} +{{- define "api7-ingress-controller-manager.webhook.serviceName" -}} +{{- $suffix := "-webhook-svc" -}} +{{- $maxLen := sub 63 (len $suffix) | int -}} +{{- $baseName := include "api7-ingress-controller-manager.name.fullname" . | trunc $maxLen | trimSuffix "-" -}} +{{- printf "%s%s" $baseName $suffix -}} +{{- end }} + +{{/* +Webhook secret name - ensure it stays within 63 character limit +*/}} +{{- define "api7-ingress-controller-manager.webhook.secretName" -}} +{{- $suffix := "-webhook-cert" -}} +{{- $maxLen := sub 63 (len $suffix) | int -}} +{{- $baseName := include "api7-ingress-controller-manager.name.fullname" . | trunc $maxLen | trimSuffix "-" -}} +{{- printf "%s%s" $baseName $suffix -}} +{{- end }} diff --git a/charts/ingress-controller/templates/cluster_role.yaml b/charts/ingress-controller/templates/cluster_role.yaml index 3ff238d..fd327a2 100644 --- a/charts/ingress-controller/templates/cluster_role.yaml +++ b/charts/ingress-controller/templates/cluster_role.yaml @@ -17,7 +17,6 @@ rules: - pods - secrets - services - - endpoints verbs: - get - list @@ -79,7 +78,6 @@ rules: - gateway.networking.k8s.io resources: - gatewayclasses - - gateways verbs: - get - list @@ -90,6 +88,7 @@ rules: resources: - gatewayclasses/status - gateways/status + - grpcroutes/status - httproutes/status - referencegrants/status verbs: @@ -98,23 +97,19 @@ rules: - apiGroups: - gateway.networking.k8s.io resources: + - gateways + - grpcroutes - httproutes - verbs: - - get - - list - - watch -- apiGroups: - - gateway.networking.k8s.io - resources: - referencegrants verbs: + - get - list - - update - watch - apiGroups: - networking.k8s.io resources: - ingressclasses + - ingresses verbs: - get - list @@ -122,20 +117,18 @@ rules: - apiGroups: - networking.k8s.io resources: - - ingresses + - ingresses/status verbs: - get - - list - update - - watch - apiGroups: - - networking.k8s.io + - "" resources: - - ingresses/status + - endpoints verbs: - get - - update - + - list + - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/charts/ingress-controller/templates/configmap.yaml b/charts/ingress-controller/templates/configmap.yaml index 382254a..a823013 100644 --- a/charts/ingress-controller/templates/configmap.yaml +++ b/charts/ingress-controller/templates/configmap.yaml @@ -22,3 +22,11 @@ data: type: {{ .Values.config.provider.type | default "api7ee" }} sync_period: {{ .Values.config.provider.syncPeriod | default "0s" }} init_sync_delay: {{ .Values.config.provider.initSyncDelay | default "20m" }} + {{- if .Values.webhook.enabled }} + webhook: + enable: true + port: {{ .Values.webhook.port }} + tls_cert_file: "tls.crt" + tls_key_file: "tls.key" + tls_cert_dir: "/certs" + {{- end }} diff --git a/charts/ingress-controller/templates/deployment.yaml b/charts/ingress-controller/templates/deployment.yaml index 1023b35..758a394 100644 --- a/charts/ingress-controller/templates/deployment.yaml +++ b/charts/ingress-controller/templates/deployment.yaml @@ -41,6 +41,15 @@ spec: - name: {{ .Release.Name }}-ingress-config mountPath: /app/conf/config.yaml subPath: config.yaml + {{- if .Values.webhook.enabled }} + - name: webhook-certs + mountPath: /certs + readOnly: true + {{- end }} + ports: + - name: webhook + containerPort: {{ .Values.webhook.port }} + protocol: TCP livenessProbe: httpGet: path: /healthz @@ -112,6 +121,11 @@ spec: - name: {{ .Release.Name }}-ingress-config configMap: name: {{ .Release.Name }}-ingress-config + {{- if .Values.webhook.enabled }} + - name: webhook-certs + secret: + secretName: {{ include "api7-ingress-controller-manager.webhook.secretName" . }} + {{- end }} securityContext: runAsNonRoot: false serviceAccountName: {{ .Release.Name }} diff --git a/charts/ingress-controller/templates/webhook.yaml b/charts/ingress-controller/templates/webhook.yaml new file mode 100644 index 0000000..b427ab5 --- /dev/null +++ b/charts/ingress-controller/templates/webhook.yaml @@ -0,0 +1,238 @@ +{{- if .Values.webhook.enabled }} +{{- $certCert := "" -}} +{{- $certKey := "" -}} +{{- $caCert := "" -}} +{{- if not .Values.webhook.certificate.provided }} +{{- $cn := printf "%s.%s.svc" (include "api7-ingress-controller-manager.webhook.serviceName" .) .Release.Namespace -}} +{{- $ca := genCA "api7-ingress-webhook-ca" 3650 -}} +{{- $cert := genSignedCert $cn nil (list $cn) 3650 $ca -}} +{{- $certCert = $cert.Cert -}} +{{- $certKey = $cert.Key -}} +{{- $caCert = $ca.Cert -}} + +{{- $certSecret := (lookup "v1" "Secret" .Release.Namespace (include "api7-ingress-controller-manager.webhook.secretName" .)) -}} +{{- if $certSecret }} +{{- $certCert = (b64dec (get $certSecret.data "tls.crt")) -}} +{{- $certKey = (b64dec (get $certSecret.data "tls.key")) -}} +{{- $caCert = (b64dec (get $certSecret.data "ca.crt")) -}} +{{- end }} +{{- end }} + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "api7-ingress-controller-manager.name.fullname" . }}-webhook + labels: + {{- include "api7-ingress-controller-manager.labels" . | nindent 4 }} +webhooks: +- name: vapisixroute-v2.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-apisix-apache-org-v2-apisixroute + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["apisix.apache.org"] + apiVersions: ["v2"] + resources: ["apisixroutes"] +- name: vapisixconsumer-v2.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-apisix-apache-org-v2-apisixconsumer + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["apisix.apache.org"] + apiVersions: ["v2"] + resources: ["apisixconsumers"] +- name: vapisixtls-v2.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-apisix-apache-org-v2-apisixtls + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["apisix.apache.org"] + apiVersions: ["v2"] + resources: ["apisixtlses"] +- name: vconsumer-v1alpha1.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-apisix-apache-org-v1alpha1-consumer + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["apisix.apache.org"] + apiVersions: ["v1alpha1"] + resources: ["consumers"] +- name: vgatewayproxy-v1alpha1.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-apisix-apache-org-v1alpha1-gatewayproxy + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["apisix.apache.org"] + apiVersions: ["v1alpha1"] + resources: ["gatewayproxies"] +- name: vingress-v1.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-networking-k8s-io-v1-ingress + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + resources: ["ingresses"] +- name: vingressclass-v1.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-networking-k8s-io-v1-ingressclass + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + resources: ["ingressclasses"] +- name: vgateway-v1.kb.io + admissionReviewVersions: ["v1"] + clientConfig: + {{- if not .Values.webhook.certificate.provided }} + caBundle: {{ b64enc $caCert }} + {{- else }} + caBundle: {{ .Values.webhook.certificate.caBundle }} + {{- end }} + service: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-gateway-networking-k8s-io-v1-gateway + failurePolicy: {{ .Values.webhook.failurePolicy }} + {{- with .Values.webhook.timeoutSeconds }} + timeoutSeconds: {{ . }} + {{- end }} + sideEffects: None + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: ["gateway.networking.k8s.io"] + apiVersions: ["v1"] + resources: ["gateways"] + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "api7-ingress-controller-manager.webhook.serviceName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "api7-ingress-controller-manager.labels" . | nindent 4 }} +spec: + ports: + - name: webhook + port: 443 + protocol: TCP + targetPort: webhook + selector: + {{- include "api7-ingress-controller-manager.selectorLabels" . | nindent 4 }} + +{{- if not .Values.webhook.certificate.provided }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "api7-ingress-controller-manager.webhook.secretName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "api7-ingress-controller-manager.labels" . | nindent 4 }} +type: kubernetes.io/tls +data: + tls.crt: {{ b64enc $certCert }} + tls.key: {{ b64enc $certKey }} + ca.crt: {{ b64enc $caCert }} +{{- end }} +{{- end }} diff --git a/charts/ingress-controller/values.yaml b/charts/ingress-controller/values.yaml index db1153e..a7e152a 100644 --- a/charts/ingress-controller/values.yaml +++ b/charts/ingress-controller/values.yaml @@ -61,3 +61,21 @@ config: type: "api7ee" syncPeriod: "0s" initSyncDelay: "20m" + +# Admission webhook configuration +webhook: + # -- Enable or disable admission webhook + enabled: true + # -- The port for the webhook server to listen on + port: 9443 + # -- Failure policy for the webhook (Fail or Ignore) + failurePolicy: Fail + # -- Timeout in seconds for the webhook + timeoutSeconds: 10 + certificate: + # -- Set to true if you want to provide your own certificate + provided: false + # -- Secret name containing the certificate (required if provided is true) + # secretName: "my-webhook-cert" + # -- CA bundle in base64 format (required if provided is true) + # caBundle: ""