Reduce IAM API to only user and policies
This commit is contained in:
parent
f03e2ca5c5
commit
6f831fd190
@ -119,7 +119,7 @@ type IAMAuth0Tenant struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IAMPolicy struct {
|
type IAMPolicy struct {
|
||||||
Domain string `json:"group"`
|
Domain string `json:"domain"`
|
||||||
Resource string `json:"resource"`
|
Resource string `json:"resource"`
|
||||||
Actions []string `json:"actions"`
|
Actions []string `json:"actions"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ func NewIAM(iam iam.IAM) *IAMHandler {
|
|||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param config body api.IAMUser true "User definition"
|
// @Param config body api.IAMUser true "User definition"
|
||||||
|
// @Param domain query string false "Domain of the acting user"
|
||||||
// @Success 200 {object} api.IAMUser
|
// @Success 200 {object} api.IAMUser
|
||||||
// @Failure 400 {object} api.Error
|
// @Failure 400 {object} api.Error
|
||||||
// @Failure 500 {object} api.Error
|
// @Failure 500 {object} api.Error
|
||||||
@ -35,10 +36,8 @@ func NewIAM(iam iam.IAM) *IAMHandler {
|
|||||||
// @Router /api/v3/iam/user [post]
|
// @Router /api/v3/iam/user [post]
|
||||||
func (h *IAMHandler) AddUser(c echo.Context) error {
|
func (h *IAMHandler) AddUser(c echo.Context) error {
|
||||||
ctxuser := util.DefaultContext(c, "user", "")
|
ctxuser := util.DefaultContext(c, "user", "")
|
||||||
|
superuser := util.DefaultContext(c, "superuser", false)
|
||||||
if !h.iam.Enforce(ctxuser, "$none", "iam:/user", "write") {
|
domain := util.DefaultQuery(c, "domain", "$none")
|
||||||
return api.Err(http.StatusForbidden, "Forbidden")
|
|
||||||
}
|
|
||||||
|
|
||||||
user := api.IAMUser{}
|
user := api.IAMUser{}
|
||||||
|
|
||||||
@ -48,17 +47,27 @@ func (h *IAMHandler) AddUser(c echo.Context) error {
|
|||||||
|
|
||||||
iamuser, iampolicies := user.Unmarshal()
|
iamuser, iampolicies := user.Unmarshal()
|
||||||
|
|
||||||
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+iamuser.Name, "write") {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range iampolicies {
|
||||||
|
if !h.iam.Enforce(ctxuser, p.Domain, "iam:"+iamuser.Name, "write") {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Not allowed to write policy: %v", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !superuser && iamuser.Superuser {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Only superusers can add superusers")
|
||||||
|
}
|
||||||
|
|
||||||
err := h.iam.CreateIdentity(iamuser)
|
err := h.iam.CreateIdentity(iamuser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.Err(http.StatusBadRequest, "Bad request", "%s", err)
|
return api.Err(http.StatusBadRequest, "Bad request", "%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range iampolicies {
|
for _, p := range iampolicies {
|
||||||
if len(p.Domain) != 0 {
|
h.iam.AddPolicy(p.Name, p.Domain, p.Resource, p.Actions)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
h.iam.AddPolicy(p.Name, "$none", p.Resource, p.Actions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.iam.SaveIdentities()
|
err = h.iam.SaveIdentities()
|
||||||
@ -76,6 +85,7 @@ func (h *IAMHandler) AddUser(c echo.Context) error {
|
|||||||
// @ID iam-3-delete-user
|
// @ID iam-3-delete-user
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param name path string true "Username"
|
// @Param name path string true "Username"
|
||||||
|
// @Param domain query string false "Domain of the acting user"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 404 {object} api.Error
|
// @Failure 404 {object} api.Error
|
||||||
// @Failure 500 {object} api.Error
|
// @Failure 500 {object} api.Error
|
||||||
@ -83,17 +93,25 @@ func (h *IAMHandler) AddUser(c echo.Context) error {
|
|||||||
// @Router /api/v3/iam/user/{name} [delete]
|
// @Router /api/v3/iam/user/{name} [delete]
|
||||||
func (h *IAMHandler) RemoveUser(c echo.Context) error {
|
func (h *IAMHandler) RemoveUser(c echo.Context) error {
|
||||||
ctxuser := util.DefaultContext(c, "user", "")
|
ctxuser := util.DefaultContext(c, "user", "")
|
||||||
|
superuser := util.DefaultContext(c, "superuser", false)
|
||||||
|
domain := util.DefaultQuery(c, "domain", "$none")
|
||||||
name := util.PathParam(c, "name")
|
name := util.PathParam(c, "name")
|
||||||
|
|
||||||
if !h.iam.Enforce(ctxuser, "$none", "iam:/user", "write") {
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+name, "write") {
|
||||||
return api.Err(http.StatusForbidden, "Forbidden")
|
return api.Err(http.StatusForbidden, "Forbidden")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all policies of that user
|
iamuser, err := h.iam.GetIdentity(name)
|
||||||
h.iam.RemovePolicy(name, "", "", nil)
|
if err != nil {
|
||||||
|
return api.Err(http.StatusNotFound, "Not found", "%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !superuser && iamuser.Superuser {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Only superusers can remove superusers")
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the user
|
// Remove the user
|
||||||
err := h.iam.DeleteIdentity(name)
|
err = h.iam.DeleteIdentity(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.Err(http.StatusBadRequest, "Bad request", "%s", err)
|
return api.Err(http.StatusBadRequest, "Bad request", "%s", err)
|
||||||
}
|
}
|
||||||
@ -103,6 +121,9 @@ func (h *IAMHandler) RemoveUser(c echo.Context) error {
|
|||||||
return api.Err(http.StatusInternalServerError, "Internal server error", "%s", err)
|
return api.Err(http.StatusInternalServerError, "Internal server error", "%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all policies of that user
|
||||||
|
h.iam.RemovePolicy(name, "", "", nil)
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, "OK")
|
return c.JSON(http.StatusOK, "OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +135,7 @@ func (h *IAMHandler) RemoveUser(c echo.Context) error {
|
|||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param name path string true "Username"
|
// @Param name path string true "Username"
|
||||||
|
// @Param domain query string false "Domain of the acting user"
|
||||||
// @Param user body api.IAMUser true "User definition"
|
// @Param user body api.IAMUser true "User definition"
|
||||||
// @Success 200 {object} api.IAMUser
|
// @Success 200 {object} api.IAMUser
|
||||||
// @Failure 400 {object} api.Error
|
// @Failure 400 {object} api.Error
|
||||||
@ -123,15 +145,26 @@ func (h *IAMHandler) RemoveUser(c echo.Context) error {
|
|||||||
// @Router /api/v3/iam/user/{name} [put]
|
// @Router /api/v3/iam/user/{name} [put]
|
||||||
func (h *IAMHandler) UpdateUser(c echo.Context) error {
|
func (h *IAMHandler) UpdateUser(c echo.Context) error {
|
||||||
ctxuser := util.DefaultContext(c, "user", "")
|
ctxuser := util.DefaultContext(c, "user", "")
|
||||||
|
superuser := util.DefaultContext(c, "superuser", false)
|
||||||
|
domain := util.DefaultQuery(c, "domain", "$none")
|
||||||
name := util.PathParam(c, "name")
|
name := util.PathParam(c, "name")
|
||||||
|
|
||||||
if !h.iam.Enforce(ctxuser, "$none", "iam:/user", "write") {
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+name, "write") {
|
||||||
return api.Err(http.StatusForbidden, "Forbidden")
|
return api.Err(http.StatusForbidden, "Forbidden")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamuser, err := h.iam.GetIdentity(name)
|
var iamuser iam.User
|
||||||
if err != nil {
|
var err error
|
||||||
return api.Err(http.StatusNotFound, "Not found", "%s", err)
|
|
||||||
|
if name != "$anon" {
|
||||||
|
iamuser, err = h.iam.GetIdentity(name)
|
||||||
|
if err != nil {
|
||||||
|
return api.Err(http.StatusNotFound, "Not found", "%s", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iamuser = iam.User{
|
||||||
|
Name: "$anon",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iampolicies := h.iam.ListPolicies(name, "", "", nil)
|
iampolicies := h.iam.ListPolicies(name, "", "", nil)
|
||||||
@ -145,19 +178,31 @@ func (h *IAMHandler) UpdateUser(c echo.Context) error {
|
|||||||
|
|
||||||
iamuser, iampolicies = user.Unmarshal()
|
iamuser, iampolicies = user.Unmarshal()
|
||||||
|
|
||||||
err = h.iam.UpdateIdentity(name, iamuser)
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+iamuser.Name, "write") {
|
||||||
if err != nil {
|
return api.Err(http.StatusForbidden, "Forbidden")
|
||||||
return api.Err(http.StatusBadRequest, "Bad request", "%s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h.iam.RemovePolicy(name, "$none", "", nil)
|
for _, p := range iampolicies {
|
||||||
|
if !h.iam.Enforce(ctxuser, p.Domain, "iam:"+iamuser.Name, "write") {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Not allowed to write policy: %v", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !superuser && iamuser.Superuser {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Only superusers can modify superusers")
|
||||||
|
}
|
||||||
|
|
||||||
|
if name != "$anon" {
|
||||||
|
err = h.iam.UpdateIdentity(name, iamuser)
|
||||||
|
if err != nil {
|
||||||
|
return api.Err(http.StatusBadRequest, "Bad request", "%s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.iam.RemovePolicy(name, "", "", nil)
|
||||||
|
|
||||||
for _, p := range iampolicies {
|
for _, p := range iampolicies {
|
||||||
if len(p.Domain) != 0 {
|
h.iam.AddPolicy(p.Name, p.Domain, p.Resource, p.Actions)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
h.iam.AddPolicy(p.Name, "$none", p.Resource, p.Actions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.iam.SaveIdentities()
|
err = h.iam.SaveIdentities()
|
||||||
@ -168,6 +213,71 @@ func (h *IAMHandler) UpdateUser(c echo.Context) error {
|
|||||||
return c.JSON(http.StatusOK, user)
|
return c.JSON(http.StatusOK, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateUserPolicies replaces existing user policies
|
||||||
|
// @Summary Replace policies of an user
|
||||||
|
// @Description Replace policies of an user
|
||||||
|
// @Tags v16.?.?
|
||||||
|
// @ID iam-3-update-user
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param name path string true "Username"
|
||||||
|
// @Param domain query string false "Domain of the acting user"
|
||||||
|
// @Param user body []api.IAMPolicy true "Policy definitions"
|
||||||
|
// @Success 200 {array} api.IAMPolicy
|
||||||
|
// @Failure 400 {object} api.Error
|
||||||
|
// @Failure 404 {object} api.Error
|
||||||
|
// @Failure 500 {object} api.Error
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /api/v3/iam/user/{name}/policy [put]
|
||||||
|
func (h *IAMHandler) UpdateUserPolicies(c echo.Context) error {
|
||||||
|
ctxuser := util.DefaultContext(c, "user", "")
|
||||||
|
superuser := util.DefaultContext(c, "superuser", false)
|
||||||
|
domain := util.DefaultQuery(c, "domain", "$none")
|
||||||
|
name := util.PathParam(c, "name")
|
||||||
|
|
||||||
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+name, "write") {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
var iamuser iam.User
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if name != "$anon" {
|
||||||
|
iamuser, err = h.iam.GetIdentity(name)
|
||||||
|
if err != nil {
|
||||||
|
return api.Err(http.StatusNotFound, "Not found", "%s", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iamuser = iam.User{
|
||||||
|
Name: "$anon",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
policies := []api.IAMPolicy{}
|
||||||
|
|
||||||
|
if err := util.ShouldBindJSON(c, &policies); err != nil {
|
||||||
|
return api.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range policies {
|
||||||
|
if !h.iam.Enforce(ctxuser, p.Domain, "iam:"+iamuser.Name, "write") {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Not allowed to write policy: %v", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !superuser && iamuser.Superuser {
|
||||||
|
return api.Err(http.StatusForbidden, "Forbidden", "Only superusers can modify superusers")
|
||||||
|
}
|
||||||
|
|
||||||
|
h.iam.RemovePolicy(name, "", "", nil)
|
||||||
|
|
||||||
|
for _, p := range policies {
|
||||||
|
h.iam.AddPolicy(iamuser.Name, p.Domain, p.Resource, p.Actions)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, policies)
|
||||||
|
}
|
||||||
|
|
||||||
// GetUser returns the user with the given name
|
// GetUser returns the user with the given name
|
||||||
// @Summary List an user by its name
|
// @Summary List an user by its name
|
||||||
// @Description List aa user by its name
|
// @Description List aa user by its name
|
||||||
@ -175,24 +285,44 @@ func (h *IAMHandler) UpdateUser(c echo.Context) error {
|
|||||||
// @ID iam-3-get-user
|
// @ID iam-3-get-user
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param name path string true "Username"
|
// @Param name path string true "Username"
|
||||||
|
// @Param domain query string false "Domain of the acting user"
|
||||||
// @Success 200 {object} api.IAMUser
|
// @Success 200 {object} api.IAMUser
|
||||||
// @Failure 404 {object} api.Error
|
// @Failure 404 {object} api.Error
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Router /api/v3/iam/user/{name} [get]
|
// @Router /api/v3/iam/user/{name} [get]
|
||||||
func (h *IAMHandler) GetUser(c echo.Context) error {
|
func (h *IAMHandler) GetUser(c echo.Context) error {
|
||||||
ctxuser := util.DefaultContext(c, "user", "")
|
ctxuser := util.DefaultContext(c, "user", "")
|
||||||
|
superuser := util.DefaultContext(c, "superuser", false)
|
||||||
|
domain := util.DefaultQuery(c, "domain", "$none")
|
||||||
name := util.PathParam(c, "name")
|
name := util.PathParam(c, "name")
|
||||||
|
|
||||||
if !h.iam.Enforce(ctxuser, "$none", "iam:/user", "read") {
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+name, "read") {
|
||||||
return api.Err(http.StatusForbidden, "Forbidden")
|
return api.Err(http.StatusForbidden, "Forbidden")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamuser, err := h.iam.GetIdentity(name)
|
var iamuser iam.User
|
||||||
if err != nil {
|
var err error
|
||||||
return api.Err(http.StatusNotFound, "Not found", "%s", err)
|
|
||||||
|
if name != "$anon" {
|
||||||
|
iamuser, err = h.iam.GetIdentity(name)
|
||||||
|
if err != nil {
|
||||||
|
return api.Err(http.StatusNotFound, "Not found", "%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !superuser && name != iamuser.Name {
|
||||||
|
if !h.iam.Enforce(ctxuser, domain, "iam:"+name, "write") {
|
||||||
|
iamuser = iam.User{
|
||||||
|
Name: iamuser.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iamuser = iam.User{
|
||||||
|
Name: "$anon",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iampolicies := h.iam.ListPolicies(name, "$none", "", nil)
|
iampolicies := h.iam.ListPolicies(name, "", "", nil)
|
||||||
|
|
||||||
user := api.IAMUser{}
|
user := api.IAMUser{}
|
||||||
user.Marshal(iamuser, iampolicies)
|
user.Marshal(iamuser, iampolicies)
|
||||||
|
|||||||
@ -77,8 +77,8 @@ func DefaultQuery(c echo.Context, name, defValue string) string {
|
|||||||
return param
|
return param
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultContext(c echo.Context, name, defValue string) string {
|
func DefaultContext[T any](c echo.Context, name string, defValue T) T {
|
||||||
value, ok := c.Get(name).(string)
|
value, ok := c.Get(name).(T)
|
||||||
if !ok {
|
if !ok {
|
||||||
return defValue
|
return defValue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
// - Auth0 access token
|
// - Auth0 access token
|
||||||
// - Basic auth
|
// - Basic auth
|
||||||
//
|
//
|
||||||
// The path prefix /api/login is treated specially in order to accomodate
|
// The path prefix /api/login is treated specially in order to accommodate
|
||||||
// different ways of identification (UserPass, Auth0). All other /api paths
|
// different ways of identification (UserPass, Auth0). All other /api paths
|
||||||
// only allow JWT as authentication method.
|
// only allow JWT as authentication method.
|
||||||
//
|
//
|
||||||
@ -202,11 +202,15 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
|
|||||||
resource = "fs:" + resource
|
resource = "fs:" + resource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
superuser := false
|
||||||
|
|
||||||
if identity != nil {
|
if identity != nil {
|
||||||
username = identity.Name()
|
username = identity.Name()
|
||||||
|
superuser = identity.IsSuperuser()
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Set("user", username)
|
c.Set("user", username)
|
||||||
|
c.Set("superuser", superuser)
|
||||||
|
|
||||||
if len(domain) == 0 {
|
if len(domain) == 0 {
|
||||||
domain = "$none"
|
domain = "$none"
|
||||||
|
|||||||
@ -537,18 +537,8 @@ func (s *server) setRoutesV3(v3 *echo.Group) {
|
|||||||
v3.POST("/iam/user", s.v3handler.iam.AddUser)
|
v3.POST("/iam/user", s.v3handler.iam.AddUser)
|
||||||
v3.GET("/iam/user/:name", s.v3handler.iam.GetUser)
|
v3.GET("/iam/user/:name", s.v3handler.iam.GetUser)
|
||||||
v3.PUT("/iam/user/:name", s.v3handler.iam.UpdateUser)
|
v3.PUT("/iam/user/:name", s.v3handler.iam.UpdateUser)
|
||||||
|
v3.PUT("/iam/user/:name/policy", s.v3handler.iam.UpdateUserPolicies)
|
||||||
v3.DELETE("/iam/user/:name", s.v3handler.iam.RemoveUser)
|
v3.DELETE("/iam/user/:name", s.v3handler.iam.RemoveUser)
|
||||||
|
|
||||||
v3.POST("/iam/group", s.v3handler.iam.AddGroup)
|
|
||||||
v3.GET("/iam/group", s.v3handler.iam.ListGroups)
|
|
||||||
v3.GET("/iam/group/:group", s.v3handler.iam.GetGroup)
|
|
||||||
v3.DELETE("/iam/group/:group", s.v3handler.iam.RemoveGroup)
|
|
||||||
|
|
||||||
v3.POST("/iam/group/:group/user", s.v3handler.iam.AddGroupUser)
|
|
||||||
v3.GET("/iam/group/:group/user", s.v3handler.iam.ListGroupUsers)
|
|
||||||
v3.GET("/iam/group/:group/user/:name", s.v3handler.iam.GetGroupUser)
|
|
||||||
v3.PUT("/iam/group/:group/user/:name", s.v3handler.iam.UpdateGroupUser)
|
|
||||||
v3.DELETE("/iam/group/:group/user/:name", s.v3handler.iam.RemoveGroupUser)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// v3 Restreamer
|
// v3 Restreamer
|
||||||
|
|||||||
@ -130,7 +130,7 @@ func (am *access) ListPolicies(name, domain, resource string, actions []string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (am *access) HasDomain(name string) bool {
|
func (am *access) HasDomain(name string) bool {
|
||||||
groups := am.adapter.getAllGroups()
|
groups := am.adapter.getAllDomains()
|
||||||
|
|
||||||
for _, g := range groups {
|
for _, g := range groups {
|
||||||
if g == name {
|
if g == name {
|
||||||
@ -142,7 +142,7 @@ func (am *access) HasDomain(name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (am *access) ListDomains() []string {
|
func (am *access) ListDomains() []string {
|
||||||
return am.adapter.getAllGroups()
|
return am.adapter.getAllDomains()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *access) Enforce(name, domain, resource, action string) (bool, string) {
|
func (am *access) Enforce(name, domain, resource, action string) (bool, string) {
|
||||||
|
|||||||
140
iam/adapter.go
140
iam/adapter.go
@ -20,7 +20,7 @@ type adapter struct {
|
|||||||
fs fs.Filesystem
|
fs fs.Filesystem
|
||||||
filePath string
|
filePath string
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
groups []Group
|
domains []Domain
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ func (a *adapter) LoadPolicy(model model.Model) error {
|
|||||||
|
|
||||||
func (a *adapter) loadPolicyFile(model model.Model) error {
|
func (a *adapter) loadPolicyFile(model model.Model) error {
|
||||||
if _, err := a.fs.Stat(a.filePath); os.IsNotExist(err) {
|
if _, err := a.fs.Stat(a.filePath); os.IsNotExist(err) {
|
||||||
a.groups = []Group{}
|
a.domains = []Domain{}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,18 +65,18 @@ func (a *adapter) loadPolicyFile(model model.Model) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
groups := []Group{}
|
domains := []Domain{}
|
||||||
|
|
||||||
err = json.Unmarshal(data, &groups)
|
err = json.Unmarshal(data, &domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
rule := [5]string{}
|
rule := [5]string{}
|
||||||
for _, group := range groups {
|
for _, domain := range domains {
|
||||||
rule[0] = "p"
|
rule[0] = "p"
|
||||||
rule[2] = group.Name
|
rule[2] = domain.Name
|
||||||
for name, roles := range group.Roles {
|
for name, roles := range domain.Roles {
|
||||||
rule[1] = "role:" + name
|
rule[1] = "role:" + name
|
||||||
for _, role := range roles {
|
for _, role := range roles {
|
||||||
rule[3] = role.Resource
|
rule[3] = role.Resource
|
||||||
@ -88,7 +88,7 @@ func (a *adapter) loadPolicyFile(model model.Model) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, policy := range group.Policies {
|
for _, policy := range domain.Policies {
|
||||||
rule[1] = policy.Username
|
rule[1] = policy.Username
|
||||||
rule[3] = policy.Resource
|
rule[3] = policy.Resource
|
||||||
rule[4] = formatActions(policy.Actions)
|
rule[4] = formatActions(policy.Actions)
|
||||||
@ -99,9 +99,9 @@ func (a *adapter) loadPolicyFile(model model.Model) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rule[0] = "g"
|
rule[0] = "g"
|
||||||
rule[3] = group.Name
|
rule[3] = domain.Name
|
||||||
|
|
||||||
for _, ug := range group.UserRoles {
|
for _, ug := range domain.UserRoles {
|
||||||
rule[1] = ug.Username
|
rule[1] = ug.Username
|
||||||
rule[2] = "role:" + ug.Role
|
rule[2] = "role:" + ug.Role
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ func (a *adapter) loadPolicyFile(model model.Model) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.groups = groups
|
a.domains = domains
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ func (a *adapter) importPolicy(model model.Model, rule []string) error {
|
|||||||
copy(copiedRule, rule)
|
copy(copiedRule, rule)
|
||||||
|
|
||||||
a.logger.Debug().WithFields(log.Fields{
|
a.logger.Debug().WithFields(log.Fields{
|
||||||
"username": copiedRule[1],
|
"subject": copiedRule[1],
|
||||||
"domain": copiedRule[2],
|
"domain": copiedRule[2],
|
||||||
"resource": copiedRule[3],
|
"resource": copiedRule[3],
|
||||||
"actions": copiedRule[4],
|
"actions": copiedRule[4],
|
||||||
@ -149,7 +149,7 @@ func (a *adapter) SavePolicy(model model.Model) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *adapter) savePolicyFile() error {
|
func (a *adapter) savePolicyFile() error {
|
||||||
jsondata, err := json.MarshalIndent(a.groups, "", " ")
|
jsondata, err := json.MarshalIndent(a.domains, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ func (a *adapter) addPolicy(ptype string, rule []string) error {
|
|||||||
actions = formatActions(rule[3])
|
actions = formatActions(rule[3])
|
||||||
|
|
||||||
a.logger.Debug().WithFields(log.Fields{
|
a.logger.Debug().WithFields(log.Fields{
|
||||||
"username": username,
|
"subject": username,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"resource": resource,
|
"resource": resource,
|
||||||
"actions": actions,
|
"actions": actions,
|
||||||
@ -222,47 +222,47 @@ func (a *adapter) addPolicy(ptype string, rule []string) error {
|
|||||||
domain = rule[2]
|
domain = rule[2]
|
||||||
|
|
||||||
a.logger.Debug().WithFields(log.Fields{
|
a.logger.Debug().WithFields(log.Fields{
|
||||||
"username": username,
|
"subject": username,
|
||||||
"role": role,
|
"role": role,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
}).Log("adding role mapping")
|
}).Log("adding role mapping")
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("unknown ptype: %s", ptype)
|
return fmt.Errorf("unknown ptype: %s", ptype)
|
||||||
}
|
}
|
||||||
|
|
||||||
var group *Group = nil
|
var dom *Domain = nil
|
||||||
for i := range a.groups {
|
for i := range a.domains {
|
||||||
if a.groups[i].Name == domain {
|
if a.domains[i].Name == domain {
|
||||||
group = &a.groups[i]
|
dom = &a.domains[i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if group == nil {
|
if dom == nil {
|
||||||
g := Group{
|
g := Domain{
|
||||||
Name: domain,
|
Name: domain,
|
||||||
Roles: map[string][]Role{},
|
Roles: map[string][]Role{},
|
||||||
UserRoles: []MapUserRole{},
|
UserRoles: []MapUserRole{},
|
||||||
Policies: []GroupPolicy{},
|
Policies: []DomainPolicy{},
|
||||||
}
|
}
|
||||||
|
|
||||||
a.groups = append(a.groups, g)
|
a.domains = append(a.domains, g)
|
||||||
group = &a.groups[len(a.groups)-1]
|
dom = &a.domains[len(a.domains)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if ptype == "p" {
|
if ptype == "p" {
|
||||||
if strings.HasPrefix(username, "role:") {
|
if strings.HasPrefix(username, "role:") {
|
||||||
if group.Roles == nil {
|
if dom.Roles == nil {
|
||||||
group.Roles = make(map[string][]Role)
|
dom.Roles = make(map[string][]Role)
|
||||||
}
|
}
|
||||||
|
|
||||||
role := strings.TrimPrefix(username, "role:")
|
role := strings.TrimPrefix(username, "role:")
|
||||||
group.Roles[role] = append(group.Roles[role], Role{
|
dom.Roles[role] = append(dom.Roles[role], Role{
|
||||||
Resource: resource,
|
Resource: resource,
|
||||||
Actions: actions,
|
Actions: actions,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
group.Policies = append(group.Policies, GroupPolicy{
|
dom.Policies = append(dom.Policies, DomainPolicy{
|
||||||
Username: username,
|
Username: username,
|
||||||
Role: Role{
|
Role: Role{
|
||||||
Resource: resource,
|
Resource: resource,
|
||||||
@ -271,7 +271,7 @@ func (a *adapter) addPolicy(ptype string, rule []string) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
group.UserRoles = append(group.UserRoles, MapUserRole{
|
dom.UserRoles = append(dom.UserRoles, MapUserRole{
|
||||||
Username: username,
|
Username: username,
|
||||||
Role: strings.TrimPrefix(role, "role:"),
|
Role: strings.TrimPrefix(role, "role:"),
|
||||||
})
|
})
|
||||||
@ -288,7 +288,7 @@ func (a *adapter) hasPolicy(ptype string, rule []string) (bool, error) {
|
|||||||
var actions string
|
var actions string
|
||||||
|
|
||||||
if ptype == "p" {
|
if ptype == "p" {
|
||||||
if len(rule) != 4 {
|
if len(rule) < 4 {
|
||||||
return false, fmt.Errorf("invalid rule length. must be 'user/role, domain, resource, actions'")
|
return false, fmt.Errorf("invalid rule length. must be 'user/role, domain, resource, actions'")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +297,10 @@ func (a *adapter) hasPolicy(ptype string, rule []string) (bool, error) {
|
|||||||
resource = rule[2]
|
resource = rule[2]
|
||||||
actions = formatActions(rule[3])
|
actions = formatActions(rule[3])
|
||||||
} else if ptype == "g" {
|
} else if ptype == "g" {
|
||||||
|
if len(rule) < 3 {
|
||||||
|
return false, fmt.Errorf("invalid rule length. must be 'user, role, domain'")
|
||||||
|
}
|
||||||
|
|
||||||
username = rule[0]
|
username = rule[0]
|
||||||
role = rule[1]
|
role = rule[1]
|
||||||
domain = rule[2]
|
domain = rule[2]
|
||||||
@ -304,16 +308,16 @@ func (a *adapter) hasPolicy(ptype string, rule []string) (bool, error) {
|
|||||||
return false, fmt.Errorf("unknown ptype: %s", ptype)
|
return false, fmt.Errorf("unknown ptype: %s", ptype)
|
||||||
}
|
}
|
||||||
|
|
||||||
var group *Group = nil
|
var dom *Domain = nil
|
||||||
for i := range a.groups {
|
for i := range a.domains {
|
||||||
if a.groups[i].Name == domain {
|
if a.domains[i].Name == domain {
|
||||||
group = &a.groups[i]
|
dom = &a.domains[i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if group == nil {
|
if dom == nil {
|
||||||
// if we can't find any group with that name, then the policy doesn't exist
|
// if we can't find any domain with that name, then the policy doesn't exist
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +329,7 @@ func (a *adapter) hasPolicy(ptype string, rule []string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isRole {
|
if isRole {
|
||||||
roles, ok := group.Roles[username]
|
roles, ok := dom.Roles[username]
|
||||||
if !ok {
|
if !ok {
|
||||||
// unknown role, policy doesn't exist
|
// unknown role, policy doesn't exist
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -337,7 +341,7 @@ func (a *adapter) hasPolicy(ptype string, rule []string) (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, p := range group.Policies {
|
for _, p := range dom.Policies {
|
||||||
if p.Username == username && p.Resource == resource && formatActions(p.Actions) == actions {
|
if p.Username == username && p.Resource == resource && formatActions(p.Actions) == actions {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -345,7 +349,7 @@ func (a *adapter) hasPolicy(ptype string, rule []string) (bool, error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
role = strings.TrimPrefix(role, "role:")
|
role = strings.TrimPrefix(role, "role:")
|
||||||
for _, user := range group.UserRoles {
|
for _, user := range dom.UserRoles {
|
||||||
if user.Username == username && user.Role == role {
|
if user.Username == username && user.Role == role {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -407,7 +411,7 @@ func (a *adapter) removePolicy(ptype string, rule []string) error {
|
|||||||
actions = formatActions(rule[3])
|
actions = formatActions(rule[3])
|
||||||
|
|
||||||
a.logger.Debug().WithFields(log.Fields{
|
a.logger.Debug().WithFields(log.Fields{
|
||||||
"username": username,
|
"subject": username,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"resource": resource,
|
"resource": resource,
|
||||||
"actions": actions,
|
"actions": actions,
|
||||||
@ -418,18 +422,18 @@ func (a *adapter) removePolicy(ptype string, rule []string) error {
|
|||||||
domain = rule[2]
|
domain = rule[2]
|
||||||
|
|
||||||
a.logger.Debug().WithFields(log.Fields{
|
a.logger.Debug().WithFields(log.Fields{
|
||||||
"username": username,
|
"subject": username,
|
||||||
"role": role,
|
"role": role,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
}).Log("adding role mapping")
|
}).Log("adding role mapping")
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("unknown ptype: %s", ptype)
|
return fmt.Errorf("unknown ptype: %s", ptype)
|
||||||
}
|
}
|
||||||
|
|
||||||
var group *Group = nil
|
var dom *Domain = nil
|
||||||
for i := range a.groups {
|
for i := range a.domains {
|
||||||
if a.groups[i].Name == domain {
|
if a.domains[i].Name == domain {
|
||||||
group = &a.groups[i]
|
dom = &a.domains[i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,7 +446,7 @@ func (a *adapter) removePolicy(ptype string, rule []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isRole {
|
if isRole {
|
||||||
roles := group.Roles[username]
|
roles := dom.Roles[username]
|
||||||
|
|
||||||
newRoles := []Role{}
|
newRoles := []Role{}
|
||||||
|
|
||||||
@ -454,11 +458,11 @@ func (a *adapter) removePolicy(ptype string, rule []string) error {
|
|||||||
newRoles = append(newRoles, role)
|
newRoles = append(newRoles, role)
|
||||||
}
|
}
|
||||||
|
|
||||||
group.Roles[username] = newRoles
|
dom.Roles[username] = newRoles
|
||||||
} else {
|
} else {
|
||||||
policies := []GroupPolicy{}
|
policies := []DomainPolicy{}
|
||||||
|
|
||||||
for _, p := range group.Policies {
|
for _, p := range dom.Policies {
|
||||||
if p.Username == username && p.Resource == resource && formatActions(p.Actions) == actions {
|
if p.Username == username && p.Resource == resource && formatActions(p.Actions) == actions {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -466,14 +470,14 @@ func (a *adapter) removePolicy(ptype string, rule []string) error {
|
|||||||
policies = append(policies, p)
|
policies = append(policies, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
group.Policies = policies
|
dom.Policies = policies
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
role = strings.TrimPrefix(role, "role:")
|
role = strings.TrimPrefix(role, "role:")
|
||||||
|
|
||||||
users := []MapUserRole{}
|
users := []MapUserRole{}
|
||||||
|
|
||||||
for _, user := range group.UserRoles {
|
for _, user := range dom.UserRoles {
|
||||||
if user.Username == username && user.Role == role {
|
if user.Username == username && user.Role == role {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -481,22 +485,22 @@ func (a *adapter) removePolicy(ptype string, rule []string) error {
|
|||||||
users = append(users, user)
|
users = append(users, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
group.UserRoles = users
|
dom.UserRoles = users
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the group if there are no rules and policies
|
// Remove the group if there are no rules and policies
|
||||||
if len(group.Roles) == 0 && len(group.UserRoles) == 0 && len(group.Policies) == 0 {
|
if len(dom.Roles) == 0 && len(dom.UserRoles) == 0 && len(dom.Policies) == 0 {
|
||||||
groups := []Group{}
|
groups := []Domain{}
|
||||||
|
|
||||||
for _, g := range a.groups {
|
for _, g := range a.domains {
|
||||||
if g.Name == group.Name {
|
if g.Name == dom.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
groups = append(groups, g)
|
groups = append(groups, g)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.groups = groups
|
a.domains = groups
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -507,25 +511,25 @@ func (a *adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int,
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *adapter) getAllGroups() []string {
|
func (a *adapter) getAllDomains() []string {
|
||||||
names := []string{}
|
names := []string{}
|
||||||
|
|
||||||
for _, group := range a.groups {
|
for _, domain := range a.domains {
|
||||||
if group.Name[0] == '$' {
|
if domain.Name[0] == '$' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
names = append(names, group.Name)
|
names = append(names, domain.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
type Group struct {
|
type Domain struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Roles map[string][]Role `json:"roles"`
|
Roles map[string][]Role `json:"roles"`
|
||||||
UserRoles []MapUserRole `json:"userroles"`
|
UserRoles []MapUserRole `json:"userroles"`
|
||||||
Policies []GroupPolicy `json:"policies"`
|
Policies []DomainPolicy `json:"policies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Role struct {
|
type Role struct {
|
||||||
@ -538,7 +542,7 @@ type MapUserRole struct {
|
|||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupPolicy struct {
|
type DomainPolicy struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Role
|
Role
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,18 +18,18 @@ func TestAddPolicy(t *testing.T) {
|
|||||||
err = a.AddPolicy("p", "p", []string{"foobar", "group", "resource", "action"})
|
err = a.AddPolicy("p", "p", []string{"foobar", "group", "resource", "action"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 1, len(a.groups))
|
require.Equal(t, 1, len(a.domains))
|
||||||
|
|
||||||
data, err := memfs.ReadFile("/policy.json")
|
data, err := memfs.ReadFile("/policy.json")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
g := []Group{}
|
g := []Domain{}
|
||||||
err = json.Unmarshal(data, &g)
|
err = json.Unmarshal(data, &g)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, "group", g[0].Name)
|
require.Equal(t, "group", g[0].Name)
|
||||||
require.Equal(t, 1, len(g[0].Policies))
|
require.Equal(t, 1, len(g[0].Policies))
|
||||||
require.Equal(t, GroupPolicy{
|
require.Equal(t, DomainPolicy{
|
||||||
Username: "foobar",
|
Username: "foobar",
|
||||||
Role: Role{
|
Role: Role{
|
||||||
Resource: "resource",
|
Resource: "resource",
|
||||||
@ -62,24 +62,24 @@ func TestRemovePolicy(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 1, len(a.groups))
|
require.Equal(t, 1, len(a.domains))
|
||||||
require.Equal(t, 2, len(a.groups[0].Policies))
|
require.Equal(t, 2, len(a.domains[0].Policies))
|
||||||
|
|
||||||
err = a.RemovePolicy("p", "p", []string{"foobar1", "group", "resource1", "action1"})
|
err = a.RemovePolicy("p", "p", []string{"foobar1", "group", "resource1", "action1"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 1, len(a.groups))
|
require.Equal(t, 1, len(a.domains))
|
||||||
require.Equal(t, 1, len(a.groups[0].Policies))
|
require.Equal(t, 1, len(a.domains[0].Policies))
|
||||||
|
|
||||||
err = a.RemovePolicy("p", "p", []string{"foobar2", "group", "resource2", "action2"})
|
err = a.RemovePolicy("p", "p", []string{"foobar2", "group", "resource2", "action2"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 0, len(a.groups))
|
require.Equal(t, 0, len(a.domains))
|
||||||
|
|
||||||
data, err := memfs.ReadFile("/policy.json")
|
data, err := memfs.ReadFile("/policy.json")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
g := []Group{}
|
g := []Domain{}
|
||||||
err = json.Unmarshal(data, &g)
|
err = json.Unmarshal(data, &g)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|||||||
@ -17,22 +17,7 @@ func resourceMatch(request, domain, policy string) bool {
|
|||||||
var match bool
|
var match bool
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if reqPrefix == "api" {
|
if reqPrefix == "api" || reqPrefix == "fs" || reqPrefix == "rtmp" || reqPrefix == "srt" {
|
||||||
match, err = globMatch(polResource, reqResource, rune('/'))
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else if reqPrefix == "fs" {
|
|
||||||
match, err = globMatch(polResource, reqResource, rune('/'))
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else if reqPrefix == "rtmp" {
|
|
||||||
match, err = globMatch(polResource, reqResource, rune('/'))
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else if reqPrefix == "srt" {
|
|
||||||
match, err = globMatch(polResource, reqResource, rune('/'))
|
match, err = globMatch(polResource, reqResource, rune('/'))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
@ -83,17 +68,12 @@ func actionMatchFunc(args ...interface{}) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getPrefix(s string) (string, string) {
|
func getPrefix(s string) (string, string) {
|
||||||
splits := strings.SplitN(s, ":", 2)
|
prefix, resource, found := strings.Cut(s, ":")
|
||||||
|
if !found {
|
||||||
if len(splits) == 0 {
|
return "", s
|
||||||
return "", ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(splits) == 1 {
|
return prefix, resource
|
||||||
return "", splits[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return splits[0], splits[1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func globMatch(pattern, name string, separators ...rune) (bool, error) {
|
func globMatch(pattern, name string, separators ...rune) (bool, error) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user