Unverified Commit 4a3dc9ae authored by Wang Yan's avatar Wang Yan Committed by GitHub
Browse files

Revert "Enable robot account to support scan pull case"

parent d18678a4
Showing with 142 additions and 239 deletions
+142 -239
......@@ -28,8 +28,7 @@ const (
ActionDelete = Action("delete")
ActionList = Action("list")
ActionOperate = Action("operate")
ActionScannerPull = Action("scanner-pull") // for robot account created by scanner to pull image, bypass the policy check
ActionOperate = Action("operate")
)
// const resource variables
......
......@@ -47,22 +47,16 @@ func filterPolicies(namespace rbac.Namespace, policies []*rbac.Policy) []*rbac.P
return results
}
mp := getAllPolicies(namespace)
mp := map[string]bool{}
for _, policy := range project.GetAllPolicies(namespace) {
mp[policy.String()] = true
}
for _, policy := range policies {
if mp[policy.String()] {
results = append(results, policy)
}
}
return results
}
// getAllPolicies gets all of supported policies supported in project and external policies supported for robot account
func getAllPolicies(namespace rbac.Namespace) map[string]bool {
mp := map[string]bool{}
for _, policy := range project.GetAllPolicies(namespace) {
mp[policy.String()] = true
}
scannerPull := &rbac.Policy{Resource: namespace.Resource(rbac.ResourceRepository), Action: rbac.ActionScannerPull}
mp[scannerPull.String()] = true
return mp
return results
}
......@@ -44,11 +44,10 @@ func TestGetPolicies(t *testing.T) {
func TestNewRobot(t *testing.T) {
policies := []*rbac.Policy{
{Resource: "/project/1/repository", Action: "pull"},
{Resource: "/project/1/repository", Action: "scanner-pull"},
{Resource: "/project/library/repository", Action: "pull"},
{Resource: "/project/library/repository", Action: "push"},
}
robot := NewRobot("test", rbac.NewProjectNamespace(1, false), policies)
assert.Len(t, robot.GetPolicies(), 2)
assert.Len(t, robot.GetPolicies(), 1)
}
package robot
package token
import (
"errors"
......@@ -6,8 +6,8 @@ import (
"github.com/goharbor/harbor/src/common/rbac"
)
// Claim implements the interface of jwt.Claims
type Claim struct {
// RobotClaims implements the interface of jwt.Claims
type RobotClaims struct {
jwt.StandardClaims
TokenID int64 `json:"id"`
ProjectID int64 `json:"pid"`
......@@ -15,7 +15,7 @@ type Claim struct {
}
// Valid valid the claims "tokenID, projectID and access".
func (rc Claim) Valid() error {
func (rc RobotClaims) Valid() error {
if rc.TokenID < 0 {
return errors.New("Token id must an valid INT")
}
......
package robot
package token
import (
"github.com/goharbor/harbor/src/common/rbac"
......@@ -15,7 +15,7 @@ func TestValid(t *testing.T) {
policies := []*rbac.Policy{}
policies = append(policies, rbacPolicy)
rClaims := &Claim{
rClaims := &RobotClaims{
TokenID: 1,
ProjectID: 2,
Access: policies,
......@@ -32,7 +32,7 @@ func TestUnValidTokenID(t *testing.T) {
policies := []*rbac.Policy{}
policies = append(policies, rbacPolicy)
rClaims := &Claim{
rClaims := &RobotClaims{
TokenID: -1,
ProjectID: 2,
Access: policies,
......@@ -49,7 +49,7 @@ func TestUnValidProjectID(t *testing.T) {
policies := []*rbac.Policy{}
policies = append(policies, rbacPolicy)
rClaims := &Claim{
rClaims := &RobotClaims{
TokenID: 1,
ProjectID: -2,
Access: policies,
......@@ -59,7 +59,7 @@ func TestUnValidProjectID(t *testing.T) {
func TestUnValidPolicy(t *testing.T) {
rClaims := &Claim{
rClaims := &RobotClaims{
TokenID: 1,
ProjectID: 2,
Access: nil,
......
......@@ -6,36 +6,46 @@ import (
"errors"
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/common/utils/log"
"time"
)
// Token is a jwt token for harbor robot account,
type Token struct {
// HToken htoken is a jwt token for harbor robot account,
// which contains the robot ID, project ID and the access permission for the project.
// It used for authn/authz for robot account in Harbor.
type HToken struct {
jwt.Token
Opt *Options
Claim jwt.Claims
}
// New ...
func New(opt *Options, claims jwt.Claims) (*Token, error) {
err := claims.Valid()
func New(tokenID, projectID, expiresAt int64, access []*rbac.Policy) (*HToken, error) {
rClaims := &RobotClaims{
TokenID: tokenID,
ProjectID: projectID,
Access: access,
StandardClaims: jwt.StandardClaims{
IssuedAt: time.Now().UTC().Unix(),
ExpiresAt: expiresAt,
Issuer: DefaultOptions().Issuer,
},
}
err := rClaims.Valid()
if err != nil {
return nil, err
}
return &Token{
Token: *jwt.NewWithClaims(opt.SignMethod, claims),
Opt: opt,
Claim: claims,
return &HToken{
Token: *jwt.NewWithClaims(DefaultOptions().SignMethod, rClaims),
}, nil
}
// Raw get the Raw string of token
func (tk *Token) Raw() (string, error) {
key, err := tk.Opt.GetKey()
func (htk *HToken) Raw() (string, error) {
key, err := DefaultOptions().GetKey()
if err != nil {
return "", nil
}
raw, err := tk.Token.SignedString(key)
raw, err := htk.Token.SignedString(key)
if err != nil {
log.Debugf(fmt.Sprintf("failed to issue token %v", err))
return "", err
......@@ -43,14 +53,14 @@ func (tk *Token) Raw() (string, error) {
return raw, err
}
// Parse ...
func Parse(opt *Options, rawToken string, claims jwt.Claims) (*Token, error) {
key, err := opt.GetKey()
// ParseWithClaims ...
func ParseWithClaims(rawToken string, claims jwt.Claims) (*HToken, error) {
key, err := DefaultOptions().GetKey()
if err != nil {
return nil, err
}
token, err := jwt.ParseWithClaims(rawToken, claims, func(token *jwt.Token) (interface{}, error) {
if token.Method.Alg() != opt.SignMethod.Alg() {
if token.Method.Alg() != DefaultOptions().SignMethod.Alg() {
return nil, errors.New("invalid signing method")
}
switch k := key.(type) {
......@@ -71,7 +81,7 @@ func Parse(opt *Options, rawToken string, claims jwt.Claims) (*Token, error) {
log.Errorf(fmt.Sprintf("invalid jwt token, %v", token))
return nil, errors.New("invalid jwt token")
}
return &Token{
return &HToken{
Token: *token,
}, nil
}
......@@ -5,10 +5,8 @@ import (
"testing"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/core/config"
robot_claim "github.com/goharbor/harbor/src/pkg/token/claims/robot"
"github.com/stretchr/testify/assert"
)
......@@ -35,15 +33,7 @@ func TestNew(t *testing.T) {
projectID := int64(321)
tokenExpiration := time.Duration(10) * 24 * time.Hour
expiresAt := time.Now().UTC().Add(tokenExpiration).Unix()
robot := robot_claim.Claim{
TokenID: tokenID,
ProjectID: projectID,
Access: policies,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expiresAt,
},
}
token, err := New(DefaultTokenOptions(), robot)
token, err := New(tokenID, projectID, expiresAt, policies)
assert.Nil(t, err)
assert.Equal(t, token.Header["alg"], "RS256")
......@@ -64,15 +54,7 @@ func TestRaw(t *testing.T) {
tokenExpiration := time.Duration(10) * 24 * time.Hour
expiresAt := time.Now().UTC().Add(tokenExpiration).Unix()
robot := robot_claim.Claim{
TokenID: tokenID,
ProjectID: projectID,
Access: policies,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expiresAt,
},
}
token, err := New(DefaultTokenOptions(), robot)
token, err := New(tokenID, projectID, expiresAt, policies)
assert.Nil(t, err)
rawTk, err := token.Raw()
......@@ -82,8 +64,8 @@ func TestRaw(t *testing.T) {
func TestParseWithClaims(t *testing.T) {
rawTk := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MTIzLCJQcm9qZWN0SUQiOjAsIkFjY2VzcyI6W3siUmVzb3VyY2UiOiIvcHJvamVjdC9saWJyYXkvcmVwb3NpdG9yeSIsIkFjdGlvbiI6InB1bGwiLCJFZmZlY3QiOiIifV0sIlN0YW5kYXJkQ2xhaW1zIjp7ImV4cCI6MTU0ODE0MDIyOSwiaXNzIjoiaGFyYm9yLXRva2VuLWlzc3VlciJ9fQ.Jc3qSKN4SJVUzAvBvemVpRcSOZaHlu0Avqms04qzPm4ru9-r9IRIl3mnSkI6m9XkzLUeJ7Kiwyw63ghngnVKw_PupeclOGC6s3TK5Cfmo4h-lflecXjZWwyy-dtH_e7Us_ItS-R3nXDJtzSLEpsGHCcAj-1X2s93RB2qD8LNSylvYeDezVkTzqRzzfawPJheKKh9JTrz-3eUxCwQard9-xjlwvfUYULoHTn9npNAUq4-jqhipW4uE8HL-ym33AGF57la8U0RO11hmDM5K8-PiYknbqJ_oONeS3HBNym2pEFeGjtTv2co213wl4T5lemlg4SGolMBuJ03L7_beVZ0o-MKTkKDqDwJalb6_PM-7u3RbxC9IzJMiwZKIPnD3FvV10iPxUUQHaH8Jz5UZ2pFIhi_8BNnlBfT0JOPFVYATtLjHMczZelj2YvAeR1UHBzq3E0jPpjjwlqIFgaHCaN_KMwEvadTo_Fi2sEH4pNGP7M3yehU_72oLJQgF4paJarsmEoij6ZtPs6xekBz1fccVitq_8WNIz9aeCUdkUBRwI5QKw1RdW4ua-w74ld5MZStWJA8veyoLkEb_Q9eq2oAj5KWFjJbW5-ltiIfM8gxKflsrkWAidYGcEIYcuXr7UdqEKXxtPiWM0xb3B91ovYvO5402bn3f9-UGtlcestxNHA"
rClaims := &robot_claim.Claim{}
_, _ = Parse(DefaultTokenOptions(), rawTk, rClaims)
rClaims := &RobotClaims{}
_, _ = ParseWithClaims(rawTk, rClaims)
assert.Equal(t, int64(123), rClaims.TokenID)
assert.Equal(t, int64(0), rClaims.ProjectID)
assert.Equal(t, "/project/libray/repository", rClaims.Access[0].Resource.String())
......
......@@ -11,9 +11,9 @@ import (
)
const (
defaultTTL = 60 * time.Minute
defaultIssuer = "harbor-token-defaultIssuer"
defaultSignedMethod = "RS256"
ttl = 60 * time.Minute
issuer = "harbor-token-issuer"
signedMethod = "RS256"
)
// Options ...
......@@ -25,6 +25,23 @@ type Options struct {
Issuer string
}
// DefaultOptions ...
func DefaultOptions() *Options {
privateKeyFile := config.TokenPrivateKeyPath()
privateKey, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
log.Errorf(fmt.Sprintf("failed to read private key %v", err))
return nil
}
opt := &Options{
SignMethod: jwt.GetSigningMethod(signedMethod),
PrivateKey: privateKey,
Issuer: issuer,
TTL: ttl,
}
return opt
}
// GetKey ...
func (o *Options) GetKey() (interface{}, error) {
var err error
......@@ -59,20 +76,3 @@ func (o *Options) GetKey() (interface{}, error) {
return nil, fmt.Errorf(fmt.Sprintf("unsupported sign method, %s", o.SignMethod))
}
}
// DefaultTokenOptions ...
func DefaultTokenOptions() *Options {
privateKeyFile := config.TokenPrivateKeyPath()
privateKey, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
log.Errorf(fmt.Sprintf("failed to read private key %v", err))
return nil
}
opt := &Options{
SignMethod: jwt.GetSigningMethod(defaultSignedMethod),
PrivateKey: privateKey,
Issuer: defaultIssuer,
TTL: defaultTTL,
}
return opt
}
......@@ -8,15 +8,15 @@ import (
)
func TestNewOptions(t *testing.T) {
defaultOpt := DefaultTokenOptions()
defaultOpt := DefaultOptions()
assert.NotNil(t, defaultOpt)
assert.Equal(t, defaultOpt.SignMethod, jwt.GetSigningMethod("RS256"))
assert.Equal(t, defaultOpt.Issuer, "harbor-token-defaultIssuer")
assert.Equal(t, defaultOpt.Issuer, "harbor-token-issuer")
assert.Equal(t, defaultOpt.TTL, 60*time.Minute)
}
func TestGetKey(t *testing.T) {
defaultOpt := DefaultTokenOptions()
defaultOpt := DefaultOptions()
key, err := defaultOpt.GetKey()
assert.Nil(t, err)
assert.NotNil(t, key)
......
......@@ -208,7 +208,7 @@ func RefreshToken(ctx context.Context, token *Token) (*Token, error) {
return &Token{Token: *t, IDToken: it}, nil
}
// GroupsFromToken returns the list of group name in the token, the claims of the group list is set in OIDCSetting.
// GroupsFromToken returns the list of group name in the token, the claim of the group list is set in OIDCSetting.
// It's designed not to return errors, in case of unexpected situation it will log and return empty list.
func GroupsFromToken(token *gooidc.IDToken) []string {
if token == nil {
......@@ -217,7 +217,7 @@ func GroupsFromToken(token *gooidc.IDToken) []string {
}
setting := provider.setting.Load().(models.OIDCSetting)
if len(setting.GroupsClaim) == 0 {
log.Warning("Group claims is not set in OIDC setting returning empty group list.")
log.Warning("Group claim is not set in OIDC setting returning empty group list.")
return []string{}
}
var c map[string]interface{}
......@@ -233,7 +233,7 @@ func groupsFromClaim(claimMap map[string]interface{}, k string) []string {
var res []string
g, ok := claimMap[k].([]interface{})
if !ok {
log.Warningf("Unable to get groups from claims, claims: %+v, groups claims key: %s", claimMap, k)
log.Warningf("Unable to get groups from claims, claims: %+v, groups claim key: %s", claimMap, k)
return res
}
for _, e := range g {
......
......@@ -34,6 +34,7 @@ import (
"github.com/goharbor/harbor/src/common/security/local"
robotCtx "github.com/goharbor/harbor/src/common/security/robot"
"github.com/goharbor/harbor/src/common/security/secret"
"github.com/goharbor/harbor/src/common/token"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/auth"
"github.com/goharbor/harbor/src/core/config"
......@@ -43,8 +44,6 @@ import (
"github.com/goharbor/harbor/src/pkg/authproxy"
"github.com/goharbor/harbor/src/pkg/robot"
pkg_token "github.com/goharbor/harbor/src/pkg/token"
robot_claim "github.com/goharbor/harbor/src/pkg/token/claims/robot"
)
// ContextValueKey for content value
......@@ -189,16 +188,15 @@ func (r *robotAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
if !strings.HasPrefix(robotName, common.RobotPrefix) {
return false
}
rClaims := &robot_claim.Claim{}
opt := pkg_token.DefaultTokenOptions()
rtk, err := pkg_token.Parse(opt, robotTk, rClaims)
rClaims := &token.RobotClaims{}
htk, err := token.ParseWithClaims(robotTk, rClaims)
if err != nil {
log.Errorf("failed to decrypt robot token, %v", err)
return false
}
// Do authn for robot account, as Harbor only stores the token ID, just validate the ID and disable.
ctr := robot.RobotCtr
robot, err := ctr.GetRobotAccount(rtk.Claims.(*robot_claim.Claim).TokenID)
robot, err := ctr.GetRobotAccount(htk.Claims.(*token.RobotClaims).TokenID)
if err != nil {
log.Errorf("failed to get robot %s: %v", robotName, err)
return false
......@@ -217,7 +215,7 @@ func (r *robotAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
}
log.Debug("creating robot account security context...")
pm := config.GlobalProjectMgr
securCtx := robotCtx.NewSecurityContext(robot, pm, rtk.Claims.(*robot_claim.Claim).Access)
securCtx := robotCtx.NewSecurityContext(robot, pm, htk.Claims.(*token.RobotClaims).Access)
setSecurCtxAndPM(ctx.Request, securCtx, pm)
return true
}
......
......@@ -25,7 +25,6 @@ import (
"github.com/goharbor/harbor/src/core/middlewares/listrepo"
"github.com/goharbor/harbor/src/core/middlewares/multiplmanifest"
"github.com/goharbor/harbor/src/core/middlewares/readonly"
"github.com/goharbor/harbor/src/core/middlewares/regtoken"
"github.com/goharbor/harbor/src/core/middlewares/sizequota"
"github.com/goharbor/harbor/src/core/middlewares/url"
"github.com/goharbor/harbor/src/core/middlewares/vulnerable"
......@@ -73,7 +72,6 @@ func (b *DefaultCreator) geMiddleware(mName string) alice.Constructor {
SIZEQUOTA: func(next http.Handler) http.Handler { return sizequota.New(next) },
COUNTQUOTA: func(next http.Handler) http.Handler { return countquota.New(next) },
IMMUTABLE: func(next http.Handler) http.Handler { return immutable.New(next) },
REGTOKEN: func(next http.Handler) http.Handler { return regtoken.New(next) },
}
return middlewares[mName]
}
......@@ -26,14 +26,13 @@ const (
SIZEQUOTA = "sizequota"
COUNTQUOTA = "countquota"
IMMUTABLE = "immutable"
REGTOKEN = "regtoken"
)
// ChartMiddlewares middlewares for chart server
var ChartMiddlewares = []string{CHART}
// Middlewares with sequential organization
var Middlewares = []string{READONLY, URL, REGTOKEN, MUITIPLEMANIFEST, LISTREPO, CONTENTTRUST, VULNERABLE, SIZEQUOTA, IMMUTABLE, COUNTQUOTA}
var Middlewares = []string{READONLY, URL, MUITIPLEMANIFEST, LISTREPO, CONTENTTRUST, VULNERABLE, SIZEQUOTA, IMMUTABLE, COUNTQUOTA}
// MiddlewaresLocal ...
var MiddlewaresLocal = []string{SIZEQUOTA, IMMUTABLE, COUNTQUOTA}
......@@ -49,10 +49,6 @@ func (cth contentTrustHandler) ServeHTTP(rw http.ResponseWriter, req *http.Reque
cth.next.ServeHTTP(rw, req)
return
}
if scannerPull, ok := util.ScannerPullFromContext(req.Context()); ok && scannerPull {
cth.next.ServeHTTP(rw, req)
return
}
if !util.GetPolicyChecker().ContentTrustEnabled(img.ProjectName) {
cth.next.ServeHTTP(rw, req)
return
......
package regtoken
import (
"github.com/docker/distribution/registry/auth"
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/middlewares/util"
pkg_token "github.com/goharbor/harbor/src/pkg/token"
"github.com/goharbor/harbor/src/pkg/token/claims/registry"
"net/http"
"strings"
)
// regTokenHandler is responsible for decoding the registry token in the docker pull request header,
// as harbor adds customized claims action into registry auth token, the middlerware is for decode it and write it into
// request context, then for other middlerwares in chain to use it to bypass request validation.
type regTokenHandler struct {
next http.Handler
}
// New ...
func New(next http.Handler) http.Handler {
return &regTokenHandler{
next: next,
}
}
// ServeHTTP ...
func (r *regTokenHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
imgRaw := req.Context().Value(util.ImageInfoCtxKey)
if imgRaw == nil {
r.next.ServeHTTP(rw, req)
return
}
img, _ := req.Context().Value(util.ImageInfoCtxKey).(util.ImageInfo)
if img.Digest == "" {
r.next.ServeHTTP(rw, req)
return
}
parts := strings.Split(req.Header.Get("Authorization"), " ")
if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
r.next.ServeHTTP(rw, req)
return
}
rawToken := parts[1]
opt := pkg_token.DefaultTokenOptions()
regTK, err := pkg_token.Parse(opt, rawToken, &registry.Claim{})
if err != nil {
log.Errorf("failed to decode reg token: %v, the error is skipped and round the request to native registry.", err)
r.next.ServeHTTP(rw, req)
return
}
accessItems := []auth.Access{}
accessItems = append(accessItems, auth.Access{
Resource: auth.Resource{
Type: rbac.ResourceRepository.String(),
Name: img.Repository,
},
Action: rbac.ActionScannerPull.String(),
})
accessSet := regTK.Claims.(*registry.Claim).GetAccess()
for _, access := range accessItems {
if accessSet.Contains(access) {
*req = *(req.WithContext(util.NewScannerPullContext(req.Context(), true)))
}
}
r.next.ServeHTTP(rw, req)
}
package regtoken
import (
"fmt"
"github.com/goharbor/harbor/src/core/middlewares/util"
"github.com/stretchr/testify/suite"
"net/http"
"net/http/httptest"
"os"
"testing"
)
type HandlerSuite struct {
suite.Suite
}
func doPullManifestRequest(projectName, name, tag string, next ...http.HandlerFunc) int {
repository := fmt.Sprintf("%s/%s", projectName, name)
url := fmt.Sprintf("/v2/%s/manifests/%s", repository, tag)
req, _ := http.NewRequest("GET", url, nil)
token := "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkNWUTc6REM3NTpHVEROOkxTTUs6VUFJTjpIUUVWOlZVSDQ6Q0lRRDpRV01COlM0Qzc6U0c0STpGRUhYIn0.eyJpc3MiOiJoYXJib3ItdG9rZW4taXNzdWVyIiwic3ViIjoicm9ib3QkZGVtbzExIiwiYXVkIjoiaGFyYm9yLXJlZ2lzdHJ5IiwiZXhwIjoxNTcxNzYzOTI2LCJuYmYiOjE1NzE3NjM4NjYsImlhdCI6MTU3MTc2Mzg2NiwianRpIjoiTnRaZWx4Z01KTUU1MXlEMCIsImFjY2VzcyI6W3sidHlwZSI6InJlcG9zaXRvcnkiLCJuYW1lIjoibGlicmFyeS9oZWxsby13b3JsZCIsImFjdGlvbnMiOlsicHVzaCIsIioiLCJwdWxsIiwic2Nhbm5lcnB1bGwiXX1dfQ.GlWuvtoxmChnpvbWaG5901Z9-g63DrzyNUREWlDbR5gnNeuOKjLNyE4QpogAQKx2yYtcGxbqNL3VfJkExJ_gMS0Qw8e10utGOawwqD4oqf_J06eKq4HzpZJengZfcjMA4g2RoeOlqdVdwimB_PdX9vkBO1od0wX0Cc2v0p2w5TkibcThKRoeLeVs2oRewkKLuVHNSM8wwRIlAvpWJuNnvRCFlHRkLcZM_KpGXqT7H-PZETTisWCi1pMxeYEwIsDFLlTKdV8LaiDeDmH-RaLOsuyAySYEW9Ynk5K3P_dUl2c_SYQXloPyi0MvXxSn6EWE4eHF2oQDM_SvIzR9sOVB8TtjMjKKMQ4yr_mqgMcfEpnInJATExBR56wmxNdLESncHl8rUYCe2jCjQFuR9NGQA1tGdjI4NoBN-OVD0dBs9rm_mkb2tgD-3gEhyzAw6hg0uzDsF7bj5Aq8scoi42UurhX2bZM89s4-TWBp4DWuBG0HDiwpOiBvB3RMm6MpQxsqrl0hQm_WH18L6QCknAW2e3d_6DJWJ0eBzISrhDr7LkqJKl1J8pv4zqoh_EUVeLyzTmjEULm-VbnpVF4wW5yTLF3S6F7Ox4vwWtVfi1XQNVOcJDB3VPUsRgiTTuCW-ZGcBLw-OdIcwaJ3T_QZkEjUw1f6i1JcGa0Mpgl83aLiSdQ 0xc0003c77c0 map[alg:RS256 kid:CVQ7:DC75:GTDN:LSMK:UAIN:HQEV:VUH4:CIQD:QWMB:S4C7:SG4I:FEHX typ:JWT] 0xc000496000 GlWuvtoxmChnpvbWaG5901Z9-g63DrzyNUREWlDbR5gnNeuOKjLNyE4QpogAQKx2yYtcGxbqNL3VfJkExJ_gMS0Qw8e10utGOawwqD4oqf_J06eKq4HzpZJengZfcjMA4g2RoeOlqdVdwimB_PdX9vkBO1od0wX0Cc2v0p2w5TkibcThKRoeLeVs2oRewkKLuVHNSM8wwRIlAvpWJuNnvRCFlHRkLcZM_KpGXqT7H-PZETTisWCi1pMxeYEwIsDFLlTKdV8LaiDeDmH-RaLOsuyAySYEW9Ynk5K3P_dUl2c_SYQXloPyi0MvXxSn6EWE4eHF2oQDM_SvIzR9sOVB8TtjMjKKMQ4yr_mqgMcfEpnInJATExBR56wmxNdLESncHl8rUYCe2jCjQFuR9NGQA1tGdjI4NoBN-OVD0dBs9rm_mkb2tgD-3gEhyzAw6hg0uzDsF7bj5Aq8scoi42UurhX2bZM89s4-TWBp4DWuBG0HDiwpOiBvB3RMm6MpQxsqrl0hQm_WH18L6QCknAW2e3d_6DJWJ0eBzISrhDr7LkqJKl1J8pv4zqoh_EUVeLyzTmjEULm-VbnpVF4wW5yTLF3S6F7Ox4vwWtVfi1XQNVOcJDB3VPUsRgiTTuCW-ZGcBLw-OdIcwaJ3T_QZkEjUw1f6i1JcGa0Mpgl83aLiSdQ"
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
rr := httptest.NewRecorder()
var n http.HandlerFunc
if len(next) > 0 {
n = next[0]
} else {
n = func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusNotFound)
}
}
h := New(http.HandlerFunc(n))
h.ServeHTTP(util.NewCustomResponseWriter(rr), req)
return rr.Code
}
func (suite *HandlerSuite) TestPullManifest() {
code1 := doPullManifestRequest("library", "photon", "release-1.10")
suite.Equal(http.StatusNotFound, code1)
}
func TestMain(m *testing.M) {
if result := m.Run(); result != 0 {
os.Exit(result)
}
}
func TestRunHandlerSuite(t *testing.T) {
suite.Run(t, new(HandlerSuite))
}
......@@ -49,8 +49,6 @@ type contextKey string
const (
// ImageInfoCtxKey the context key for image information
ImageInfoCtxKey = contextKey("ImageInfo")
// ScannerPullCtxKey the context key for robot account to bypass the pull policy check.
ScannerPullCtxKey = contextKey("ScannerPullCheck")
// TokenUsername ...
// TODO: temp solution, remove after vmware/harbor#2242 is resolved.
TokenUsername = "harbor-core"
......@@ -445,17 +443,6 @@ func ManifestInfoFromContext(ctx context.Context) (*ManifestInfo, bool) {
return info, ok
}
// NewScannerPullContext returns context with policy check info
func NewScannerPullContext(ctx context.Context, scannerPull bool) context.Context {
return context.WithValue(ctx, ScannerPullCtxKey, scannerPull)
}
// ScannerPullFromContext returns whether to bypass policy check
func ScannerPullFromContext(ctx context.Context) (bool, bool) {
info, ok := ctx.Value(ScannerPullCtxKey).(bool)
return info, ok
}
// NewBlobInfoContext returns context with blob info
func NewBlobInfoContext(ctx context.Context, info *BlobInfo) context.Context {
return context.WithValue(ctx, blobInfoKey, info)
......
......@@ -52,11 +52,6 @@ func (vh vulnerableHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request)
return
}
if scannerPull, ok := util.ScannerPullFromContext(req.Context()); ok && scannerPull {
vh.next.ServeHTTP(rw, req)
return
}
// Is vulnerable policy set?
projectVulnerableEnabled, projectVulnerableSeverity, wl := util.GetPolicyChecker().VulnerablePolicy(img.ProjectName)
if !projectVulnerableEnabled {
......@@ -114,10 +109,10 @@ func (vh vulnerableHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request)
return
}
// Print scannerPull CVE list
// Print bypass CVE list
if len(summary.CVEBypassed) > 0 {
for _, cve := range summary.CVEBypassed {
log.Infof("Vulnerable policy check: scannerPull CVE %s", cve)
log.Infof("Vulnerable policy check: bypass CVE %s", cve)
}
}
......
......@@ -133,9 +133,6 @@ func permToActions(p string) []string {
if strings.Contains(p, "R") {
res = append(res, "pull")
}
if strings.Contains(p, "S") {
res = append(res, "scanner-pull")
}
return res
}
......
......@@ -177,8 +177,6 @@ func (rep repositoryFilter) filter(ctx security.Context, pm promgr.ProjectManage
permission = "RWM"
} else if ctx.Can(rbac.ActionPush, resource) {
permission = "RW"
} else if ctx.Can(rbac.ActionScannerPull, resource) {
permission = "RS"
} else if ctx.Can(rbac.ActionPull, resource) {
permission = "R"
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment