Skip to content

Commit acf1bfd

Browse files
authored
gocached: support namespaces (#34)
Remove the special-case concept of "global writes" and instead allow callers to provide a namespace mapping function that makes policy decisions about which clients are globally trusted and which clients should be isolated from each other. As a result, all clients are now able to write, but not necessarily into the shared global namespace. All clients can still read from the global namespace, as well as their own. The Namespaces table already existed in the schema, but we drop the lowercase constraint. However, there are some breaking changes in the package API, WithJWTAuth now takes issuer URLs only and policy moves into the new WithNamespaceMapping option. cmd/gocached implements the spirit of the old API in terms of a namespace mapping function, with the main difference that it now allows writes if you don't have the global claims, but just into your own isolated namespace. Updates tailscale/corp#38092 Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
1 parent d48e363 commit acf1bfd

3 files changed

Lines changed: 434 additions & 249 deletions

File tree

cmd/gocached/gocached.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"flag"
1010
"fmt"
1111
"log"
12-
"maps"
1312
"net"
1413
"net/http"
1514
"os"
@@ -77,15 +76,27 @@ func main() {
7776
log.Fatal("must specify --jwt-claim at least once when --jwt-issuer is set")
7877
}
7978

80-
globalClaims := map[string]string{}
81-
maps.Copy(globalClaims, jwtClaims)
82-
maps.Copy(globalClaims, globalJWTClaims)
83-
84-
opts = append(opts, gocached.WithJWTAuth(gocached.JWTIssuerConfig{
85-
Issuer: *jwtIssuer,
86-
RequiredClaims: jwtClaims,
87-
GlobalWriteClaims: globalClaims,
88-
}))
79+
opts = append(opts,
80+
gocached.WithJWTAuth(*jwtIssuer),
81+
gocached.WithNamespaceMapping(func(claims map[string]any) (gocached.Namespace, error) {
82+
var ns gocached.Namespace
83+
for k, want := range jwtClaims {
84+
if got := claims[k]; got != want {
85+
return "", fmt.Errorf("claim %q = %v, want %v", k, got, want)
86+
}
87+
if ns != "" {
88+
ns += ","
89+
}
90+
ns += gocached.Namespace(fmt.Sprintf("%s=%s", k, want))
91+
}
92+
for k, want := range globalJWTClaims {
93+
if got := claims[k]; got != want {
94+
return ns, nil
95+
}
96+
}
97+
return gocached.GlobalNamespace, nil
98+
}),
99+
)
89100
}
90101

91102
srv, err := gocached.NewServer(opts...)

0 commit comments

Comments
 (0)