mirror of
https://github.com/mcloh/Enterprise-MCP-Service-Bus.git
synced 2026-11-06 06:24:12 +00:00
M0 + M1 done
This commit is contained in:
20
RI/config/policies/entitlement.rego
Normal file
20
RI/config/policies/entitlement.rego
Normal file
@@ -0,0 +1,20 @@
|
||||
# Entitlement policy (EP-03-T02, README.md §25 Passo 1, §6.5.A).
|
||||
#
|
||||
# permit if requested_tool IN entitlement(authenticated_client)
|
||||
#
|
||||
# `input.client_profile` is the client profile *name* the Gateway already
|
||||
# resolved from the authenticated client_id (EP-01-T03 -> identity/models.py
|
||||
# ClientRegistration.profile) -- never a value read from the request body.
|
||||
# `data.emcp.client_profiles` is pushed into OPA by the Entitlement Manager
|
||||
# (EP-04-T02) from the validated ClientProfile YAML (EP-04-T01); this policy
|
||||
# never parses YAML itself.
|
||||
package emcp.entitlement
|
||||
|
||||
import rego.v1
|
||||
|
||||
default allow := false
|
||||
|
||||
allow if {
|
||||
profile := data.emcp.client_profiles[input.client_profile]
|
||||
input.tool in profile.allowed_tools
|
||||
}
|
||||
21
RI/config/policies/entitlement_test.rego
Normal file
21
RI/config/policies/entitlement_test.rego
Normal file
@@ -0,0 +1,21 @@
|
||||
package emcp.entitlement_test
|
||||
|
||||
import rego.v1
|
||||
import data.emcp.entitlement
|
||||
|
||||
test_allow_when_tool_in_entitlement if {
|
||||
entitlement.allow with input as {"client_profile": "Sales.Read", "tool": "sales.customer.get"}
|
||||
with data.emcp.client_profiles as {"Sales.Read": {"allowed_tools": ["sales.customer.get"]}}
|
||||
}
|
||||
|
||||
test_deny_when_tool_not_in_entitlement if {
|
||||
# README.md §45 Teste 1/2: finance.createPayment must never be reachable
|
||||
# by a Sales.Read client, discovered or not.
|
||||
not entitlement.allow with input as {"client_profile": "Sales.Read", "tool": "finance.createPayment"}
|
||||
with data.emcp.client_profiles as {"Sales.Read": {"allowed_tools": ["sales.customer.get"]}}
|
||||
}
|
||||
|
||||
test_deny_when_client_profile_unknown if {
|
||||
not entitlement.allow with input as {"client_profile": "NoSuchProfile", "tool": "sales.customer.get"}
|
||||
with data.emcp.client_profiles as {"Sales.Read": {"allowed_tools": ["sales.customer.get"]}}
|
||||
}
|
||||
68
RI/config/policies/transaction.rego
Normal file
68
RI/config/policies/transaction.rego
Normal file
@@ -0,0 +1,68 @@
|
||||
# Transaction policy (EP-03-T03, README.md §25 Passo 2, §6.5.B, §26).
|
||||
#
|
||||
# permit quote.create if
|
||||
# amount <= client.transaction_limit
|
||||
# AND region IN client.allowed_regions
|
||||
# AND customer.classification != "restricted"
|
||||
#
|
||||
# Restricts a tool *already granted* by entitlement.rego -- this policy never
|
||||
# adds a tool absent from the client's entitlement (README.md §25, "A
|
||||
# Transaction Policy pode negar ou restringir. Ela não pode adicionar uma
|
||||
# tool inexistente no Client Entitlement."). `allow` here is meaningless on
|
||||
# its own; the PDP client (EP-03-T04) only consults it after entitlement.rego
|
||||
# already allowed the same (client_profile, tool) pair.
|
||||
#
|
||||
# input: {
|
||||
# "client_profile": "Sales.Write",
|
||||
# "tool": "sales.quote.create",
|
||||
# "arguments": {"amount": 100000, "region": "BR-SP"},
|
||||
# "customer_classification": "standard"
|
||||
# }
|
||||
package emcp.transaction
|
||||
|
||||
import rego.v1
|
||||
|
||||
default allow := false
|
||||
|
||||
default require_approval := false
|
||||
|
||||
allow if {
|
||||
profile := data.emcp.client_profiles[input.client_profile]
|
||||
within_transaction_limit(profile)
|
||||
within_allowed_regions(profile)
|
||||
not restricted_customer
|
||||
}
|
||||
|
||||
# README.md §26: above the profile's approval_threshold, a transaction that
|
||||
# would otherwise be allowed instead requires human approval (EP-14) -- it is
|
||||
# never silently allowed, and never silently upgraded to a hard deny either.
|
||||
require_approval if {
|
||||
allow
|
||||
profile := data.emcp.client_profiles[input.client_profile]
|
||||
threshold := profile.restrictions.approval_threshold
|
||||
amount := object.get(input.arguments, "amount", 0)
|
||||
amount > threshold
|
||||
}
|
||||
|
||||
within_transaction_limit(profile) if {
|
||||
not profile.restrictions.max_transaction_value
|
||||
}
|
||||
|
||||
within_transaction_limit(profile) if {
|
||||
limit := profile.restrictions.max_transaction_value
|
||||
amount := object.get(input.arguments, "amount", 0)
|
||||
amount <= limit
|
||||
}
|
||||
|
||||
within_allowed_regions(profile) if {
|
||||
not profile.restrictions.allowed_regions
|
||||
}
|
||||
|
||||
within_allowed_regions(profile) if {
|
||||
region := object.get(input.arguments, "region", "")
|
||||
region in profile.restrictions.allowed_regions
|
||||
}
|
||||
|
||||
restricted_customer if {
|
||||
input.customer_classification == "restricted"
|
||||
}
|
||||
72
RI/config/policies/transaction_test.rego
Normal file
72
RI/config/policies/transaction_test.rego
Normal file
@@ -0,0 +1,72 @@
|
||||
package emcp.transaction_test
|
||||
|
||||
import rego.v1
|
||||
import data.emcp.transaction
|
||||
|
||||
sales_write_profile := {"restrictions": {
|
||||
"max_transaction_value": 500000,
|
||||
"allowed_regions": ["BR-SP", "BR-RJ"],
|
||||
"approval_threshold": 100000,
|
||||
}}
|
||||
|
||||
test_allow_within_limit_and_region if {
|
||||
transaction.allow with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 50000, "region": "BR-SP"},
|
||||
"customer_classification": "standard",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
}
|
||||
|
||||
test_deny_above_transaction_limit if {
|
||||
not transaction.allow with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 600000, "region": "BR-SP"},
|
||||
"customer_classification": "standard",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
}
|
||||
|
||||
test_deny_outside_allowed_region if {
|
||||
not transaction.allow with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 50000, "region": "BR-MG"},
|
||||
"customer_classification": "standard",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
}
|
||||
|
||||
test_deny_restricted_customer if {
|
||||
not transaction.allow with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 50000, "region": "BR-SP"},
|
||||
"customer_classification": "restricted",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
}
|
||||
|
||||
test_require_approval_above_threshold if {
|
||||
# README.md §26: allowed, but only with human approval, above threshold.
|
||||
transaction.allow with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 150000, "region": "BR-SP"},
|
||||
"customer_classification": "standard",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
|
||||
transaction.require_approval with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 150000, "region": "BR-SP"},
|
||||
"customer_classification": "standard",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
}
|
||||
|
||||
test_no_approval_required_below_threshold if {
|
||||
not transaction.require_approval with input as {
|
||||
"client_profile": "Sales.Write",
|
||||
"tool": "sales.quote.create",
|
||||
"arguments": {"amount": 50000, "region": "BR-SP"},
|
||||
"customer_classification": "standard",
|
||||
} with data.emcp.client_profiles as {"Sales.Write": sales_write_profile}
|
||||
}
|
||||
Reference in New Issue
Block a user