@backstage/plugin-permission-node
Version:
Common permission and authorization utilities for backend plugins
89 lines (85 loc) • 3.22 kB
JavaScript
'use strict';
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
class ServerPermissionClient {
#auth;
#permissionClient;
#permissionEnabled;
static fromConfig(config, options) {
const { auth, discovery } = options;
const permissionClient = new pluginPermissionCommon.PermissionClient({ discovery, config });
const permissionEnabled = config.getOptionalBoolean("permission.enabled") ?? false;
return new ServerPermissionClient({
auth,
permissionClient,
permissionEnabled
});
}
constructor(options) {
this.#auth = options.auth;
this.#permissionClient = options.permissionClient;
this.#permissionEnabled = options.permissionEnabled;
}
async authorizeConditional(queries, options) {
const credentials = await this.#getIncomingCredentials(options);
if (credentials && this.#auth.isPrincipal(credentials, "service")) {
return this.#servicePrincipalDecision(queries, credentials);
} else if (!this.#permissionEnabled) {
return queries.map((_) => ({ result: pluginPermissionCommon.AuthorizeResult.ALLOW }));
}
return this.#permissionClient.authorizeConditional(
queries,
await this.#getRequestOptions(options)
);
}
async authorize(requests, options) {
const credentials = await this.#getIncomingCredentials(options);
if (credentials && this.#auth.isPrincipal(credentials, "service")) {
return this.#servicePrincipalDecision(requests, credentials);
} else if (!this.#permissionEnabled) {
return requests.map((_) => ({ result: pluginPermissionCommon.AuthorizeResult.ALLOW }));
}
return this.#permissionClient.authorize(
requests,
await this.#getRequestOptions(options)
);
}
async #getRequestOptions(options) {
if (options && "credentials" in options) {
if (this.#auth.isPrincipal(options.credentials, "none")) {
return {};
}
return this.#auth.getPluginRequestToken({
onBehalfOf: options.credentials,
targetPluginId: "permission"
});
}
return options;
}
async #getIncomingCredentials(options) {
if (options && "credentials" in options) {
return options.credentials;
}
return void 0;
}
/**
* For service principals, we can always make an immediate definitive decision
* based on their associated access restrictions (if any).
*/
#servicePrincipalDecision(input, credentials) {
const { permissionNames, permissionAttributes } = credentials.principal.accessRestrictions ?? {};
return input.map((item) => {
if (permissionNames && !permissionNames.includes(item.permission.name)) {
return { result: pluginPermissionCommon.AuthorizeResult.DENY };
}
if (permissionAttributes?.action) {
const action = item.permission.attributes?.action;
if (!action || !permissionAttributes.action.includes(action)) {
return { result: pluginPermissionCommon.AuthorizeResult.DENY };
}
}
return { result: pluginPermissionCommon.AuthorizeResult.ALLOW };
});
}
}
exports.ServerPermissionClient = ServerPermissionClient;
//# sourceMappingURL=ServerPermissionClient.cjs.js.map