@infosys_ltd/backstage-plugin-permission-backend-module-catalog-policy
Version:
The catalog-policy backend module for the permission plugin.
158 lines (151 loc) • 5.23 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var errors = require('@backstage/errors');
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
var backendPluginApi = require('@backstage/backend-plugin-api');
var alpha = require('@backstage/plugin-permission-node/alpha');
class openFgaPolicyEvaluator {
static fromConfig(configApi, discoveryApi) {
const baseUrl = configApi.getOptionalString("openfga.baseUrl") ?? "";
const storeId = configApi.getOptionalString("openfga.storeId") ?? "";
const authorizationModelId = configApi.getOptionalString("openfga.authorizationModelId") ?? "";
if (!storeId || !authorizationModelId) {
console.error("Missing configuration values for OpenFGA. Please check your app-config.yaml.");
}
return new openFgaPolicyEvaluator({
discoveryApi,
baseUrl,
storeId,
authorizationModelId
});
}
constructor(opts) {
this.discoveryApi = opts.discoveryApi;
this.baseUrl = opts.baseUrl;
this.storeId = opts.storeId;
this.authorizationModelId = opts.authorizationModelId;
this.permissionResponse = null;
}
getPermissionResponse() {
return this.permissionResponse;
}
async fetch(input, init) {
const apiUrl = `${this.baseUrl}${input}`;
const response = await fetch(apiUrl, init);
if (!response.ok) {
throw await errors.ResponseError.fromResponse(response);
}
return await response.json();
}
async sendPermissionRequest(entityName, action, userName) {
const url = `/stores/${this.storeId}/check`;
const relation = typeof action === "string" && action.toLowerCase() === "delete" ? "catalog_entity_delete" : "catalog_entity_read";
const requestBody = {
tuple_key: {
user: `${userName}`,
relation,
object: `catalog_entity:${entityName}`
},
authorization_model_id: this.authorizationModelId
};
const response = await this.fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody)
});
this.permissionResponse = response;
return response;
}
async addPolicy(entityName, accessType, userName) {
const url = `/stores/${this.storeId}/write`;
const requestBody = {
writes: {
tuple_keys: [
{
user: `${userName}`,
relation: accessType,
object: `catalog_entity:${entityName}`
}
]
},
authorization_model_id: this.authorizationModelId
};
const response = await this.fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody)
});
return response;
}
async revokePolicy(entityName, accessType, userName) {
const url = `/stores/${this.storeId}/write`;
const requestBody = {
deletes: {
tuple_keys: [
{
user: `${userName}`,
relation: accessType,
object: `catalog_entity:${entityName}`
}
]
},
authorization_model_id: this.authorizationModelId
};
const response = await this.fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody)
});
return response;
}
}
class OpenFgaCatalogPolicy {
constructor(configApi, discoveryApi) {
this.openFgaClient = openFgaPolicyEvaluator.fromConfig(
configApi,
discoveryApi
);
}
async handle(request, user) {
const identityUser = user;
if (pluginPermissionCommon.isResourcePermission(request.permission, "catalog-entity")) {
if (request.permission.name === "catalog.entity.delete") {
const entityName = "example-website";
const userName = identityUser?.identity.ownershipEntityRefs;
try {
const response = await this.openFgaClient.sendPermissionRequest(
entityName,
"Delete",
userName
);
return response.allowed ? { result: pluginPermissionCommon.AuthorizeResult.ALLOW } : { result: pluginPermissionCommon.AuthorizeResult.DENY };
} catch (error) {
console.error("Error checking permission:", error);
return { result: pluginPermissionCommon.AuthorizeResult.DENY };
}
}
return { result: pluginPermissionCommon.AuthorizeResult.ALLOW };
}
return { result: pluginPermissionCommon.AuthorizeResult.DENY };
}
}
const permissionModuleCatalogPolicy = backendPluginApi.createBackendModule({
pluginId: "permission",
moduleId: "catalog-policy",
register(reg) {
reg.registerInit({
deps: {
config: backendPluginApi.coreServices.rootConfig,
policy: alpha.policyExtensionPoint,
discovery: backendPluginApi.coreServices.discovery
},
async init({ config, policy, discovery }) {
policy.setPolicy(new OpenFgaCatalogPolicy(config, discovery));
}
});
}
});
exports.OpenFgaCatalogPolicy = OpenFgaCatalogPolicy;
exports.default = permissionModuleCatalogPolicy;
exports.openFgaPolicyEvaluator = openFgaPolicyEvaluator;
//# sourceMappingURL=index.cjs.js.map