mirror of
https://github.com/project-zot/zot.git
synced 2024-12-30 22:34:13 -05:00
17d1338af1
This change introduces OpenID authn by using providers such as Github, Gitlab, Google and Dex. User sessions are now used for web clients to identify and persist an authenticated users session, thus not requiring every request to use credentials. Another change is apikey feature, users can create/revoke their api keys and use them to authenticate when using cli clients such as skopeo. eg: login: /auth/login?provider=github /auth/login?provider=gitlab and so on logout: /auth/logout redirectURL: /auth/callback/github /auth/callback/gitlab and so on If network policy doesn't allow inbound connections, this callback wont work! for more info read documentation added in this commit. Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> Signed-off-by: Petu Eusebiu <peusebiu@cisco.com> Co-authored-by: Alex Stan <alexandrustan96@yahoo.ro>
120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
package requestcontext
|
|
|
|
import (
|
|
"context"
|
|
|
|
glob "github.com/bmatcuk/doublestar/v4" //nolint:gci
|
|
|
|
"zotregistry.io/zot/errors"
|
|
)
|
|
|
|
type Key int
|
|
|
|
// request-local context key.
|
|
var authzCtxKey = Key(0) //nolint: gochecknoglobals
|
|
|
|
// pointer needed for use in context.WithValue.
|
|
func GetContextKey() *Key {
|
|
return &authzCtxKey
|
|
}
|
|
|
|
// AccessControlContext - contains user authn/authz information.
|
|
type AccessControlContext struct {
|
|
// read method action
|
|
ReadGlobPatterns map[string]bool
|
|
// detectManifestCollision behaviour action
|
|
DmcGlobPatterns map[string]bool
|
|
IsAdmin bool
|
|
Username string
|
|
Groups []string
|
|
}
|
|
|
|
/*
|
|
GetAccessControlContext returns an AccessControlContext struct made available on all http requests
|
|
(using context.Context values) by authz and authn middlewares.
|
|
|
|
its methods and attributes can be used in http.Handlers to get user info for that specific request
|
|
(username, groups, if it's an admin, if it can access certain resources).
|
|
*/
|
|
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 whether or not the user/anonymous who made the request has read permission on 'repository'.
|
|
func (acCtx *AccessControlContext) CanReadRepo(repository string) bool {
|
|
if acCtx.ReadGlobPatterns != nil {
|
|
return acCtx.matchesRepo(acCtx.ReadGlobPatterns, repository)
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
/*
|
|
returns whether or not the user/anonymous who made the request
|
|
has detectManifestCollision permission on 'repository'.
|
|
*/
|
|
func (acCtx *AccessControlContext) CanDetectManifestCollision(repository string) bool {
|
|
if acCtx.DmcGlobPatterns != nil {
|
|
return acCtx.matchesRepo(acCtx.DmcGlobPatterns, repository)
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
/*
|
|
returns whether or not 'repository' can be found in the list of patterns
|
|
on which the user who made the request has read permission on.
|
|
*/
|
|
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
|
|
}
|
|
|
|
// request-local context key.
|
|
var amwCtxKey = Key(1) //nolint: gochecknoglobals
|
|
|
|
// pointer needed for use in context.WithValue.
|
|
func GetAuthnMiddlewareCtxKey() *Key {
|
|
return &amwCtxKey
|
|
}
|
|
|
|
type AuthnMiddlewareContext struct {
|
|
AuthnType string
|
|
}
|
|
|
|
func GetAuthnMiddlewareContext(ctx context.Context) (*AuthnMiddlewareContext, error) {
|
|
authnMiddlewareCtxKey := GetAuthnMiddlewareCtxKey()
|
|
if authnMiddlewareCtx := ctx.Value(authnMiddlewareCtxKey); authnMiddlewareCtx != nil {
|
|
amCtx, ok := authnMiddlewareCtx.(AuthnMiddlewareContext)
|
|
if !ok {
|
|
return nil, errors.ErrBadType
|
|
}
|
|
|
|
return &amCtx, nil
|
|
}
|
|
|
|
return nil, nil //nolint: nilnil
|
|
}
|