goharbor / harbor

An open source trusted cloud native registry project that stores, signs, and scans content.
https://goharbor.io
Apache License 2.0
23.57k stars 4.71k forks source link

Robots UI Fails to Load After Harbor Upgrade Due to Missing Access Attribute #20734

Closed camAtGitHub closed 3 weeks ago

camAtGitHub commented 1 month ago

Hello, Here is a yummy bug for you. I'm hoping you may have a fix I could implement for our production harbor system 😃 Thanks for looking!

Expected behavior and actual behavior: Expected behavior: When upgrading from Harbor version 2.7 to 2.9 and then 2.11, the Robot screen should continue to load correctly in the UI, even if the project contained Legacy robot accounts.

Actual behavior: After the version upgrades, if the project contained Legacy robot accounts, the Robot screen would no longer load in the UI. This is due to the fact that the permission array was empty, but it should have contained an array with the access attribute, which does not exist.

Steps to reproduce the problem:

  1. Upgrade Harbor from version 2.7.0 to 2.9.0
  2. Upgrade Harbor from version 2.9.0 to 2.11.0
  3. Confirm that the project contains Legacy robot accounts
  4. Observe that the Robot screen no longer loads in the UI

Versions:

Additional context:

Developer Tools Error message The browser development tools console displays the following error message: ``` TypeError: Cannot read properties of undefined (reading 'access') main.782b5181ceecb1db.js:1 at fe (3322.4402085913684103.js:1:18618) at ev (main.782b5181ceecb1db.js:1:286640) at mv (main.782b5181ceecb1db.js:1:296335) at vv (main.782b5181ceecb1db.js:1:297552) at _v (main.782b5181ceecb1db.js:1:297385) at mv (main.782b5181ceecb1db.js:1:296614) at vv (main.782b5181ceecb1db.js:1:297552) at RS (main.782b5181ceecb1db.js:1:297415) at yv (main.782b5181ceecb1db.js:1:297690) at mv (main.782b5181ceecb1db.js:1:297076) ```
https://acme.com/api/v2.0/systeminfo ```json {"auth_mode":"ldap_auth","banner_message":"","current_time":"2024-07-11T13:56:24.527Z","external_url":"https://acme.com","harbor_version":"v2.11.0-70255684","has_ca_root":false,"notification_enable":true,"oidc_provider_name":"","primary_auth_mode":false,"project_creation_restriction":"adminonly","read_only":false,"registry_storage_provider_name":"filesystem","registry_url":"acme.com","self_registration":false} ```
https://acme.com/api/v2.0/permissions ```json {"project":[{"action":"list","resource":"log"},{"action":"read","resource":"project"},{"action":"delete","resource":"project"},{"action":"update","resource":"project"},{"action":"read","resource":"metadata"},{"action":"create","resource":"metadata"},{"action":"delete","resource":"metadata"},{"action":"list","resource":"metadata"},{"action":"update","resource":"metadata"},{"action":"read","resource":"repository"},{"action":"update","resource":"repository"},{"action":"delete","resource":"repository"},{"action":"list","resource":"repository"},{"action":"pull","resource":"repository"},{"action":"push","resource":"repository"},{"action":"read","resource":"artifact"},{"action":"create","resource":"artifact"},{"action":"list","resource":"artifact"},{"action":"delete","resource":"artifact"},{"action":"create","resource":"scan"},{"action":"read","resource":"scan"},{"action":"stop","resource":"scan"},{"action":"create","resource":"sbom"},{"action":"stop","resource":"sbom"},{"action":"read","resource":"sbom"},{"action":"create","resource":"tag"},{"action":"list","resource":"tag"},{"action":"delete","resource":"tag"},{"action":"list","resource":"accessory"},{"action":"read","resource":"artifact-addition"},{"action":"create","resource":"artifact-label"},{"action":"delete","resource":"artifact-label"},{"action":"create","resource":"scanner"},{"action":"read","resource":"scanner"},{"action":"read","resource":"preheat-policy"},{"action":"create","resource":"preheat-policy"},{"action":"delete","resource":"preheat-policy"},{"action":"list","resource":"preheat-policy"},{"action":"update","resource":"preheat-policy"},{"action":"create","resource":"immutable-tag"},{"action":"delete","resource":"immutable-tag"},{"action":"list","resource":"immutable-tag"},{"action":"update","resource":"immutable-tag"},{"action":"read","resource":"notification-policy"},{"action":"create","resource":"notification-policy"},{"action":"delete","resource":"notification-policy"},{"action":"list","resource":"notification-policy"},{"action":"update","resource":"notification-policy"},{"action":"read","resource":"tag-retention"},{"action":"create","resource":"tag-retention"},{"action":"delete","resource":"tag-retention"},{"action":"list","resource":"tag-retention"},{"action":"update","resource":"tag-retention"},{"action":"read","resource":"label"},{"action":"create","resource":"label"},{"action":"delete","resource":"label"},{"action":"list","resource":"label"},{"action":"update","resource":"label"},{"action":"read","resource":"quota"}],"system":[{"action":"list","resource":"audit-log"},{"action":"read","resource":"preheat-instance"},{"action":"create","resource":"preheat-instance"},{"action":"delete","resource":"preheat-instance"},{"action":"list","resource":"preheat-instance"},{"action":"update","resource":"preheat-instance"},{"action":"list","resource":"project"},{"action":"create","resource":"project"},{"action":"read","resource":"replication-policy"},{"action":"create","resource":"replication-policy"},{"action":"delete","resource":"replication-policy"},{"action":"list","resource":"replication-policy"},{"action":"update","resource":"replication-policy"},{"action":"read","resource":"replication"},{"action":"create","resource":"replication"},{"action":"list","resource":"replication"},{"action":"list","resource":"replication-adapter"},{"action":"read","resource":"registry"},{"action":"create","resource":"registry"},{"action":"delete","resource":"registry"},{"action":"list","resource":"registry"},{"action":"update","resource":"registry"},{"action":"read","resource":"scan-all"},{"action":"update","resource":"scan-all"},{"action":"stop","resource":"scan-all"},{"action":"create","resource":"scan-all"},{"action":"read","resource":"system-volumes"},{"action":"read","resource":"garbage-collection"},{"action":"create","resource":"garbage-collection"},{"action":"list","resource":"garbage-collection"},{"action":"update","resource":"garbage-collection"},{"action":"stop","resource":"garbage-collection"},{"action":"read","resource":"purge-audit"},{"action":"create","resource":"purge-audit"},{"action":"list","resource":"purge-audit"},{"action":"update","resource":"purge-audit"},{"action":"stop","resource":"purge-audit"},{"action":"list","resource":"jobservice-monitor"},{"action":"stop","resource":"jobservice-monitor"},{"action":"read","resource":"scanner"},{"action":"create","resource":"scanner"},{"action":"delete","resource":"scanner"},{"action":"list","resource":"scanner"},{"action":"update","resource":"scanner"},{"action":"read","resource":"label"},{"action":"create","resource":"label"},{"action":"delete","resource":"label"},{"action":"update","resource":"label"},{"action":"read","resource":"security-hub"},{"action":"list","resource":"security-hub"},{"action":"read","resource":"catalog"},{"action":"read","resource":"quota"},{"action":"list","resource":"quota"}]} ```
(Broken/Legacy project robots) https://acme.com/api/v2.0/robots?q=Level%253Dproject%252CProjectID%253D2&page_size=15&page=1 ```json [ { "creation_time": "2020-02-05T03:58:14.227Z", "description": "alex rpmbuild test account", "disable": false, "duration": 0, "editable": false, "expires_at": 1891915094, "id": 38, "level": "project", "name": "robot$alex", "permissions": [], "update_time": "2020-02-05T03:58:14.227Z" }, { "creation_time": "2020-03-02T01:09:47.321Z", "disable": false, "duration": 0, "editable": false, "expires_at": 1894151387, "id": 42, "level": "project", "name": "robot$cmTest", "permissions": [], "update_time": "2020-03-02T01:09:47.321Z" } ] ```
(Working project (example) robots) https://acme.com/api/v2.0/robots?q=Level%253Dproject%252CProjectID%253D11&page_size=15&page=1 ```json [ { "creation_time": "2024-07-11T13:47:44.261Z", "description": "del me", "disable": false, "duration": 7, "editable": true, "expires_at": 1721310464, "id": 916424, "level": "project", "name": "robot$bp-test-k8s-cache+cam-del-me", "permissions": [ { "access": [ { "action": "read", "resource": "label" }, { "action": "read", "resource": "artifact" } ], "kind": "project", "namespace": "bp-test-k8s-cache" } ], "update_time": "2024-07-11T13:47:44.261Z" } ] ```

