turbot/steampipe-mod-github-compliance

Control: 2.4.6 Ensure pipeline steps sign the SBOM produced

Description

An SBOM is a file that specifies each component of software or a build process. It should be generated after every pipeline run. After it is generated, it must then be signed.

Rationale

An SBOM is a file used to validate the integrity and security of a build pipeline. Signing it ensures that no one tampered with the file when it was delivered. Such interference can happen if someone tries to hide unusual activity. Validating the SBOM signature can detect this activity and prevent much greater incident.

Audit

For each pipeline, ensure it signs the SBOM it produces on every run.

Remediation

For each pipeline, configure it to sign its produced SBOM on every run.

Usage

Run the control in your terminal:

powerpipe control run github_compliance.control.cis_supply_chain_v100_2_4_6

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run github_compliance.control.cis_supply_chain_v100_2_4_6 --share

SQL

This control uses a named query:

with repositories as (
select
name_with_owner,
url
from
github_my_repository
order by
name_with_owner
),
pipelines as (
select
name,
repository_full_name,
pipeline
from
github_workflow
where
repository_full_name in (select name_with_owner from repositories)
),
build_jobs_sbom_details as (
select
p.repository_full_name,
count(*) filter (
where
(
(step ->> 'type' = 'task'
and (step -> 'task' ->> 'name')::text in (
'argonsecurity/actions/generate-manifest',
'anchore/sbom-action',
'CycloneDX/gh-\w+-generate-sbom'
)
)
or (step ->> 'type' = 'shell'
and ((step -> 'shell' ->> 'script')::text like glob('billy generate') or
(step -> 'shell' ->> 'script')::text like glob('trivy sbom') or
(step -> 'shell' ->> 'script')::text like glob('trivy .* --format cyclonedx') or
(step -> 'shell' ->> 'script')::text like glob('syft .*') or
(step -> 'shell' ->> 'script')::text like glob('spdx-sbom-generator') or
(step -> 'shell' ->> 'script')::text like glob('cyclonedx-\w+') or
(step -> 'shell' ->> 'script')::text like glob('jake sbom')
)
)
)
) as jobs_with_sbom,
count(*) filter (
where
(job -> 'metadata' -> 'build')::bool
and (
not (step ->> 'type' = 'task'
and (step -> 'task' ->> 'name')::text in (
'argonsecurity/actions/generate-manifest',
'anchore/sbom-action',
'CycloneDX/gh-\w+-generate-sbom'
)
)
or not (step ->> 'type' = 'shell'
and ((step -> 'shell' ->> 'script')::text like glob('billy generate') or
(step -> 'shell' ->> 'script')::text like glob('trivy sbom') or
(step -> 'shell' ->> 'script')::text like glob('trivy .* --format cyclonedx') or
(step -> 'shell' ->> 'script')::text like glob('syft .*') or
(step -> 'shell' ->> 'script')::text like glob('spdx-sbom-generator') or
(step -> 'shell' ->> 'script')::text like glob('cyclonedx-\w+') or
(step -> 'shell' ->> 'script')::text like glob('jake sbom')
)
)
)
) as jobs_without_sbom
from
pipelines as p,
jsonb_array_elements(pipeline -> 'jobs') as job,
jsonb_array_elements(job -> 'steps') as step
group by
p.repository_full_name,
pipeline
),
pipeline_with_sbom_job_details as (
select
repository_full_name,
count(*) filter (where jobs_with_sbom > 0) as pipeline_with_sbom_jobs,
count(*) filter (where jobs_without_sbom > 0) as pipeline_without_sbom_jobs
from
build_jobs_sbom_details
group by
repository_full_name
)
select
-- Required Columns
r.url as resource,
case
when ps.pipeline_without_sbom_jobs > 0 then 'alarm'
when ps.repository_full_name is null then 'info'
else 'ok'
end as status,
case
when ps.pipeline_without_sbom_jobs > 0 then ps.pipeline_without_sbom_jobs::text || ' pipeline(s) contain a build job without SBOM generation.'
when ps.repository_full_name is null then 'No pipelines available in the repository.'
else 'All pipeline(s) contain a build job with SBOM generation.'
end as reason,
-- Additional Dimensions
r.name_with_owner
from
repositories as r
left join pipeline_with_sbom_job_details as ps on r.name_with_owner = ps.repository_full_name;

Tags