Should the k8s Cluster Certificate Authority be kept secret? - kubernetes

I have an azure aks cluster and a local kubeconfig:
apiVersion: v1
kind: Config
clusters:
- name: my-cluster
cluster:
certificate-authority-data: LS0...0tCg==
server: https://api-server:443
contexts:
- name: my-context
context:
cluster: my-cluster
namespace: samples
user: my-context-user
current-context: my-context
users:
- name: my-context-user
user:
token: ey...jI
that is used for connecting to the cluster, listing pods etc.
From what I understand its important that the token in the kubeconfig is kept secret/private. But whats about the certificate-authority-data?
Since its just used to verify the the API server certificate I guess it has the same status as a public key and can be made public available at least for internal team members.
And is there and documentation that confirms this?
I did not find any info regarding that here or here.

All clients (pods, normal users using kubeconfigfile, service accounts, component clients: kubelet to kube-apiserver etc.) are suing ca.crt in order to recognize self-signed certificates.
As we can see in the docs
Client certificate authentication is enabled by passing the --client-ca-file=SOMEFILE option to API server. The referenced file must contain one or more certificate authorities to use to validate client certificates presented to the API server. If a client certificate is presented and verified, the common name of the subject is used as the user name for the request. As of Kubernetes 1.4, client certificates can also indicate a user's group memberships using the certificate's organization fields. To include multiple group memberships for a user, include multiple organization fields in the certificate.
In k8s cluster boostraped using kubeadm by default kube-apiserver is consigured with --client-ca-file=/etc/kubernetes/pki/ca.crt.
As you can see in the docs certificate-authority ca.crt should be be referenced in any config file for all clients which are used to securely connect with k8s cluster.
Sometimes you may want to use Base64-encoded data embedded here instead of separate certificate files; in that case you need to add the suffix -data to the keys, for example, certificate-authority-data, client-certificate-data, client-key-data
By default this value is Base64-encoded and embedded in tho the KubeconfigFile.
When your workload is accessing the k8s API from within a Pod
You can find also information about
# Reference the internal certificate authority (CA)
CACERT=${SERVICEACCOUNT}/ca.crt
by default ca.crt is located in /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Why ca.crt is included in all kubeconfigFiles - as we can see in the docs
A client node may refuse to recognize a self-signed CA certificate as valid. For a non-production deployment, or for a deployment that runs behind a company firewall, you can distribute a self-signed CA certificate to all clients and refresh the local list for valid certificates.
According to your last statement.
Since its just used to verify the the API server certificate I guess it has the same status as a public key and can be made public available at least for internal team members
certificate-authority-data should be included in all kubeconfig files for all internal team members, while client-key-data or tokens should be kept secret between different clients.

Related

cert-manager zerossl without EAB or API key

I have a Kubernetes cluster with nginx ingress.
I am trying to have ZeroSSL to provision SSL. I have setup ClusterIssuer and Ingress. The cluster issuer fails with error "Failed to register ACME account: 400 urn:ietf:params:acme:error:externalAccountRequired: The request must include a value for the "externalAccountBinding" field"
This application will be installed by many users. I do not want everyone to create a ZeroSSL account and provide an EAB. How can I enable only email based ClusterIssuer for ZeroSSL?
I know this is possible because I found the following
Ref: https://github.com/nginx-proxy/acme-companion/wiki/Zero-SSL
If you don't have a ZeroSSL account, you can let acme-companion create
a Zero SSL account with the adress provided in the ACME_EMAIL or
DEFAULT_EMAIL environment variable. Note that the adresse that will be
used must be a valid email adress that you actually own.
Acme.sh uses ZeroSSL and does not need EAB. It can work with just email. If no EAB provided, it will use email to create EAB. Ref: https://github.com/acmesh-official/acme.sh/blob/7221d488e54dfc6bcb30ca562f6d6e38ec5bf6ce/acme.sh#L3683
How can I make cert-manager to auto generate EAB using the email and use it to issue SSL?

Azure App Service Certificate ssl to AKS ingress

