Hardening Manifest
Overview
Because contributors cannot generate their own pipelines, contributors will need a hardening_manifest.yaml
file in their repository to go through the hardening process. The hardening manifest contains important information such as: the name of the image, build arguments for the container, labels for the container, a list of software dependencies, and the maintainers for the container. This hardening manifest file provides a common format for the tools surrounding the Iron Bank to source relevant information from.
The hardening_manifest.yaml provides details about the container that is built. It also enables contributors to download private artifacts which are not located in the standard dependency systems (e.g. Red Hat Universal Base Image dependencies). The artifacts are acquired and then made available for the Dockerfile when the pipeline is run. It also allows pulling a different file types (including Docker images and files directly from S3 buckets) so that contributors may, for example, use a multi-stage build approach.
The file should be in the root of the project and should include the following sections.
Hardening Manifest Example
apiVersion: v1
# The repository name in registry1, excluding /ironbank/
name: "opensource/memcached/memcached"
# List of tags to push for the repository in registry1
# The most specific version should be the first tag and will be shown
# on ironbank.dso.mil
tags:
- "1.6.15"
- "latest"
# Build args passed to Dockerfile ARGs
args:
BASE_IMAGE: "redhat/ubi/ubi9"
BASE_TAG: "9.3"
# Docker image labels
labels:
org.opencontainers.image.title: "memcached"
# Human-readable description of the software packaged in the image
org.opencontainers.image.description: "Free & open source, high-performance, distributed memory object caching system,"
# License(s) under which contained software is distributed
org.opencontainers.image.licenses: "BSD"
# URL to find more information on the image
org.opencontainers.image.url: "https://memcached.org/"
# Name of the distributing entity, organization or individual
org.opencontainers.image.vendor: "Danga Interactive"
org.opencontainers.image.version: "1.6.15"
# Keywords to help with search (ex. "cicd,gitops,golang")
mil.dso.ironbank.image.keywords: "memory,cache,caching"
# This value can be "opensource" or "commercial"
mil.dso.ironbank.image.type: "opensource"
# Product the image belongs to for grouping multiple images
mil.dso.ironbank.product.name: "memcached"
# List of resources to make available to the offline build context
resources:
- url: "https://github.com/memcached/memcached/archive/1.6.15.tar.gz"
filename: "memcached.tar.gz"
validation:
type: sha256
value: 4b7e83155bc4fd4103a30dc7f49de024f06978cde10e0df74e5c6f8a04e389a5
# List of project maintainers
maintainers:
- email: "email@example.com"
# The name of the current container owner
name: "First Last"
# The gitlab username of the current container owner
username: "example.username"
# True only for members of the Iron Bank Container Hardening Team
cht_member: false
Hardening Manifest's Schema
name
The name
section in the hardening_manifest.yaml file is a string providing the repository's name and path appearing in registry1.
hardening_manifest.yaml name field.
name: "opensource/memcached/memcached"
tags
The tags
section in the hardening_manifest.yaml file lists the tags the image is tagged with when being pushed to harbor. The first tag in the list is the authoritative tag used to reference the image. It should be the most specific tag. The list may contain more broad tags, and should also contain the latest
tag as the last element in the list.
For example ubi9 could be tagged with 9.3
as the authoritative tag, 9
as a broader tag, and latest
as the most broad tag and last tag in the list.
hardening_manifest.yaml tags field.
tags:
- "9.3"
- "9"
- "latest"
args
The args
section in the hardening_manifest.yaml file provides build arguments to the container build. It contains the BASE_IMAGE
and BASE_TAG
arguments along with any other build arguments you wish to provide.
hardening_manifest.yaml args field.
args:
BASE_IMAGE: "redhat/ubi/ubi9"
BASE_TAG: "9.3"
labels
The labels
section in the hardening_manifest.yaml file provides the standard OCI labels along with some custom ironbank labels. These are all baked into the image for use on the frontend.
Label | Description |
---|---|
org.opencontainers.image.title |
Name of the image |
org.opencontainers.image.description |
Human-readable description of the software packaged in the image |
org.opencontainers.image.licenses |
License(s) under which contained software is distributed |
org.opencontainers.image.url |
URL to find more information on the image |
org.opencontainers.image.vendor |
Name of the distributing entity, organization or individual |
org.opencontainers.image.version |
Authoritative version of the software |
mil.dso.ironbank.image.keywords |
Keywords to help with search (ex. "cicd,gitops,golang") |
mil.dso.ironbank.image.type |
This value can be "opensource" or "commercial" |
mil.dso.ironbank.product.name |
Product the image belongs to for grouping multiple images |
hardening_manifest.yaml labels field.
labels:
org.opencontainers.image.title: "memcached"
# Human-readable description of the software packaged in the image
org.opencontainers.image.description: "Free & open source, high-performance, distributed memory object caching system,"
# License(s) under which contained software is distributed
org.opencontainers.image.licenses: "BSD"
# URL to find more information on the image
org.opencontainers.image.url: "https://memcached.org/"
# Name of the distributing entity, organization or individual
org.opencontainers.image.vendor: "Danga Interactive"
org.opencontainers.image.version: "1.6.15"
# Keywords to help with search (ex. "cicd,gitops,golang")
mil.dso.ironbank.image.keywords: "memory,cache,caching"
# This value can be "opensource" or "commercial"
mil.dso.ironbank.image.type: "opensource"
# Product the image belongs to for grouping multiple images
mil.dso.ironbank.product.name: "memcached"
resources
The resources
section in the hardening_manifest.yaml file defines all of the dependencies for the container. Each dependency must include:
- File URL - a direct link to the resource being downloaded
- Desired file name - the staging name for the build context (to be referenced by the Dockerfile)
- The validation method - a means to verify that the resource which is being downloaded is in fact the intended resource; supported validation types:
sha256
,sha512
hardening_manifest.yaml resources field.
resources:
- url: "https://s3.amazonaws.com/path/to/your/package-1.0.0.tar.gz"
filename: "package-1.0.0.tar.gz"
validation:
type: "sha256"
value: "3d6b4cfca92067edd5c860c212ff5153d1e162b8791408bc671900309eb555ec" # must be lowercase
You can also use images from valid Docker image registries such as docker.io quay.io gcr.io k8s.io etc... For example
hardening_manifest.yaml resources docker image.
resources:
- tag: bitnami/kubectl:1.27.3
url: docker://docker.io/bitnami/kubectl@sha256:df4773de390caa4a75d150d78d5096a5108796f27e2d5a1542e534b0d8899fac
Arm64 dockerfile image resources
Append ".arm64" to docker resources that need to be available to the arm64 image build.
hardening_manifest.yaml resources arm64 docker image.
resources:
- tag: bitnami/kubectl:1.27.3.arm64
url: docker://docker.io/bitnami/kubectl@sha256:a1542e534b0d8899facdde390caa4af477375d150d78d5096a5108796f27e2d5
It is important for contributors to be aware of the way in which the resources included in the hardening_manifest.yaml file can impact the container hardening process. While there are no restrictions on the types of resources that can be drawn in for use in the Dockerfile build or even on the location where the resources are acquired from, downloading resources from less-than-reputable sources or ones with vulnerabilities can result in the user having to mitigate more findings generated by the scans or risk a container being not hosted by Iron Bank.
Currently, basic and aws authentication methods are available to retrieve external resources. x509 authentication will be included in the future as an authentication method. You will need to at least include the SHA checksum associated with the downloaded resource in order to allow for verification within the pipeline.
See Resource Credentials for additional instructions.
Utilizing hardening_manifest.yaml artifacts in the Dockerfile
Once the hardening_manifest.yaml
file has been set up correctly, contributors can utilize the artifacts when performing the build of their Dockerfile. The pipeline downloads the specified artifact, verifies that the artifact is the same one that the contributor is expecting to be downloaded by comparing the checksum values provided by the contributor and the checksum calculated on the downloaded artifact. The artifact(s) will then be passed to the build stage if the values match. Otherwise, the pipeline will fail at this stage.
To use a downloaded artifact, add a COPY command to the Dockerfile. The artifact is copied over from the host environment to the container for use in the build. For example, if the artifact file name you chose was dependencyX.tar.gz
, you may choose to set this as an argument in the Dockerfile and reference it by a variable name, before copying the artifact to your desired location. See below:
ARG IMPORTANT_DEPENDENCY=dependencyX.tar.gz
COPY ["${IMPORTANT_DEPENDENCY}", "/some/dir"]
RUN tar -zxvf /some/dir/${IMPORTANT_DEPENDENCY}
maintainers
The maintainers
section in the hardening_manifest.yaml file provides contact information for the individuals in charge of maintaining the image. It should include the name, email, and gitlab username for all the individuals maintaining the image. There is also a boolean cht_member
field which should only be present (and marked true
) if the individual is a member of the container hardening team.
This section will be used to contact contributors in the event of new findings, automatically assign Gitlab issues, bug reports, and more. Please ensure that all members listed in maintainers section are up-to-date.
hardening_manifest.yaml maintainers field.
maintainers:
- email: "email@example.com"
# The name of the current container owner
name: "First Last"
# The gitlab username of the current container owner
username: "example.username"
cht_member: true
Resource Credentials
Members frequently require resources that are only available to authenticated users. Examples of this include Docker containers inside of private registries, artifacts in private S3 buckets, and other resources retrieved over HTTP behind auth walls. To facilitate building containers in the Repo1 pipeline using these resources, valid credentials to be used in the artifact gathering process may be provided on a subgroup (to DSOP) or project level.
Warning
Artifacts downloaded from authenticated sources are not protected since they are available in the CI pipeline which is open to the public.
Note
Credentials provided at the subgroup level will be inherited by any folders and projects within the subgroup.
Requesting Credentials
If you are needing to use credentials in your project to access private resources in the hardening_manifest.yaml
, you will need to open a new issue in the corresponding project in repo1 and apply the "CSO::To Do" label. DO NOT include any sensitive information in this issue. Once we have reviewed your request, we will then reach out via Mattermost IL4/5 or send a DoD Safe drop off request. Once we have the required information we will create the variables for you in repo1 so the credential ID can then be added to the hardening_manifest.yaml
.
Supported Credentials
- Basic: Username and Password used for getting resources whose url fields begin with either
docker://
orhttp[s]://
- S3: AWS Access Key ID and AWS Secret Access Keys used for getting resources whose url fields begin with
s3://
If you are using Basic Authentication (HTTP or HTTPS) then we will need the username, the password and the ID for the credentials.
An example would be User – gitlab, Password – gitlabpassword and the ID – some-id
After we have created these variables the hardening_manifest.yaml would look something like this.
auth:
type: basic
id: some-id
If you are using S3 credentials then we will need the S3 access key, secret key and ID.
For a particular resource, add the following fields to the resource map in hardening_manifest.yaml:
- The type field in your resource auth map should be set to S3
- The id field will be ID you provide.
- There is an additional region field included for the S3 resource whose value is the AWS region in which the s3 bucket exists (e.g. us-west-1)
auth:
type: s3
id: some-id
region: us-west-1