Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Sales Demos Policy

ASecurity

Deploy AAP Policy as Code backed by OPA: one OPA server on the cluster loaded with the pinned ynotbhatc/rego_policy_libraries release, AAP pointed at it, and policies attached to the `Policy as Code -` demo templates (secret-shaped extra vars, a change window with break-glass, a required change ticket, and a wiring canary). Runs playbooks/install_opa.yml after config.yml, then proves it from AAP — a blocked launch and an allowed one. TRIGGER when: the user wants to demo or set up Policy as Co...

2 stars
0 votes
0 copies
0 views
Added 10/6/2026
devopsgobashkubernetesgitapi

Works with

apimcp

Security Analysis

A100/100

Scanned 10/6/2026

$npx -y skills add ericcames/sales.demos --skill sales-demos-policy --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sales Demos Policy?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Sales Demos Policy
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ericcames-sales-demos-policy/badge)](https://www.skillsdirectory.com/skills/ericcames-sales-demos-policy)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: sales-demos-policy
description: "Deploy AAP Policy as Code backed by OPA: one OPA server on the cluster loaded with the pinned ynotbhatc/rego_policy_libraries release, AAP pointed at it, and policies attached to the `Policy as Code -` demo templates (secret-shaped extra vars, a change window with break-glass, a required change ticket, and a wiring canary). Runs playbooks/install_opa.yml after config.yml, then proves it from AAP — a blocked launch and an allowed one. TRIGGER when: the user wants to demo or set up Policy as Code, policy enforcement, OPA or Open Policy Agent with AAP, wants a job blocked by policy, wants a change window, change freeze, break-glass or change-ticket demo, asks about rego_policy_libraries, opa_query_path or OPA_HOST, or asks about issue #841. SKIP: if the user wants CIS/STIG compliance scanning of VMs — that is sales-demos-ocpvirt-demo (OpenSCAP) — or Kubernetes admission policy (Gatekeeper), which this repo does not deploy."
---

# sales-demos-policy

Deploy AAP's **Policy as Code** feature end to end: AAP asks an OPA server
*"may this job run?"* before launching a guarded job, and blocks it with a
readable reason when the answer is no. Takes about 2 minutes.

This skill contains **no logic**. The work is in
[`playbooks/install_opa.yml`](../../../playbooks/install_opa.yml); every input
is in [`inventory/group_vars/aap/opa_policy.yml`](../../../inventory/group_vars/aap/opa_policy.yml),
which also records how AAP calls OPA. See `CLAUDE.md` → *Skills and playbooks*.

## What it does

1. `config.yml` (existing) sets `OPA_HOST`/`OPA_PORT` and creates the
   `Policy as Code - Hello` template.
2. `install_opa.yml` fetches the policies from
   [`ynotbhatc/rego_policy_libraries`](https://github.com/ynotbhatc/rego_policy_libraries)
   at the pinned tag, runs their own tests in an initContainer, starts one OPA
   pod behind a ClusterIP Service, and asks it two questions through the API
   service proxy.
3. It asserts AAP is pointed at the server, then attaches each entry in
   `opa_policy_associations` through the controller API — no collection
   module accepts `opa_query_path` yet: `extra_vars_control` on
   `Policy as Code - Hello`, `deny_all` on `Policy as Code - Canary`,
   `maintenance_window` on `Policy as Code - Change Window`,
   `required_labels` on `Policy as Code - Change Ticket`.

`config.yml` also creates the demo identity, `policy-demo` in `app-team`
(`policy_demo_rbac.yml`), with Execute on those templates only.

**The change window is weekends only, in `policy_change_window_timezone`**
(default `America/Phoenix`). Set it to the presenter's zone in `local.yml`:
in UTC, a Friday evening in the US is already Saturday and the template
would *run* on screen. The `break-glass` label, given at launch, lets it
through.

**`Policy as Code - Change Ticket` needs a `change-ticket:CHG<7 digits>`
label at launch.** With no ticket, or a malformed one, it is blocked, and the
two refusals read differently. `change-ticket:CHG0012345` exists as code so
the demo is repeatable.

**A label is a marker, not a permission — do not present break-glass as
RBAC-protected.** AAP lets anyone who can view the label's organization apply
it at launch (`LabelAccess` in `awx/main/access.py`), so any org member can
break glass. `policy-demo` gets HTTP 403 applying *any* label only because it
is not an org member. Making break-glass a privilege needs the policy to also
check who launched, which the library does not do yet.

**Policies are attached to demo templates only, never an organization.** The
library denies superuser launches by default, and this platform runs as admin.

## Preflight Check

```bash
ENV=${ENV:-sandbox}
./utilities/preflight.sh "$ENV" --k8s

# The library tag is reachable from here (AAP's EE needs the same access)
TAG=$(sed -n 's/^policy_library_version: *//p' inventory/group_vars/aap/opa_policy.yml)
curl -fsI "https://raw.githubusercontent.com/ynotbhatc/rego_policy_libraries/$TAG/enforcement/aap/extra_vars_control.rego" >/dev/null \
  && echo "✅ rego_policy_libraries $TAG reachable" \
  || echo "❌ cannot fetch rego_policy_libraries $TAG — check the tag in opa_policy.yml"
```

Then confirm the cluster and AAP answer — call, do not read config:

- `mcp__openshift-<env>__namespaces_list` with `fieldSelector=metadata.name=default`
- `mcp__aap-<env>__me_list`

If any check fails, stop and tell the user which one and the fix. Do not run
with a failing prerequisite.

## Collect inputs

| Variable | Default | Meaning |
|---|---|---|
| `ENV` (inventory limit) | `sandbox` | `sandbox`, `demo` or `edge` |

## Run

`config.yml` first — it owns `OPA_HOST` and the demo template, and
`install_opa.yml` asserts both instead of creating them:

```bash
./utilities/run-playbook.sh playbooks/config.yml -i inventory --limit "$ENV" -e target_env="$ENV"
./utilities/run-playbook.sh playbooks/install_opa.yml -i inventory --limit "$ENV" -e target_env="$ENV"
```

The wrapper names the log in `~/ansible-logs/`, passes the vault id and
reports the real exit status. Never pipe a run through `tee`.

From AAP instead: launch `AAP Ecosystem - Install Policy Server` after
`config.yml` has run.

## Verify it in the EE before merging a change

See `/sales-demos-verify-ee`. The one command:

```bash
utilities/run-in-ee.sh playbooks/install_opa.yml \
  -i inventory --limit "$ENV" -e target_env="$ENV" \
  --vault-id sales.demos@~/secrets/.vault_pass_sales_demos
```

## Verify — ask the targets, not the recap

1. **OPA is running.** `mcp__openshift-<env>__pods_list_in_namespace` for
   `policy-as-code` — one `opa-*` pod, Running, init container completed.
2. **AAP is pointed at it.** `mcp__aap-<env>__settings_retrieve` with
   `category_slug=policyascode` — `OPA_HOST` is
   `opa.policy-as-code.svc.cluster.local`, port `8181`.
3. **The policy blocks, through AAP.** Launch `Policy as Code - Hello` twice
   (API, because `job_templates_launch_create` drops extra_vars):
   - with `{"greeting": "hello"}` → job **successful**
   - with `{"greeting": "hello", "db_password": "x"}` → job **failed** before
     running, with *"looks like a secret — pass it through a credential or
     Ansible Vault"* in its explanation
4. **The canary is blocked.** Launch `Policy as Code - Canary` with no extra
   vars → job **failed** before running, with *"All automation is blocked:
   this is the Policy as Code wiring canary"*. It is attached to `deny_all`
   and must never run. **If it runs, AAP is not reaching OPA**, and every
   other "allowed" result above proves nothing: the policies default a
   missing field to allowed, so broken wiring looks like a permissive policy.
5. **As a non-admin.** Launch `Hello` with basic auth as `policy-demo`
   (password `env_secrets[<env>].policy_demo_password`) → successful, and its
   decision-log input shows `"is_superuser": false` and
   `"teams": [{"id": …, "name": "app-team"}]`.
6. **The change window.** On a weekday in `policy_change_window_timezone`,
   launch `Policy as Code - Change Window`:
   - no labels → job **failed** before running, *"Friday is not an approved
     day for automation (allowed: ["Saturday", "Sunday"])"*
   - with `{"labels": [<id of break-glass>]}` as admin → **successful**, and
     the job carries both `break-glass` and `policy` labels — the record
   - the same as `policy-demo` → **HTTP 403**, because it is not an org
     member — not because break-glass is protected (see above)
   On a weekend in that zone the first launch runs — that is the policy
   working, not failing.
7. **The change ticket.** Launch `Policy as Code - Change Ticket`:
   - no labels → job **failed**, *"Label 'change-ticket' is required in
     'key:value' form matching ^CHG[0-9]{7}$, but no value was supplied."*
   - with `{"labels": [<id of change-ticket:CHG0012345>]}` as admin →
     **successful**, and the ticket is on the job
   The malformed case (`change-ticket:12345`) is asserted by
   `install_opa.yml` against OPA directly, so sandbox needs no junk label —
   AAP labels have no delete endpoint.
8. **OPA saw them all.** `mcp__openshift-<env>__pods_log` on the OPA pod — two
   `decision_id` entries per launch, carrying the full input AAP sent. Filter
   the log on `"msg":"Decision Log"` — health probes fill the rest.
   Every `extra_vars` value reads `**REDACTED**` and the key is kept: step 3b's
   entry shows `"db_password":"**REDACTED**"`, never the `x` that was typed.
   `install_opa.yml` asserts the same thing on its own smoke queries.

If launch 3b or the canary *succeeds*, enforcement is off: check step 2 and
the template's `opa_query_path`.

## Undo

Clear `opa_query_path` on the template (PATCH it to `""`) and the template
runs unguarded; delete the `policy-as-code` namespace to remove the server.
With no path attached anywhere, `OPA_HOST` being set does nothing.

Attribution

ericcamesericcames
View sourceSee grades on GitHubMore from ericcames →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Terraform Module Library

Build reusable Terraform modules for AWS, Azure, and GCP infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.

401991 votes

sematext-otel

Wire a service's OpenTelemetry output to Sematext Cloud. Walks through region, App-type, instrumentation flow (managed OTLP endpoint vs Sematext Agent), and signal selection (traces/metrics/logs), then produces the exact env-var block and points at a runnable reference example in this repo. Invoke when instrumenting a new app for Sematext.

01 votes

Deployment Patterns

Deployment workflows, CI/CD pipeline patterns, Docker containerization, health checks, rollback strategies, and production readiness checklists for web applications. Use when setting up deployment infrastructure or planning releases.

2699140 votes

Babysit

Watch a pull request or review cycle until it is ready to merge. Use when asked to babysit, monitor, or keep checking PR comments, reviews, and CI until all actionable issues are resolved.

971540 votes

V7 Roster

Interact with the Paperclip control plane API for task coordination and governance. Use when checking assignments, updating issue status, posting comments, delegating work, managing routines, or calling Paperclip API endpoints.

953190 votes
View all in devops →