diff --git a/.controlplane/readme.md b/.controlplane/readme.md index 735f133a..3744e032 100644 --- a/.controlplane/readme.md +++ b/.controlplane/readme.md @@ -34,6 +34,12 @@ For review apps, GitHub needs one repository secret: | --- | --- | | `CPLN_TOKEN_STAGING` | Service-account token for `shakacode-open-source-examples-staging`. | +Use a staging/review token that cannot access production Control Plane +resources. In public repositories, generated review-app deploys skip fork PR +heads because Docker builds use repository secrets; if a forked change needs a +review app, first move the reviewed change to a trusted branch in this +repository. + No review-app repository variables are required for the standard path. The workflow infers `qa-react-webpack-rails-tutorial` and `shakacode-open-source-examples-staging` from `.controlplane/controlplane.yml`, @@ -111,6 +117,13 @@ Generate `SECRET_KEY_BASE` with `openssl rand -hex 64` and managed Postgres and Redis services and update `DATABASE_URL` and `REDIS_URL` accordingly. +Review apps run pull request code, so anything mounted through +`cpln://secret/...` can be read by that code after it starts. Keep the +`qa-react-webpack-rails-tutorial-secrets` dictionary limited to review-safe +values: disposable databases, review-only renderer credentials, and a Pro +license value that is acceptable for review-app exposure. Do not reuse +production or long-lived staging secret dictionaries for review apps. + ### Advanced Overrides Most repos should leave these unset. They exist so forks and clones can test @@ -483,6 +496,10 @@ this automated process. When an approved collaborator comments exactly After the review app exists, new pushes to the PR redeploy it automatically. Use `+review-app-delete` to delete it manually; closing the PR deletes it automatically. Use `+review-app-help` for the review-app command reference. +Fork PR heads are skipped for deploys because the workflow builds Docker images +with repository secrets. A trusted comment on a fork PR still should not deploy +the fork head; move the reviewed change to a branch in this repository when a +review app is needed. Pushes to the staging branch deploy staging, and production promotion is manual from the `cpflow-promote-staging-to-production` workflow. If staging moves off `master`, update both the `STAGING_APP_BRANCH` repository diff --git a/.controlplane/shakacode-team.md b/.controlplane/shakacode-team.md index cd4926c6..a4b7fb4b 100644 --- a/.controlplane/shakacode-team.md +++ b/.controlplane/shakacode-team.md @@ -13,6 +13,14 @@ Deployments are handled by Control Plane configuration in this repo and GitHub A - New pushes to a PR redeploy only after the review app already exists. - Add `+review-app-delete` to delete a review app manually; closing the PR also deletes it automatically. Use `+review-app-help` for the command reference. +- Public fork PRs can receive help comments, but deploys are limited to branches + in this repository because Docker builds use repository secrets. If a forked + change needs a review app, first move the reviewed change to a trusted branch + in this repository. +- Review apps run pull request code. Keep `CPLN_TOKEN_STAGING`, + `qa-react-webpack-rails-tutorial-secrets`, database credentials, renderer + credentials, and license values limited to review/staging use. Never mount + production secrets into review apps. ### Staging Environment - **Automatic**: Any merge to the `master` branch automatically deploys to staging @@ -34,6 +42,9 @@ Required repository secret for review apps and staging: - `CPLN_TOKEN_STAGING` +Use a staging/review service-account token that cannot access the production +Control Plane org or production secret dictionaries. + Required repository variables for staging deploys: - `CPLN_ORG_STAGING=shakacode-open-source-examples-staging` diff --git a/.controlplane/templates/app.yml b/.controlplane/templates/app.yml index 5ed7c689..d780acba 100644 --- a/.controlplane/templates/app.yml +++ b/.controlplane/templates/app.yml @@ -42,7 +42,8 @@ spec: # Control Plane Secret named by {{APP_SECRETS}} before deploy. cpflow # resolves {{APP_SECRETS}} to `{APP_PREFIX}-secrets` — which means review # apps all share one `qa-react-webpack-rails-tutorial-secrets` (thanks to - # match_if_app_name_starts_with: true on the qa template). + # match_if_app_name_starts_with: true on the qa template). Review apps run + # pull request code, so every mounted secret must be review-safe. - name: RENDERER_PASSWORD value: cpln://secret/{{APP_SECRETS}}.RENDERER_PASSWORD - name: REACT_ON_RAILS_PRO_LICENSE diff --git a/.controlplane/templates/org.yml b/.controlplane/templates/org.yml index c04129e8..4be7ee03 100644 --- a/.controlplane/templates/org.yml +++ b/.controlplane/templates/org.yml @@ -4,8 +4,10 @@ # other sensitive information that is shared across multiple apps # in the same organization. -# The qa-* dictionary is bootstrapped via this template; prod and -# staging dictionaries are created manually with real values. +# The qa-* dictionary is bootstrapped via this template for review apps. +# Review apps run pull request code, so values in this dictionary must be +# disposable or otherwise acceptable for review-app exposure. Prod and staging +# dictionaries are created manually with separate real values. # Initial bootstrap (once, manually, not in CI): # cpflow apply-template secrets -a qa-react-webpack-rails-tutorial --org shakacode-open-source-examples-staging @@ -21,7 +23,8 @@ data: # Both sides of the Rails/Node renderer handshake must match. # Generate with `openssl rand -hex 32`. RENDERER_PASSWORD: "replace-with-openssl-rand-hex-32" - # JWT from https://pro.reactonrails.com/; same token across envs. + # JWT from https://pro.reactonrails.com/. Use a review-safe token for public + # review apps if the production token must not be exposed to pull request code. REACT_ON_RAILS_PRO_LICENSE: "replace-with-pro-license-jwt" --- diff --git a/.github/cpflow-help.md b/.github/cpflow-help.md index 77b20ee2..fcdfdd90 100644 --- a/.github/cpflow-help.md +++ b/.github/cpflow-help.md @@ -23,11 +23,23 @@ For the normal generated review-app path, GitHub needs one repository secret: | --- | --- | --- | | `CPLN_TOKEN_STAGING` | Repository secret | Control Plane service-account token for the staging/review org. | +For public repositories, use a staging/review token that cannot access +production Control Plane resources. Generated review-app deploys skip fork PR +heads because Docker builds use repository secrets. If a forked change needs a +review app, first move the reviewed change to a trusted branch in this +repository. + No repository variables are required for the standard review-app path when `.controlplane/controlplane.yml` has exactly one review app entry with `match_if_app_name_starts_with: true`. cpflow infers the review-app prefix and staging org from that config. +Review apps run pull request code. Any value mounted through +`cpln://secret/...` can be read by that code after the workload starts, so keep +review-app secret dictionaries limited to disposable databases, review-only +renderer credentials, and license values that are acceptable for review-app +exposure. + Optional overrides exist for forks, clones, and unusual apps: | Name | Notes | @@ -119,7 +131,7 @@ Most apps do not need these: | Name | Notes | | --- | --- | | `DOCKER_BUILD_EXTRA_ARGS` | Newline-delimited extra Docker build tokens. | -| `DOCKER_BUILD_SSH_KEY` | Private SSH key for Docker builds that fetch private dependencies. | +| `DOCKER_BUILD_SSH_KEY` | Read-only, revocable deploy key for Docker builds that fetch private dependencies. Do not use a personal SSH key. | | `DOCKER_BUILD_SSH_KNOWN_HOSTS` | SSH known_hosts entries when SSH build hosts are not GitHub.com. | | `REVIEW_APP_DEPLOYING_ICON_URL` | Cosmetic custom image URL for the animated deploying icon. Set to `none` to use the text fallback icon. | | `STAGING_APP_BRANCH` | Custom staging branch. The branch must also appear in `cpflow-deploy-staging.yml`'s push filter. |