<p>I have the following <code>MutatingWebhookConfiguration</code></p>
<pre><code>apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: example-webhook
webhooks:
  - name: example-webhook.default.svc.cluster.local
    admissionReviewVersions:
      - &quot;v1beta1&quot;
    sideEffects: &quot;None&quot;
    timeoutSeconds: 30
    objectSelector:
      matchLabels:
        example-webhook-enabled: &quot;true&quot;
    clientConfig:
      service:
        name: example-webhook
        namespace: default
        path: &quot;/mutate&quot;
      caBundle: &quot;LS0tLS1CR...&quot;
    rules:
      - operations: [ &quot;CREATE&quot; ]
        apiGroups: [&quot;&quot;]
        apiVersions: [&quot;v1&quot;]
        resources: [&quot;pods&quot;]
</code></pre>
<p>I want to inject the <code>webhook</code> pod in an <code>istio</code> enabled namespace with <code>istio</code> having strict TLS mode on.</p>
<p>Therefore, (I thought) TLS should not be needed in my <code>example-webhook</code> service so it is crafted as follows:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: example-webhook
  namespace: default
spec:
  selector:
    app: example-webhook
  ports:
    - port: 80
      targetPort: webhook
      name: webhook
</code></pre>
<p>However when creating a <code>Pod</code> (that does indeed trigger the webhook) I get the following error:</p>
<pre><code>▶ k create -f demo-pod.yaml
Error from server (InternalError): error when creating &quot;demo-pod.yaml&quot;: Internal error occurred: failed calling webhook &quot;example-webhook.default.svc.cluster.local&quot;: Post &quot;https://example-webhook.default.svc:443/mutate?timeout=30s&quot;: no service port 443 found for service &quot;example-webhook&quot;
</code></pre>
<p>Can't I configure the webhook not to be called on <code>443</code> but rather on <code>80</code>? Either way TLS termination is done by the <code>istio</code> sidecar.</p>
<p>Is there a way around this using <code>VirtualService</code> / <code>DestinationRule</code>?</p>
<p><strong>edit</strong>: on top of that, why is it trying to reach the service in the <code>example-webhook.default.svc</code> endpoint? (while it should be doing so in <code>example-webhook.default.svc.cluster.local</code>) ?</p>
<h3>Update 1</h3>
<p>I have tried to use <code>https</code> as follows:</p>
<p>I have created a certificate and private key, using istio's CA.</p>
<p>I can verify that my DNS names in the cert are valid as follows (from another pod)</p>
<pre><code>echo | openssl s_client -showcerts -servername example-webhook.default.svc -connect example-webhook.default.svc:443 2&gt;/dev/null | openssl x509 -inform pem -noout -text
</code></pre>
<pre><code>...
 Subject: C = GR, ST = Attica, L = Athens, O = Engineering, OU = FOO, CN = *.cluster.local, emailAddress = me@myemail.com
...
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:*.default.svc.cluster.local, DNS:example-webhook, DNS:example-webhook.default.svc
...
</code></pre>
<p>but now pod creation fails as follows:</p>
<pre><code>▶ k create -f demo-pod.yaml
Error from server (InternalError): error when creating &quot;demo-pod.yaml&quot;: Internal error occurred: failed calling webhook &quot;example-webhook.default.svc.cluster.local&quot;: Post &quot;https://example-webhook.default.svc:443/mutate?timeout=30s&quot;: x509: certificate is not valid for any names, but wanted to match example-webhook.default.svc
</code></pre>
<h3>Update 2</h3>
<p>The fact that the certs the webhook pod are running with were appropriately created using the <code>istio</code> CA cert, is also validated.</p>
<pre><code>curl --cacert istio_cert https://example-webhook.default.svc
Test
</code></pre>
<p>where <code>istio_cert</code> is the file containing istio's CA certificate</p>
<p>What is going on?</p>

<p>Not sure if you can use webhook on port 80...</p>
<p>Perhaps some of this will be useful to you, I used the following script to generate certificates, you can change it to suit your needs:</p>
<pre><code>#!/bin/bash

set -e

service=webhook-svc
namespace=default
secret=webhook-certs
csrName=${service}.${namespace}

cat &lt;&lt;EOF &gt;&gt; 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}
DNS.2 = ${service}.${namespace}
DNS.3 = ${service}.${namespace}.svc
EOF

openssl genrsa -out server-key.pem 2048
openssl req -new -key server-key.pem -subj &quot;/CN=${service}.${namespace}.svc&quot; -out server.csr -config csr.conf

kubectl delete csr ${csrName} 2&gt;/dev/null || true

cat &lt;&lt;EOF | kubectl create -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: ${csrName}
spec:
  groups:
  - system:authenticated
  request: $(&lt; server.csr base64 | tr -d '\n')
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

sleep 5

kubectl certificate approve ${csrName}

for i in {1 .. 10}
do
    serverCert=$(kubectl get csr ${csrName} -o jsonpath='{.status.certificate}')
    if [[ ${serverCert} != '' ]]; then
        break
    fi
    sleep 1
done
if [[ ${serverCert} == '' ]]; then
    echo &quot;ERROR: After approving csr ${csrName}, the signed certificate did not appear on the resource. Giving up after 10 attempts.&quot; &gt;&amp;2
    exit 1
fi


echo &quot;${serverCert}&quot; | openssl base64 -d -A -out server-cert.pem


# create the secret with CA cert and server cert/key
kubectl create secret generic ${secret} \
        --from-file=key.pem=server-key.pem \
        --from-file=cert.pem=server-cert.pem \
        --dry-run -o yaml |
    kubectl -n ${namespace} apply -f -
</code></pre>
<p>The script creates a secret, which I then mounted into the webhook, deployment.yaml:</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: webhook-deployment
  namespace: default
  labels:
    app: webhook
  annotations:
    sidecar.istio.io/inject: &quot;false&quot;
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webhook
  template:
    metadata:
      labels:
        app: webhook
      annotations:
        sidecar.istio.io/inject: &quot;false&quot;
    spec:
      containers:
        - name: webhook
          image: webhook:v1
          imagePullPolicy: IfNotPresent
          volumeMounts:
          - name: webhook-certs
            mountPath: /certs
            readOnly: true
      volumes:
      - name: webhook-certs
        secret:
          secretName: webhook-certs
</code></pre>
<p>service.yaml:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: webhook-svc
  namespace: default
  labels:
    app: webhook
spec:
  ports:
  - port: 443
    targetPort: 8443
  selector:
    app: webhook
</code></pre>
