Skip to content
Back to skills

Sales Demos Portal

BSecurity

Deploy the AAP self-service portal (Red Hat Developer Hub with the AAP plugin) via Helm chart into an RHDP environment. Runs playbooks/portal.yml, which creates the OAuth application, deploys the chart, and syncs the org list. TRIGGER when: the user wants to deploy the self-service portal, asks about RHDH or Developer Hub, or wants non-admin users to launch templates from a browser. SKIP: if the portal is already deployed and the user wants to use it, or if the user wants to install OpenShift...

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
devopspythongobashazureapi

Works with

  • cli
  • api
  • mcp

Security analysis

B88/100
  • criticalPipes output to a shell interpreter

Pro shows the line behind each finding and how to fix it

Scanned October 6, 2026

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

Installs into .claude/skills of the current project.

Are you the author of Sales Demos Portal?

Add the live security badge to your README. It updates with every re-scan.

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

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

Download with Pro
SKILL.md
---
name: sales-demos-portal
description: "Deploy the AAP self-service portal (Red Hat Developer Hub with the AAP plugin) via Helm chart into an RHDP environment. Runs playbooks/portal.yml, which creates the OAuth application, deploys the chart, and syncs the org list. TRIGGER when: the user wants to deploy the self-service portal, asks about RHDH or Developer Hub, or wants non-admin users to launch templates from a browser. SKIP: if the portal is already deployed and the user wants to use it, or if the user wants to install OpenShift Virtualization — that is sales-demos-setup."
---

# sales-demos-portal

Deploy the AAP self-service portal into an RHDP environment. Takes about 11
minutes end to end.

This skill contains **no logic**. All the work is in
[`playbooks/portal.yml`](../../../playbooks/portal.yml). See `CLAUDE.md` →
*Skills and playbooks*.

## What it does

1. Creates a gateway OAuth application (delete + recreate — never PATCH
   `client_secret`, the gateway hashes differently and gives `invalid_client`).
2. Creates the `aap-portal` namespace, a durable service token, and three
   Secrets the chart expects.
3. Deploys `redhat-rhaap-portal` 2.1.0 via Helm.
4. Updates the OAuth redirect URI to the actual portal Route.
5. Syncs the org list from AAP so all organizations are visible.
6. Patches the portal ConfigMap: 1-minute sync interval, permissions disabled
   so non-admin users can see and launch templates.

## Preflight Check

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

# helm binary is available
command -v helm >/dev/null \
  && echo "✅ helm $(helm version --short 2>/dev/null)" \
  || echo "❌ helm not found — https://helm.sh/docs/intro/install/"

# Kubeconfig for Helm module
ENV=${ENV:-sandbox}
test -f ".kube/${ENV}.kubeconfig" \
  && echo "✅ kubeconfig exists for $ENV" \
  || bash utilities/make-kubeconfig.sh "$ENV"
```

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

```bash
python3 - <<'PY'
import os, ssl, json, urllib.request
ctx = ssl.create_default_context(); ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
req = urllib.request.Request(os.environ["OCP_URL"].rstrip("/") + "/apis",
                             headers={"Authorization": "Bearer " + os.environ["OCP_TOKEN"]})
groups = json.load(urllib.request.urlopen(req, context=ctx, timeout=20))["groups"]
print("✅ cluster reachable — %d API groups" % len(groups))
PY
```

## Collect inputs

Only one input, and it has a default. Ask the user only if it is ambiguous:

| Variable | Default | Meaning |
|---|---|---|
| `ENV` (inventory limit) | `sandbox` | Which environment to target — `sandbox` or `demo` |

## Run

```bash
mkdir -p ~/ansible-logs
export ANSIBLE_LOG_PATH=~/ansible-logs/portal-sandbox-$(date +%F-%H%M).log

./utilities/run-ansible.sh playbooks/portal.yml -i inventory --limit sandbox -e target_env=sandbox \
  --vault-id sales.demos@~/secrets/.vault_pass_sales_demos
