Memebrships: Refactor Store interface
Use unified memberships table.
Add few internal API endpoints.
Change-Id: I80ac5a0f5c262e04d7898cca571b938a35d68d39
diff --git a/core/auth/proxy/main.go b/core/auth/proxy/main.go
index f8ab620..a4a2efc 100644
--- a/core/auth/proxy/main.go
+++ b/core/auth/proxy/main.go
@@ -35,6 +35,7 @@
var f embed.FS
var noAuthPathRegexps []*regexp.Regexp
+var allowedGroups []Group
func initPathPatterns() error {
for _, p := range strings.Split(*noAuthPathPatterns, ",") {
@@ -51,6 +52,38 @@
return nil
}
+type getGroupReq struct {
+ GroupId string `json:"groupId"`
+}
+
+type getGroupResp struct {
+ Self Group `json:"self"`
+}
+
+func initAllowedGroups() error {
+ for _, groupId := range strings.Split(*groups, ",") {
+ gid := strings.TrimSpace(groupId)
+ if len(gid) == 0 {
+ continue
+ }
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(getGroupReq{gid}); err != nil {
+ return err
+ }
+ resp, err := http.Post(fmt.Sprintf("%s/api/get-group", *membershipAddr), "application/json", &buf)
+ if err != nil {
+ return err
+ }
+ var info getGroupResp
+ if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
+ return err
+ }
+ fmt.Println(info.Self)
+ allowedGroups = append(allowedGroups, info.Self)
+ }
+ return nil
+}
+
type cachingHandler struct {
h http.Handler
}
@@ -91,7 +124,7 @@
type UnauthorizedPageData struct {
MembershipPublicAddr string
- Groups []string
+ Groups []Group
}
func renderUnauthorizedPage(w http.ResponseWriter, groups []string) {
@@ -102,7 +135,7 @@
}
data := UnauthorizedPageData{
MembershipPublicAddr: *membershipPublicAddr,
- Groups: groups,
+ Groups: allowedGroups,
}
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusUnauthorized)
@@ -141,13 +174,13 @@
}
if *groups != "" {
hasPermission := false
- tg, err := getTransitiveGroups(user.Identity.Traits.Username)
+ tg, err := getGroupsUserCanActAs(user.Identity.Id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- for _, i := range strings.Split(*groups, ",") {
- if slices.Contains(tg, strings.TrimSpace(i)) {
+ for _, i := range allowedGroups {
+ if slices.Contains(tg, i) {
hasPermission = true
break
}
@@ -219,44 +252,35 @@
if err != nil {
return nil, err
}
- data := make(map[string]any)
- if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
- return nil, err
- }
- // TODO(gio): remove debugging
- b, err := json.MarshalIndent(data, "", " ")
- if err != nil {
- return nil, err
- }
- fmt.Println(string(b))
- var buf bytes.Buffer
- if err := json.NewEncoder(&buf).Encode(data); err != nil {
- return nil, err
- }
- tmp := buf.String()
if resp.StatusCode == http.StatusOK {
u := &user{}
- if err := json.NewDecoder(strings.NewReader(tmp)).Decode(u); err != nil {
+ if err := json.NewDecoder(resp.Body).Decode(u); err != nil {
return nil, err
}
return u, nil
}
e := &authError{}
- if err := json.NewDecoder(strings.NewReader(tmp)).Decode(e); err != nil {
+ if err := json.NewDecoder(resp.Body).Decode(e); err != nil {
return nil, err
}
if e.Error.Status == "Unauthorized" {
return nil, nil
}
- return nil, fmt.Errorf("Unknown error: %s", tmp)
+ return nil, fmt.Errorf("Unknown error")
+}
+
+type Group struct {
+ Id string `json:"id"`
+ Title string `json:"title"`
+ Description string `json:"description"`
}
type MembershipInfo struct {
- MemberOf []string `json:"memberOf"`
+ CanActAs []Group `json:"canActAs"`
}
-func getTransitiveGroups(user string) ([]string, error) {
- resp, err := http.Get(fmt.Sprintf("%s/%s", *membershipAddr, user))
+func getGroupsUserCanActAs(user string) ([]Group, error) {
+ resp, err := http.Get(fmt.Sprintf("%s/api/user/%s", *membershipAddr, user))
if err != nil {
return nil, err
}
@@ -264,7 +288,7 @@
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
return nil, err
}
- return info.MemberOf, nil
+ return info.CanActAs, nil
}
func main() {
@@ -275,6 +299,9 @@
if err := initPathPatterns(); err != nil {
log.Fatal(err)
}
+ if err := initAllowedGroups(); err != nil {
+ log.Fatal(err)
+ }
http.Handle("/.auth/static/", http.StripPrefix("/.auth", cachingHandler{http.FileServer(http.FS(f))}))
http.HandleFunc("/", handle)
fmt.Printf("Starting HTTP server on port: %d\n", *port)
diff --git a/core/auth/proxy/unauthorized.html b/core/auth/proxy/unauthorized.html
index 130cf81..28c8913 100644
--- a/core/auth/proxy/unauthorized.html
+++ b/core/auth/proxy/unauthorized.html
@@ -15,7 +15,7 @@
<p>
Only members of
{{ range $index, $group := .Groups }}
- <a href="{{ $.MembershipPublicAddr }}/group/{{ $group }}">{{ $group }}</a>{{ if not (IsLast $index $.Groups) }},{{ end }}
+ <a href="{{ $.MembershipPublicAddr }}/group/{{ $group.Id }}">{{ $group.Title }}</a>{{ if not (IsLast $index $.Groups) }},{{ end }}
{{ end }}
are authorized to access this page.
</p>