Protected packages: Npm package push protection for admin user
requested to merge gitlab-community/gitlab:323970-protected-packages-npm-push-protection-follow-up-bugfix-user-role-admin into master
-
Please check this box if this contribution uses AI-generated content (including content generated by GitLab Duo features) as outlined in the GitLab DCO & CLA
What does this MR do and why?
Admin users should be able to publish npm packages regardless if the package is protected or not, see quote from GitLab permission guide GitLab administrators have all permissions
. Unfortunately, the current implementation does not bypass the package push protection for admin users, see collapsed section below. This MR wants to tackle and considers the admin mode and admin user when pushing an npm package.
Open console output
➜ git:(main) source .env && NPM_TOKEN=$PAT_ADMIN_USER_WITH_SCOPE_ADMIN_MODE npm publish
npm verb cli /Users/client-siemens/.asdf/installs/nodejs/20.12.2/bin/node /Users/client-siemens/.asdf/installs/nodejs/20.12.2/bin/npm
npm info using npm@10.5.0
npm info using node@v20.12.2
npm verb title npm publish
npm verb argv "publish"
npm verb logfile logs-max:10 dir:/Users/client-siemens/.npm/_logs/2024-06-16T08_46_27_779Z-
npm verb logfile /Users/client-siemens/.npm/_logs/2024-06-16T08_46_27_779Z-debug-0.log
npm verb publish [ '.' ]
npm notice
npm notice 📦 @npm-package-push-protection-bugfix-user-role-admin/npm-package-3@1.0.3
npm notice === Tarball Contents ===
npm notice 15B .tool-versions
npm notice 439B README.md
npm notice 261B package.json
npm notice === Tarball Details ===
npm notice name: @npm-package-push-protection-bugfix-user-role-admin/npm-package-3
npm notice version: 1.0.3
npm notice filename: npm-package-push-protection-bugfix-user-role-admin-npm-package-3-1.0.3.tgz
npm notice package size: 552 B
npm notice unpacked size: 715 B
npm notice shasum: b02e9ca6e65875f2ab908d111afafbfc53f1d21a
npm notice integrity: sha512-SihCVW5cpulq0[...]2G75AU4xWvbdQ==
npm notice total files: 3
npm notice
npm notice Publishing to http://gdk.test:3000/api/v4/projects/39/packages/npm/ with tag latest and default access
npm http fetch PUT 403 http://gdk.test:3000/api/v4/projects/39/packages/npm/@npm-package-push-protection-bugfix-user-role-admin%2fnpm-package-3 6413ms
npm verb stack HttpErrorGeneral: 403 Forbidden - PUT http://gdk.test:3000/api/v4/projects/39/packages/npm/@npm-package-push-protection-bugfix-user-role-admin%2fnpm-package-3 - Package protected.
npm verb stack at /Users/client-siemens/.asdf/installs/nodejs/20.12.2/lib/node_modules/npm/node_modules/npm-registry-fetch/lib/check-response.js:95:15
npm verb stack at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
npm verb stack at async publish (/Users/client-siemens/.asdf/installs/nodejs/20.12.2/lib/node_modules/npm/node_modules/libnpmpublish/lib/publish.js:53:15)
npm verb stack at async otplease (/Users/client-siemens/.asdf/installs/nodejs/20.12.2/lib/node_modules/npm/lib/utils/otplease.js:4:12)
npm verb stack at async Publish.exec (/Users/client-siemens/.asdf/installs/nodejs/20.12.2/lib/node_modules/npm/lib/commands/publish.js:126:7)
npm verb stack at async module.exports (/Users/client-siemens/.asdf/installs/nodejs/20.12.2/lib/node_modules/npm/lib/cli-entry.js:61:5)
npm verb statusCode 403
npm verb pkgid @npm-package-push-protection-bugfix-user-role-admin/npm-package-3@1.0.3
npm verb cwd /Users/client-siemens/Development/protected-packages-examples/npm_package-@npm-package-push-protection-bugfix-user-role-admin
npm verb Darwin 23.5.0
npm verb node v20.12.2
npm verb npm v10.5.0
npm ERR! code E403
npm ERR! 403 403 Forbidden - PUT http://gdk.test:3000/api/v4/projects/39/packages/npm/@npm-package-push-protection-bugfix-user-role-admin%2fnpm-package-3 - Package protected.
npm ERR! 403 In most cases, you or one of your dependencies are requesting
npm ERR! 403 a package version that is forbidden by your security policy, or
npm ERR! 403 on a server you do not have access to.
npm verb exit 1
npm verb code 1
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
MR Checklist (@gerardo-navarro)
-
Changelog entry added, if necessary -
Documentation created/updated via this MR -
Documentation reviewed by technical writer or follow-up review issue created -
Tests added for this feature/bug -
Tested in all supported browsers -
Conforms to the code review guidelines -
Conforms to the merge request performance guidelines -
Conforms to the style guides -
Conforms to the javascript style guides -
Conforms to the database guides
Screenshots or screen recordings
Before
An admin user is not able to publish a package that is protected.
Test performance `FPROF=1` before branch
=> FPROF=1 bundle exec rspec spec/services/packages/npm/create_package_service_spec.rb
[TEST PROF INFO] FactoryProf enabled (simple mode)
Run options: include {:focus=>true}
All examples were filtered out; ignoring {:focus=>true}
[TEST PROF INFO] No factories detected
[TEST PROF INFO] No factories detected
[TEST PROF INFO] No factories detected
[TEST PROF INFO] No factories detected
[TEST PROF INFO] No factories detected
[TEST PROF INFO] No factories detected
Test environment set up in 2.781266 seconds
...................................................................................................................................................................................................................
Finished in 42.4 seconds (files took 21.88 seconds to load)
211 examples, 0 failures
[TEST PROF INFO] Time spent in factories: 00:09.153 (19.19% of total time)
[TEST PROF INFO] Factories usage
Total: 156
Total top-level: 51
Total time: 00:09.153 (out of 00:56.799)
Total uniq factories: 10
total top-level total time time per call top-level time name
42 12 0.2786s 0.0066s 0.0676s organization
27 3 2.6944s 0.0998s 0.7630s namespace
27 3 6.1647s 0.2283s 0.8113s project
24 24 7.0818s 0.2951s 7.0818s ci_build
24 0 6.2791s 0.2616s 0.0000s ci_pipeline
3 3 0.3253s 0.1084s 0.3253s user
3 3 0.0811s 0.0270s 0.0811s npm_package
3 0 0.0394s 0.0131s 0.0000s package_file
2 2 0.0123s 0.0062s 0.0123s package_protection_rule
1 1 0.0108s 0.0108s 0.0108s license
After
An admin user is able to publish a package that is protected.
Test performance `FPROF=1` after branch
=> FPROF=1 bundle exec rspec spec/services/packages/npm/create_package_service_spec.rb
Test environment set up in 2.451375 seconds
.............................................................................................................................................................................................................................................................
Finished in 47.8 seconds (files took 19.09 seconds to load)
253 examples, 0 failures
[TEST PROF INFO] Time spent in factories: 00:10.072 (19.23% of total time)
[TEST PROF INFO] Factories usage
Total: 221
Total top-level: 61
Total time: 00:10.072 (out of 01:00.789)
Total uniq factories: 12
total top-level total time time per call top-level time name
52 15 0.3185s 0.0061s 0.0858s organization
33 3 2.7125s 0.0822s 0.6441s namespace
33 3 7.1272s 0.2160s 0.8141s project
30 30 8.0441s 0.2681s 8.0441s ci_build
30 0 7.1824s 0.2394s 0.0000s ci_pipeline
30 0 0.1171s 0.0039s 0.0000s ci_stage
3 3 0.3369s 0.1123s 0.3369s user
3 3 0.0770s 0.0257s 0.0770s npm_package
3 0 0.0392s 0.0131s 0.0000s package_file
2 2 0.0131s 0.0065s 0.0131s package_protection_rule
1 1 0.0462s 0.0462s 0.0462s admin
1 1 0.0116s 0.0116s 0.0116s license
How to set up and validate locally
- Enabled the feature flag :
Feature.enable(:packages_protected_packages)
- Create new project with a non-admin user
- Ensure that the existing admin user (e.g.
root
) is not a member of this newly created project - Create a package protection rule for packages in this project, see
Settings
=>Package and registries
=>Protected packages
- Try to publish a package with the admin user; in other words, use the personal access token (pat) of the admin user that includes the scope
:admin_mode
to publish the package; please ensure the field:package_name_pattern
defined in the package protection rule matches the package name that is publishedsource .env && NPM_TOKEN=$PAT_ADMIN_USER_WITH_SCOPE_ADMIN_MODE npm publish
- The package should have been published successfully because the user is an admin and even though the admin user is not a member of the project.
- When you use another personal access token of the admin user that does not include the scope
:admin_mode
, then pushing a package will fail because the admin user is not a project member💥 ; please ensure that you have enabled the admin mode for your instance, see https://docs.gitlab.com/ee/administration/settings/sign_in_restrictions.html#use-the-rails-console-to-enable-admin-modesource .env && NPM_TOKEN=$PAT_ADMIN_USER_WITHOUT_SCOPE_ADMIN_MODE npm publish
Related to #323970
Edited by Gerardo Navarro