Skip to content

Commit

Permalink
Merge branch 'goharbor:release-2.10.0' into release-2.10.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Vad1mo authored Jan 15, 2024
2 parents f1d7545 + cf41c69 commit 007d41d
Show file tree
Hide file tree
Showing 15 changed files with 53 additions and 25 deletions.
5 changes: 5 additions & 0 deletions src/common/rbac/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ var (
{Resource: ResourceSecurityHub, Action: ActionList},

{Resource: ResourceCatalog, Action: ActionRead},

{Resource: ResourceQuota, Action: ActionRead},
{Resource: ResourceQuota, Action: ActionList},
},
"Project": {
{Resource: ResourceLog, Action: ActionList},
Expand Down Expand Up @@ -221,6 +224,8 @@ var (
{Resource: ResourceLabel, Action: ActionDelete},
{Resource: ResourceLabel, Action: ActionList},
{Resource: ResourceLabel, Action: ActionUpdate},

{Resource: ResourceQuota, Action: ActionRead},
},
}
)
11 changes: 7 additions & 4 deletions src/controller/proxy/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ func (c *controller) UseLocalManifest(ctx context.Context, art lib.ArtifactInfo,
if c.cache == nil {
return a != nil && string(desc.Digest) == a.Digest, nil, nil // digest matches
}

// Pass digest to the cache key, digest is more stable than tag, because tag could be updated
if len(art.Digest) == 0 {
art.Digest = string(desc.Digest)
}
err = c.cache.Fetch(ctx, manifestListKey(art.Repository, art), &content)
if err != nil {
if errors.Is(err, cache.ErrNotFound) {
Expand Down Expand Up @@ -318,8 +321,8 @@ func getRemoteRepo(art lib.ArtifactInfo) string {
}

func getReference(art lib.ArtifactInfo) string {
if len(art.Tag) > 0 {
return art.Tag
if len(art.Digest) > 0 {
return art.Digest
}
return art.Digest
return art.Tag
}
2 changes: 1 addition & 1 deletion src/controller/proxy/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func TestGetRef(t *testing.T) {
{
name: `normal`,
in: lib.ArtifactInfo{Repository: "hello-world", Tag: "latest", Digest: "sha256:aabbcc"},
want: "latest",
want: "sha256:aabbcc",
},
{
name: `digest_only`,
Expand Down
5 changes: 4 additions & 1 deletion src/controller/proxy/manifestcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ func (m *ManifestListCache) CacheContent(ctx context.Context, remoteRepo string,
log.Errorf("failed to get reference, reference is empty, skip to cache manifest list")
return
}
// some registry will not return the digest in the HEAD request, if no digest returned, cache manifest list content with tag
// cache key should contain digest if digest exist
if len(art.Digest) == 0 {
art.Digest = string(digest.FromBytes(payload))
}
key := manifestListKey(art.Repository, art)
log.Debugf("cache manifest list with key=cache:%v", key)
if err := m.cache.Save(ctx, manifestListContentTypeKey(art.Repository, art), contentType, manifestListCacheInterval); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const ACTION_RESOURCE_I18N_MAP = {
'immutable-tag': 'ROBOT_ACCOUNT.IMMUTABLE_TAG',
log: 'ROBOT_ACCOUNT.LOG',
'notification-policy': 'ROBOT_ACCOUNT.NOTIFICATION_POLICY',
quota: 'ROBOT_ACCOUNT.QUOTA',
};

export function convertKey(key: string) {
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/de-de-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/en-us-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/es-es-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/fr-fr-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/pt-br-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/tr-tr-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
1 change: 1 addition & 0 deletions src/portal/src/i18n/lang/zh-tw-lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@
"IMMUTABLE_TAG": "Immutable Tag",
"LOG": "Log",
"NOTIFICATION_POLICY": "Notification Policy",
"QUOTA": "Quota",
"BACK": "Back",
"NEXT": "Next",
"FINISH": "Finish",
Expand Down
17 changes: 13 additions & 4 deletions tests/apitests/python/test_system_permission.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class Permission:


def __init__(self, url, method, expect_status_code, payload=None, res_id_field=None, payload_id_field=None, id_from_header=False):
def __init__(self, url, method, expect_status_code=None, payload=None, res_id_field=None, payload_id_field=None, id_from_header=False):
self.url = url
self.method = method
self.expect_status_code = expect_status_code
Expand All @@ -33,7 +33,10 @@ def call(self):
if ID_PLACEHOLDER in self.url:
self.url = self.url.replace(ID_PLACEHOLDER, str(self.payload.get(self.payload_id_field)))
response = requests.request(self.method, self.url, data=json.dumps(self.payload), verify=False, auth=(user_name, password), headers={"Content-Type": "application/json"})
assert response.status_code == self.expect_status_code, "Failed to call the {} {}, expected status code is {}, but got {}, error msg is {}".format(self.method, self.url, self.expect_status_code, response.status_code, response.text)
if self.expect_status_code == None:
assert response.status_code != 403, "Failed to call the {} {}, expected status code is not 403, but got {}, error msg is {}".format(self.method, self.url, response.status_code, response.text)
else:
assert response.status_code == self.expect_status_code, "Failed to call the {} {}, expected status code is {}, but got {}, error msg is {}".format(self.method, self.url, self.expect_status_code, response.status_code, response.text)
if self.res_id_field and self.payload_id_field and self.id_from_header == False:
self.payload[self.payload_id_field] = int(json.loads(response.text)[self.res_id_field])
elif self.res_id_field and self.payload_id_field and self.id_from_header == True:
Expand Down Expand Up @@ -228,7 +231,7 @@ def call(self):
}
create_scan_all_schedule = Permission("{}/system/scanAll/schedule".format(harbor_base_url), "POST", 201, scan_all_weekly_schedule_payload)
update_scan_all_schedule = Permission("{}/system/scanAll/schedule".format(harbor_base_url), "PUT", 200, scan_all_reset_schedule_payload)
stop_scan_all = Permission("{}/system/scanAll/stop".format(harbor_base_url), "POST", 202)
stop_scan_all = Permission("{}/system/scanAll/stop".format(harbor_base_url), "POST")
scan_all_metrics = Permission("{}/scans/all/metrics".format(harbor_base_url), "GET", 200)
scan_all_schedule_metrics = Permission("{}/scans/schedule/metrics".format(harbor_base_url), "GET", 200)
# scan all permissions end
Expand Down Expand Up @@ -328,6 +331,11 @@ def call(self):
update_purge_audit_schedule = Permission("{}/system/purgeaudit/schedule".format(harbor_base_url), "PUT", 200, purge_audit_payload)
# purge-audit permissions end

# quota permissions start
list_quota = Permission("{}/quotas".format(harbor_base_url), "GET", 200)
read_quota = Permission("{}/quotas/{}".format(harbor_base_url, "88888888"), "GET", 404)
# quota permissions end


resource_permissions = {
"audit-log": [list_audit_logs],
Expand All @@ -345,7 +353,8 @@ def call(self):
"security-hub": [read_summary, list_vul],
"catalog": [read_catalog],
"garbage-collection": [create_gc, list_gc, read_gc, stop_gc, read_gc_log, read_gc_schedule, update_gc_schedule],
"purge-audit": [create_purge_audit, list_purge_audit, read_purge_audit, stop_purge_audit, read_purge_audit_log, read_purge_audit_schedule, update_purge_audit_schedule]
"purge-audit": [create_purge_audit, list_purge_audit, read_purge_audit, stop_purge_audit, read_purge_audit_log, read_purge_audit_schedule, update_purge_audit_schedule],
"quota": [list_quota, read_quota]
}
resource_permissions["all"] = [item for sublist in resource_permissions.values() for item in sublist]

Expand Down
4 changes: 2 additions & 2 deletions tests/resources/Harbor-Pages/Project_Robot_Account.robot
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ Create A Project Robot Account
${permission_count}= Create Dictionary
${total}= Set Variable 0
IF '${first_resource}' == 'all'
Set To Dictionary ${permission_count} all=55
${total}= Set Variable 55
Set To Dictionary ${permission_count} all=56
${total}= Set Variable 56
Retry Element Click //span[text()='Select all']
ELSE
FOR ${item} IN @{resources}
Expand Down
26 changes: 13 additions & 13 deletions tests/robot-cases/Group1-Nightly/Common.robot
Original file line number Diff line number Diff line change
Expand Up @@ -636,12 +636,12 @@ Test Case - Project Level Robot Account
Push image ${ip} robot1${d} ${token} project${d} hello-world:latest is_robot=${true}
Pull image ${ip} robot1${d} ${token} project${d} hello-world:latest is_robot=${true}
Check Project Robot Account Permission robot1${d} ${permission_count}
Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} project${d} hello-world latest repository
Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all 1
Retry Action Keyword Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} project${d} hello-world latest repository
Retry Action Keyword Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all 1
${resources}= Create List all
${robot_account_name} ${token} ${permission_count}= Create A Project Robot Account robot2${d} days days=10 description=For testing resources=${resources}
Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} project${d} hello-world latest all
Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all 1
Retry Action Keyword Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} project${d} hello-world latest all
Retry Action Keyword Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all 1
Close Browser

Test Case - Push Docker Manifest Index and Display
Expand Down Expand Up @@ -721,9 +721,9 @@ Test Case - System Robot Account Cover All Projects
${robot_account_name} ${token}= Create A System Robot Account sys${d} never description=For testing cover_all_system_resources=${true} cover_all_project_resources=${true}
Push image ${ip} '${robot_account_name}' ${token} project${d} hello-world:latest
Pull image ${ip} '${robot_account_name}' ${token} project${d} hello-world:latest
Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all
Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} ${project_name} hello-world latest all
Retry Wait Element Visible //clr-dg-row[.//clr-dg-cell[contains(.,'${robot_account_name}')] and .//clr-icon[contains(@class, 'color-green')] and .//button[text()=' 51 PERMISSION(S) '] and .//span[contains(.,'Never Expires')] and .//clr-dg-cell[text()='For testing'] ]
Retry Action Keyword Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all
Retry Action Keyword Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} ${project_name} hello-world latest all
Retry Wait Element Visible //clr-dg-row[.//clr-dg-cell[contains(.,'${robot_account_name}')] and .//clr-icon[contains(@class, 'color-green')] and .//button[text()=' 53 PERMISSION(S) '] and .//span[contains(.,'Never Expires')] and .//clr-dg-cell[text()='For testing'] ]
System Robot Account Exist ${robot_account_name} all
Close Browser

