Pruebas
La recopilación de pruebas es uno de los aspectos fundamentales de la arquitectura de referencia de DevSecOps. Las pruebas de conformidad crean el seguimiento de auditoría que los auditores buscan durante una auditoría de conformidad. Uno de los objetivos de DevSecOps es la generación y el almacenamiento automatizados de pruebas en archivos pruebas auditables.
La forma en que los pipelines de DevSecOps manejan las pruebas (formato de archivo y estructura del casillero) es:
- Pruebas v2 (pruebas basadas en activos)
Creación de pruebas
La prueba difiere de los artefactos que han creado los pasos de la etapa de interconexión como, por ejemplo, los resultados de las pruebas de unidad o los archivos XML o JSON. Cada tarea debe informar a varias herramientas que gestionan pruebas como, por ejemplo, la creación, el formateo y el almacenamiento de pruebas.
Cualquier prueba, comprobación o exploración genérica puede producir pruebas dentro de una etapa de interconexión utilizando los pasos de las herramientas de DevSecOps o las interconexiones que se muestran en la imagen siguiente. Las herramientas de DevSecOps deben ser capaces de recibir el resultado de la tarea, crear las pruebas y almacenarlas en el armario de pruebas.
El formato de pruebas contiene el resultado de la tarea (tanto si se ha pasado como si no), enlaza a los artefactos creados y enlaza a cualquier problema de incidencias que se cree en función del resultado de la tarea.
Estas herramientas sólo se centran en la recopilación de pruebas y no cambian el comportamiento del proceso de compilación. La interconexión de referencia de DevSecOps no se interrumpe debido a los resultados de error de la tarea. Se puede crear y desplegar una imagen con pruebas y vulnerabilidades con errores si existen pruebas de las comprobaciones y de los errores, si se avisa al equipo, si una solicitud de cambio creada durante el despliegue muestra la evidencia de estos problemas y si la solicitud de cambio se aprueba manualmente.
Flujo de pruebas
El siguiente diagrama muestra cómo se gestionan las pruebas y cómo fluyen a través de las etapas de integración continua y despliegue continuo.
Cada prueba que se recopila en las distintas etapas de la arquitectura de DevOps se almacena en los archivos de pruebas auditables. Durante el despliegue, esta prueba se recopila para crear un resumen de pruebas que se guarda en el archivo de pruebas al final de la ejecución del despliegue.
El resumen de pruebas se adjunta a la solicitud de cambio, que se publica en el almacén de solicitudes de cambio. Durante una aprobación manual de solicitud de cambio, el aprobador es consciente de cualquier problema que se encuentre durante la compilación.
Pruebas v2 (formato actual)
Bloqueador de pruebas v2
Las pruebas se almacenan en una jerarquía plana, en la que cada prueba se identifica mediante su propio hash SHA256, lo que proporciona una capa de protección de la integridad (es decir, se puede detectar cualquier modificación del contenido de las pruebas). Como cada prueba está relacionada con uno o más activos, los algoritmos de resumen de pruebas descubren las pruebas relevantes en función de los activos.
La única jerarquía es la diferenciación de tipos y alguna agrupación hash similar a la estructura de los objetos hash Git.
Ejemplo
.
└── raw/
├── assets/
│ └── xx/
│ └── abcdef123456789/
│ ├── evidences/
│ │ ├── 00abcdef123456789
│ │ └── 01abcdef123456789
│ └── index.json
├── attachments/
│ ├── aa/
│ │ └── abcdef123456789/
│ │ └── content
│ └── ab/
│ └── abcdef123456789/
│ └── content
├── cd/
│ ├── c9b77749-fd59-4d32-bbdb-18e55db1615d/
│ └── summary.json
| └── evdience-checks.json
├── cc/
│ ├── absd7749-fd59-4d32-bbdb-18e55db1615d/
│ └── summary.json
| └── evdience-checks.json
└── evidences/
├── 00/
│ └── abcdef123456789/
│ └── index.json
└── 01 /
└── abcdef123456789/
└── index.json
Colección de pruebas v2
Las pruebas v2 deben recopilarse lo más cerca posible del proceso que ha creado el resultado para una prueba. Después de cada ejecución de escaneo, después de cada prueba, por ejemplo.
Para recopilar pruebas, se puede utilizar el script collect-evidence en los pipelines DevSecOps.
Formato de pruebas v2
Una prueba representa el resultado de un escaneo, prueba, etc. Las pruebas siempre están conectadas al menos a un único activo. Se permiten varios activos, como por ejemplo una única suite de pruebas de extremo a extremo que probablemente pruebe varios activos juntos.
Un activo representa algo que puede probar, explorar, etc., como un Git commit en un repositorio, o un docker image, o cualquier activo generic con un URI.
Los tipos Evidence y Asset representan el esquema de los elementos del casillero v2: pruebas y activo. Aunque el esquema utiliza la sintaxis de tipografía, puede convertirlo para que utilice el esquema de JSON.
type SHA1 = string; // 40 character string representing a SHA-1 hash in hexadecimal format
type SHA256 = string; // 64 character string representing a SHA256 hash in hexadecimal format
type IssueURL = string; // Link to issues on a git service provide like GitHub or GitLab
type RepositoryURL = string; // Link to a git repository
type AssetURI = string; // URI of an Asset, like an image or a repository link and git hash
type FileName = string; // file basename of the attachment
interface Evidence {
version: 2;
id: SHA256;
date: string;
evidence_type_id: string;
evidence_type_version: string;
origin: {
// scope defines a contextual set for multiple evidence, usually a SHA256 identifier or a CI/CD run ID
scope: SHA256;
// any further IDs can be used to determine evidence origin, see example
[index: string]: string;
},
details: {
result: 'success' | 'failure' | 'pending';
tool: string;
// field "details" can have any arbitrary key-value pairs to provide metadata
[index: string]: string;
}
attachments: Record<string, string> | EvidenceAssetAttachment[];
assets: string[] | EvidenceAssetAttachment[];
issues: IssueURL[],
findings?: IncidentFinding[];
}
export interface IncidentFinding {
id: string;
url: string;
due_date: string;
first_found?: string;
severity: ("high", "medium", "low", "critical, "informational");
has_exempt: boolean;
found_status: ("new", "existing", "autoclosed", "readonly");
}
export interface EvidenceAssetAttachment {
url: string; // hash of the asset or attachment
hash: string; // complete url of the asset or attachment
uri?: string; // name of the asset
}
interface Asset {
version: 1;
id: SHA256;
uri: AssetURI;
date: string;
type: 'commit' | 'image' | 'generic';
origin: {
// any IDs can be used to determine asset origin, see example
[index: string]: string;
},
details: Record<string, string>,
// Assets can relate to each other, for example
// an Image Asset can relate to the Git Commit Asset
// it was built from on code level
related: SHA256[];
}
Ejemplo
Ejemplo de activo v2
{
"version": "1",
"id": "cdd3ee20188d2f5bfb7f14bdb9c7fa99b22184ca195d9fa0a953dfbe9b1769cb",
"uri": "https://github.com/<org-name>/e2e-hello-compliance-app-20220412084808399.git#8c2a65373cb4fd27bccff646e8bdf63d02cae856",
"origin": {
"toolchain_crn": "crn:v1:bluemix:public:toolchain:us-south:a/40111714589c4f7099032529b26a7a63:fd3f2bf6-00f1-417f-b1a2-7df894223115::",
"pipeline_run_id": "a5e89ecc-a413-4dcb-b129-ff870ef3be85",
"pipeline_id": "66b583d9-3d1b-4b34-9e3a-cb807bf0c5ab"
},
"details": {
"sha": "8c2a65373cb4fd27bccff646e8bdf63d02cae856",
"repository": "https://github.com/<org-name>/e2e-hello-compliance-app-20220412084808399.git"
},
"date": "2022-04-20T09:26:46.226Z",
"type": "commit",
"related": [
"26a0f02126461e6505d5001d50ac71e585c280479a01cc70e36397a784440bf8"
]
}
Ejemplo de pruebas v2
{
"version": "2",
"id": "3fd209270fbaf46137ec3966affac2a431a835e750301c7c44d583e0e426e29e",
"date": "2022-04-20T09:33:43.782Z",
"evidence_type_id": "com.ibm.code_vulnerability_scan",
"evidence_type_version": "1.0.0",
"details": {
"result": "failure",
"tool": "cra"
},
"origin": {
"toolchain_crn": "crn:v1:bluemix:public:toolchain:us-south:a/779c0808c946b9e15cc2e63013fded8c:68213c68-4794-4d5e-ab50-f33d0d6190e4::",
"pipeline_id": "c17f18a6-24dd-4949-abb7-2b374f4691b6",
"pipeline_run_id": "d7a88836-72a1-402b-bb28-701439a543ae",
"pipeline_run_url": "https://cloud.ibm.com/devops/pipelines/tekton/c17f18a6-24dd-4949-abb7-2b374f4691b6/runs/d7a88836-72a1-402b-bb28-701439a543ae/code-compliance-checks/run-stage/?env_id=ibm:yp:us-south",
"scope": "117458e26512b0308d93cf6852958e5e875294a982d2b4ea2e9f463b4551a846"
},
"assets": [
{
"hash": "cdd3ee20188d2f5bfb7f14bdb9c7fa99b22184ca195d9fa0a953dfbe9b1769cb",
"uri": "https://github.com/<org-name>/e2e-hello-compliance-app-20220412084808399.git#8c2a65373cb4fd27bccff646e8bdf63d02cae856",
"url": "https://s3.private.us-south.cloud-object-storage.appdomain.cloud/test/assets/cdd3ee20188d2f5bfb7f14bdb9c7fa99b22184ca195d9fa0a953dfbe9b1769cb/index.json"
}
],
"issues": [
"https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/1",
"https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/2",
"https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/3",
],
"findings": [
{
"id": "CVE-2022-42011",
"due_date": "2024-04-20",
"severity": "medium",
"first_found": "2024-03-06",
"url": "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/3",
"found_status": "new",
"has_exempt": true
},
{
"id": "CVE-2022-42010",
"due_date": "2024-04-20",
"severity": "medium",
"first_found": "2024-03-06",
"url": "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/1",
"found_status": "existing",
"has_exempt": false
},
{
"id": "CVE-2023-34969",
"due_date": "2024-04-20",
"severity": "medium",
"first_found": "2024-03-06",
"url": "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/2",
"found_status": "existing",
"has_exempt": true
}
],
"attachments": [
{
"hash": "9a841ef856a5de813dbe440b102b9bff3ca1831630292cff7323c557704f386b",
"url": "https://s3.private.us-south.cloud-object-storage.appdomain.cloud/test/assets/9a841ef856a5de813dbe440b102b9bff3ca1831630292cff7323c557704f386b/index.json"
}
]
}
Resumen de pruebas v2
La interconexión de DevSecOps crea un documento de resumen de pruebas. Este documento contiene las pruebas más recientes que se crean durante cada una de las compilaciones de integración continua que despliegan una imagen, y las pruebas que se crean durante el propio despliegue. El resumen se crea para la solicitud de cambio necesaria para desplegar cualquier etapa.
interface Summary {
version: '2.0'; // schema version
date: string; // ISO-8601, UTC, ie. YYYY-MM-DDThh:mm:ssZ
toolchain_crn: string; // CRN of the toolchain that generated the summary
pipeline_id: string; // ID of the pipeline that generated the summary
pipeline_run_id: string; // ID of the pipeline run that generated the summary
evidences: Evidence[];
}
Este resumen no realiza ninguna agregación de resultados. Son los datos brutos de las pruebas recopiladas v2, tal y como se encontraron para los activos relacionados con una solicitud de cambio.