```

**Always set `ANSIBLE_LOG_PATH`** — this run takes about 11 minutes and the log
is the only evidence left if it fails. Logs live outside the repo, in
`~/ansible-logs/`. Tell the user the path so they can find it later.

**Never pipe the run through `tee`.** In a pipeline the exit status comes from
`tee`, not `ansible-playbook`, so a failed run reports success.

Tell the user this takes about 11 minutes and stream the output.

## Verify it in the EE before merging a change

See `/sales-demos-verify-ee` for why and how. The one command:

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

## Verify on the cluster

**A green playbook run is not proof.** Ask the cluster using the
`openshift-sandbox` (or `openshift-demo`) MCP tools:

1. Check namespace exists: `pods_list_in_namespace` for `aap-portal`
2. Check deployment is ready: `resources_get` for Deployment
   `rhaap-portal-redhat-developer-hub` in `aap-portal`
3. Check Route exists: `resources_list` for Routes in `aap-portal`

Then open the portal URL in a browser. It should show the Red Hat Developer Hub
login page. Log in with the AAP credentials — templates from the configured
organizations should be visible.

4. Confirm the two self-service entry points are in the catalog:
   `Self-Service - Request Linux Server` and
   `Self-Service - Request Windows Server`. Each should render its survey as a
   request form (hypervisor, VM size tier, workload role, how many VMs). Allow
   one sync interval — the catalog refreshes every minute.

## The portal cannot surface workflows, and that is why those two exist

The catalog syncs JOB templates only. There is no setting to change it: the
plugin has no workflow provider at all.

**Measured 2026-09-08, not inferred from the docs** (which are silent on the
question). `playbooks/portal.yml` writes
`catalog.providers.rhaap.production.sync.jobTemplates` because that is the only
key available, and grepping the deployed plugin bundle inside the running
`rhaap-portal` pod (chart 2.1.0) returns 200 occurrences of `jobTemplates` and
**zero** of `workflowJobTemplates`, `WorkflowJobTemplate` or
`AAPWorkflowJobTemplateProvider`. dc1.azure reached the same conclusion the same
way and records it in its own `playbooks/launch_workflow.yml`.

So the demo's headline entry points — `Linux Day 1 - 0 Workflow`,
`Windows Day 1 - 0 Workflow`, `Cluster Day 0`, `Windows Day 2 - 0 Break Fix` —
are invisible to the portal on their own. #242 closed that for the two
provisioning paths with thin launcher job templates that fire the workflow
(`playbooks/launch_workflow.yml`). If a future workflow needs to be portal-
reachable, it needs a launcher too; do not go looking for a config key.

## When it finishes

Report the playbook summary **and** the verification result above, then tell the
user the portal is live and accessible at the URL shown.

## If it fails

| Symptom | Cause | Fix |
|---|---|---|
| `401` / `Unauthorized` on the first task | RHDP bearer token expired | Refresh `openshift_api_token` in the vault, re-run `make-kubeconfig.sh` |
| `invalid_client` at `/o/token/` | OAuth client_secret was PATCHed instead of recreated | The playbook deletes and recreates; if this still happens, manually delete the `aap-selfservice-portal` application in the gateway |
| Helm deploy hangs or times out | Chart repo unreachable or cluster resources exhausted | Check `helm repo add openshift-charts https://charts.openshift.io/ && helm search repo redhat-rhaap-portal` |
| `rhaap-portal-app-config not found` | Helm deployment failed silently | Check the Helm release: `helm list -n aap-portal --kubeconfig .kube/<env>.kubeconfig` |
| Portal shows `UNRECOGNIZED` or no templates | Org sync not applied or still syncing | Wait 1 minute for the sync interval, or re-run the playbook |
| A workflow is missing from the catalog | Expected — the plugin syncs job templates only, and has no workflow provider | Not a fault to fix. Give the workflow a launcher job template, as #242 did for the two provisioning workflows |
| `Self-Service - Request …` is missing | `config.yml` has not run since #242, or it ran against the other environment | Re-run `config.yml` with the right `--limit`, then wait one sync interval |
| `Attempting to decrypt but no vault secrets found` | `--vault-id` missing from the command | Add `--vault-id sales.demos@~/secrets/.vault_pass_sales_demos` |

Never paste a live cluster hostname or token into a commit message, issue, or
PR. This repo is public — see `CLAUDE.md`.

Attribution

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

Loading comments…