Expand All @@ -739,15 +739,15 @@ Test Case - System Robot Account
${project_id}= Set Variable ${words}[-2]
Switch To Robot Account
${robot_account_name} ${token}= Create A System Robot Account sys1${d} days days=100 description=For testing cover_all_system_resources=${true}
Retry Wait Element Visible //clr-dg-row[.//clr-dg-cell[contains(.,'${robot_account_name}')] and .//clr-icon[contains(@class, 'color-green')] and .//button[text()=' 51 PERMISSION(S) '] and .//span[contains(.,'99d 23h')] and .//clr-dg-cell[text()='For testing'] and .//clr-dg-cell//span[text()=' None ']]
Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all
Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} ${project_name} hello-world latest all 1
Retry Wait Element Visible //clr-dg-row[.//clr-dg-cell[contains(.,'${robot_account_name}')] and .//clr-icon[contains(@class, 'color-green')] and .//button[text()=' 53 PERMISSION(S) '] and .//span[contains(.,'99d 23h')] and .//clr-dg-cell[text()='For testing'] and .//clr-dg-cell//span[text()=' None ']]
Retry Action Keyword Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all
Retry Action Keyword Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} ${project_name} hello-world latest all 1

${robot_account_name} ${token}= Create A System Robot Account sys2${d} days days=2 description=For testing cover_all_project_resources=${true}
Push image ${ip} '${robot_account_name}' ${token} project${d} hello-world:latest
Retry Wait Element Visible //clr-dg-row[.//clr-dg-cell[contains(.,'${robot_account_name}')] and .//clr-icon[contains(@class, 'color-green')] and .//span[text()='All projects with'] and .//button[text()=' 55 PERMISSION(S) '] and .//span[contains(.,'1d 23h')] and .//clr-dg-cell[text()='For testing'] and .//clr-dg-cell//span[text()=' None ']]
Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all 1
Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} ${project_name} hello-world latest all
Retry Wait Element Visible //clr-dg-row[.//clr-dg-cell[contains(.,'${robot_account_name}')] and .//clr-icon[contains(@class, 'color-green')] and .//span[text()='All projects with'] and .//button[text()=' 56 PERMISSION(S) '] and .//span[contains(.,'1d 23h')] and .//clr-dg-cell[text()='For testing'] and .//clr-dg-cell//span[text()=' None ']]
Retry Action Keyword Check System Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} all 1
Retry Action Keyword Check Project Robot Account API Permission ${robot_account_name} ${token} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${project_id} ${project_name} hello-world latest all
Close Browser

Test Case - Go To Harbor Api Page
Expand Down

0 comments on commit 007d41d

Please sign in to comment.