Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/github.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"index": "docs/README.md",
"architecture": "docs/architecture.md",
"configBoundary": "docs/config-boundary.md",
"authorizationAuthority": "docs/authorization-authority.md",
"serviceBoundary": "docs/service-boundary.md",
"dokployServiceDeployments": "docs/dokploy-service-deployments.md",
"driverDescriptors": "docs/driver-descriptors.md",
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/authz-policy-reconcile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.primary
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand Down Expand Up @@ -146,6 +147,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.product-health-monitoring
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand Down Expand Up @@ -205,6 +207,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-route-binding
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -216,6 +219,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-external-route-binding
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -227,6 +231,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-testing-ingress-route
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -238,6 +243,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-testing-route-binding-refresh
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -249,6 +255,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-testing-target-replacement
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -260,6 +267,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-opw-preview-feedback
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -271,6 +279,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-opw-production-enrollment
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -282,6 +291,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-production-enrollment
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -293,6 +303,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-production-operation-read
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand All @@ -304,6 +315,7 @@ jobs:
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@39aecc250d6dee91204e24673725bd1ea1ca6bda # main
with:
mode: ${{ inputs.mode }}
expected_managed_set_id: operator.odoo-production-backup-restore
reviewed_plan_sha256: ${{ inputs.reviewed_plan_sha256 }}
reason: ${{ inputs.reason }}
related_issue: ${{ inputs.related_issue }}
Expand Down
89 changes: 1 addition & 88 deletions .github/workflows/deploy-launchplane.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,6 @@ on:
description: Exact immutable Launchplane image digest to deploy instead of building a new one.
required: false
type: string
authz_managed_mode:
description: Bootstrap review or apply of managed authorization without deploying Launchplane.
required: false
default: none
type: choice
options:
- none
- dry_run
- apply
authz_managed_reviewed_plan_sha256:
description: Managed plan SHA-256 returned by the reviewed dry run; required for apply.
required: false
type: string
authz_managed_reason:
description: Single-line operator reason bound into the managed review plan.
required: false
type: string
authz_managed_related_issue:
description: Single-line issue or change reference bound into the managed review plan.
required: false
type: string
omit_every_code_env:
description: Temporarily omit Every Code env for one compatibility deploy.
required: false
Expand Down Expand Up @@ -86,8 +65,7 @@ jobs:
(github.event_name == 'workflow_dispatch' &&
github.ref_type == 'branch' &&
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
inputs.break_glass_confirm == '' &&
inputs.authz_managed_mode == 'none')
inputs.break_glass_confirm == '')
runs-on:
- self-hosted
- ${{ vars.LAUNCHPLANE_RUNNER_LABEL }}
Expand Down Expand Up @@ -1181,66 +1159,6 @@ jobs:
launchplane-v2-deployed-smoke.json
} >> "$GITHUB_STEP_SUMMARY"

operator-authz-managed-validate:
if: >-
github.event_name == 'workflow_dispatch' &&
github.ref_type == 'branch' &&
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
inputs.authz_managed_mode != 'none'
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- name: Validate managed authz isolation
shell: bash
env:
BREAK_GLASS_CONFIRM: ${{ inputs.break_glass_confirm }}
BREAK_GLASS_IMAGE_REFERENCE: ${{ inputs.break_glass_image_reference }}
BREAK_GLASS_REASON: ${{ inputs.break_glass_reason }}
DEPLOY_IMAGE_REFERENCE: ${{ inputs.image_reference }}
OMIT_EVERY_CODE_ENV: ${{ inputs.omit_every_code_env }}
OMIT_NPMPLUS_ENV: ${{ inputs.omit_npmplus_env }}
OMIT_OWNER_AGENT_ENV: ${{ inputs.omit_owner_agent_env }}
OMIT_TERMINAL_AGENT_ENV: ${{ inputs.omit_terminal_agent_env }}
run: |
set -euo pipefail
if [ -n "$DEPLOY_IMAGE_REFERENCE" ]; then
echo "Managed authz reconciliation cannot include a deploy image input." >&2
exit 1
fi
if [ "$OMIT_EVERY_CODE_ENV" = "true" ] ||
[ "$OMIT_TERMINAL_AGENT_ENV" = "true" ] ||
[ "$OMIT_OWNER_AGENT_ENV" = "true" ] ||
[ "$OMIT_NPMPLUS_ENV" = "true" ]; then
echo "Managed authz reconciliation cannot include deploy compatibility inputs." >&2
exit 1
fi
if [ -n "$BREAK_GLASS_CONFIRM" ] ||
[ -n "$BREAK_GLASS_IMAGE_REFERENCE" ] ||
[ -n "$BREAK_GLASS_REASON" ]; then
echo "Managed authz reconciliation cannot include break-glass rollback inputs." >&2
exit 1
fi

