<p>I have been trying to find how to do this but so far have found nothing, I am quite new to Kubernetes so I might just have looked over it. I want to use my own certificate for the Kubernetes API server, is this possible? And if so, can someone perhaps give me a link?</p>

<p>Ok, so here is my idea. We know we cannot change cluster certs, but there is other way to do it. We should be able to proxy through ingress.</p>
<p>First we enabled ingres addon:</p>
<pre><code>➜  ~ minikube addons enable ingress
</code></pre>
<p>Given <code>tls.crt</code> and <code>tls.key</code> we create a secret (you don't need to do this if you are using certmanager but this requires some additinal steps I am not going to describe here):</p>
<pre><code>➜  ~ kubectl create secret tls my-tls --cert=tls.crt --key tls.key
</code></pre>
<p>and an ingress object:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-k8s
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: &quot;HTTPS&quot;
spec:
  tls:
  - hosts:
    - foo.bar.com
    secretName: my-tls
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes
            port:
              number: 443
</code></pre>
<p>Notice what docs say about CN and FQDN: <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/#tls" rel="nofollow noreferrer">k8s docs</a>:</p>
<blockquote>
<p>Referencing this secret in an Ingress tells the Ingress controller to secure the channel from the client to the load balancer using TLS. <strong>You need to make sure the TLS secret you created came from a certificate that contains a Common Name (CN), also known as a Fully Qualified Domain Name (FQDN) for https-example.foo.com</strong>.</p>
</blockquote>
<p>The only issue with this approach is that we cannot use certificates for authentication when accessing from the outside.</p>
<p>But we can use tokens. Here is a page in k8s docs: <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/" rel="nofollow noreferrer">https://kubernetes.io/docs/reference/access-authn-authz/authentication/</a> that lists all possible methods of authentication.</p>
<p>For testing I choose serviceaccout token but feel free to experiment with others.</p>
<p>Let's create a service account, bind a role to it, and try to access the cluster:</p>
<pre><code>➜  ~ kubectl create sa cadmin
serviceaccount/cadmin created
➜  ~ kubectl create clusterrolebinding --clusterrole cluster-admin --serviceaccount default:cadmin cadminbinding
clusterrolebinding.rbac.authorization.k8s.io/cadminbinding created
</code></pre>
<p>Now we follow these instructions: <a href="https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/" rel="nofollow noreferrer">access-cluster-api</a> from docs to try to access the cluster with sa token.</p>
<pre><code>➜  ~ APISERVER=https://$(minikube ip)
➜  ~ TOKEN=$(kubectl get secret $(kubectl get serviceaccount cadmin -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
➜  ~ curl $APISERVER/api --header &quot;Authorization: Bearer $TOKEN&quot; --insecure -H &quot;Host: foo.bar.com&quot;
{
  &quot;kind&quot;: &quot;APIVersions&quot;,
  &quot;versions&quot;: [
    &quot;v1&quot;
  ],
  &quot;serverAddressByClientCIDRs&quot;: [
    {
      &quot;clientCIDR&quot;: &quot;0.0.0.0/0&quot;,
      &quot;serverAddress&quot;: &quot;192.168.39.210:8443&quot;
    }
  ]
}
</code></pre>
<blockquote>
<p>note: I am testing it with invalid/selfsigned certificates and I don't own the foo.bar.com domain so I need to pass Host header by hand. For you it may look a bit different, so don't just copypate; try to understand what's happening and adjust it. If you have a domain you should be able to access it directly (no <code>$(minikube ip)</code> necessary).</p>
</blockquote>
<p>As you should see, it worked! We got a valid response from api server.</p>
<p>But we probably don't want to use curl to access k8s.</p>
<p>Let's create a kubeconfig with the token.</p>
<pre><code>kubectl config set-credentials cadmin --token $TOKEN --kubeconfig my-config
kubectl config set-cluster mini --kubeconfig my-config --server https://foo.bar.com
kubectl config set-context mini --kubeconfig my-config --cluster mini --user cadmin
kubectl config use-context --kubeconfig my-config mini
</code></pre>
<p>And now we can access k8s with this config:</p>
<pre><code>➜  ~ kubectl get po --kubeconfig my-config
No resources found in default namespace.
</code></pre>
