From 932d1d28e8df26c2f036c1e11fe566fa832f68d8 Mon Sep 17 00:00:00 2001 From: Jamie Greeff Date: Wed, 31 Aug 2022 12:40:10 +0100 Subject: [PATCH] cmd/nginx-auth: ability to check application capabilities A header `Expected-Cap` can now be passed which can be used to assert that `WhoIsResponse.Caps` contains the provided capability. This allows for ACL rules to define capabilities that can be checked here in cmd/nginx-auth, meaning that ACLs can be used to control access to various web services at Layer 7. Signed-off-by: Jamie Greeff --- cmd/nginx-auth/nginx-auth.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cmd/nginx-auth/nginx-auth.go b/cmd/nginx-auth/nginx-auth.go index ee55ca74f..afb3f9e1a 100644 --- a/cmd/nginx-auth/nginx-auth.go +++ b/cmd/nginx-auth/nginx-auth.go @@ -21,6 +21,7 @@ import ( "os" "strings" + "golang.org/x/exp/slices" "github.com/coreos/go-systemd/activation" "tailscale.com/client/tailscale" ) @@ -89,6 +90,20 @@ func main() { return } + if expectedCap := r.Header.Get("Expected-Cap"); expectedCap != "" { + if info.Caps == nil { + w.WriteHeader(http.StatusForbidden) + log.Printf("user does not have any caps, wanted: %s", url.QueryEscape(expectedCap)) + return + } + + if !slices.Contains(info.Caps, expectedCap) { + w.WriteHeader(http.StatusForbidden) + log.Printf("user is missing expected cap, has: %s, wanted: %s", strings.Join(info.Caps[:], ","), url.QueryEscape(expectedCap)) + return + } + } + h := w.Header() h.Set("Tailscale-Login", strings.Split(info.UserProfile.LoginName, "@")[0]) h.Set("Tailscale-User", info.UserProfile.LoginName)