From d8d276c245380f603fc96004bc2f41885a75a7a4 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 6 Sep 2018 18:28:20 +0300 Subject: [PATCH] docs(docs-infra): update preview server docs to account for recent changes (#25671) Mostly (but not exclusively) a follow-up to #23576. PR Close #25671 --- .../docs/misc--integrate-with-ci.md | 3 +- .../docs/overview--general.md | 25 +++--- .../docs/overview--http-status-codes.md | 4 +- .../docs/overview--security-model.md | 82 +++++++++++-------- .../docs/vm-setup--set-up-secrets.md | 7 +- 5 files changed, 65 insertions(+), 56 deletions(-) diff --git a/aio/aio-builds-setup/docs/misc--integrate-with-ci.md b/aio/aio-builds-setup/docs/misc--integrate-with-ci.md index f97de2e987..8b98924d55 100644 --- a/aio/aio-builds-setup/docs/misc--integrate-with-ci.md +++ b/aio/aio-builds-setup/docs/misc--integrate-with-ci.md @@ -5,4 +5,5 @@ TODO (gkalpak): Add docs. Mention: - Testing on CI. Relevant files: `scripts/ci/test-aio.sh`, `aio/aio-builds-setup/scripts/test.sh` - Deploying from CI. - Relevant files: `scripts/ci/deploy.sh`, `aio/scripts/deploy-to-firebase.sh` + Relevant files: `.circleci/config.yml`, `scripts/ci/deploy.sh`, `aio/scripts/build-artifacts.sh`, + `aio/scripts/deploy-to-firebase.sh` diff --git a/aio/aio-builds-setup/docs/overview--general.md b/aio/aio-builds-setup/docs/overview--general.md index 4b4560f2d0..e6d4e376c6 100644 --- a/aio/aio-builds-setup/docs/overview--general.md +++ b/aio/aio-builds-setup/docs/overview--general.md @@ -34,34 +34,31 @@ container: ### On CI (CircleCI) -- Build job completes successfully. -- The CI script checks whether the build job was initiated by a PR against the angular/angular - master branch. -- The CI script checks whether the PR has touched any files that might affect the angular.io app - (currently the `aio/` or `packages/` directories, ignoring spec files). +- The CI script builds the angular.io project. - The CI script gzips and stores the build artifacts in the CI infrastructure. -- When the build completes CircleCI triggers a webhook on the preview-server. +- When the build completes, CircleCI triggers a webhook on the preview-server. More info on how to set things up on CI can be found [here](misc--integrate-with-ci.md). ### Hosting build artifacts - - nginx receives the webhook trigger and passes it through to the preview server. +- The preview-server runs several preliminary checks to determine whether the request is valid and + whether the corresponding PR can have a (public or non-public) preview (more details can be found + [here](overview--security-model.md)). - The preview-server makes a request to CircleCI for the URL of the AIO build artifacts. - The preview-server makes a request to this URL to receive the artifact - failing if the size exceeds the specified max file size - and stores it in a temporary location. -- The preview-server runs several checks to determine whether the request should be accepted and - whether it should be publicly accessible or stored for later verification (more details can be - found [here](overview--security-model.md)). +- The preview-server runs more checks to determine whether the preview should be publicly accessible + or stored for later verification (more details can be found [here](overview--security-model.md)). - The preview-server changes the "visibility" of the associated PR, if necessary. For example, if builds for the same PR had been previously deployed as non-public and the current build has been automatically verified, all previous builds are made public as well. If the PR transitions from "non-public" to "public", the preview-server posts a comment on the corresponding PR on GitHub mentioning the SHAs and the links where the previews can be found. - The preview-server verifies that it is not trying to overwrite an existing build. -- The preview-server deploys the artifacts to a sub-directory named after the PR number and the first - few characters of the SHA: `//` +- The preview-server deploys the artifacts to a sub-directory named after the PR number and the + first few characters of the SHA: `//` (Non-publicly accessible PRs will be stored in a different location, but again derived from the PR number and SHA.) - If the PR is publicly accessible, the preview-server posts a comment on the corresponding PR on @@ -101,8 +98,8 @@ More info on the possible HTTP status codes and their meaning can be found ### Removing obsolete artifacts In order to avoid flooding the disk with unnecessary build artifacts, there is a cronjob that runs a -clean-up tasks once a day. The task retrieves all open PRs from GitHub and removes all directories -that do not correspond with an open PR. +clean-up task once a day. The task retrieves all open PRs from GitHub and removes all directories +that do not correspond to an open PR. ### Health-check diff --git a/aio/aio-builds-setup/docs/overview--http-status-codes.md b/aio/aio-builds-setup/docs/overview--http-status-codes.md index 505b34b0db..170e66a865 100644 --- a/aio/aio-builds-setup/docs/overview--http-status-codes.md +++ b/aio/aio-builds-setup/docs/overview--http-status-codes.md @@ -1,8 +1,8 @@ # Overview - HTTP Status Codes -This is a list of all the possible HTTP status codes returned by the nginx and preview servers, along -with a brief explanation of what they mean: +This is a list of all the possible HTTP status codes returned by the nginx and preview servers, +along with a brief explanation of what they mean: ## `http://*.ngbuilds.io/*` diff --git a/aio/aio-builds-setup/docs/overview--security-model.md b/aio/aio-builds-setup/docs/overview--security-model.md index 38ee9cb15d..453ad412b9 100644 --- a/aio/aio-builds-setup/docs/overview--security-model.md +++ b/aio/aio-builds-setup/docs/overview--security-model.md @@ -11,8 +11,8 @@ part of the CI process and serving them publicly. ## Security objectives -- **Prevent hosting arbitrary content to on servers.** - Since there is no restriction on who can submit a PR, we cannot allow arbitrary untrusted PRs' +- **Prevent hosting arbitrary content on our servers.** + Since there is no restriction on who can submit a PR, we cannot allow arbitrary, untrusted PRs' build artifacts to be hosted. - **Prevent overwriting other people's hosted build artifacts.** @@ -40,40 +40,49 @@ part of the CI process and serving them publicly. ### In a nutshell The implemented approach can be broken up to the following sub-tasks: -0. Receive notification from CircleCI of a completed build. -1. Verify that the build is valid and download the artifact. -2. Fetch the PR's metadata, including author and labels. -3. Check whether the PR can be automatically verified as "trusted" (based on its author or labels). -4. If necessary, update the corresponding PR's verification status. -5. Deploy the artifacts to the corresponding PR's directory. -6. Prevent overwriting previously deployed artifacts (which ensures that the guarantees established +1. Receive notification from CircleCI of a completed build. +2. Verify that the build is valid and can have a preview. +3. Download the build artifact. +4. Fetch the PR's metadata, including author and labels. +5. Check whether the PR can be automatically verified as "trusted" (based on its author or labels). +6. If necessary, update the corresponding PR's verification status. +7. Deploy the artifacts to the corresponding PR's directory. +8. Prevent overwriting previously deployed artifacts (which ensures that the guarantees established during deployment will remain valid until the artifacts are removed). -7. Prevent hosted preview files from accessing anything outside their directory. +9. Prevent hosted preview files from accessing anything outside their directory. ### Implementation details This section describes how each of the aforementioned sub-tasks is accomplished: -0. **Receive notification from CircleCI of a completed build** +1. **Receive notification from CircleCI of a completed build** CircleCI is configured to trigger a webhook on our preview-server whenever a build completes. The payload contains the number of the build that completed. -1. **Verify that the build is valid and download the artifact.** +2. **Verify that the build is valid and can have a preview.** We cannot trust that the data in the webhook trigger is authentic, so we only extract the build number and then run a direct query against the CircleCI API to get hold of the real data for the given build number. - If the build was not successful then we ignore this trigger. Otherwise we check that the - associated github organisation and repository are what we expect (e.g. angular/angular). + We perform a number of preliminary checks: + - Was the webhook triggered by the designated CircleCI job (currently `aio_preview`)? + - Was the build successful? + - Are the associated GitHub organisation and repository what we expect (e.g. `angular/angular`)? + - Has the PR touched any files that might affect the angular.io app (currently the `aio/` or + `packages/` directories, ignoring spec files)? - Next we make another call to the CircleCI API to get a list of the URLS for artifacts of that + If any of the preliminary checks fails, the process is aborted and not preview is generated. + +3. **Download the build artifact.** + + Next we make another call to the CircleCI API to get a list of the URLs for artifacts of that build. If there is one that matches the configured artifact path, we download the contents of the build artifact and store it in a local folder. This download has a maximum size limit to prevent PRs from producing artifacts that are so large they would cause the preview server to crash. -2. **Fetch the PR's metadata, including author and labels**. +4. **Fetch the PR's metadata, including author and labels**. Once we have securely downloaded the artifact for a build, we retrieve the PR's metadata - including the author's username and the labels - using the @@ -81,7 +90,7 @@ This section describes how each of the aforementioned sub-tasks is accomplished: To avoid rate-limit restrictions, we use a Personal Access Token (issued by [@mary-poppins](https://github.com/mary-poppins)). -3. **Check whether the PR can be automatically verified as "trusted"**. +5. **Check whether the PR can be automatically verified as "trusted"**. "Trusted" means that we are confident that the build artifacts are suitable for being deployed and publicly accessible on the preview server. There are two ways to check that: @@ -93,31 +102,32 @@ This section describes how each of the aforementioned sub-tasks is accomplished: `read:org` scope issued by a user that can "see" the specified GitHub organization. Here too, we use the token by @mary-poppins. -4. **If necessary update the corresponding PR's verification status**. +6. **If necessary update the corresponding PR's verification status**. Once we have determined whether the PR is considered "trusted", we update its "visibility" (i.e. whether it is publicly accessible or not), based on the new verification status. For example, if a PR was initially considered "not trusted" but the check triggered by a new build determined - otherwise, the PR (and all the previously hosted previews) are made public. It works the same + otherwise, the PR (and all the previously downloaded previews) are made public. It works the same way if a PR has gone from "trusted" to "not trusted". -5. **Deploy the artifacts to the corresponding PR's directory.** +7. **Deploy the artifacts to the corresponding PR's directory.** - With the preceding steps, we have verified that the build artifacts are valid. - Additionally, we have determined whether the PR can be trusted to have its previews - publicly accessible or whether further verification is necessary. The artifacts will be stored to - the PR's directory, but will not be publicly accessible unless the PR has been verified. - Essentially, as long as sub-tasks 1, 2 and 3 can be securely accomplished, it is possible to - "project" the trust we have in a team's members through the PR to the build artifacts. + With the preceding steps, we have verified that the build artifacts are valid. Additionally, we + have determined whether the PR can be trusted to have its previews publicly accessible or whether + further verification is necessary. -6. **Prevent overwriting previously deployed artifacts**. + The artifacts will be stored to the PR's directory, but will not be publicly accessible unless + the PR has been verified. Essentially, as long as sub-tasks 2, 3, 4 and 5 can be securely + accomplished, it is possible to "project" the trust we have in a team's members through the PR to + the build artifacts. + +8. **Prevent overwriting previously deployed artifacts**. In order to enforce this restriction (and ensure that the deployed artifacts' validity is - preserved throughout their "lifetime"), the server that handles the artifacts (currently a Node.js - Express server) rejects builds that have already been handled. + preserved throughout their "lifetime"), the server that handles the artifacts (currently a Node.js Express server) rejects builds that have already been handled. _Note: A PR can contain multiple builds; one for each SHA that was built on CircleCI._ -7. **Prevent hosted preview files from accessing anything outside their directory.** +9. **Prevent hosted preview files from accessing anything outside their directory.** Nginx (which is used to serve the hosted preview) has been configured to not follow symlinks outside of the directory where the preview files are stored. @@ -130,10 +140,10 @@ This section describes how each of the aforementioned sub-tasks is accomplished: This means that any secret access keys need only be stored on the preview-server and not on any of the CI build infrastructure (e.g. CircleCI). -- Each trusted PR author has full control over the content that is hosted as a preview for their PRs. - Part of the security model relies on the trustworthiness of these authors. +- Each trusted PR author has full control over the content that is hosted as a preview for their + PRs. Part of the security model relies on the trustworthiness of these authors. -- Adding the specified label on a PR to mark it as trusted, gives the author full control over - the content that is hosted for the specific PR preview (e.g. by pushing more commits to it). - The user adding the label is responsible for ensuring that this control is not abused and that - the PR is either closed (one way of another) or the access is revoked. +- Adding the specified label on a PR to mark it as trusted, gives the author full control over the + content that is hosted for the specific PR preview (e.g. by pushing more commits to it). The user + adding the label is responsible for ensuring that this control is not abused and that the PR is + either closed (one way of another) or the access is revoked. diff --git a/aio/aio-builds-setup/docs/vm-setup--set-up-secrets.md b/aio/aio-builds-setup/docs/vm-setup--set-up-secrets.md index 90d025165e..48e890401c 100644 --- a/aio/aio-builds-setup/docs/vm-setup--set-up-secrets.md +++ b/aio/aio-builds-setup/docs/vm-setup--set-up-secrets.md @@ -8,7 +8,7 @@ Necessary secrets: 1. `GITHUB_TOKEN` - Used for: - Retrieving open PRs without rate-limiting. - - Retrieving PR author. + - Retrieving PR info, such as author, labels, changed files. - Retrieving members of the trusted GitHub teams. - Posting comments with preview links on PRs. @@ -25,8 +25,9 @@ Necessary secrets: - Generate new token with the `public_repo` scope. 2. `CIRCLE_CI_TOKEN` - - Visit https://circleci.com/gh/angular/angular/edit#api - - Create an API token with `Build Artifacts` scope + - Visit https://circleci.com/gh/angular/angular/edit#api. + - Create an API token with `Build Artifacts` scope. + ## Save secrets on the VM