epack install tool validate
Adds to epack.yaml, resolves dependencies, downloads binary.
Run the tool on an evidence pack:
epack tool validate --pack ./evidence.pack
Pass tool-specific arguments after --
Or add manually to epack.yaml:
tools:
validate:
source: https://github.com/locktivity/epack-tool-validate
Then run epack install to lock and sync.
epack-tool-validate is an epack tool that validates evidence packs against compliance profile YAML files. It evaluates whether the artifacts in a pack satisfy the requirements defined in a profile.
The tool performs validation in several stages:
Profiles are YAML files that define compliance requirements:
id: my-compliance-profile
name: My Compliance Profile
version: "1.0.0"
description: A compliance profile for validation
requirements:
- id: REQ-001
name: MFA Required
control: CC6.2
category: Access Control
satisfied_by:
any_of:
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.mfa_enabled
op: eq
value: true
Requirements can use two clause modes:
Conditions use JSONPath expressions to evaluate artifact metadata:
| Operator | Description |
|---|---|
eq |
Equals |
neq |
Not equals |
gt |
Greater than |
gte |
Greater than or equal |
lt |
Less than |
lte |
Less than or equal |
exists |
Value exists (not null) |
not_exists |
Value does not exist (null) |
max_age_days |
ISO date or RFC3339 timestamp is no older than value days (date-only values may be up to one day in the future to absorb timezone differences) |
When using JSONPath expressions that return multiple values (e.g., $.accounts[*].mfa_enabled), you must specify how to evaluate them:
metadata_conditions:
all:
- path: $.accounts[*].mfa_enabled
op: eq
value: true
cardinality: all # ALL values must satisfy the condition
| Cardinality | Description |
|---|---|
| (empty) | Default. Path must return exactly one value |
all |
Every value must satisfy the condition |
any |
At least one value must satisfy the condition |
none |
No value should satisfy the condition |
Clauses can specify a severity level for graded compliance:
satisfied_by:
any_of:
# No severity = full pass
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 100
# Severity = graded failure
- type: evidencepack/idp-posture@v1
severity: low
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 90
Clauses can require artifacts to be recent:
- type: evidencepack/vuln-scan@v1
freshness:
max_age_days: 30
metadata_conditions:
all:
- path: $.critical_count
op: eq
value: 0
Use max_age_days when the date to check is inside the artifact body rather than the artifact's manifest timestamp:
- type: evidencepack/pentest-report@v1
metadata_conditions:
all:
- path: $.metadata.test_date
op: max_age_days
value: 365
Evaluation is three-valued. A value that is absent from an artifact (a missing
field, an explicit null, an array element without the field, or an empty
result set) cannot pass or fail a comparison: the condition, its clause, and
the requirement score as unknown with failure_kind:, never as a pass or a graded failure. The presence
"insufficient_evidence"
operators (exists, not_exists) stay two-valued, since absence is exactly
what they test.
Combination follows the evidence: in any_of, a definite pass wins and any
unknown clause otherwise blocks a verdict; in all_of, a definite miss fails
the requirement even when other clauses are unknown. The overall status rolls
up as fail over unknown over pass, and summary.unknown counts the
requirements that could not be scored. Unknown requirements never appear in
key_failures.
Not every requirement is machine-checkable. A written policy or a signed
agreement has no artifact field to compare, so a requirement can declare
manual: true instead of satisfied_by. Manual requirements report status:, count under
"manual"summary.manual, and never affect the overall status;
they are answered by asserted support and human review.
Asserted support comes from control mapping artifacts
(evidencepack/control-mapping@v1) sealed into the pack by its publisher.
Each entry maps a requirement to a piece of evidence: an artifact (optionally
a JSON pointer into it) or an indexed document (optionally a quoted passage in
its extracted text). The tool joins entries to the profile's requirements,
resolves each reference against the pack, and reports the results in the
asserted_support output section. Any requirement can receive entries, so a
machine-checked requirement shows its computed result and its mapped evidence
side by side.
Mappings are assertions, not verification results. A broken or stale mapping
produces warnings (MAPPING_UNRESOLVED, MAPPING_PROFILE_MISMATCH,
INVALID_MAPPING_ENTRY, MANUAL_UNSUPPORTED), never a failure. See
Configuration for the join rules,
resolution states, and output shape.
The tool outputs a validation.json file containing:
{
"status": "pass",
"profile": {
"id": "my-compliance-profile",
"name": "My Compliance Profile",
"version": "1.0.0",
"digest": "sha256:abc123..."
},
"validated_at": "2024-06-15T12:00:00Z",
"validated_at_label": "just now",
"pack_digest": "sha256:def456...",
"summary": {
"total": 5,
"passed": 5,
"failed": 0,
"missing": 0,
"warnings": 0
},
"requirements": [
{
"id": "REQ-001",
"name": "MFA Required",
"control": "CC6.2",
"category": "Access Control",
"status": "pass",
"artifact": "artifacts/idp-posture.json",
"path": "$.enabled",
"expected": {"op": "eq", "value": true},
"actual": true,
"checks": [
{
"clause_index": 0,
"schema": "evidencepack/idp-posture@v1",
"status": "pass",
"artifact": "artifacts/idp-posture.json",
"conditions": [
{
"path": "$.enabled",
"expected": {"op": "eq", "value": true},
"actual": true,
"passed": true
}
]
}
]
}
],
"by_category": {
"Access Control": {"passed": 3, "failed": 0, "missing": 0},
"System Operations": {"passed": 2, "failed": 0, "missing": 0}
}
}
Overlays allow customizing profiles without modifying the original:
id: my-overlay
name: Production Overlay
# Modify existing requirements
modify:
- id: REQ-001
name: Stricter MFA Requirement
satisfied_by:
any_of:
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 100
# Skip requirements
skip:
- REQ-003
- REQ-004
# Add new requirements
add:
- id: REQ-NEW
name: New Requirement
satisfied_by:
any_of:
- type: evidencepack/custom@v1
Overlays are applied in order, with last-write-wins semantics.
epack-tool-validate requires a compliance profile to validate against. The profile path is specified in the tool configuration.
| Requirement | Value |
|---|---|
| Requires Pack | Yes |
| Network Access | No |
| Option | Type | Required | Description |
|---|---|---|---|
profile |
string | Yes* | Path to a single profile YAML file |
profiles |
[]string | Yes* | List of profile paths (MVP: only one supported) |
overlays |
[]string | No | List of overlay YAML files to apply |
*Either profile or profiles must be specified. If both are provided, profiles takes precedence.
Add to your build configuration:
# epack.yaml
tools:
validate:
source: locktivity/epack-tool-validate@v1
config:
profile: profiles/security-policy.yaml
Apply environment-specific customizations:
# epack.yaml
tools:
validate:
source: locktivity/epack-tool-validate@v1
config:
profile: profiles/security-policy.yaml
overlays:
- profiles/overlays/production.yaml
- profiles/overlays/us-region.yaml
Profiles are YAML files with the following structure:
id: my-security-profile # Unique identifier
name: My Security Profile # Human-readable name
version: "1.0.0" # Semantic version
description: Example profile # Optional description
requirements:
- id: REQ-001 # Unique requirement ID
name: Access Control Policy # Requirement name
control: CC6.1 # Optional control reference
category: Access Control # Optional category for grouping
description: > # Optional prose: what satisfies this
Policy must name an approving officer and a review cadence.
satisfied_by:
any_of: # OR: any clause can satisfy
- type: evidencepack/idp-posture@v1
metadata_conditions:
all: # AND: all conditions must match
- path: $.has_access_policy
op: eq
value: true
| Field | Type | Description |
|---|---|---|
type |
string | Required. Artifact schema to match (e.g., evidencepack/idp-posture@v1) |
severity |
string | Optional. Failure severity: critical, high, medium, low |
freshness.max_age_days |
int | Optional. Maximum age of artifact in days |
metadata_conditions.all |
[]Condition | Optional. Conditions that must all be true |
| Field | Type | Description |
|---|---|---|
path |
string | JSONPath expression (e.g., $.mfa_coverage) |
op |
string | Operator: eq, neq, gt, gte, lt, lte, exists, not_exists, max_age_days |
value |
any | Expected value (not required for exists/not_exists) |
cardinality |
string | For multi-value paths: all, any, none (empty = single value required) |
max_age_days expects value to be a non-negative number of days (validated at profile compile time) and the JSONPath value to be an ISO date (YYYY-MM-DD) or RFC3339 timestamp. It passes when the date is no older than the configured number of days and not in the future. Date-only values carry no timezone, so they are allowed up to one day in the future; RFC3339 timestamps must not be in the future at all.
The following JSONPath patterns are supported:
| Pattern | Example | Description |
|---|---|---|
| Root field | $.field |
Access top-level field |
| Nested field | $.nested.field |
Access nested field |
| Array index | $.array[0] |
Access specific array element |
| Last element | $.array[-1] |
Access last array element |
| Wildcard | $.array[*].field |
Access field in all array elements (requires cardinality) |
| Recursive descent | $..field |
Access field at any depth (requires cardinality) |
Note: Multi-value patterns (wildcards, recursive descent) require a cardinality field to specify how multiple results are evaluated. See Cardinality.
When a JSONPath expression can return multiple values, you must specify how to evaluate them:
metadata_conditions:
all:
- path: $.accounts[*].mfa_enabled
op: eq
value: true
cardinality: all # ALL accounts must have MFA enabled
| Cardinality | Description |
|---|---|
| (empty) | Default. Path must return exactly one value |
all |
Every value must satisfy the condition |
any |
At least one value must satisfy the condition |
none |
No value should satisfy the condition |
Examples:
# All accounts must have MFA enabled
- path: $.accounts[*].mfa_enabled
op: eq
value: true
cardinality: all
# At least one environment must be production
- path: $.deployments[*].environment
op: eq
value: production
cardinality: any
# No user should have admin role
- path: $.users[*].role
op: eq
value: admin
cardinality: none
Partial presence detection: For cardinality: all, the validator checks that ALL array elements have the field. If some elements are missing the field entirely, validation fails. For example, $.accounts[*].mfa_enabled with cardinality: all will fail if 2 out of 3 accounts have mfa_enabled: true but the third account has no mfa_enabled field - the result will show "2 of 3 elements have field".
Note: Partial presence detection requires a simple wildcard path (e.g., $.accounts[*].field). Recursive descent paths ($..field) cannot detect partial presence since there's no single base array to count.
A requirement with manual: true declares that no machine check answers it. It is answered by asserted support (control mapping entries, see Control Mappings) and human review.
requirements:
- id: REQ-POLICY
name: Information Security Policy
control: PL-01
category: Governance
description: Current version, stating review cadence of at least annually.
manual: true
The optional description carries what would satisfy the requirement, in prose. It is echoed on each requirement in validation.json, so a reviewer sees the acceptance criteria beside the outcome and any asserted support.
Rules:
any_of, all_of, or manual: true.id or control; without either it could never receive asserted support.status: "manual", count under summary.manual, and never affect the overall status. summary.total minus summary.manual is the machine-checked denominator.MANUAL_UNSUPPORTED warning.Overlays customize profiles without modifying the original:
id: production-overlay # Optional identifier
name: Production Overlay # Optional name
# Modify existing requirements (replaces entire requirement)
modify:
- id: REQ-001
name: Stricter Access Control
satisfied_by:
any_of:
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.has_access_policy
op: eq
value: true
- path: $.policy_reviewed_days
op: lte
value: 90
# Skip requirements entirely
skip:
- REQ-003
- REQ-004
# Add new requirements
add:
- id: REQ-PROD-001
name: Production-Specific Check
category: Production
satisfied_by:
any_of:
- type: evidencepack/deploy-info@v1
metadata_conditions:
all:
- path: $.environment
op: eq
value: production
modify replaces the entire requirement (last-write-wins)skip removes requirements from evaluationadd appends new requirements (ID must be unique)tools:
validate:
source: locktivity/epack-tool-validate@v1
config:
profile: profiles/compliance.yaml
tools:
validate:
source: locktivity/epack-tool-validate@v1
config:
profile: profiles/security-policy.yaml
overlays:
- profiles/overlays/skip-manual.yaml
- profiles/overlays/environment-prod.yaml
Use environment variables in overlay paths:
tools:
validate:
source: locktivity/epack-tool-validate@v1
config:
profile: profiles/security-baseline.yaml
overlays:
- profiles/overlays/${ENVIRONMENT}.yaml
Use YAML anchors to share configuration between multiple tool instances:
tools:
validate:
source: locktivity/epack-tool-validate@v1
config: &base-validate
profile: profiles/security-baseline.yaml
validate-strict:
source: locktivity/epack-tool-validate@v1
config:
<<: *base-validate
overlays:
- profiles/overlays/strict.yaml
When the pack contains control mapping artifacts (schema evidencepack/control-mapping@v1), the tool reports their entries as asserted support beside its computed results. Mappings are publisher assertions: they never change any requirement outcome or the overall status. No configuration is needed; mapping support is automatic.
Each mapping entry references one requirement of the validated profile and one piece of evidence in the pack. The tool joins entries to requirements:
| Entry field | Joins to |
|---|---|
requirement |
The requirement with that id |
control |
The first requirement with that control value |
type |
The single requirement whose clauses use that artifact schema (ambiguous types match nothing) |
Mappings whose profile.id names a different profile are ignored. A mapping whose profile.digest differs from the validated profile's digest is still reported, with each entry marked "stale": true and a MAPPING_PROFILE_MISMATCH warning.
Evidence references resolve best-effort against the pack:
artifact resolves against the pack's artifact paths. An RFC 6901 pointer resolves into the artifact's JSON content; when it names a scalar, the entry carries the cited value in value.document_id resolves through a document index artifact (schema evidencepack/document-index@v1). A quote anchor is searched in the document's extracted text; a table anchor resolves at document level, since packs carry no tabular extraction yet.Each reported entry carries a resolution state:
| State | Meaning |
|---|---|
resolved |
Target (and anchor, where an extraction exists) found |
document_only |
Document found, but the anchor's extraction is absent |
unresolved |
Target or anchor not found in the pack |
The asserted_support output section is keyed by profile ID:
"asserted_support": {
"my-security-profile": [
{
"requirement": "REQ-001",
"requirement_id": "REQ-001",
"evidence": {"artifact": "artifacts/idp-posture.json", "pointer": "/mfa_coverage"},
"label": "MFA coverage from the IdP export",
"resolution": "resolved",
"value": 100,
"source": "artifacts/control-mappings.json"
}
]
}
requirement, control, or type echoes the join the entry claimed; requirement_id is the joined requirement's id in this profile and is absent when the claim matched nothing.
Mapping issues surface as warnings, in the warnings array of validation.json and in the run's result.json. They are never errors and never affect status:
| Code | Meaning |
|---|---|
INVALID_MAPPING_ENTRY |
Entry violates the mapping schema's constraints; the entry is reported in the warning and skipped |
MAPPING_UNRESOLVED |
Entry cites an artifact, document, pointer, or quote not found in the pack, or references a requirement not present in the profile |
MAPPING_PROFILE_MISMATCH |
Mapping's profile digest differs from the profile validated |
MANUAL_UNSUPPORTED |
A manual: true requirement has no asserted support entries |
| File | Description |
|---|---|
validation.json |
JSON file containing validation results |
| Exit Code | Meaning |
|---|---|
| 0 | Validation completed (check validation.json for pass/fail) |
| 1 | Operational error (profile not found, invalid YAML, etc.) |
Note: A failing validation (requirements not met) still exits with code 0. Check the status field in validation.json: pass, fail, or unknown (evidence absent for at least one requirement, none failing).
Run validation on an evidence pack:
epack tool validate --pack ./my-evidence.epack
{
"status": "pass",
"profile": {
"id": "security-baseline",
"name": "Security Baseline",
"version": "1.0.0"
},
"validated_at": "2024-06-15T12:00:00Z",
"pack_digest": "sha256:abc123...",
"summary": {
"total": 5,
"passed": 5,
"failed": 0,
"warnings": 0
},
"requirements": [
{
"id": "REQ-001",
"name": "MFA Enabled",
"status": "pass",
"artifact": "artifacts/idp-posture.json"
}
]
}
All requirements are satisfied.
{
"status": "fail",
"profile": {
"id": "security-baseline",
"name": "Security Baseline",
"version": "1.0.0"
},
"summary": {
"total": 5,
"passed": 3,
"failed": 1,
"missing": 1,
"warnings": 0
},
"requirements": [
{
"id": "REQ-001",
"name": "MFA Coverage",
"status": "fail",
"severity": "high",
"expected": {
"op": "gte",
"value": 100
},
"actual": 85,
"delta": -15,
"message": "conditions not satisfied",
"artifact": "artifacts/idp-posture.json",
"path": "$.mfa_coverage",
"failure_kind": "condition",
"checks": [
{
"clause_index": 0,
"schema": "evidencepack/idp-posture@v1",
"status": "fail",
"artifact": "artifacts/idp-posture.json",
"message": "conditions not satisfied",
"conditions": [
{
"path": "$.mfa_coverage",
"expected": {"op": "gte", "value": 100},
"actual": 85,
"delta": -15,
"passed": false
}
]
}
]
},
{
"id": "REQ-002",
"name": "Vulnerability Scan",
"status": "fail",
"severity": "high",
"failure_kind": "missing",
"message": "no artifact with schema evidencepack/vuln-scan@v1",
"checks": [
{
"clause_index": 0,
"schema": "evidencepack/vuln-scan@v1",
"status": "missing",
"message": "no artifact with schema evidencepack/vuln-scan@v1"
}
]
}
],
"key_failures": [
{"id": "REQ-001", "name": "MFA Coverage", "severity": "high"},
{"id": "REQ-002", "name": "Vulnerability Scan", "severity": "high"}
]
}
The key_failures array highlights critical and high severity failures.
Output fields for failed requirements:
| Field | Description |
|---|---|
expected |
The condition that needed to be satisfied (op and value) |
actual |
The actual value found in the artifact |
delta |
Numeric difference from expected (for numeric comparisons) |
path |
JSONPath that was evaluated |
artifact |
Path to the artifact that was checked |
failure_kind |
Structured failure classification such as missing or condition |
checks |
Per-clause evaluation details, including missing or passing checks |
id: access-control-basic
name: Basic Access Control Profile
version: "1.0.0"
requirements:
- id: AC-001
name: MFA Enabled
control: AC-1
category: Access Control
satisfied_by:
any_of:
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.mfa_enabled
op: eq
value: true
- id: AC-002
name: Password Policy
control: AC-2
category: Access Control
satisfied_by:
any_of:
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.password_policy.min_length
op: gte
value: 12
- path: $.password_policy.require_special
op: eq
value: true
This profile uses graduated severity for MFA coverage thresholds:
id: mfa-graduated
name: MFA Coverage with Graduated Compliance
version: "1.0.0"
requirements:
- id: MFA-001
name: MFA Coverage
control: CC6.2
category: Access Control
satisfied_by:
any_of:
# Full compliance (100%) - no severity = PASS
- type: evidencepack/idp-posture@v1
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 100
# 90%+ coverage - low severity
- type: evidencepack/idp-posture@v1
severity: low
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 90
# 75%+ coverage - medium severity
- type: evidencepack/idp-posture@v1
severity: medium
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 75
# Anything less - high severity
- type: evidencepack/idp-posture@v1
severity: high
metadata_conditions:
all:
- path: $.mfa_coverage
op: gte
value: 0
| MFA Coverage | Result | Severity |
|---|---|---|
| 100% | Pass | - |
| 95% | Fail | low |
| 80% | Fail | medium |
| 50% | Fail | high |
id: vuln-scan-fresh
name: Vulnerability Scanning Profile
version: "1.0.0"
requirements:
- id: VS-001
name: Recent Vulnerability Scan
control: CC7.1
category: System Operations
satisfied_by:
any_of:
- type: evidencepack/vuln-scan@v1
freshness:
max_age_days: 7
metadata_conditions:
all:
- path: $.critical_count
op: eq
value: 0
- id: VS-002
name: No High Vulnerabilities
control: CC7.2
category: System Operations
satisfied_by:
any_of:
- type: evidencepack/vuln-scan@v1
freshness:
max_age_days: 30
metadata_conditions:
all:
- path: $.high_count
op: lte
value: 5
This requirement needs ALL clauses to be satisfied:
requirements:
- id: DEPLOY-001
name: Production Deployment Checks
category: Deployment
satisfied_by:
all_of:
- type: evidencepack/deploy-info@v1
metadata_conditions:
all:
- path: $.environment
op: eq
value: production
- type: evidencepack/approval@v1
metadata_conditions:
all:
- path: $.approved
op: eq
value: true
- type: evidencepack/test-results@v1
metadata_conditions:
all:
- path: $.all_passed
op: eq
value: true
Use cardinality when checking conditions across arrays:
requirements:
- id: CLOUD-001
name: Root MFA Enabled (All Accounts)
category: Identity
satisfied_by:
any_of:
- type: evidencepack/cloud-posture@v1
metadata_conditions:
all:
# Check ALL accounts have root MFA enabled
- path: $.accounts[*].iam.root_mfa_enabled
op: eq
value: true
cardinality: all
- id: CLOUD-002
name: At Least One High-Availability Region
category: Infrastructure
satisfied_by:
any_of:
- type: evidencepack/cloud-posture@v1
metadata_conditions:
all:
# At least one region has HA enabled
- path: $.regions[*].high_availability
op: eq
value: true
cardinality: any
- id: CLOUD-003
name: No Public S3 Buckets
category: Data Protection
satisfied_by:
any_of:
- type: evidencepack/cloud-posture@v1
metadata_conditions:
all:
# NO bucket should be public
- path: $.s3_buckets[*].public_access
op: eq
value: true
cardinality: none
| Cardinality | Use Case |
|---|---|
all |
Every item must satisfy (e.g., all accounts have MFA) |
any |
At least one item must satisfy (e.g., one region has HA) |
none |
No item should satisfy (e.g., no public buckets) |
A requirement no machine check answers declares manual: true. It is
answered by control mapping entries sealed into the pack and by human review:
requirements:
- id: GOV-001
name: Information Security Policy
control: PL-01
category: Governance
manual: true
When the pack carries a control mapping artifact
(evidencepack/control-mapping@v1), its entries appear in the
asserted_support section of validation.json:
"asserted_support": {
"my-compliance-profile": [
{
"control": "PL-01",
"requirement_id": "GOV-001",
"evidence": {
"document_id": "doc-8f2c1a9e",
"quote": {"exact": "reviewed at least annually and approved by the CISO"}
},
"label": "Information Security Policy.pdf",
"resolution": "resolved",
"source": "artifacts/control-mappings.json"
}
]
}
The manual requirement reports status: "manual" and never affects the
overall status. See Configuration for
the join rules, resolution states, and warning codes.
id: skip-manual
name: Skip Manual Review Requirements
skip:
- MANUAL-001
- MANUAL-002
- MANUAL-003
id: production-overlay
name: Production Environment Overlay
modify:
- id: VS-001
name: Strict Vulnerability Scan (Production)
satisfied_by:
any_of:
- type: evidencepack/vuln-scan@v1
freshness:
max_age_days: 1 # Daily scans in production
metadata_conditions:
all:
- path: $.critical_count
op: eq
value: 0
- path: $.high_count
op: eq
value: 0
add:
- id: PROD-001
name: Production Monitoring Active
category: Production
satisfied_by:
any_of:
- type: evidencepack/monitoring@v1
metadata_conditions:
all:
- path: $.active
op: eq
value: true
name: Compliance Check
on:
push:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install epack
run: |
go install github.com/locktivity/epack/cmd/epack@latest
- name: Build evidence pack
run: epack collect -o evidence.epack
- name: Validate compliance
run: |
epack tool validate --pack evidence.epack
# Check validation result
STATUS=$(jq -r '.status' validation.json)
if [ "$STATUS" != "pass" ]; then
echo "Compliance check failed"
jq '.key_failures' validation.json
exit 1
fi
echo "Compliance check passed"
compliance:
stage: test
script:
- epack collect -o evidence.epack
- epack tool validate --pack evidence.epack
- |
if [ "$(jq -r '.status' validation.json)" != "pass" ]; then
echo "Compliance failures:"
jq '.requirements[] | select(.status == "fail")' validation.json
exit 1
fi
artifacts:
paths:
- validation.json
when: always
Ensure your artifacts have the expected schema:
# List artifact schemas in pack
epack inspect --pack evidence.epack | jq '.artifacts[].schema'
Test your JSONPath expressions against artifact content:
# Extract artifact and test JSONPath
unzip -p evidence.epack artifacts/idp-posture.json | jq '$.mfa_coverage'
If profile compilation fails, check:
any_of or all_of (not both)type fieldcritical, high, medium, low..) have a cardinality fieldall, any, none**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.8...v0.1.9
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.7...v0.1.8 **Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.7...v0.1.8
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.6...v0.1.7
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.5...v0.1.6
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.4...v0.1.5
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.3...v0.1.4
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.2...v0.1.3
**Full Changelog**: https://github.com/locktivity/epack-tool-validate/compare/v0.1.1...v0.1.2