operator-authz-managed:
needs: operator-authz-managed-validate
if: >-
github.event_name == 'workflow_dispatch' &&
github.ref_type == 'branch' &&
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
inputs.authz_managed_mode != 'none'
permissions:
contents: read
id-token: write
uses: cbusillo/launchplane/.github/workflows/reusable-authz-policy-reconcile.yml@4dbef2945b0a297a6edaa949a42d8c7d4cbc01cd # main
with:
mode: ${{ inputs.authz_managed_mode }}
reviewed_plan_sha256: ${{ inputs.authz_managed_reviewed_plan_sha256 }}
reason: ${{ inputs.authz_managed_reason }}
related_issue: ${{ inputs.authz_managed_related_issue }}
secrets:
managed_set_json: ${{ secrets.LAUNCHPLANE_AUTHZ_MANAGED_SET_JSON }}

emergency-dokploy-rollback:
if: >-
github.event_name == 'workflow_dispatch' &&
Expand All @@ -1266,15 +1184,10 @@ jobs:
- name: Validate manual break-glass request
shell: bash
env:
AUTHZ_MANAGED_MODE: ${{ inputs.authz_managed_mode }}
BREAK_GLASS_IMAGE_REFERENCE: ${{ inputs.break_glass_image_reference }}
BREAK_GLASS_REASON: ${{ inputs.break_glass_reason }}
run: |
set -euo pipefail
if [ "$AUTHZ_MANAGED_MODE" != "none" ]; then
echo "Break-glass rollback cannot be combined with managed authz reconciliation." >&2
exit 1
fi
: "${LAUNCHPLANE_DOKPLOY_TARGET_TYPE:?Missing LAUNCHPLANE_DOKPLOY_TARGET_TYPE variable}"
: "${LAUNCHPLANE_DOKPLOY_TARGET_ID:?Missing LAUNCHPLANE_DOKPLOY_TARGET_ID variable}"
if [ -z "$BREAK_GLASS_IMAGE_REFERENCE" ]; then
Expand Down
48 changes: 47 additions & 1 deletion .github/workflows/generic-web-preview-authorization.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ jobs:
plan_sha256: ${{ steps.plan.outputs.plan_sha256 }}
product: ${{ steps.inputs.outputs.product }}
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
WORKFLOW_REF: ${{ github.ref }}
LAUNCHPLANE_URL: ${{ vars.LAUNCHPLANE_PUBLIC_URL }}
MODE: ${{ inputs.mode }}
OPERATION: ${{ inputs.operation }}
Expand Down Expand Up @@ -111,6 +113,11 @@ jobs:
return value

