This repository is a monorepo for all cloud.gov Pages build tasks which run as Cloud Foundry Tasks.
Each task has its own subfolder in tasks/. These subfolders contain all the task-specific code needed to both create (via Docker and Cloud Foundry) and run the task.
Shared code used across tasks is located in lib/.
hardening: TBD
All container images are stored in the pages-cf-build-tasks repository on ECR. They are tagged with the task folder name and environment name: ((build-task))-((deploy-env))
New build tasks are registered in the pages-core application by creating a new BuildTaskType instance via migration. They should follow this standard:
await db.insert('build_task_type',
['name', 'description', 'metadata', 'createdAt', 'updatedAt', 'runner', 'startsWhen', 'url'],
[
taskTypeName,
taskTypeDescription,
{
"appName": appName,
"template": {
"command": `python build-task/main.py ${additionalFlags}`,
"disk_in_mb": diskInMb
}
},
new Date(),
new Date(),
'cf_task',
startsWhen,
url
],
callback
);The operator should supply the following values:
taskTypeName: A human-readable task name. Example: "OWASP ZAP Vulnerability Scan"taskTypeDescription: A human-readable task description. Example: "This scan identifies potential website security issues like unintended exposure of sensitive data, SQL injection opportunities, cross-site scripting (XSS) flaws, and the use of components with known vulnerabilities."appName: Akebab-caseapplication name for the matching Cloud Foundary app this will be deployed as. It should include a template variableenvfor matching the various deployed environments (dev,staging,production). Example:pages-owasp-zap-task-${env}. This will correspond to the folder in this repo that hosts the code.additionalFlags: see Docker CommanddiskInMb: An integer value of the disk-space necessary (in megabytes) for running the docker image of the task.startsWhen: One ofbuildorcomplete. Tasks markedbuildwill run at the start of an associated Pages build. Tasks markedcompletewill run after the build completes.url: A link to additional documentation about the task.
The command sent to a build task will always be of the following form:
python build-task/main.py <operator-defined-flags> <default-parameters>Note
This section is a bit technical, requires fairly detailed knowledge of pages-core, and possibly needs further clarification. Please flag any questions or improvements as issues/PRs
-
operator-defined-flags: These flags are used for information that thepages-coreapplication should pass to the build task. They are defined in the migration (as shown above) and take the form-x {{templated information}} -y {{more info}} -z {{etc}}. For templating, they have access to a single model/variabletaskwithinpages-core: this is theBuildTaskmodel and provides access to all associated properties, as well as those on linked models (Build,BuildType,Site). For example, if the task requires a site's url to scan, this could be passed as a "target" flag like so:--target {{task.Build.url}}. Within the task code, the operator must register these added flags (method: TBD) to access it within their code. -
default-parameters: These parameters are always sent by thepages-coreapplication and are necessary for use in the common steps like updating the build task status and uploading artifacts to S3. These parameters include the following values:STATUS_CALLBACK,TASK_ID,AWS_DEFAULT_REGION,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,BUCKETand are available inside the task script asparams[parameter_name](exampleparams['TASK_ID'])
Adding the code for a new task is done in this repository. Each task
needs a folder within tasks which should be named corresponding to the appName defined above (example: the folder example becomes pages-example-task-dev). There are two files required to be inside this folder and a third optional file:
definition.py: This is the main site of task-specific code. It needs to export one class, a subclass ofBaseBuildTask. The custom class has two requirements:- It must implement a
handlerfunction which returns a dictionary with three keys:
{ 'artifact': '/absolute/path/to/file' 'message': 'task message', 'count': 5 # count of "issues" raised by the scan }- It has extra parsers defined for any
operator-defined-flags. An example is shown attasks/example/definition.py
- It must implement a
.env: Environment variables which are added as Build arguments to the final docker image. The only required value isBASE_IMAGE.build.sh: (optional) This script is run to configure task-specific dependecies needed in the final docker image.
All tasks use the same Dockerfile with different build arguments supplied. Each task is built via the concourse task oci-build-task. The .env file referenced above is supplied as BUILD_ARGS_FILE so that BASE_IMAGE is available at build time. TASK_FOLDER is interpolated by the concourse across step and supplied as BUILD_ARG_TASK_FOLDER. All base images are required to have python available.
See CHANGELOG.md