@cerbos/embedded
Version:
Client library for interacting with embedded Cerbos policy decision points generated by Cerbos Hub from server-side Node.js and browser-based applications
119 lines • 4.35 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DecisionLogger = void 0;
const ulid_1 = require("ulid");
const core_1 = require("@cerbos/core");
class DecisionLogger {
log;
userAgent;
ulid;
constructor(log, userAgent) {
this.log = log;
this.userAgent = userAgent;
this.ulid = (0, ulid_1.monotonicFactory)();
}
async logCheckResources(request, auxData, headers, response, bundleMetadata, error) {
const callId = this.ulid();
const inputs = request.resources.map(({ resource, actions }) => ({
...(0, core_1._checkInputFromProtobuf)({
$typeName: "cerbos.engine.v1.CheckInput",
requestId: request.requestId,
principal: request.principal,
resource,
actions,
}),
auxData,
}));
const outputs = [];
const effectivePolicies = {};
if (response) {
response.cerbosCallId = callId;
for (const result of response.results) {
(0, core_1._requireField)("CheckResourcesResponse.ResultEntry.resource", result.resource);
(0, core_1._requireField)("CheckResourcesResponse.ResultEntry.meta", result.meta);
const actions = {};
for (const [action, effect] of Object.entries(result.actions)) {
const meta = result.meta.actions[action];
actions[action] = {
$typeName: "cerbos.engine.v1.CheckOutput.ActionEffect",
effect,
policy: meta?.matchedPolicy ?? "",
scope: meta?.matchedScope ?? "",
};
if (meta?.matchedPolicy && !effectivePolicies[meta.matchedPolicy]) {
for (const ancestor of ancestors(meta.matchedPolicy)) {
effectivePolicies[ancestor] ??= {
commit_hash: bundleMetadata.commit,
...bundleMetadata.sourceAttributes[`cerbos.${ancestor}`],
};
}
}
}
outputs.push((0, core_1._checkOutputFromProtobuf)({
$typeName: "cerbos.engine.v1.CheckOutput",
requestId: response.requestId,
resourceId: result.resource.id,
actions,
outputs: result.outputs,
effectiveDerivedRoles: result.meta.effectiveDerivedRoles,
validationErrors: result.validationErrors,
}));
}
}
await this.log({
callId,
method: {
name: "CheckResources",
inputs,
outputs,
error: errorMessage(error),
},
timestamp: new Date(),
metadata: metadata(headers),
oversized: false,
auditTrail: {
effectivePolicies,
},
peer: {
address: "",
authInfo: "",
forwardedFor: "",
userAgent: this.userAgent,
},
policySource: {
kind: "embeddedPDP",
url: bundleMetadata.url ?? "",
commit: bundleMetadata.commit,
builtAt: bundleMetadata.builtAt,
},
});
}
}
exports.DecisionLogger = DecisionLogger;
function errorMessage(error) {
if (error === undefined) {
return undefined;
}
if (error instanceof Error) {
return error.message;
}
return "Unknown error";
}
function metadata(headers) {
const metadata = {};
for (const [name, value] of headers) {
(metadata[name] ??= []).push(value);
}
return metadata;
}
const scopedPolicyIdPattern = /\.v[^/]+(?<separator>\/)[^/]+$/d;
function* ancestors(policyId) {
const match = scopedPolicyIdPattern.exec(policyId);
if (match) {
for (let end = match.indices.groups.separator[0]; end > 0; end = policyId.indexOf(".", end + 1)) {
yield policyId.substring(0, end);
}
}
yield policyId;
}
//# sourceMappingURL=logger.js.map