diff --git a/lib/config.d.ts b/lib/config.d.ts index dd7472e..0d4d9d1 100644 --- a/lib/config.d.ts +++ b/lib/config.d.ts @@ -2,4 +2,5 @@ import { Config } from '@verdaccio/legacy-types'; export interface FleetbaseRegistryAuthConfig extends Config { fleetbaseHost: string; fleetbaseApiKey: string; + protectedPrefixes: string; } diff --git a/lib/index.d.ts b/lib/index.d.ts index dc4d47f..f7ec067 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -5,7 +5,10 @@ export default class FleetbaseAuthPlugin implements IPluginAuth { private config; private fleetbaseClient; private logger; + private protectedPrefixes; + private defaultProtectedPrefixes; constructor(config: Config, options: any); + isNotProtectedPackage(packageName: string): boolean; authenticate(identity: string, password: string, callback: Callback): Promise; adduser(identity: string, password: string, callback: Callback): Promise; allow_access(user: RemoteUser, pkg: (Config & PackageAccess) | (AllowAccess & PackageAccess), callback: AuthAccessCallback): Promise; diff --git a/lib/index.js b/lib/index.js index 20a7cb0..24fe497 100644 --- a/lib/index.js +++ b/lib/index.js @@ -10,16 +10,22 @@ class FleetbaseAuthPlugin { config; fleetbaseClient; logger; + protectedPrefixes; + defaultProtectedPrefixes = '@fleetbase,fleetbase,@flb,@fleetbase-extension,@flb-extension'; constructor(config, options) { this.config = Object.assign(config, config.auth['@fleetbase/verdaccio-fleetbase-auth']); this.logger = options.logger; - this.logger.debug({ - config: JSON.stringify({ - fleetbaseHost: (0, getConfigValue_1.default)('FLEETBASE_HOST', this.config), - fleetbaseApiKey: (0, getConfigValue_1.default)('FLEETBASE_API_KEY', this.config), - }, null, 4), - }, 'FLEETBASE CLIENT ENV/CONFIG VARS: @{config}'); this.fleetbaseClient = (0, fleetbaseClient_1.createFleetbaseClient)(this.config); + this.protectedPrefixes = (0, getConfigValue_1.default)('PROTECTED_PREFIXES', this.config) ?? '@fleetbase,fleetbase,@flb,@fleetbase-extension,@flb-extension'; + } + isNotProtectedPackage(packageName) { + const prefixes = this.protectedPrefixes.split(','); + for (const prefix of prefixes) { + if (packageName.startsWith(prefix)) { + return false; + } + } + return true; } async authenticate(identity, password, callback) { this.logger.debug({ identity }, 'Auth::authenticate() - Authenticating user with identity: @{identity}'); @@ -27,8 +33,8 @@ class FleetbaseAuthPlugin { const response = await this.fleetbaseClient.post('auth/authenticate', { identity, password }); this.logger.debug({ response: response.data }, 'Auth::authenticate() - Response from Fleetbase: @{response}'); const { groups } = response.data; - this.logger.debug({ groups: JSON.stringify(groups) }, 'Auth::authenticate() -Groups: @{groups}'); - callback(null, groups ?? []); + this.logger.debug({ groups: JSON.stringify(groups) }, 'Auth::authenticate() - Groups: @{groups}'); + callback(null, groups); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Authentication failed for creating developer account'; @@ -55,8 +61,16 @@ class FleetbaseAuthPlugin { // Allow access should check with Fleetbase API and see that registry user has access to the extension this.logger.debug({ user }, 'Auth::allow_access() - User: @{user}'); this.logger.debug({ pkg }, 'Auth::allow_access() - Package: @{pkg}'); + // If not a protected package just allow access without server check + if (this.isNotProtectedPackage(pkg.name)) { + this.logger.debug({ packageName: pkg.name }, 'Auth::allow_access() - (No Check) Access Allowed: @{packageName}'); + callback(null, true); + return; + } + // Check with server if access is allowed try { - const response = await this.fleetbaseClient.post('auth/check-access', { identity: user.name }); + this.logger.debug({ packageName: pkg.name, identity: user.name, groups: user.groups }, 'Auth::allow_access() Request Params: { identity: @{identity}, package: @{packageName}, groups: @{groups} }'); + const response = await this.fleetbaseClient.post('auth/check-access', { identity: user.name, package: pkg.name, groups: user.groups }); this.logger.debug({ response: response.data }, 'Auth::allow_access() - Response from Fleetbase: @{response}'); const { allowed } = response.data; this.logger.debug({ allowed }, 'Auth::allow_access() - Allowed: @{allowed}'); @@ -75,7 +89,7 @@ class FleetbaseAuthPlugin { this.logger.debug({ user }, 'Auth::allow_publish() - User: @{user}'); this.logger.debug({ pkg }, 'Auth::allow_publish() - Package: @{pkg}'); try { - const response = await this.fleetbaseClient.post('auth/check-publish', { identity: user.name, package: pkg.name }); + const response = await this.fleetbaseClient.post('auth/check-publish', { identity: user.name, package: pkg.name, groups: user.groups }); this.logger.debug({ response: response.data }, 'Auth::allow_publish() - Response from Fleetbase: @{response}'); const { allowed } = response.data; this.logger.debug({ allowed }, 'Auth::allow_publish() - Allowed: @{allowed}'); diff --git a/package-lock.json b/package-lock.json index 4d7ee65..0826615 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@fleetbase/verdaccio-fleetbase-auth", - "version": "0.0.2", + "version": "0.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@fleetbase/verdaccio-fleetbase-auth", - "version": "0.0.2", + "version": "0.0.3", "license": "AGPL-3.0-or-later", "dependencies": { "@verdaccio/commons-api": "10.2.0", diff --git a/package.json b/package.json index 20a39c6..e66b201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/verdaccio-fleetbase-auth", - "version": "0.0.2", + "version": "0.0.3", "description": "Authentication to verdaccio for Fleetbase extension developers.", "keywords": [ "verdaccio", diff --git a/src/config.ts b/src/config.ts index fb35209..022b6d9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,7 @@ import { Config } from '@verdaccio/legacy-types'; export interface FleetbaseRegistryAuthConfig extends Config { - fleetbaseHost: string; - fleetbaseApiKey: string; + fleetbaseHost: string; + fleetbaseApiKey: string; + protectedPrefixes: string; } diff --git a/src/index.ts b/src/index.ts index 8a3d137..6dc9833 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,24 +10,24 @@ export default class FleetbaseAuthPlugin implements IPluginAuth { private config: FleetbaseRegistryAuthConfig; private fleetbaseClient: IFleetbaseClient; private logger: Logger; + private protectedPrefixes: string; + private defaultProtectedPrefixes: string = '@fleetbase,fleetbase,@flb,@fleetbase-extension,@flb-extension'; public constructor(config: Config, options: any) { this.config = Object.assign(config, config.auth['@fleetbase/verdaccio-fleetbase-auth']); this.logger = options.logger; - this.logger.debug( - { - config: JSON.stringify( - { - fleetbaseHost: getConfigValue('FLEETBASE_HOST', this.config), - fleetbaseApiKey: getConfigValue('FLEETBASE_API_KEY', this.config), - }, - null, - 4 - ), - }, - 'FLEETBASE CLIENT ENV/CONFIG VARS: @{config}' - ); this.fleetbaseClient = createFleetbaseClient(this.config); + this.protectedPrefixes = getConfigValue('PROTECTED_PREFIXES', this.config) ?? '@fleetbase,fleetbase,@flb,@fleetbase-extension,@flb-extension'; + } + + public isNotProtectedPackage(packageName: string): boolean { + const prefixes = this.protectedPrefixes.split(','); + for (const prefix of prefixes) { + if (packageName.startsWith(prefix)) { + return false; + } + } + return true; } public async authenticate(identity: string, password: string, callback: Callback): Promise { @@ -37,9 +37,9 @@ export default class FleetbaseAuthPlugin implements IPluginAuth { const response = await this.fleetbaseClient.post('auth/authenticate', { identity, password }); this.logger.debug({ response: response.data }, 'Auth::authenticate() - Response from Fleetbase: @{response}'); const { groups } = response.data; - this.logger.debug({ groups: JSON.stringify(groups) }, 'Auth::authenticate() -Groups: @{groups}'); + this.logger.debug({ groups: JSON.stringify(groups) }, 'Auth::authenticate() - Groups: @{groups}'); - callback(null, groups ?? []); + callback(null, groups); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Authentication failed for creating developer account'; const conflict = getConflict(errorMessage); @@ -67,8 +67,21 @@ export default class FleetbaseAuthPlugin implements IPluginAuth { // Allow access should check with Fleetbase API and see that registry user has access to the extension this.logger.debug({ user }, 'Auth::allow_access() - User: @{user}'); this.logger.debug({ pkg }, 'Auth::allow_access() - Package: @{pkg}'); + + // If not a protected package just allow access without server check + if (this.isNotProtectedPackage(pkg.name)) { + this.logger.debug({ packageName: pkg.name }, 'Auth::allow_access() - (No Check) Access Allowed: @{packageName}'); + callback(null, true); + return; + } + + // Check with server if access is allowed try { - const response = await this.fleetbaseClient.post('auth/check-access', { identity: user.name }); + this.logger.debug( + { packageName: pkg.name, identity: user.name, groups: user.groups }, + 'Auth::allow_access() Request Params: { identity: @{identity}, package: @{packageName}, groups: @{groups} }' + ); + const response = await this.fleetbaseClient.post('auth/check-access', { identity: user.name, package: pkg.name, groups: user.groups }); this.logger.debug({ response: response.data }, 'Auth::allow_access() - Response from Fleetbase: @{response}'); const { allowed } = response.data; this.logger.debug({ allowed }, 'Auth::allow_access() - Allowed: @{allowed}'); @@ -88,7 +101,7 @@ export default class FleetbaseAuthPlugin implements IPluginAuth { this.logger.debug({ user }, 'Auth::allow_publish() - User: @{user}'); this.logger.debug({ pkg }, 'Auth::allow_publish() - Package: @{pkg}'); try { - const response = await this.fleetbaseClient.post('auth/check-publish', { identity: user.name, package: pkg.name }); + const response = await this.fleetbaseClient.post('auth/check-publish', { identity: user.name, package: pkg.name, groups: user.groups }); this.logger.debug({ response: response.data }, 'Auth::allow_publish() - Response from Fleetbase: @{response}'); const { allowed } = response.data; this.logger.debug({ allowed }, 'Auth::allow_publish() - Allowed: @{allowed}');