2022-08-16 03:57:09 -05:00
|
|
|
package requestcontext
|
|
|
|
|
2022-11-18 12:35:28 -05:00
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
glob "github.com/bmatcuk/doublestar/v4" //nolint:gci
|
2023-01-09 15:37:44 -05:00
|
|
|
|
2022-11-18 12:35:28 -05:00
|
|
|
"zotregistry.io/zot/errors"
|
|
|
|
)
|
|
|
|
|
2022-08-16 03:57:09 -05:00
|
|
|
type Key int
|
|
|
|
|
|
|
|
// request-local context key.
|
2022-10-05 05:21:14 -05:00
|
|
|
var authzCtxKey = Key(0) //nolint: gochecknoglobals
|
2022-08-16 03:57:09 -05:00
|
|
|
|
|
|
|
// pointer needed for use in context.WithValue.
|
|
|
|
func GetContextKey() *Key {
|
|
|
|
return &authzCtxKey
|
|
|
|
}
|
|
|
|
|
|
|
|
// AccessControlContext context passed down to http.Handlers.
|
|
|
|
type AccessControlContext struct {
|
2022-11-18 12:35:28 -05:00
|
|
|
// read method action
|
|
|
|
ReadGlobPatterns map[string]bool
|
|
|
|
// detectManifestCollision behaviour action
|
|
|
|
DmcGlobPatterns map[string]bool
|
|
|
|
IsAdmin bool
|
|
|
|
Username string
|
2023-03-08 14:47:15 -05:00
|
|
|
Groups []string
|
2022-11-18 12:35:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetAccessControlContext(ctx context.Context) (*AccessControlContext, error) {
|
|
|
|
authzCtxKey := GetContextKey()
|
|
|
|
if authCtx := ctx.Value(authzCtxKey); authCtx != nil {
|
|
|
|
acCtx, ok := authCtx.(AccessControlContext)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.ErrBadType
|
|
|
|
}
|
|
|
|
|
|
|
|
return &acCtx, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil //nolint: nilnil
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns either a user has or not rights on 'repository'.
|
|
|
|
func (acCtx *AccessControlContext) matchesRepo(globPatterns map[string]bool, repository string) bool {
|
|
|
|
var longestMatchedPattern string
|
|
|
|
|
|
|
|
// because of the longest path matching rule, we need to check all patterns from config
|
|
|
|
for pattern := range globPatterns {
|
|
|
|
matched, err := glob.Match(pattern, repository)
|
|
|
|
if err == nil {
|
|
|
|
if matched && len(pattern) > len(longestMatchedPattern) {
|
|
|
|
longestMatchedPattern = pattern
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allowed := globPatterns[longestMatchedPattern]
|
|
|
|
|
|
|
|
return allowed
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns either a user has or not read rights on 'repository'.
|
|
|
|
func (acCtx *AccessControlContext) CanReadRepo(repository string) bool {
|
2023-03-08 14:47:15 -05:00
|
|
|
if acCtx.ReadGlobPatterns != nil {
|
|
|
|
return acCtx.matchesRepo(acCtx.ReadGlobPatterns, repository)
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
2022-11-18 12:35:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// returns either a user has or not detectManifestCollision rights on 'repository'.
|
|
|
|
func (acCtx *AccessControlContext) CanDetectManifestCollision(repository string) bool {
|
2023-03-08 14:47:15 -05:00
|
|
|
if acCtx.DmcGlobPatterns != nil {
|
|
|
|
return acCtx.matchesRepo(acCtx.DmcGlobPatterns, repository)
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
2022-08-16 03:57:09 -05:00
|
|
|
}
|