Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 61 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ as authentication provider for the private npm registry
[![build](https://travis-ci.org/bufferoverflow/verdaccio-gitlab.svg?branch=master)](https://travis-ci.org/bufferoverflow/verdaccio-gitlab)
[![dependencies](https://david-dm.org/bufferoverflow/verdaccio-gitlab/status.svg)](https://david-dm.org/bufferoverflow/verdaccio-gitlab)

The main goal and the difference from other sinopia/verdaccio plugins are
The main goal and differences from other sinopia/verdaccio plugins are
the following:

- no admin token required
- user authenticates with Personal Access Token
- owned groups (no subgroups) are added to the user
- publish packages if package scope or name is an owned group name
- access & publish packages depending on user rights in gitlab

> This is experimental!

## Gitlab Version Compatibility

- If `legacy_mode: false`: Gitlab 11.2+
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please write false or not defined here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's indicated below in the configuration options list that legacy_mode: false is the default, but I will make it also explicit here.

- If `legacy_mode: true`: Gitlab 9.0+

## Use it

You need at least node version 8.x.x, codename **carbon**.
Expand All @@ -44,9 +48,6 @@ listen:
auth:
gitlab:
url: https://gitlab.com
authCache:
enabled: true
ttl: 300

uplinks:
npmjs:
Expand Down Expand Up @@ -92,29 +93,72 @@ yarn publish --registry http://localhost:4873
a GitLab group (as owner) which has the same name as your package name. You
also need a fresh login, so that Verdaccio recognizes your owned groups.

## Access Levels

Access and publish access rights depend on the mode used.

In the default mode, packages are available:

- *access* is allowed depending on verdaccio `package` configuration
directives (unauthenticated / authenticated)
- *publish* is allowed if the package name matches the logged in user
id, or if the package name / scope of the package matches one of the
user groups and the user has `$auth.gitlab.publish` access rights on
the group

For instance, assuming the following configuration:

- `auth.gitlab.publish` = `$maintainer`
- the gitlab user `sample_user` had access to group `group1` as
`$maintainer` and `group2` as `$reporter`
- then this user could publish any of the npm packages:
- `sample_user`
- any package under `group1/**`
- error if the user tries to publish any package under `group2/**`

If using the legacy mode, the system behaves as in normal mode with
fixed `$auth.gitlab.publish` = `$owner`

## Configuration Options

The full set of configuration options is:

```yaml
auth:
gitlab:
url: <url>
authCache:
enabled: <boolean>
ttl: <integer>
legacy_mode: <boolean>
publish: <string>
```

<!-- markdownlint-disable MD013 -->
| Option | Default | Type | Description |
| ------ | ------- | ---- | ----------- |
| `url` | `<empty>` | url | mandatory, the url of the gitlab server |
| `authCache: enabled` | `true` | boolean | activate in-memory authentication cache |
| `authCache: ttl` | `300` (`0`=unlimited) | integer | time-to-live of entries in the authentication cache, in seconds |
| `legacy_mode` | `false` | boolean | gitlab versions pre-11.2 do not support groups api queries based on access level; this enables the legacy behaviour of only allowing npm publish operations on groups where the logged in user has owner rights |
| `publish` | `$maintainer` | [`$guest`, `$reporter`, `$developer`, `$maintainer`, `$owner`] | group minimum access level of the logged in user required for npm publish operations (does not apply in legacy mode) |
<!-- markdownlint-enable MD013 -->

## Authentication Cache

In order to avoid too many authentication requests to the underlying
gitlab instance, the plugin provides an in-memory cache that will save
the detected groups of the users for a configurable ttl in seconds.
No clear-text password will be saved in-memory, just an SHA-256 hash
and the groups information.

No clear-text password will is saved in-memory, just an SHA-256 hash of
the user+password, plus the groups information.

By default, the cache will be enabled and the credentials will be stored
for 300 seconds. The ttl is checked on access, but there's also an
internal timer that will check expired values regularly, so data of
users not actively interacting with the system will also be eventually
invalidated.

```yaml
auth:
gitlab:
url: https://gitlab.com
authCache:
enabled: (default true)
ttl: (default: 300)
```

*Please note* that this implementation is in-memory and not
multi-process; if the cluster module is used for starting several
verdaccio processes, each process will store its own copy of the cache,
Expand Down
3 changes: 2 additions & 1 deletion conf/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ auth:
authCache:
enabled: true
ttl: 300
publish: $maintainer

uplinks:
npmjs:
Expand All @@ -31,5 +32,5 @@ packages:
gitlab: true

logs:
- {type: stdout, format: pretty, level: info }
- { type: stdout, format: pretty, level: info }
#- {type: file, path: verdaccio.log, level: info}
36 changes: 36 additions & 0 deletions conf/localhost.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
storage: /tmp/storage/data
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is nearly the same as conf/docker.yml , why do we need this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops, that's for my local testing, shouldn't be there


plugins: /tmp/plugins

listen:
- 0.0.0.0:4873

auth:
gitlab:
url: http://localhost:50080
authCache:
enabled: true
ttl: 300
publish: $maintainer

uplinks:
npmjs:
url: https://registry.npmjs.org/

packages:
'@*/*':
# scoped packages
access: $all
publish: $authenticated
proxy: npmjs
gitlab: true

'**':
access: $all
publish: $authenticated
proxy: npmjs
gitlab: true

logs:
- { type: stdout, format: pretty, level: trace }
#- {type: file, path: verdaccio.log, level: info}
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: '3'

services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
image: 'gitlab/gitlab-ce:nightly'
restart: always
environment:
- GITLAB_ROOT_PASSWORD=verdaccio
Expand Down
14 changes: 9 additions & 5 deletions src/authcache.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class AuthCache {
});
this.storage.on('expired', (key, value) => {
if (this.logger.trace()) {
this.logger.trace(`[gitlab] expired key: ${key} with value: ${value}`);
this.logger.trace(`[gitlab] expired key: ${key} with value:`, value);
}
});
}
Expand All @@ -45,15 +45,19 @@ export class AuthCache {

}

export type UserDataGroups = {
publish: string[]
};

export class UserData {
_username: string;
_groups: string[];
_groups: UserDataGroups;

get username(): string { return this._username; }
get groups(): string[] { return this._groups; }
set groups(groups: string[]) { this._groups = groups; }
get groups(): UserDataGroups { return this._groups; }
set groups(groups: UserDataGroups) { this._groups = groups; }

constructor(username: string, groups: string[]) {
constructor(username: string, groups: UserDataGroups) {
this._username = username;
this._groups = groups;
}
Expand Down
Loading