Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rego template endpoint #96

Merged
merged 33 commits into from
Feb 12, 2024
Merged

Rego template endpoint #96

merged 33 commits into from
Feb 12, 2024

Conversation

samteb
Copy link
Contributor

@samteb samteb commented Feb 6, 2024

No description provided.

@@ -84,4 +87,10 @@ export class AdminService {

return payload.request.data
}

async setPolicyRules(payload: SetPolicyRulesRequest): Promise<PolicyCriterionBuilder[]> {
await this.opaService.generateRegoFile(payload.request.data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you plan to save these policies in the database as well, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes but not on the engine part. see this discussion:
https://narvalxyz.slack.com/archives/C067Q1TDA9G/p1707310563319479

Comment on lines 37 to 94
generateRegoFile(policies: PolicyCriterionBuilder[]): void {
Handlebars.registerHelper('criterion', function (item) {
const criterion: Criterion = item.criterion
const args = item.args

if (args === null) {
return `${criterion}`
}

if (!isEmpty(args)) {
if (Array.isArray(args)) {
if (typeof args[0] === 'string') {
return `${criterion}({${args.map((el) => `"${el}"`).join(', ')}})`
}

if (criterion === Criterion.CHECK_APPROVALS) {
return `approvals = ${criterion}([${args.map((el) => JSON.stringify(el)).join(', ')}])`
}

return `${criterion}([${args.map((el) => JSON.stringify(el)).join(', ')}])`
}

return `${criterion}(${JSON.stringify(args)})`
}
})

Handlebars.registerHelper('reason', function (item) {
if (item.then === Then.PERMIT) {
const reason = [
`"type": "${item.then}"`,
`"policyId": "${item.name}"`,
'"approvalsSatisfied": approvals.approvalsSatisfied',
'"approvalsMissing": approvals.approvalsMissing'
]
return `reason = {${reason.join(', ')}}`
}

if (item.then === Then.FORBID) {
const reason = {
type: item.then,
policyId: item.name,
approvalsSatisfied: [],
approvalsMissing: []
}
return `reason = ${JSON.stringify(reason)}`
}
})

const templateSource = readFileSync('./apps/authz/src/opa/template/template.hbs', 'utf-8')

const template = Handlebars.compile(templateSource)

const regoContent = template({ policies })

writeFileSync(`./apps/authz/src/opa/rego/generated/${uuidv4()}.rego`, regoContent, 'utf-8')

console.log('Policy .rego file generated successfully.')
}
Copy link
Collaborator

@wcalderipe wcalderipe Feb 7, 2024

Choose a reason for hiding this comment

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

Here's a suggestion on how to unit test this logic:

  • Separate side effects from policy generation logic. If you move the template file reading and Rego file writing elsewhere, the logic essentially becomes: given a policy schema and a template string, you produce a policy string on the other side (the Rego logic).
  • Unit test each criterion defined in policy-build.type.ts. For a given template and criterion A, specify what you expect as a policy. Do this without merging criteria into a single policy. This approach will provide comprehensive documentation of what you expect for smaller system components.
  • Unit test a few criteria together to generate a policy and check if the outcome matches your expectations. This will provide us confidence on criteria composition.

Copy link
Collaborator

Choose a reason for hiding this comment

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

These types of logic to map from standard A to B are often a major source of bugs. Let's get that covered so we can move faster without breaking things 😉

apps/authz/src/app/opa/opa.service.ts Outdated Show resolved Hide resolved
apps/authz/src/app/opa/opa.service.ts Show resolved Hide resolved
packages/authz-shared/src/lib/type/policy-builder.type.ts Outdated Show resolved Hide resolved
apps/authz/src/app/__test__/e2e/admin.spec.ts Outdated Show resolved Hide resolved
apps/authz/src/app/__test__/e2e/admin.spec.ts Outdated Show resolved Hide resolved
packages/authz-shared/src/index.ts Outdated Show resolved Hide resolved
packages/authz-shared/src/lib/type/policy-builder.type.ts Outdated Show resolved Hide resolved
packages/authz-shared/src/lib/util/caip.util.ts Outdated Show resolved Hide resolved
@samteb samteb merged commit 45008d0 into main Feb 12, 2024
3 checks passed
@samteb samteb deleted the rego-template-endpoint branch February 12, 2024 07:34
mattschoch pushed a commit that referenced this pull request Jun 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants