generated from coulomb/repo-seed
Add Markitect check fixtures
This commit is contained in:
239
examples/markitect/check_fixtures.yaml
Normal file
239
examples/markitect/check_fixtures.yaml
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
- id: fixture:markitect-public-document-allow
|
||||||
|
request:
|
||||||
|
id: check:markitect-public-document
|
||||||
|
subject:
|
||||||
|
id: user:visitor
|
||||||
|
type: Human
|
||||||
|
tenant: tenant:alpha
|
||||||
|
action: read
|
||||||
|
resource:
|
||||||
|
id: document:public-note
|
||||||
|
type: document
|
||||||
|
system: markitect-tool
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
labels:
|
||||||
|
- public
|
||||||
|
trust_zone: public
|
||||||
|
caring_context:
|
||||||
|
id: descriptor:public-document-reader
|
||||||
|
profile: caring-0.4.0-rc2
|
||||||
|
subject_type: Human
|
||||||
|
organization_relation: Customer
|
||||||
|
canonical_role: Doer
|
||||||
|
scope:
|
||||||
|
level: Resource
|
||||||
|
id: document:public-note
|
||||||
|
tenant: tenant:alpha
|
||||||
|
planes:
|
||||||
|
- Data
|
||||||
|
capabilities:
|
||||||
|
- View
|
||||||
|
exposure_modes:
|
||||||
|
- Plaintext
|
||||||
|
conditions:
|
||||||
|
- Logged
|
||||||
|
expect:
|
||||||
|
effect: allow
|
||||||
|
reason: public_document
|
||||||
|
metadata:
|
||||||
|
expected_caring_descriptor: descriptor:public-document-reader
|
||||||
|
expected_conformance_findings: []
|
||||||
|
expected_exposure_modes:
|
||||||
|
- Plaintext
|
||||||
|
expected_audit_behavior: sampled_allow
|
||||||
|
- id: fixture:markitect-internal-document-deny
|
||||||
|
request:
|
||||||
|
id: check:markitect-internal-document-deny
|
||||||
|
subject:
|
||||||
|
id: user:visitor
|
||||||
|
type: Human
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
groups: []
|
||||||
|
action: read
|
||||||
|
resource:
|
||||||
|
id: document:internal-note
|
||||||
|
type: document
|
||||||
|
system: markitect-tool
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
labels:
|
||||||
|
- internal
|
||||||
|
trust_zone: internal
|
||||||
|
expect:
|
||||||
|
effect: deny
|
||||||
|
reason: no_matching_rule
|
||||||
|
metadata:
|
||||||
|
expected_caring_descriptor: null
|
||||||
|
expected_conformance_findings: []
|
||||||
|
expected_exposure_modes:
|
||||||
|
- None
|
||||||
|
expected_audit_behavior: always_record
|
||||||
|
- id: fixture:markitect-internal-document-reader-allow
|
||||||
|
request:
|
||||||
|
id: check:markitect-internal-document-reader
|
||||||
|
subject:
|
||||||
|
id: user:alice
|
||||||
|
type: Human
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
groups:
|
||||||
|
- group:platform-architecture
|
||||||
|
action: read
|
||||||
|
resource:
|
||||||
|
id: document:internal-note
|
||||||
|
type: document
|
||||||
|
system: markitect-tool
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
labels:
|
||||||
|
- internal
|
||||||
|
trust_zone: internal
|
||||||
|
caring_context:
|
||||||
|
id: descriptor:internal-document-reader
|
||||||
|
profile: caring-0.4.0-rc2
|
||||||
|
subject_type: Human
|
||||||
|
organization_relation: Customer
|
||||||
|
canonical_role: Doer
|
||||||
|
scope:
|
||||||
|
level: Resource
|
||||||
|
id: document:internal-note
|
||||||
|
tenant: tenant:alpha
|
||||||
|
planes:
|
||||||
|
- Data
|
||||||
|
capabilities:
|
||||||
|
- View
|
||||||
|
exposure_modes:
|
||||||
|
- Masked
|
||||||
|
- Plaintext
|
||||||
|
conditions:
|
||||||
|
- Logged
|
||||||
|
restrictions:
|
||||||
|
- ExportBlocked
|
||||||
|
expect:
|
||||||
|
effect: allow
|
||||||
|
reason: reader_group
|
||||||
|
metadata:
|
||||||
|
expected_caring_descriptor: descriptor:internal-document-reader
|
||||||
|
expected_conformance_findings: []
|
||||||
|
expected_exposure_modes:
|
||||||
|
- Masked
|
||||||
|
- Plaintext
|
||||||
|
expected_audit_behavior: sampled_allow
|
||||||
|
- id: fixture:markitect-restricted-export-steward-mfa
|
||||||
|
request:
|
||||||
|
id: check:markitect-restricted-export
|
||||||
|
subject:
|
||||||
|
id: user:steward
|
||||||
|
type: Human
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
roles:
|
||||||
|
- steward
|
||||||
|
action: export
|
||||||
|
resource:
|
||||||
|
id: export:internal-note-review-bundle
|
||||||
|
type: export
|
||||||
|
system: markitect-tool
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
labels:
|
||||||
|
- export
|
||||||
|
trust_zone: external
|
||||||
|
context:
|
||||||
|
mfa: true
|
||||||
|
reason: customer-approved export
|
||||||
|
caring_context:
|
||||||
|
id: descriptor:restricted-export-steward
|
||||||
|
profile: caring-0.4.0-rc2
|
||||||
|
subject_type: Human
|
||||||
|
organization_relation: Customer
|
||||||
|
canonical_role: Maintainer
|
||||||
|
scope:
|
||||||
|
level: Record
|
||||||
|
id: export:internal-note-review-bundle
|
||||||
|
tenant: tenant:alpha
|
||||||
|
planes:
|
||||||
|
- Data
|
||||||
|
- Audit
|
||||||
|
capabilities:
|
||||||
|
- Export
|
||||||
|
exposure_modes:
|
||||||
|
- Exportable
|
||||||
|
- Plaintext
|
||||||
|
conditions:
|
||||||
|
- MFARequired
|
||||||
|
- Logged
|
||||||
|
expect:
|
||||||
|
effect: allow
|
||||||
|
reason: steward_export_mfa
|
||||||
|
conformance_findings:
|
||||||
|
- code: MARKITECT-EXPORT-MFA-LOGGED
|
||||||
|
severity: info
|
||||||
|
message: Export is allowed only with steward role, MFA, and logging.
|
||||||
|
metadata:
|
||||||
|
expected_caring_descriptor: descriptor:restricted-export-steward
|
||||||
|
expected_exposure_modes:
|
||||||
|
- Exportable
|
||||||
|
- Plaintext
|
||||||
|
expected_audit_behavior: always_record
|
||||||
|
- id: fixture:markitect-context-package-activation
|
||||||
|
request:
|
||||||
|
id: check:markitect-context-package-activation
|
||||||
|
subject:
|
||||||
|
id: user:alice
|
||||||
|
type: Human
|
||||||
|
tenant: tenant:alpha
|
||||||
|
action: activate_context
|
||||||
|
resource:
|
||||||
|
id: context-package:internal-note-review
|
||||||
|
type: context_package
|
||||||
|
system: markitect-tool
|
||||||
|
tenant: tenant:alpha
|
||||||
|
attributes:
|
||||||
|
labels:
|
||||||
|
- internal
|
||||||
|
- generated
|
||||||
|
context:
|
||||||
|
freshness_seconds: 600
|
||||||
|
policy_version: markitect-gateway-v1
|
||||||
|
caring_context:
|
||||||
|
id: descriptor:context-package-activation
|
||||||
|
profile: caring-0.4.0-rc2
|
||||||
|
subject_type: Human
|
||||||
|
organization_relation: Customer
|
||||||
|
canonical_role: Verifier
|
||||||
|
scope:
|
||||||
|
level: Dataset
|
||||||
|
id: context-package:internal-note-review
|
||||||
|
tenant: tenant:alpha
|
||||||
|
planes:
|
||||||
|
- Intent
|
||||||
|
- Policy
|
||||||
|
capabilities:
|
||||||
|
- Use
|
||||||
|
- Execute
|
||||||
|
exposure_modes:
|
||||||
|
- Metadata
|
||||||
|
- Masked
|
||||||
|
conditions:
|
||||||
|
- PurposeBound
|
||||||
|
- Logged
|
||||||
|
expect:
|
||||||
|
effect: allow
|
||||||
|
reason: fresh_context_package
|
||||||
|
obligations:
|
||||||
|
- type: record_context_activation
|
||||||
|
parameters:
|
||||||
|
freshness_seconds: 600
|
||||||
|
conformance_findings:
|
||||||
|
- code: MARKITECT-CONTEXT-FRESHNESS
|
||||||
|
severity: info
|
||||||
|
message: Context package activation includes policy version and freshness metadata.
|
||||||
|
metadata:
|
||||||
|
expected_caring_descriptor: descriptor:context-package-activation
|
||||||
|
expected_exposure_modes:
|
||||||
|
- Metadata
|
||||||
|
- Masked
|
||||||
|
expected_audit_behavior: always_record
|
||||||
152
examples/markitect/check_policy_package.md
Normal file
152
examples/markitect/check_policy_package.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
---
|
||||||
|
id: markitect.gateway.check-fixtures
|
||||||
|
name: Markitect gateway check fixtures
|
||||||
|
namespace: markitect:gateway
|
||||||
|
version: v1
|
||||||
|
status: draft
|
||||||
|
package: flexauth.markitect.gateway
|
||||||
|
actions:
|
||||||
|
- read
|
||||||
|
- export
|
||||||
|
- activate_context
|
||||||
|
owner: team:platform-architecture
|
||||||
|
fixtures:
|
||||||
|
- check_fixtures.yaml
|
||||||
|
caring:
|
||||||
|
profile: caring-0.4.0-rc2
|
||||||
|
enforce: false
|
||||||
|
canonical_roles:
|
||||||
|
- Doer
|
||||||
|
- Maintainer
|
||||||
|
- Verifier
|
||||||
|
organization_relations:
|
||||||
|
- Customer
|
||||||
|
scopes:
|
||||||
|
- level: Resource
|
||||||
|
id: document:public-note
|
||||||
|
tenant: tenant:alpha
|
||||||
|
- level: Resource
|
||||||
|
id: document:internal-note
|
||||||
|
tenant: tenant:alpha
|
||||||
|
- level: Dataset
|
||||||
|
id: context-package:internal-note-review
|
||||||
|
tenant: tenant:alpha
|
||||||
|
planes:
|
||||||
|
- Intent
|
||||||
|
- Data
|
||||||
|
- Audit
|
||||||
|
capabilities:
|
||||||
|
- View
|
||||||
|
- Export
|
||||||
|
- Use
|
||||||
|
- Execute
|
||||||
|
exposure_modes:
|
||||||
|
- Metadata
|
||||||
|
- Masked
|
||||||
|
- Plaintext
|
||||||
|
- Exportable
|
||||||
|
conditions:
|
||||||
|
- MFARequired
|
||||||
|
- PurposeBound
|
||||||
|
- Logged
|
||||||
|
restrictions:
|
||||||
|
- ExportBlocked
|
||||||
|
metadata:
|
||||||
|
source: examples/markitect/check_policy_package.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Markitect Gateway Check Fixtures
|
||||||
|
|
||||||
|
This package captures the first Markitect gateway scenarios as executable Rego
|
||||||
|
and external fixtures.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
```rego
|
||||||
|
import future.keywords.if
|
||||||
|
import future.keywords.in
|
||||||
|
|
||||||
|
default decision := {"effect": "deny", "reason": "no_matching_rule"}
|
||||||
|
|
||||||
|
decision := {"effect": "allow", "reason": "public_document"} if {
|
||||||
|
input.action == "read"
|
||||||
|
input.resource.type == "document"
|
||||||
|
"public" in object.get(input.resource.attributes, "labels", [])
|
||||||
|
}
|
||||||
|
|
||||||
|
decision := {"effect": "allow", "reason": "reader_group"} if {
|
||||||
|
input.action == "read"
|
||||||
|
input.resource.type == "document"
|
||||||
|
"internal" in object.get(input.resource.attributes, "labels", [])
|
||||||
|
"group:platform-architecture" in object.get(input.subject.attributes, "groups", [])
|
||||||
|
"View" in input.caring_context.capabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
decision := {
|
||||||
|
"effect": "allow",
|
||||||
|
"reason": "steward_export_mfa",
|
||||||
|
"conformance_findings": [{
|
||||||
|
"code": "MARKITECT-EXPORT-MFA-LOGGED",
|
||||||
|
"severity": "info",
|
||||||
|
"message": "Export is allowed only with steward role, MFA, and logging."
|
||||||
|
}]
|
||||||
|
} if {
|
||||||
|
input.action == "export"
|
||||||
|
"steward" in object.get(input.subject.attributes, "roles", [])
|
||||||
|
input.context.mfa == true
|
||||||
|
"Export" in input.caring_context.capabilities
|
||||||
|
"Exportable" in input.caring_context.exposure_modes
|
||||||
|
}
|
||||||
|
|
||||||
|
decision := {
|
||||||
|
"effect": "allow",
|
||||||
|
"reason": "fresh_context_package",
|
||||||
|
"obligations": [{
|
||||||
|
"type": "record_context_activation",
|
||||||
|
"parameters": {"freshness_seconds": input.context.freshness_seconds}
|
||||||
|
}],
|
||||||
|
"conformance_findings": [{
|
||||||
|
"code": "MARKITECT-CONTEXT-FRESHNESS",
|
||||||
|
"severity": "info",
|
||||||
|
"message": "Context package activation includes policy version and freshness metadata."
|
||||||
|
}]
|
||||||
|
} if {
|
||||||
|
input.action == "activate_context"
|
||||||
|
input.resource.type == "context_package"
|
||||||
|
input.policy_version != ""
|
||||||
|
input.context.freshness_seconds <= 900
|
||||||
|
"Use" in input.caring_context.capabilities
|
||||||
|
"Execute" in input.caring_context.capabilities
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
```rego test
|
||||||
|
package flexauth.markitect.gateway_test
|
||||||
|
|
||||||
|
import future.keywords.if
|
||||||
|
import data.flexauth.markitect.gateway
|
||||||
|
|
||||||
|
test_public_document_allows if {
|
||||||
|
gateway.decision.effect == "allow" with input as {
|
||||||
|
"action": "read",
|
||||||
|
"resource": {
|
||||||
|
"type": "document",
|
||||||
|
"attributes": {"labels": ["public"]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_export_requires_mfa if {
|
||||||
|
gateway.decision.effect == "deny" with input as {
|
||||||
|
"action": "export",
|
||||||
|
"subject": {"attributes": {"roles": ["steward"]}},
|
||||||
|
"context": {"mfa": false},
|
||||||
|
"caring_context": {
|
||||||
|
"capabilities": ["Export"],
|
||||||
|
"exposure_modes": ["Exportable"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
57
internal/markitect/check_fixtures_test.go
Normal file
57
internal/markitect/check_fixtures_test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package markitect_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/netkingdom/flex-auth/internal/policy"
|
||||||
|
"github.com/netkingdom/flex-auth/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMarkitectCheckFixturePackageValidates(t *testing.T) {
|
||||||
|
pkg, err := policy.LoadAndValidateFile(context.Background(), filepath.Join("..", "..", "examples", "markitect", "check_policy_package.md"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("LoadAndValidateFile: %v", err)
|
||||||
|
}
|
||||||
|
if !pkg.Valid {
|
||||||
|
t.Fatalf("pkg.Valid = false: %+v", pkg.Validation)
|
||||||
|
}
|
||||||
|
if len(pkg.Fixtures) != 5 {
|
||||||
|
t.Fatalf("Fixtures len = %d; want 5", len(pkg.Fixtures))
|
||||||
|
}
|
||||||
|
|
||||||
|
wantEffects := map[string]api.DecisionEffect{
|
||||||
|
"fixture:markitect-public-document-allow": api.DecisionEffectAllow,
|
||||||
|
"fixture:markitect-internal-document-deny": api.DecisionEffectDeny,
|
||||||
|
"fixture:markitect-internal-document-reader-allow": api.DecisionEffectAllow,
|
||||||
|
"fixture:markitect-restricted-export-steward-mfa": api.DecisionEffectAllow,
|
||||||
|
"fixture:markitect-context-package-activation": api.DecisionEffectAllow,
|
||||||
|
}
|
||||||
|
for _, fixture := range pkg.Fixtures {
|
||||||
|
if fixture.Expect.Effect != wantEffects[fixture.ID] {
|
||||||
|
t.Fatalf("%s effect = %q; want %q", fixture.ID, fixture.Expect.Effect, wantEffects[fixture.ID])
|
||||||
|
}
|
||||||
|
assertFixtureMetadata(t, fixture)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, result := range pkg.Validation.Fixtures {
|
||||||
|
if !result.Passed {
|
||||||
|
t.Fatalf("fixture %s failed: %s actual=%+v", result.ID, result.Error, result.Actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertFixtureMetadata(t *testing.T, fixture api.PolicyFixture) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if _, ok := fixture.Metadata["expected_caring_descriptor"]; !ok {
|
||||||
|
t.Fatalf("%s missing expected_caring_descriptor metadata", fixture.ID)
|
||||||
|
}
|
||||||
|
if _, ok := fixture.Metadata["expected_exposure_modes"]; !ok {
|
||||||
|
t.Fatalf("%s missing expected_exposure_modes metadata", fixture.ID)
|
||||||
|
}
|
||||||
|
if _, ok := fixture.Metadata["expected_audit_behavior"]; !ok {
|
||||||
|
t.Fatalf("%s missing expected_audit_behavior metadata", fixture.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -413,15 +412,21 @@ func expectationMatches(expected, actual api.DecisionExpectation) bool {
|
|||||||
if expected.Reason != "" && expected.Reason != actual.Reason {
|
if expected.Reason != "" && expected.Reason != actual.Reason {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(expected.Obligations) > 0 && !reflect.DeepEqual(expected.Obligations, actual.Obligations) {
|
if len(expected.Obligations) > 0 && !jsonEqual(expected.Obligations, actual.Obligations) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(expected.ConformanceFindings) > 0 && !reflect.DeepEqual(expected.ConformanceFindings, actual.ConformanceFindings) {
|
if len(expected.ConformanceFindings) > 0 && !jsonEqual(expected.ConformanceFindings, actual.ConformanceFindings) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func jsonEqual(left, right any) bool {
|
||||||
|
leftData, leftErr := json.Marshal(left)
|
||||||
|
rightData, rightErr := json.Marshal(right)
|
||||||
|
return leftErr == nil && rightErr == nil && string(leftData) == string(rightData)
|
||||||
|
}
|
||||||
|
|
||||||
func toRegoInput(value any) (map[string]any, error) {
|
func toRegoInput(value any) (map[string]any, error) {
|
||||||
data, err := json.Marshal(value)
|
data, err := json.Marshal(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ metadata-only exposure explicit.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: FLEX-WP-0003-T004
|
id: FLEX-WP-0003-T004
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "1d5de3b2-c581-4ca3-9107-93211eb02c6b"
|
state_hub_task_id: "1d5de3b2-c581-4ca3-9107-93211eb02c6b"
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user