Dedicated K8s Service Accounts
Prerequisites
-
Akeyless Gateway with network access to Kubernetes cluster.
-
Kubernetes version 1.21 and higher.
Dedicated Service Account
This flow describes the creation of a dedicated K8s Service Account which will work based on token projection.
For a Rancher cluster, please create your Rancher API Key and refer to this section to extract your Rancher server CA certificate.
Note:
To enable and use token request projection on a self-managed cluster, you must specify each of the following command line arguments to kube-apiserver:
--service-account-issuer
--service-account-key-file
--service-account-signing-key-file
--api-audiences
For more details, check out the minikube configuration example at the end of this page.
- Create a Service Account named
gateway-token-reviewer
with permission to access token review API. This Service Account will be used to validate a KubernetesJWT
coming from a pod that will try to authenticate to Akeyless.
cat << EOF > akl_gw_token_reviewer.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: gateway-token-reviewer
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: role-tokenreview-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: gateway-token-reviewer
namespace: default
EOF
Apply:
kubectl apply -f akl_gw_token_reviewer.yaml
Bearer Token Extraction for K8s Server Version 1.23 or Older
- Extract the
gateway-token-reviewer
Service Account secret name:
GW_SA_NAME=$(kubectl get sa gateway-token-reviewer \
--output jsonpath="{.secrets[*]['name']}")
- Extract the Service Account
JWT
Bearer Token (Kubernetes Server Version <= 1.23
):
SA_JWT_TOKEN=$(kubectl get secret $GW_SA_NAME \
--output 'go-template={{ .data.token | base64decode }}')
Bearer Token Extraction for K8s Server Version 1.24 or Higher
K8s won’t generate Secrets automatically for ServiceAccounts, to get your Service Account token, run the following commands instead:
- Create the long-lived service account secret (Kubernetes Server Version >= 1.24):
cat <<EOF > akl_gw_token_reviewer_token.yaml
apiVersion: v1
kind: Secret
metadata:
name: gateway-token-reviewer-token
namespace: default
annotations:
kubernetes.io/service-account.name: gateway-token-reviewer
type: kubernetes.io/service-account-token
EOF
kubectl apply -f akl_gw_token_reviewer_token.yaml
- Extract the service account
JWT
Bearer Token (Kubernetes Server Version >= 1.24
):
SA_JWT_TOKEN=$(kubectl get secret gateway-token-reviewer-token \
--output 'go-template={{.data.token | base64decode}}')
Extract K8s Cluster CA Certificate
To extract the K8s cluster CA cert used to talk to Kubernetes API run the following command:
CA_CERT=$(kubectl config view --raw --minify --flatten \
--output 'jsonpath={.clusters[].cluster.certificate-authority-data}')
CA_CERT=$(openssl s_client -host <Rancher Server> -port 443 2>&1 | sed -n -e '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/ p' | base64)
Create K8s Auth Method
- Use the Akeyless CLI to create the Kubernetes auth method which will restrict access to 2 different pods, named
mypod1
andmypod2
from the namespacemy-namespace-a
. The result contains an access Id and a private key that you will need later for the K8S Auth configuration in your Gateway:
akeyless create-auth-method-k8s -n my-k8s-auth-method --bound-pod-names mypod1 \
--bound-pod-names mypod2 --bound-namespaces my-namespace-a --json
Upon successful creation, the response:
{
"access_id": "p-abcdefg1234",
"prv_key": "LS0tLS1CRUdJTiBSUlNDUUxt.....QVRFIEtFWS0tLS0tCg=="
}
Tip
Save returned private key & AccessID for next steps inside an environment variables
$PRV_KEY
and$ACCESS_ID
.
Create K8s Gateway Auth Config Using Tokens
To discover your K8s service account issuer run the following command:
Tip
Open a new tab to run this command as it starts a server. Then, go back to your original tab to extract the issuer.
Forwarding the Kubernetes API:
kubectl proxy --api-prefix=/k8s-api
Extract the issuer:
K8S_ISSUER=$(curl -s http://localhost:8001/k8s-api/.well-known/openid-configuration | jq -r .issuer)
Or extract the issuer directly from your pod token:
K8S_ISSUER=$(jq -R 'split(".") | .[1] | @base64d | fromjson |.iss' <<< $(cat /var/run/secrets/kubernetes.io/serviceaccount/token) -r)
Use the Akeyless CLI to create the K8S auth config. The following parameters are required:
-
name: The config name (will be used during the authentication process).
-
gateway-url: Your Gateway URL (default is http://localhost:8000).
-
access-id: The
Access Id
of the Kubernetes auth method that was created. -
signing-key: The private key (The key that was created when the Kubernetes auth method was created).
-
cluster-api-type: By default work with
native-k8s
. To work with Rancher, please setrancher
. -
k8s-host: The URL of your Kubernetes API server endpoint. Or your Rancher server.
-
token-reviewer-jwt: Relevant only for native k8s - The service account
JWT
used to access the TokenReview API. -
rancher-api-key: Relevant only for Rancher - Rancher Bearer token, based on the created Rancher API Key..
-
rancher-cluster-id: Relevant only for Rancher - Rancher Cluster ID, i.e., your Rancher API Key Scope.
-
k8s-ca-cert: The certificate to use to call into your Kubernetes API.
-
k8s-issuer: The Kubernetes JWT issuer name (default - kubernetes/serviceaccount).
akeyless gateway-create-k8s-auth-config --name k8s-conf \
--gateway-url <https://Your-GW-URL>:8000 \
--access-id $ACCESS_ID \
--signing-key $PRV_KEY \
--k8s-host=<https://Your-K8s-Cluster-IP:8443> \
--token-reviewer-jwt $SA_JWT_TOKEN \
--k8s-ca-cert $CA_CERT \
--k8s-issuer $K8S_ISSUER
akeyless gateway-create-k8s-auth-config --name k8s-conf-rancher \
--gateway-url <https://Your-GW-URL>:8000 \
--access-id $ACCESS_ID \
--signing-key $PRV_KEY \
--cluster-api-type rancher \
--k8s-host=<https://Rancher Host>:443 \
--k8s-ca-cert $CA_CERT \
--k8s-issuer $K8S_ISSUER \
--rancher-api-key <API_KEY> \
--rancher-cluster-id <CLUSTER_ID> \
Authenticate from a pod in your K8s cluster
- Create a namespace with a name that the auth method access is restricted to:
kubectl create namespace my-namespace-a
- In this namespace, create a pod with a name that the auth method access is restricted to:
kubectl run mypod1 --image=nginx -n my-namespace-a
- Start an interactive shell session on the pod and perform the following commands in the pod :
kubectl exec --stdin=true --namespace my-namespace-a --tty=true mypod1 -- /bin/sh
- Install Akeyless CLI inside your pod:
curl -o akeyless https://akeyless-cli.s3.us-east-2.amazonaws.com/cli/latest/production/cli-linux-amd64
chmod +x akeyless
- Authenticate via your Kubernetes auth method with the following parameters :
-
access-id: The
Access Id
of the Kubernetes auth method that was created. -
access-type: the access type -
k8s
-
gateway-url: Your Gateway URL (default is http://localhost:8000)
-
k8s-auth-config-name: The K8s auth config name in your Gateway.
-
k8s-token-path: An optional path to a projected service account token inside the pod, for use instead of the default
/var/run/secrets/kubernetes.io/serviceaccount/token
./akeyless auth --access-id $ACCESS_ID \
--access-type k8s \
--gateway-url https://<Your-GW-URL>:8000 \
--k8s-auth-config-name k8s-conf
Upon successful authentication, the response will be:
Authentication succeeded.
Token: t-bb7b...3564a7c9
Tip
Delete the private key and Access ID which you stored as an environment variables
$PRV_KEY
and$ACCESS_ID
Available claims for K8s Auth
The following list of claims can be configured within Akeyless Access Roles (RBAC) to control and segregate the relevant policy for K8s.
"service_account_name"
"service_account_uid"
"service_account_secret_name"
"namespace"
"aud"
"pod_name" # available only when "token request projection" is enabled on your Kubernetes cluster
"pod_uid" # available only when "token request projection" is enabled on your Kubernetes cluster
Each claim can be enforced as part of your role association to enforce the right policy for your items.
Enable token request projection on Minikube
To enable token request projection on a managed K8s cluster you can follow this guide.
To get this to work with Minikube you can start your cluster with the following configuration.
minikube start \
--vm-driver=none \
--extra-config=apiserver.service-account-signing-key-file=/var/lib/minikube/certs/sa.key \
--extra-config=apiserver.service-account-key-file=/var/lib/minikube/certs/sa.pub \
--extra-config=apiserver.service-account-issuer=api \
--extra-config=apiserver.service-account-api-audiences=api,spire-server \
--extra-config=apiserver.authorization-mode=Node,RBAC \
--extra-config=kubelet.authentication-token-webhook=true
Note:
This example uses
api
as the service account issuer name, for your service accounts API audience.
Updated 21 days ago