Configure workload identity federation for the Tailscale Kubernetes Operator
Last validated:
Workload identity federation is currently in beta.
Tailscale supports workload identity federation for authenticating to a tailnet using provider-native identity tokens. The operator can use its ServiceAccount token as an OIDC identity and authenticate without requiring a long-lived OAuth client secret.
Prepare the cluster
The Kubernetes cluster's OIDC discovery endpoints must be publicly accessible. Bind the "unauthenticated" group to the "system:service-account-issuer-discovery" ClusterRole to allow unauthenticated access:
kubectl create clusterrolebinding oidc-discovery \
--clusterrole=system:service-account-issuer-discovery \
--group=system:unauthenticated
Get your cluster's issuer
The following command has a jq dependency. You may need to install jq on your device.
To get your cluster's issuer, run the following command:
ISSUER="$(kubectl get --raw /.well-known/openid-configuration | jq '.issuer')"
Configure a federated identity
Follow the steps to configure a federated identity in the admin console using the following values:
- Set the Issuer to Custom issuer.
- Set the Issuer URL to the value of
$ISSUERfrom the previous step. - Set the Subject to
system:serviceaccount:tailscale:operator. - Leave the Audience field blank.
- Create the client with
writescope for:General/Services(with thetag:k8s-operatortag)Devices/Core(with thetag:k8s-operatortag)Keys/Auth Keys(with thetag:k8s-operatortag)
Install or upgrade the Tailscale Kubernetes Operator
Make note of the required changes for your installation method before proceeding to the installation guide.
Helm
- Replace
--set-string oauth.clientSecret="<OAuth client secret>"with--set-string oauth.audience="<OIDC Audience>"when following the Helm installation guide.
Static manifests
Make the following changes in the manifest file when following the guide to install using static manifests
- Remove the
operator-oauthsecret definition (not needed). - Edit the Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: operator
namespace: tailscale
spec:
replicas: 1
selector:
matchLabels:
app: operator
strategy:
type: Recreate
template:
metadata:
labels:
app: operator
spec:
containers:
- env:
- name: OPERATOR_INITIAL_TAGS
value: tag:k8s-operator
- name: OPERATOR_HOSTNAME
value: tailscale-operator
- name: OPERATOR_SECRET
value: operator
- name: OPERATOR_LOGGING
value: info
- name: OPERATOR_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: OPERATOR_LOGIN_SERVER
value: null
- name: OPERATOR_INGRESS_CLASS_NAME
value: tailscale
- name: CLIENT_ID
value: "<OAuth client ID>"
- name: PROXY_IMAGE
value: tailscale/tailscale:stable
- name: PROXY_TAGS
value: tag:k8s
- name: APISERVER_PROXY
value: "false"
- name: PROXY_FIREWALL_MODE
value: auto
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_UID
valueFrom:
fieldRef:
fieldPath: metadata.uid
image: tailscale/k8s-operator:stable
imagePullPolicy: Always
name: operator
volumeMounts:
- mountPath: /var/run/secrets/tailscale/serviceaccount
name: oidc-jwt
readOnly: true
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: operator
volumes:
- name: oidc-jwt
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: "<OIDC Audience>"
expirationSeconds: 3600
path: token
After you have applied the manifest and verified that the operator-oauth secret is no longer being used, you can delete the secret.
Further exploration
- Understand how workload identity federation works and how it integrates with Tailscale.
- Install the Tailscale Kubernetes Operator.