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-case
application name for the matching Cloud Foundary app this will be deployed as. It should include a template variableenv
for 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 ofbuild
orcomplete
. Tasks markedbuild
will run at the start of an associated Pages build. Tasks markedcomplete
will 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-core
application 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/variabletask
withinpages-core
: this is theBuildTask
model 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-core
application 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
,BUCKET
and 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
handler
function 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