# Validating webhook (准入控制器)

## 总览

nginx ingress controller提供了在入口进入集群之前对其进行验证的选项，以确保控制器将生成有效的配置

每当启用 \[ValidatingAdmissionWebhook]\[1] 时，每次新的入口进入集群时，Kubernetes API服务器都会调用此控制器，并拒绝生成无法通过其验证的对象的Nginx配置

此功能需要对群集进行一些进一步的配置，因此它是一项可选功能，本节说明如何为您的群集启用它。

## 配置Webhook

### 生成webhook证书

#### 自签名证书

Validating webhook必须使用TLS进行服务，您需要生成一个证书。 请注意，kube API服务器正在检查证书的主机名，证书的通用名称将需要与服务名称匹配

!!! 例子 要使用命名空间`ingress-nginx`中名为`ingress-validation-webhook`的服务运行验证webhook，请运行

```bash
    openssl req -x509 -newkey rsa:2048 -keyout certificate.pem -out key.pem -days 365 -nodes -subj "/CN=ingress-validation-webhook.ingress-nginx.svc"
```

**使用KUBERNETES CA**

Kubernetes还提供了用于签署证书请求的原函数。这是有关如何使用它的示例

!!! example

```
    #!/bin/bash

    SERVICE_NAME=ingress-nginx
    NAMESPACE=ingress-nginx

    TEMP_DIRECTORY=$(mktemp -d)
    echo "creating certs in directory ${TEMP_DIRECTORY}"

    cat <<EOF >> ${TEMP_DIRECTORY}/csr.conf
    [req]
    req_extensions = v3_req
    distinguished_name = req_distinguished_name
    [req_distinguished_name]
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = ${SERVICE_NAME}
    DNS.2 = ${SERVICE_NAME}.${NAMESPACE}
    DNS.3 = ${SERVICE_NAME}.${NAMESPACE}.svc
    EOF

    openssl genrsa -out ${TEMP_DIRECTORY}/server-key.pem 2048
    openssl req -new -key ${TEMP_DIRECTORY}/server-key.pem \
        -subj "/CN=${SERVICE_NAME}.${NAMESPACE}.svc" \
        -out ${TEMP_DIRECTORY}/server.csr \
        -config ${TEMP_DIRECTORY}/csr.conf

    cat <<EOF | kubectl create -f -
    apiVersion: certificates.k8s.io/v1beta1
    kind: CertificateSigningRequest
    metadata:
      name: ${SERVICE_NAME}.${NAMESPACE}.svc
    spec:
      request: $(cat ${TEMP_DIRECTORY}/server.csr | base64 | tr -d '\n')
      usages:
      - digital signature
      - key encipherment
      - server auth
    EOF

    kubectl certificate approve ${SERVICE_NAME}.${NAMESPACE}.svc

    for x in $(seq 10); do
        SERVER_CERT=$(kubectl get csr ${SERVICE_NAME}.${NAMESPACE}.svc -o jsonpath='{.status.certificate}')
        if [[ ${SERVER_CERT} != '' ]]; then
            break
        fi
        sleep 1
    done
    if [[ ${SERVER_CERT} == '' ]]; then
        echo "ERROR: After approving csr ${SERVICE_NAME}.${NAMESPACE}.svc, the signed certificate did not appear on the resource. Giving up after 10 attempts." >&2
        exit 1
    fi
    echo ${SERVER_CERT} | openssl base64 -d -A -out ${TEMP_DIRECTORY}/server-cert.pem

    kubectl create secret generic ingress-nginx.svc \
        --from-file=key.pem=${TEMP_DIRECTORY}/server-key.pem \
        --from-file=cert.pem=${TEMP_DIRECTORY}/server-cert.pem \
        -n ${NAMESPACE}
```

#### 使用 helm

要使用helm生成证书，可以使用以下代码段

!!! 例子

```
    {{- $cn := printf "%s.%s.svc" ( include "nginx-ingress.validatingWebhook.fullname" . ) .Release.Namespace }}
    {{- $ca := genCA (printf "%s-ca" ( include "nginx-ingress.validatingWebhook.fullname" . )) .Values.validatingWebhook.certificateValidity -}}
    {{- $cert := genSignedCert $cn nil nil .Values.validatingWebhook.certificateValidity $ca -}}
```

### Ingress controller 参数

要在 ingress controller中启用此功能，您*需要*在命令行中提供3个标志

| flag                               | description                                               | example usage                                        |
| ---------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- |
| `--validating-webhook`             | The address to start an admission controller on           | `:8080`                                              |
| `--validating-webhook-certificate` | The certificate the webhook is using for its TLS handling | `/usr/local/certificates/validating-webhook.pem`     |
| `--validating-webhook-key`         | The key the webhook is using for its TLS handling         | `/usr/local/certificates/validating-webhook-key.pem` |

### kube API server参数

Validating webhook功能需要在kube API服务器端进行特定设置。根据您的kubernetes版本，默认情况下可以启用或禁用该标志。 要检查您的kube API服务器是否以必需的标志运行，请参阅kubernetes文档。

### 其他Kubernetes对象

一旦将 ingress controller和kube API服务器都配置为服务Webhook，添加即可使用以下对象配置Webhook:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-validation-webhook
  namespace: ingress-nginx
spec:
  ports:
  - name: admission
    port: 443
    protocol: TCP
    targetPort: 8080
  selector:
    app: nginx-ingress
    component: controller
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
  name: check-ingress
webhooks:
- name: validate.nginx.ingress.kubernetes.io
  rules:
  - apiGroups:
    - extensions
    apiVersions:
    - v1beta1
    operations:
    - CREATE
    - UPDATE
    resources:
    - ingresses
  failurePolicy: Fail
  clientConfig:
    service:
      namespace: ingress-nginx
      name: ingress-validation-webhook
      path: /extensions/v1beta1/ingress
    caBundle: <pem encoded ca cert that signs the server cert used by the webhook>
```

\[1]: <https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rocdu.gitbook.io/ingress-nginx-docs-cn/docs/deploy/validating-webhook.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
