Skip to content

Commit

Permalink
have option to enable robot full access
Browse files Browse the repository at this point in the history
When the system admin enable this option, the robot can be assigned with robot/user/group/quota permissions.

Signed-off-by: wang yan <wangyan@vmware.com>
  • Loading branch information
wy65701436 committed Jul 18, 2024
1 parent 0da13eb commit 1506ec5
Show file tree
Hide file tree
Showing 17 changed files with 221 additions and 21 deletions.
3 changes: 3 additions & 0 deletions src/common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,7 @@ const (

// Global Leeway used for token validation
JwtLeeway = 60 * time.Second

// Global Leeway used for token validation
EnableRobotFullAccess = "enable_robot_full_access"
)
93 changes: 89 additions & 4 deletions src/common/rbac/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@

package rbac

import "github.com/goharbor/harbor/src/pkg/permission/types"
import (
"context"

"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/pkg/permission/types"
)

// const action variables
const (
Expand Down Expand Up @@ -81,9 +86,89 @@ const (
ResourceSecurityHub = Resource("security-hub")
)

type scope string

const (
ScopeSystem = scope("System")
ScopeProject = scope("Project")
)

// RobotPermissionProvider defines the permission provider for robot account
type RobotPermissionProvider interface {
GetPermissions(s scope) []*types.Policy
}

// GetPermissionProvider gives the robot permission provider
func GetPermissionProvider(ctx context.Context) RobotPermissionProvider {
var permissionProvider RobotPermissionProvider
permissionProvider = &BaseProvider{}
if config.RobotFullAccess(ctx) {
permissionProvider = &NolimitProvider{}
}
return permissionProvider
}

// BaseProvider ...
type BaseProvider struct {
}

// GetPermissions ...
func (d *BaseProvider) GetPermissions(s scope) []*types.Policy {
return PoliciesMap[s]
}

// NolimitProvider ...
type NolimitProvider struct {
BaseProvider
}

// GetPermissions ...
func (n *NolimitProvider) GetPermissions(s scope) []*types.Policy {
if s == ScopeSystem {
return append(n.BaseProvider.GetPermissions(ScopeSystem),
&types.Policy{Resource: ResourceRobot, Action: ActionCreate},
&types.Policy{Resource: ResourceRobot, Action: ActionRead},
&types.Policy{Resource: ResourceRobot, Action: ActionUpdate},
&types.Policy{Resource: ResourceRobot, Action: ActionList},
&types.Policy{Resource: ResourceRobot, Action: ActionDelete},

&types.Policy{Resource: ResourceUser, Action: ActionCreate},
&types.Policy{Resource: ResourceUser, Action: ActionRead},
&types.Policy{Resource: ResourceUser, Action: ActionUpdate},
&types.Policy{Resource: ResourceUser, Action: ActionList},
&types.Policy{Resource: ResourceUser, Action: ActionDelete},

&types.Policy{Resource: ResourceLdapUser, Action: ActionCreate},
&types.Policy{Resource: ResourceLdapUser, Action: ActionList},

&types.Policy{Resource: ResourceQuota, Action: ActionUpdate},

&types.Policy{Resource: ResourceUserGroup, Action: ActionCreate},
&types.Policy{Resource: ResourceUserGroup, Action: ActionRead},
&types.Policy{Resource: ResourceUserGroup, Action: ActionUpdate},
&types.Policy{Resource: ResourceUserGroup, Action: ActionList},
&types.Policy{Resource: ResourceUserGroup, Action: ActionDelete})
}
if s == ScopeProject {
return append(n.BaseProvider.GetPermissions(ScopeProject),
&types.Policy{Resource: ResourceRobot, Action: ActionCreate},
&types.Policy{Resource: ResourceRobot, Action: ActionRead},
&types.Policy{Resource: ResourceRobot, Action: ActionUpdate},
&types.Policy{Resource: ResourceRobot, Action: ActionList},
&types.Policy{Resource: ResourceRobot, Action: ActionDelete},

&types.Policy{Resource: ResourceMember, Action: ActionCreate},
&types.Policy{Resource: ResourceMember, Action: ActionRead},
&types.Policy{Resource: ResourceMember, Action: ActionUpdate},
&types.Policy{Resource: ResourceMember, Action: ActionList},
&types.Policy{Resource: ResourceMember, Action: ActionDelete})
}
return []*types.Policy{}
}

var (
PoliciesMap = map[string][]*types.Policy{
"System": {
PoliciesMap = map[scope][]*types.Policy{
ScopeSystem: {
{Resource: ResourceAuditLog, Action: ActionList},

{Resource: ResourcePreatInstance, Action: ActionRead},
Expand Down Expand Up @@ -154,7 +239,7 @@ var (
{Resource: ResourceQuota, Action: ActionRead},
{Resource: ResourceQuota, Action: ActionList},
},
"Project": {
ScopeProject: {
{Resource: ResourceLog, Action: ActionList},

{Resource: ResourceProject, Action: ActionRead},
Expand Down
54 changes: 54 additions & 0 deletions src/common/rbac/const_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package rbac

import (
"context"

"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/lib/config"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"

"github.com/stretchr/testify/assert"
"testing"
)

func TestBaseProvider(t *testing.T) {
permissionProvider := &BaseProvider{}
sysPermissions := permissionProvider.GetPermissions(ScopeSystem)

for _, per := range sysPermissions {
if per.Action == ActionCreate && per.Resource == ResourceRobot {
t.Fail()
}
}
}

func TestNolimitProvider(t *testing.T) {
permissionProvider := &BaseProvider{}
sysPermissions := permissionProvider.GetPermissions(ScopeSystem)

for _, per := range sysPermissions {
if per.Action == ActionCreate && per.Resource == ResourceRobot {
t.Log("no limit provider has the permission of robot account creation")
}
}
}

func TestGetPermissionProvider(t *testing.T) {
cfg := map[string]interface{}{
common.EnableRobotFullAccess: "false",
}
config.InitWithSettings(cfg)

defaultPro := GetPermissionProvider(context.Background())
_, ok := defaultPro.(*BaseProvider)
assert.True(t, ok)

cfg = map[string]interface{}{
common.EnableRobotFullAccess: "true",
}
config.InitWithSettings(cfg)
defaultPro = GetPermissionProvider(context.Background())
_, ok = defaultPro.(*NolimitProvider)
assert.True(t, ok)

}
2 changes: 2 additions & 0 deletions src/lib/config/metadata/metadatalist.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,7 @@ var (

{Name: common.BeegoMaxMemoryBytes, Scope: SystemScope, Group: BasicGroup, EnvKey: "BEEGO_MAX_MEMORY_BYTES", DefaultValue: fmt.Sprintf("%d", common.DefaultBeegoMaxMemoryBytes), ItemType: &Int64Type{}, Editable: false, Description: `The bytes for limiting the beego max memory, default is 128GB`},
{Name: common.BeegoMaxUploadSizeBytes, Scope: SystemScope, Group: BasicGroup, EnvKey: "BEEGO_MAX_UPLOAD_SIZE_BYTES", DefaultValue: fmt.Sprintf("%d", common.DefaultBeegoMaxUploadSizeBytes), ItemType: &Int64Type{}, Editable: false, Description: `The bytes for limiting the beego max upload size, default it 128GB`},

{Name: common.EnableRobotFullAccess, Scope: SystemScope, Group: BasicGroup, EnvKey: "ENABLE_ROBOT_FULL_ACCESS", DefaultValue: "false", ItemType: &BoolType{}, Editable: true, Description: `The flag indicates if a robot is able to access full entry points of harbor`},
}
)
5 changes: 5 additions & 0 deletions src/lib/config/userconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ func ScannerSkipUpdatePullTime(ctx context.Context) bool {
return DefaultMgr().Get(ctx, common.ScannerSkipUpdatePullTime).GetBool()
}

// RobotFullAccess returns a bool to indicate if the robot can access full entry points
func RobotFullAccess(ctx context.Context) bool {
return DefaultMgr().Get(ctx, common.EnableRobotFullAccess).GetBool()
}

// BannerMessage returns the customized banner message
func BannerMessage(ctx context.Context) string {
return DefaultMgr().Get(ctx, common.BannerMessage).GetString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ export const ACTION_RESOURCE_I18N_MAP = {
'notification-policy': 'ROBOT_ACCOUNT.NOTIFICATION_POLICY',
quota: 'ROBOT_ACCOUNT.QUOTA',
sbom: 'ROBOT_ACCOUNT.SBOM',
robot: 'ROBOT_ACCOUNT.ROBOT',
user: 'ROBOT_ACCOUNT.USER',
'user-group': 'ROBOT_ACCOUNT.GROUP',
'ldap-user': 'ROBOT_ACCOUNT.LDAPUSER',
member: 'ROBOT_ACCOUNT.MEMBER',
};

export function convertKey(key: string) {
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/de-de-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,12 @@
"SELECT_PERMISSIONS": "Select Permissions",
"SELECT_SYSTEM_PERMISSIONS": "Select System Permissions",
"SELECT_PROJECT_PERMISSIONS": "Select Project Permissions",
"SYSTEM_PERMISSIONS": "System Permissions"
"SYSTEM_PERMISSIONS": "System Permissions",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "EDIT",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/en-us-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,12 @@
"SELECT_PERMISSIONS": "Select Permissions",
"SELECT_SYSTEM_PERMISSIONS": "Select System Permissions",
"SELECT_PROJECT_PERMISSIONS": "Select Project Permissions",
"SYSTEM_PERMISSIONS": "System Permissions"
"SYSTEM_PERMISSIONS": "System Permissions",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "EDIT",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/es-es-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,12 @@
"SELECT_PERMISSIONS": "Select Permissions",
"SELECT_SYSTEM_PERMISSIONS": "Select System Permissions",
"SELECT_PROJECT_PERMISSIONS": "Select Project Permissions",
"SYSTEM_PERMISSIONS": "System Permissions"
"SYSTEM_PERMISSIONS": "System Permissions",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "EDIT",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/fr-fr-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,12 @@
"SELECT_PERMISSIONS": "Selectionner les permissions",
"SELECT_SYSTEM_PERMISSIONS": "Selectionner les permissions système",
"SELECT_PROJECT_PERMISSIONS": "Selectionner les permissions projet",
"SYSTEM_PERMISSIONS": "Permissions système"
"SYSTEM_PERMISSIONS": "Permissions système",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "Éditer",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/ko-kr-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,12 @@
"SELECT_PERMISSIONS": "권한 선택",
"SELECT_SYSTEM_PERMISSIONS": "시스템 권한 선택",
"SELECT_PROJECT_PERMISSIONS": "프로젝트 권한 선택",
"SYSTEM_PERMISSIONS": "시스템 권한"
"SYSTEM_PERMISSIONS": "시스템 권한",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "편집",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/pt-br-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,12 @@
"SELECT_PERMISSIONS": "Select Permissions",
"SELECT_SYSTEM_PERMISSIONS": "Select System Permissions",
"SELECT_PROJECT_PERMISSIONS": "Select Project Permissions",
"SYSTEM_PERMISSIONS": "System Permissions"
"SYSTEM_PERMISSIONS": "System Permissions",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"GROUP": {
"GROUP": "Grupo",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/tr-tr-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,12 @@
"SELECT_PERMISSIONS": "Select Permissions",
"SELECT_SYSTEM_PERMISSIONS": "Select System Permissions",
"SELECT_PROJECT_PERMISSIONS": "Select Project Permissions",
"SYSTEM_PERMISSIONS": "System Permissions"
"SYSTEM_PERMISSIONS": "System Permissions",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "DÜZENLE",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/zh-cn-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,12 @@
"SELECT_PERMISSIONS": "选择权限",
"SELECT_SYSTEM_PERMISSIONS": "选择系统权限",
"SELECT_PROJECT_PERMISSIONS": "选择项目权限",
"SYSTEM_PERMISSIONS": "系统权限"
"SYSTEM_PERMISSIONS": "系统权限",
"ROBOT": "机器人账户",
"USER": "用户",
"LDAPUSER": "LDAP 用户",
"GROUP": "用户组",
"MEMBER": "项目成员"
},
"WEBHOOK": {
"EDIT_BUTTON": "编辑",
Expand Down
7 changes: 6 additions & 1 deletion src/portal/src/i18n/lang/zh-tw-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,12 @@
"SELECT_PERMISSIONS": "Select Permissions",
"SELECT_SYSTEM_PERMISSIONS": "Select System Permissions",
"SELECT_PROJECT_PERMISSIONS": "Select Project Permissions",
"SYSTEM_PERMISSIONS": "System Permissions"
"SYSTEM_PERMISSIONS": "System Permissions",
"ROBOT": "Robot Account",
"USER": "User",
"LDAPUSER": "LDAP User",
"GROUP": "User Group",
"MEMBER": "Project Member"
},
"WEBHOOK": {
"EDIT_BUTTON": "編輯",
Expand Down
6 changes: 3 additions & 3 deletions src/server/v2.0/handler/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package handler

import (
"context"

"github.com/go-openapi/runtime/middleware"

"github.com/goharbor/harbor/src/common/rbac"
Expand Down Expand Up @@ -71,11 +70,12 @@ func (p *permissionsAPI) GetPermissions(ctx context.Context, _ permissions.GetPe
return p.SendError(ctx, errors.ForbiddenError(errors.New("only admins(system and project) can access permissions")))
}

provider := rbac.GetPermissionProvider(ctx)
sysPermissions := make([]*types.Policy, 0)
proPermissions := rbac.PoliciesMap["Project"]
proPermissions := provider.GetPermissions(rbac.ScopeProject)
if isSystemAdmin {
// project admin cannot see the system level permissions
sysPermissions = rbac.PoliciesMap["System"]
sysPermissions = provider.GetPermissions(rbac.ScopeSystem)
}

return permissions.NewGetPermissionsOK().WithPayload(p.convertPermissions(sysPermissions, proPermissions))
Expand Down
Loading

0 comments on commit 1506ec5

Please sign in to comment.