Additional Info In a test project I have confirmed that by deleting all Legacy accounts using the API, the robot portion of the UI works once again. In another test project I also managed to tweak the database a little bit and update the robot accounts to have the very bare skeleton permissions, which also enabled the UI to work once again. However, I don't really want to be doing that to a production database.

Hoping for a solution I'm hoping you may have a fix?

🐇🥚 [For your](https://suno.com/song/d6760a3d-ddfd-4ada-90a1-60a3cf79fe6c) [hard work](https://suno.com/song/d6aa0c37-0533-4f7d-accb-f09c8f98654e)
stonezdj commented 1 month ago

Please login to the postgres SQL console and query these legacy robot account by create_time and delete them manually.

anguswilliams commented 1 month ago

Noting that I've also run into this issue, although luckily I wasn't using project specific robot accounts too heavily. The workaround described in the body fixed my issues, and I just re-created the bot accounts.

You can find bad robot accounts by querying for the projects robot accounts, and then deleting the bad accounts via the API. No need to go into the database. Any bot accounts with an empty permissions array need to be removed.

GET /api/v2.0/robots?page_size=100&page=1&q=Level%3Dproject%2CProjectID%3Dproject_ID DELETE /api/v2.0/robots/bad robot id

camAtGitHub commented 3 weeks ago

Thanks, I'm going to close this issue since the resolution is covered in the instructions.