I have bought a WildCard ssl certificate from Azure App Service Certificate. I also have an AKS Cluster. I want to put it in the secret and use in ingress. After purchase it stored secret file in Azure Key Vault. I downloaded it and then imported to create Azure Key Vault Certificate. Then with akv2k8s I created a secret file in my AKS and used it in ingress. After my application threw 'err_cert_authority_invalid' error.
Do I do anything wrong ??
There is not so many documentation on ssl and ingress. In many articles, they use 'Lets Encrypt' or 'Cert Manager'.
https://akv2k8s.io/
• It can be due to the misinterpretation that the certificate is issued by the staging environment or vice versa. Thus, for that purpose, I would suggest you to please check the ‘stable/wordpress’ helm chart with the ingress annotation 'certmanager.k8s.io/cluster-issuer': 'letsencrypt-staging'. This will result in being issued a certificate from the fake issuer. Thus, even if your certificate is ingressed in your AKS as a secret, it will be shown as being issued from a fake issuer since the chain of certificate hash validation is broken in between. Please find below the curl for that purpose: -
‘ # curl -vkI https://blog.my-domain.com/
...
* Server certificate:
* subject: CN=blog.my-domain.com
* start date: May 13 08:51:13 2019 GMT
* expire date: Aug 11 08:51:13 2019 GMT
* issuer: CN=Fake LE Intermediate X1
... ‘
Then, list the ingresses as follows: -
‘ # kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
blog-wordpress blog.my-domain.com 35.200.214.186 80, 443 8m48s ’
and the certificates too: -
‘ # kubectl get certificates
NAME READY SECRET AGE
wordpress.local-tls True wordpress.local-tls 9m ’
Then, switch the issuer of the certificate to the one that has issued the certificate originally as below: -
‘ # kubectl edit ing blog-wordpress ’
And update the annotation as below: -
‘ certmanager.k8s.io/cluster-issuer: letsencrypt-prod ’
Once the ingress manifest is updated, then the certificate manifest will automatically be updated. To verify it, open the manifest for ‘wordpress.local-tls’ certificate resource as below: -
‘ kubectl edit certificate wordpress.local-tls ’
The issuer will be seen as updated as below: -
‘ kubectl edit certificate wordpress.local-tls ’
Thus, in this way, you will be able to import a certificate secret in AKS. For more details, I would suggest you to please refer the below link for more details: -
https://github.com/vmware-archive/kube-prod-runtime/issues/532

Programmatically create users in Kubernetes

I am looking for a way to create/retrieve/update/delete a user in Kubernetes, such that I can allow him certain stuff via RoleBindings.
Everything I have found is more or less manual work on the master node. However, I imagine a service deployed in Kubernetes I could call via an API to do the magic for me without doing any manual work. Is such a thing available?
From https://kubernetes.io/docs/reference/access-authn-authz/authentication/#users-in-kubernetes
All Kubernetes clusters have two categories of users: service accounts
managed by Kubernetes, and normal users.
Kubernetes does not have objects which represent
normal user accounts. Normal users cannot be added to a cluster
through an API call.
Even though a normal user cannot be added via an API call, any user
that presents a valid certificate signed by the cluster's certificate
authority (CA) is considered authenticated.
So there is no API call to create normal user. However you can create service accounts that can have RoleBindings bound to them.
Another possibility is to create TLS certificate, sign it with Kubernetes cluster CA (using CSRs) and use it as a "normal user".

Kubernetes service account - token signature validation

In any given POD, service account token is is mounted at location.
/var/run/secrets/kubernetes.io/serviceaccount/token
I want to understand how this token is signed. What keys are used while signing this token by Kubernetes? How to get access to public key that can help in offline signature validation
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - I tried signature validation with the public key associated with this certificate. This does not seem to work.
Appreciate any help on this.
You can check the service account file from kube-apiserver pod yaml file. There is a flag which is:
--service-account-key-file=/etc/kubernetes/pki/sa.pub
From master node check /etc/kubernetes/pki directory.

How to create base authentication in kubernetes?

I want to create base authentication in kubernetes. every document say that I should create CSV or file then enter the username and password in it. but I do not want to use file I want to some database or kubernetes handle it.
what can I do for base authentication?
You can based your authentication on tokens if you don't want to use static pasword file.
First option:
Service Account Tokens
A service account is an automatically enabled authenticator that uses signed bearer tokens to verify requests.
The plugin uses two flags(which are optional):
Service accounts are usually created automatically by the API server and associated with pods running in the cluster through the ServiceAccount Admission Controller. Bearer tokens are mounted into pods at well-known locations, and allow in-cluster processes to talk to the API server. Accounts may be explicitly associated with pods using the serviceAccountName field of a PodSpec.
Service account bearer tokens are perfectly valid to use outside the cluster and can be used to create identities for long standing jobs that wish to talk to the Kubernetes API. To manually create a service account, simply use the kubectl create serviceaccount (NAME) command. This creates a service account in the current namespace and an associated secret.
The created secret holds the public CA of the API server and a signed JSON Web Token (JWT).
The signed JWT can be used as a bearer token to authenticate as the given service account. See above for how the token is included in a request. Normally these secrets are mounted into pods for in-cluster access to the API server, but can be used from outside the cluster as well.
There is some drawbacks because service account tokens are stored in secrets, any user with read access to those secrets can authenticate as the service account. Be careful when granting permissions to service accounts and read capabilities for secrets.
Second:
Install OpenID Connect (full documentation you can find here: oidc).
OpenID Connect (OIDC) is a superset of OAuth2 supported by some service providers, notably Azure Active Directory, Salesforce, and Google. The protocol’s main addition on top of OAuth2 is a field returned with the access token called an ID Token. This token is a JSON Web Token (JWT) with well known fields, such as a user’s email, signed by the server.
To identify the user, the authenticator uses the id_token (not the access_token) from the OAuth2 token response as a bearer token.
Since all of the data needed to validate who you are is in the id_token, Kubernetes doesn’t need to “phone home” to the identity provider. In a model where every request is stateless this provides a very scalable solution for authentication.
Kubernetes has no “web interface” to trigger the authentication process. There is no browser or interface to collect credentials which is why you need to authenticate to your identity provider first.
There’s no easy way to authenticate to the Kubernetes dashboard without using the kubectl proxy command or a reverse proxy that injects the id_token.
More information you can find here: kubernetes-authentication.