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>
pull/7549/head
Maisem Ali 2 years ago committed by Maisem Ali
parent 56526ff57f
commit 489e27f085

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

@ -51,13 +51,16 @@ func runAuthProxy(lc *tailscale.LocalClient, ls net.Listener, rt http.RoundTripp
lc: lc, lc: lc,
rp: &httputil.ReverseProxy{ rp: &httputil.ReverseProxy{
Director: func(r *http.Request) { Director: func(r *http.Request) {
// Replace the request with the user's identity. // We want to proxy to the Kubernetes API, but we want to use
who := r.Context().Value(whoIsKey{}).(*apitype.WhoIsResponse) // the caller's identity to do so. We do this by impersonating
r.Header.Set("Impersonate-User", who.UserProfile.LoginName) // 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("Authorization")
r.Header.Del("Impersonate-Group") r.Header.Del("Impersonate-Group")
r.Header.Del("Impersonate-User")
r.Header.Del("Impersonate-Uid") r.Header.Del("Impersonate-Uid")
for k := range r.Header { for k := range r.Header {
if strings.HasPrefix(k, "Impersonate-Extra-") { 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. // Replace the URL with the Kubernetes APIServer.
r.URL.Scheme = u.Scheme r.URL.Scheme = u.Scheme
r.URL.Host = u.Host r.URL.Host = u.Host

Loading…
Cancel
Save