mirror of https://github.com/harness/drone.git
125 lines
3.9 KiB
Go
125 lines
3.9 KiB
Go
// Copyright 2023 Harness, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/harness/gitness/app/api/render"
|
|
"github.com/harness/gitness/app/api/request"
|
|
"github.com/harness/gitness/app/auth"
|
|
"github.com/harness/gitness/app/jwt"
|
|
"github.com/harness/gitness/app/url"
|
|
"github.com/harness/gitness/registry/app/api/handler/oci"
|
|
registryauth "github.com/harness/gitness/registry/app/auth"
|
|
"github.com/harness/gitness/registry/app/common"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func OciCheckAuth(urlProvider url.Provider) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
session, _ := request.AuthSessionFrom(ctx)
|
|
url := common.GenerateOciTokenURL(urlProvider.RegistryURL(ctx))
|
|
if session.Principal == auth.AnonymousPrincipal {
|
|
scope := getScope(r)
|
|
returnUnauthorised(ctx, w, url, scope)
|
|
return
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
// BlockNonOciSourceToken blocks any request that doesn't have AccessPermissionMetadata.
|
|
func BlockNonOciSourceToken(urlProvider url.Provider) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
if session, oks := request.AuthSessionFrom(ctx); oks {
|
|
if metadata, okt := session.Metadata.(*auth.AccessPermissionMetadata); !okt ||
|
|
metadata.AccessPermissions.Source != jwt.OciSource {
|
|
log.Ctx(ctx).Warn().
|
|
Msg("blocking request - non OCI source tokens are not allowed for usage with oci endpoints")
|
|
scope := getScope(r)
|
|
url := common.GenerateOciTokenURL(urlProvider.RegistryURL(ctx))
|
|
returnUnauthorised(ctx, w, url, scope)
|
|
return
|
|
}
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
func CheckAuth() func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
session, _ := request.AuthSessionFrom(ctx)
|
|
if session.Principal == auth.AnonymousPrincipal {
|
|
render.Unauthorized(ctx, w)
|
|
return
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
func getRefsFromName(name string) (spaceRef, repoRef string) {
|
|
name = strings.Trim(name, "/")
|
|
refs := strings.Split(name, "/")
|
|
spaceRef = refs[0]
|
|
repoRef = refs[1]
|
|
return
|
|
}
|
|
|
|
func getScope(r *http.Request) string {
|
|
var scope string
|
|
path := r.URL.Path
|
|
if path != "/v2/" && path != "/v2/token" {
|
|
paramMap := common.ExtractFirstQueryParams(r.URL.Query())
|
|
rootIdentifier, registryIdentifier, _, _, _, _ := oci.ExtractPathVars(path, paramMap)
|
|
var access []registryauth.Access
|
|
access = registryauth.AppendAccess(access, r.Method, rootIdentifier+"/"+registryIdentifier)
|
|
if fromRepo := r.FormValue("from"); fromRepo != "" {
|
|
space, repoName := getRefsFromName(fromRepo)
|
|
access = registryauth.AppendAccess(access, http.MethodGet, space+"/"+repoName)
|
|
}
|
|
scope = registryauth.NewAccessSet(access...).ScopeParam()
|
|
}
|
|
return scope
|
|
}
|
|
|
|
func returnUnauthorised(ctx context.Context, w http.ResponseWriter, url string, scope string) {
|
|
header := fmt.Sprintf(`Bearer realm="%s", service="gitness-registry"`, url)
|
|
if scope != "" {
|
|
header = fmt.Sprintf(`%s, scope="%s"`, header, scope)
|
|
}
|
|
w.Header().Set("WWW-Authenticate", header)
|
|
render.Unauthorized(ctx, w)
|
|
}
|