cmd/k8s-operator: make auth proxy pass tags as Impersonate-Group

We were not handling tags at all, pass them through as Impersonate-Group headers.
And use the FQDN for tagged nodes as Impersonate-User.

Updates #5055

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali 2023-03-13 08:48:09 -07:00 committed by Maisem Ali
parent 56526ff57f
commit 489e27f085
2 changed files with 21 additions and 5 deletions

View File

@ -7,7 +7,7 @@ metadata:
name: tailscale-auth-proxy
rules:
- apiGroups: [""]
resources: ["users"]
resources: ["users", "groups"]
verbs: ["impersonate"]
---
apiVersion: rbac.authorization.k8s.io/v1

View File

@ -51,13 +51,16 @@ func runAuthProxy(lc *tailscale.LocalClient, ls net.Listener, rt http.RoundTripp
lc: lc,
rp: &httputil.ReverseProxy{
Director: func(r *http.Request) {
// Replace the request with the user's identity.
who := r.Context().Value(whoIsKey{}).(*apitype.WhoIsResponse)
r.Header.Set("Impersonate-User", who.UserProfile.LoginName)
// We want to proxy to the Kubernetes API, but we want to use
// the caller's identity to do so. We do this by impersonating
// the caller using the Kubernetes User Impersonation feature:
// https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation
// Remove all authentication headers.
// Out of paranoia, remove all authentication headers that might
// have been set by the client.
r.Header.Del("Authorization")
r.Header.Del("Impersonate-Group")
r.Header.Del("Impersonate-User")
r.Header.Del("Impersonate-Uid")
for k := range r.Header {
if strings.HasPrefix(k, "Impersonate-Extra-") {
@ -65,6 +68,19 @@ func runAuthProxy(lc *tailscale.LocalClient, ls net.Listener, rt http.RoundTripp
}
}
// Now add the impersonation headers that we want.
who := r.Context().Value(whoIsKey{}).(*apitype.WhoIsResponse)
if who.Node.IsTagged() {
// Use the nodes FQDN as the username, and the nodes tags as the groups.
// "Impersonate-Group" requires "Impersonate-User" to be set.
r.Header.Set("Impersonate-User", who.Node.Name)
for _, tag := range who.Node.Tags {
r.Header.Add("Impersonate-Group", tag)
}
} else {
r.Header.Set("Impersonate-User", who.UserProfile.LoginName)
}
// Replace the URL with the Kubernetes APIServer.
r.URL.Scheme = u.Scheme
r.URL.Host = u.Host