mode = required("MODE")
expected_ref = f"refs/heads/{os.environ['DEFAULT_BRANCH']}"
if os.environ["WORKFLOW_REF"] != expected_ref:
raise SystemExit(
"Generic-web preview authorization must run from the default branch."
)
if mode not in {"dry_run", "apply"}:
raise SystemExit("mode must be dry_run or apply.")
operation = required("OPERATION")
Expand Down Expand Up @@ -240,6 +247,11 @@ jobs:
exit 1
fi
jq '.result.configuration' authz-plan.json > authz-reconcile-request.json
managed_set_id="$(jq -r '.managed_set_id // empty' authz-reconcile-request.json)"
if [ "$managed_set_id" != "operator.generic-web-preview" ]; then
echo "Preview authz plan returned an unexpected managed set." >&2
exit 1
fi
echo "plan_sha256=$plan_sha256" >> "$GITHUB_OUTPUT"
{
echo "## Generic-web preview authorization plan"
Expand Down Expand Up @@ -267,8 +279,42 @@ jobs:
apply:
if: ${{ inputs.mode == 'apply' }}
needs: plan
concurrency:
group: launchplane-authz-policy
cancel-in-progress: false
uses: cbusillo/launchplane/.github/workflows/reusable-generic-web-preview-authz-apply.yml@d21d609514404d3420fceb7fe53857ae407d3ff8 # main
with:
product: ${{ needs.plan.outputs.product }}
plan_sha256: ${{ needs.plan.outputs.plan_sha256 }}
secrets: inherit

verify-apply:
if: ${{ inputs.mode == 'apply' }}
needs:
- plan
- apply
runs-on: ubuntu-latest
steps:
- name: Download authorization apply evidence
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.0
with:
name: generic-web-preview-authz-apply
path: .

- name: Verify applied authorization
shell: bash
env:
REVIEWED_PLAN_SHA256: ${{ needs.plan.outputs.plan_sha256 }}
run: |
set -euo pipefail
jq -e \
--arg reviewed "$REVIEWED_PLAN_SHA256" \
'.result.diff.managed_set_id == "operator.generic-web-preview" and
.result.diff.plan_sha256 == $reviewed and
(.result.changed | type == "boolean") and
(.result.diff.operational_readiness_blocked_rule_count | type == "number") and
((.result.changed | not) or
.result.diff.operational_readiness_blocked_rule_count == 0)' \
authz-apply.json >/dev/null || {
echo "Applied preview authorization did not match the reviewed contract." >&2
exit 1
}
28 changes: 22 additions & 6 deletions .github/workflows/reusable-authz-policy-reconcile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ name: Reusable Authz Policy Reconcile
required: true
type: string
expected_managed_set_id:
description: Optional exact managed-set identity required from the protected configuration.
required: false
default: ""
description: Exact managed-set identity required from the protected configuration.
required: true
type: string
reviewed_plan_sha256:
description: Plan SHA-256 returned by the reviewed dry run; required for apply.
Expand Down Expand Up @@ -129,7 +128,9 @@ jobs:
if re.fullmatch(r"[a-z0-9][a-z0-9._:/-]{0,127}", managed_set_id) is None:
raise SystemExit("Managed authz configuration requires a stable managed_set_id.")
expected_managed_set_id = os.environ.get("EXPECTED_MANAGED_SET_ID", "").strip()
if expected_managed_set_id and managed_set_id != expected_managed_set_id:
if not expected_managed_set_id:
raise SystemExit("Managed authz reconciliation requires expected_managed_set_id.")
if managed_set_id != expected_managed_set_id:
raise SystemExit(
"Managed authz configuration managed_set_id does not match the selected managed set."
)
Expand Down Expand Up @@ -281,7 +282,9 @@ jobs:
(.result.diff.plan_sha256 | test("^[0-9a-f]{64}$")) and
(.result.diff.previous_policy_sha256 | test("^[0-9a-f]{64}$")) and
(.result.diff.desired_policy_sha256 | test("^[0-9a-f]{64}$")) and
(.result.diff.desired_set_sha256 | test("^[0-9a-f]{64}$"))' \
(.result.diff.desired_set_sha256 | test("^[0-9a-f]{64}$")) and
(.result.diff.operational_readiness_blocked_rule_count | type == "number") and
(.result.diff.operational_readiness_blockers | type == "array")' \
"$RESPONSE_FILE" >/dev/null || {
echo "Launchplane managed authz response did not match the reviewed contract." >&2
exit 1
Expand All @@ -291,13 +294,20 @@ jobs:
echo "Launchplane applied a different managed authz plan than the reviewed digest." >&2
exit 1
fi
changed="$(jq -r '.result.changed' "$RESPONSE_FILE")"
readiness_blockers="$(
jq -r '.result.diff.operational_readiness_blocked_rule_count' "$RESPONSE_FILE"
)"
if [ "$MODE" = "apply" ] && [ "$changed" = "true" ] && [ "$readiness_blockers" != "0" ]; then
echo "Launchplane refused to verify an authz apply with operational-readiness blockers." >&2
exit 1
fi
jq '{
mode: .result.mode,
changed: .result.changed,
authz_policy: .result.authz_policy,
diff: .result.diff
}' "$RESPONSE_FILE" > "$EVIDENCE_DIRECTORY/summary.json"
changed="$(jq -r '.result.changed' "$RESPONSE_FILE")"
schema_migrated="$(jq -r '.result.diff.schema_migrated' "$RESPONSE_FILE")"
authorization_changed="$(jq -r '.result.diff.authorization_changed' "$RESPONSE_FILE")"
previous_policy_sha256="$(jq -r '.result.diff.previous_policy_sha256' "$RESPONSE_FILE")"
Expand All @@ -308,6 +318,10 @@ jobs:
updated="$(jq -r '.result.diff.updated_rule_count' "$RESPONSE_FILE")"
removed="$(jq -r '.result.diff.removed_rule_count' "$RESPONSE_FILE")"
unchanged="$(jq -r '.result.diff.unchanged_rule_count' "$RESPONSE_FILE")"
readiness_reasons="$(
jq -c '[.result.diff.operational_readiness_blockers[]?.reason_codes[]?] | unique' \
"$RESPONSE_FILE"
)"
{
echo "## Managed authorization reconciliation"
echo
Expand All @@ -317,6 +331,8 @@ jobs:
echo "- Authorization changed: $authorization_changed"
echo "- Schema migrated: $schema_migrated"
echo "- Rules: added=$added adopted=$adopted updated=$updated removed=$removed unchanged=$unchanged"
echo "- Operational-readiness blockers: $readiness_blockers"
echo "- Operational-readiness reason codes: $readiness_reasons"
printf '%s\n' "- Previous policy SHA-256: $previous_policy_sha256"
printf '%s\n' "- Desired policy SHA-256: $desired_policy_sha256"
printf '%s\n' "- Desired set SHA-256: $desired_set_sha256"
Expand Down
Loading
Loading