Сканирование и верификация уязвимостей
В ACP (Alauda Container Platform) можно использовать Tekton Pipeline для сборки образа и сканирования его на наличие уязвимостей.
В частности, используйте задачу trivy для генерации результатов сканирования уязвимостей, затем используйте cosign для загрузки аттестации результатов сканирования уязвимостей, и в конце используйте kyverno для проверки аттестации результатов сканирования уязвимостей.
Обзор функциональности
Этот метод использует инструменты, аналогичные trivy, для сканирования образа на наличие уязвимостей, а затем использует Kyverno для проверки результатов сканирования уязвимостей:
- Используйте Tekton Task
trivy для сканирования образа на наличие уязвимостей.
- Используйте Tekton Task
cosign для загрузки результатов сканирования уязвимостей в образ.
- Настройте правила Kyverno для проверки результатов сканирования уязвимостей.
- Используйте образ для создания Pod, чтобы проверить результаты сканирования уязвимостей.
Сценарии использования
В следующих сценариях необходимо обращаться к рекомендациям в этом документе:
- Реализация сканирования и проверки уязвимостей в кластерах Kubernetes с использованием Kyverno
- Применение политик безопасности, разрешающих развертывание только образов с приемлемым уровнем уязвимостей
- Настройка автоматического сканирования и проверки уязвимостей в CI/CD pipeline
- Обеспечение безопасности образов и соответствия требованиям по уязвимостям в production-средах
- Реализация controls безопасности цепочки поставки для контейнерных образов путем проверки их статуса уязвимостей
Предварительные требования
- Кластер Kubernetes с установленными Tekton Pipelines, Tekton Chains и Kyverno
- Registry с включенной возможностью push образов
- Установленный и настроенный
kubectl CLI для доступа к кластеру
- Установленный
cosign CLI tool
- Установленный
jq CLI tool
Обзор процесса
Пошаговые инструкции
Шаги 1–3: Базовая настройка
Эти шаги идентичны руководству Quick Start: Signed Provenance. Следуйте инструкциям в этом руководстве для:
Шаг 4: Создание примера Pipeline
Это ресурс Pipeline, который используется для сборки образа и генерации cosign vulnerability attestation.
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: chains-demo-4
spec:
params:
- default: |-
echo "Generate a Containerfile for building an image."
cat << 'EOF' > Containerfile
FROM ubuntu:latest
ENV TIME=1
EOF
echo -e "\nContainerfile contents:"
echo "-------------------"
cat Containerfile
echo "-------------------"
echo -e "\nContainerfile generated successfully!"
description: A script to generate a Containerfile for building an image.
name: generate-containerfile
type: string
- default: <registry>/test/chains/demo-4:latest
description: The target image address built
name: image
type: string
results:
- description: first image artifact output
name: first_image_ARTIFACT_OUTPUTS
type: object
value:
digest: $(tasks.build-image.results.IMAGE_DIGEST)
uri: $(tasks.build-image.results.IMAGE_URL)
tasks:
- name: generate-containerfile
params:
- name: script
value: $(params.generate-containerfile)
taskRef:
params:
- name: kind
value: task
- name: catalog
value: catalog
- name: name
value: run-script
- name: version
value: "0.1"
resolver: hub
timeout: 30m0s
workspaces:
- name: source
workspace: source
- name: build-image
params:
- name: IMAGES
value:
- $(params.image)
- name: TLS_VERIFY
value: "false"
runAfter:
- generate-containerfile
taskRef:
params:
- name: kind
value: task
- name: catalog
value: catalog
- name: name
value: buildah
- name: version
value: "0.9"
resolver: hub
timeout: 30m0s
workspaces:
- name: source
workspace: source
- name: registryconfig
workspace: registryconfig
- name: trivy-scanner
params:
- name: COMMAND
value: |-
set -x
mkdir -p .git
# support for insecure registry
export TRIVY_INSECURE=true
echo "generate cyclonedx sbom"
trivy image --skip-db-update --skip-java-db-update --scanners vuln --format cyclonedx --output .git/sbom-cyclonedx.json $(tasks.build-image.results.IMAGE_URL)@$(tasks.build-image.results.IMAGE_DIGEST)
cat .git/sbom-cyclonedx.json
echo "trivy scan vulnerabilities based on cyclonedx sbom"
trivy sbom --skip-db-update --skip-java-db-update --format cosign-vuln --output .git/trivy-scan-result.json .git/sbom-cyclonedx.json
cat .git/trivy-scan-result.json
echo "trivy scan vulnerabilities based on cyclonedx sbom and output in table format"
trivy sbom --skip-db-update --skip-java-db-update --format table .git/sbom-cyclonedx.json
runAfter:
- build-image
taskRef:
params:
- name: kind
value: task
- name: catalog
value: catalog
- name: name
value: trivy-scanner
- name: version
value: "0.4"
resolver: hub
timeout: 30m0s
workspaces:
- name: source
workspace: source
- name: registryconfig
workspace: registryconfig
- name: cosign-uploads
params:
- name: COMMAND
value: |-
set -x
export COSIGN_ALLOW_INSECURE_REGISTRY=true
export COSIGN_TLOG_UPLOAD=false
export COSIGN_KEY=$(workspaces.signkey.path)/cosign.key
echo "Signing image vuln"
cosign attest --type vuln --predicate .git/trivy-scan-result.json $(tasks.build-image.results.IMAGE_URL)@$(tasks.build-image.results.IMAGE_DIGEST)
echo "Signing image sbom"
cosign attest --type cyclonedx --predicate .git/sbom-cyclonedx.json $(tasks.build-image.results.IMAGE_URL)@$(tasks.build-image.results.IMAGE_DIGEST)
runAfter:
- trivy-scanner
taskRef:
params:
- name: kind
value: task
- name: catalog
value: catalog
- name: name
value: cosign
- name: version
value: "0.1"
resolver: hub
timeout: 30m0s
workspaces:
- name: source
workspace: source
- name: registryconfig
workspace: registryconfig
- name: signkey
workspace: signkey
workspaces:
- name: source
description: The workspace for source code.
- name: registryconfig
description: The workspace for distribution registry configuration.
- name: signkey
description: The workspace for private keys and passwords used for image signatures.
TIP
Это руководство демонстрирует упрощенный рабочий процесс: генерация Containerfile и output задачи git-clone выполняются прямо внутри pipeline.
В production-среде обычно:
- Используют задачу
git-clone для получения исходного кода из репозитория
- Собирают образ с использованием Containerfile, который уже присутствует в исходном коде
- Такой подход обеспечивает корректный version control и сохраняет разделение между кодом и конфигурацией pipeline
Пояснение полей YAML
- То же самое, что и в Step 4: Create a Sample Pipeline, но добавляет следующий контент:
workspaces:
signkey: Workspace для закрытых ключей и паролей, используемых для подписей образов.
tasks:
trivy-scanner: Задача для сканирования образа на наличие уязвимостей.
cosign-uploads: Задача для загрузки аттестации результатов сканирования уязвимостей.
:::
Сохраните это в YAML-файл с именем chains-demo-4.yaml и примените его:
$ export NAMESPACE=<default>
# create the pipeline in the namespace
$ kubectl create -n $NAMESPACE -f chains-demo-4.yaml
pipeline.tekton.dev/chains-demo-4 created
Шаг 5: Запуск примера Pipeline
Это ресурс PipelineRun, который используется для запуска pipeline.
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: chains-demo-4-
spec:
pipelineRef:
name: chains-demo-4
taskRunTemplate:
serviceAccountName: <default>
workspaces:
- name: registryconfig
secret:
secretName: <registry-credentials>
- name: signkey
secret:
secretName: <signing-secrets>
- name: source
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: <nfs>
:::details {title="Пояснение полей YAML"}
- То же самое, что и в Step 5: Run a Sample Pipeline. Ниже описаны только различия.
workspaces
signkey: имя secret с signing key.
secret.secretName: Signing secret, подготовленный на предыдущем шаге Get the signing secret. Но вам нужно создать новый secret в том же namespace, что и PipelineRun.
:::
Сохраните это в YAML-файл с именем chains-demo-4.pipelinerun.yaml и примените его:
$ export NAMESPACE=<default>
# create the pipeline run in the namespace
$ kubectl create -n $NAMESPACE -f chains-demo-4.pipelinerun.yaml
Дождитесь завершения PipelineRun.
$ kubectl get pipelinerun -n $NAMESPACE -w
chains-demo-4-<xxxxx> True Succeeded 2m 2m
Шаг 6: Дождаться подписания PipelineRun
Дождитесь, пока у PipelineRun появится аннотация chains.tekton.dev/signed: "true".
$ export NAMESPACE=<default>
$ export PIPELINERUN_NAME=<chains-demo-4-xxxxx>
$ kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o yaml | grep "chains.tekton.dev/signed"
chains.tekton.dev/signed: "true"
Когда у PipelineRun есть аннотация chains.tekton.dev/signed: "true", это означает, что образ подписан.
Шаг 7: Получить образ из PipelineRun
# Get the image URI
$ export IMAGE_URI=$(kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o jsonpath='{.status.results[?(@.name=="first_image_ARTIFACT_OUTPUTS")].value.uri}')
# Get the image digest
$ export IMAGE_DIGEST=$(kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o jsonpath='{.status.results[?(@.name=="first_image_ARTIFACT_OUTPUTS")].value.digest}')
# Combine the image URI and digest to form the full image reference
$ export IMAGE=$IMAGE_URI@$IMAGE_DIGEST
# Print the image reference
$ echo $IMAGE
<registry>/test/chains/demo-4:latest@sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046
Этот образ будет использоваться для проверки результатов сканирования уязвимостей.
Шаг 8: (Необязательно) Получить cosign vuln attestation
Если вам интересно содержимое cosign vuln attestation, можно продолжить чтение следующего материала.
Подробнее о cosign vuln attestation см. в cosign vuln attestation
Получите публичный signing key согласно разделу Get the signing public key.
# Disable tlog upload and enable private infrastructure
$ export COSIGN_TLOG_UPLOAD=false
$ export COSIGN_PRIVATE_INFRASTRUCTURE=true
$ export IMAGE=<<registry>/test/chains/demo-4:latest@sha256:5e7b466e266633464741b61b9746acd7d02c682d2e976b1674f924aa0dfa2047>
$ cosign verify-attestation --key cosign.pub --type vuln $IMAGE | jq -r '.payload | @base64d' | jq -s
Вывод будет похож на следующий и содержит результаты сканирования уязвимостей.
:::details {title="cosign vuln attestation"}
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://cosign.sigstore.dev/attestation/vuln/v1",
"predicate": {
"scanner": {
"uri": "pkg:github/aquasecurity/trivy@dev",
"version": "dev",
"result": {
"CreatedAt": "2025-06-07T07:05:30.098889688Z",
"Metadata": {
"OS": {
"Family": "ubuntu",
"Name": "24.04"
}
},
"Results": [
{
"Class": "os-pkgs",
"Packages": [
{
"Arch": "amd64",
"ID": "coreutils@9.4-3ubuntu6",
"Identifier": {
"BOMRef": "pkg:deb/ubuntu/coreutils@9.4-3ubuntu6?arch=amd64&distro=ubuntu-24.04",
"PURL": "pkg:deb/ubuntu/coreutils@9.4-3ubuntu6?arch=amd64&distro=ubuntu-24.04",
"UID": "82bb3c93286700bc"
},
"Licenses": [
"GPL-3.0-or-later",
"BSD-4-Clause-UC",
"GPL-3.0-only",
"ISC",
"FSFULLR",
"GFDL-1.3-no-invariants-only",
"GFDL-1.3-only"
],
"Name": "coreutils"
}
],
"Vulnerabilities": [
{
"CVSS": {
"nvd": {
"V2Score": 2.1,
"V2Vector": "AV:L/AC:L/Au:N/C:N/I:P/A:N",
"V3Score": 6.5,
"V3Vector": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:N"
},
"redhat": {
"V2Score": 6.2,
"V2Vector": "AV:L/AC:H/Au:N/C:C/I:C/A:C",
"V3Score": 8.6,
"V3Vector": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H"
}
},
"InstalledVersion": "9.4-3ubuntu6",
"LastModifiedDate": "2025-04-20T01:37:25.86Z",
"PkgID": "coreutils@9.4-3ubuntu6",
"PkgName": "coreutils",
"PublishedDate": "2017-02-07T15:59:00.333Z",
"References": [
"http://seclists.org/oss-sec/2016/q1/452",
"http://www.openwall.com/lists/oss-security/2016/02/28/2",
"http://www.openwall.com/lists/oss-security/2016/02/28/3",
"https://access.redhat.com/security/cve/CVE-2016-2781",
"https://lists.apache.org/thread.html/rf9fa47ab66495c78bb4120b0754dd9531ca2ff0430f6685ac9b07772%40%3Cdev.mina.apache.org%3E",
"https://lore.kernel.org/patchwork/patch/793178/",
"https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.28/v2.28-ReleaseNotes",
"https://nvd.nist.gov/vuln/detail/CVE-2016-2781",
"https://www.cve.org/CVERecord?id=CVE-2016-2781"
],
"Severity": "LOW",
"SeveritySource": "ubuntu",
"Status": "affected",
"VendorSeverity": {
"azure": 2,
"cbl-mariner": 2,
"nvd": 2,
"redhat": 2,
"ubuntu": 1
},
"VulnerabilityID": "CVE-2016-2781"
}
]
}
],
"SchemaVersion": 2
}
},
"metadata": {
"scanStartedOn": "2025-06-07T07:05:30.104726629Z",
"scanFinishedOn": "2025-06-07T07:05:30.104726629Z"
}
}
}
:::details {title="Описание полей"}
predicateType: Тип predicate.
predicate.scanner:
uri: URI сканера.
version: Версия сканера.
result: Результат сканирования уязвимостей.
CreatedAt: Время завершения сканирования уязвимостей.
Metadata:
OS:
Family: Семейство ОС.
Name: Имя ОС.
Results: Результаты сканирования уязвимостей.
Class:
os-pkgs: Пакеты ОС.
lang-pkgs: Пакеты языков.
Packages: Пакеты образа.
Vulnerabilities: Уязвимости образа.
Severity: Уровень серьезности уязвимости.
PkgID: Идентификатор пакета, связанного с уязвимостью.
PkgName: Имя пакета.
CVSS: CVSS уязвимости.
nvd: NVD уязвимости.
redhat: Red Hat уязвимости.
:::
Шаг 9: Проверка результатов сканирования уязвимостей с помощью Kyverno
Шаг 9.1: Создать политику Kyverno для отклонения образов с уязвимостями высокого риска
TIP
Для этого шага требуются права cluster administrator.
Подробнее о Kyverno ClusterPolicy см. в Kyverno ClusterPolicy
Политика выглядит следующим образом:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: reject-high-risk-image
spec:
webhookConfiguration:
failurePolicy: Fail
timeoutSeconds: 30
background: false
rules:
- name: check-image
match:
any:
- resources:
kinds:
- Pod
namespaces:
- policy
verifyImages:
- imageReferences:
- "*"
# - "<registry>/test/*"
skipImageReferences:
- "ghcr.io/trusted/*"
failureAction: Enforce
verifyDigest: false
required: false
useCache: false
imageRegistryCredentials:
allowInsecureRegistry: true
secrets:
# The credential needs to exist in the namespace where kyverno is deployed
- registry-credentials
attestations:
- type: https://cosign.sigstore.dev/attestation/vuln/v1
attestors:
- entries:
- attestor:
keys:
publicKeys: |- # <- The public key of the signer
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFZNGfYwn7+b4uSdEYLKjxWi3xtP3
UkR8hQvGrG25r0Ikoq0hI3/tr0m7ecvfM75TKh5jGAlLKSZUJpmCGaTToQ==
-----END PUBLIC KEY-----
ctlog:
ignoreSCT: true
rekor:
ignoreTlog: true
conditions:
- all:
- key: "{{ scanner.result.Results[].Vulnerabilities[].Severity }}"
operator: AllNotIn
# supported values: UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL
value: ["HIGH", "CRITICAL"]
message: |
The image contains high-risk vulnerabilities, please fix them before proceeding.
Severity levels: {{ scanner.result.Results[].Vulnerabilities[].Severity }}
- key: "{{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `1.0`][] | length(@) }}"
operator: Equals
value: 0
message: |
The image contains high-risk vulnerabilities, please fix them before proceeding.
High-risk vulnerabilities (CVSS > 1.0): {{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `1.0`].CVSS.redhat.V3Score[] }}.
Severity levels: {{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `1.0`].Severity[] }}.
PkgIDs: {{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `1.0`].PkgID[] }}.
:::details {title="Пояснение полей YAML"}
- Политика в целом соответствует политике из Image Signature Verification
spec.rules[0].verifyImages[].attestations[0].conditions
type: Тип cosign vuln attestation — https://cosign.sigstore.dev/attestation/vuln/v1
attestors: То же самое, что и выше.
conditions: Условия, которые необходимо проверить.
all: Должны выполняться все условия.
key: "{{ scanner.result.Results[].Vulnerabilities[].Severity }}": Уровень серьезности уязвимостей не должен быть HIGH или CRITICAL.
key: "{{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > 1.0][] | length(@) }}": Количество уязвимостей с CVSS score выше 1.0 должно быть равно 0.
:::
Сохраните политику в YAML-файл с именем kyverno.reject-high-risk-image.yaml и примените ее:
$ kubectl apply -f kyverno.reject-high-risk-image.yaml
clusterpolicy.kyverno.io/reject-high-risk-image configured
Шаг 9.2: Проверить политику
В namespace policy, где определена политика, создайте Pod для проверки политики.
Используйте собранный образ для создания Pod.
$ export NAMESPACE=<policy>
$ export IMAGE=<<registry>/test/chains/demo-4:latest@sha256:0f123204c44969876ed12f40066ccccbfd68361f68c91eb313ac764d59428bef>
$ kubectl run -n $NAMESPACE vuln-image --image=${IMAGE} -- sleep 3600
Если в вашем образе есть уязвимости высокого риска, Pod будет заблокирован политикой.
Вы получите такой вывод:
Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:
resource Pod/policy/high-risk was blocked due to the following policies
reject-high-risk-image:
check-image: |
image attestations verification failed, verifiedCount: 0, requiredCount: 1, error: .attestations[0].attestors[0].entries[0].keys: attestation checks failed for <registry>/test/chains/demo-4:latest and predicate https://cosign.sigstore.dev/attestation/vuln/v1: The image contains high-risk vulnerabilities, please fix them before proceeding.
High-risk vulnerabilities (CVSS > 1.0): [8.6,2.7,6.2,5.9,7.5,4.7,7.4,4.7,7.4,4.7,7.4,4.7,7.4,5.9,3.6,3.6,7.3,4.4,6.5,5.4].
Severity levels: ["LOW","MEDIUM","LOW","LOW","MEDIUM","MEDIUM","MEDIUM","MEDIUM","MEDIUM","MEDIUM","MEDIUM","MEDIUM","MEDIUM","LOW","LOW","LOW","MEDIUM","MEDIUM","MEDIUM","MEDIUM"].
PkgIDs: ["coreutils@9.4-3ubuntu6","gpgv@2.4.4-2ubuntu17","gpgv@2.4.4-2ubuntu17","libgcrypt20@1.10.3-2build1","liblzma5@5.6.1+really5.4.5-1build0.1","libpam-modules@1.5.3-5ubuntu5.1","libpam-modules@1.5.3-5ubuntu5.1","libpam-modules-bin@1.5.3-5ubuntu5.1","libpam-modules-bin@1.5.3-5ubuntu5.1","libpam-runtime@1.5.3-5ubuntu5.1","libpam-runtime@1.5.3-5ubuntu5.1","libpam0g@1.5.3-5ubuntu5.1","libpam0g@1.5.3-5ubuntu5.1","libssl3t64@3.0.13-0ubuntu3.5","login@1:4.13+dfsg1-4ubuntu3.2","passwd@1:4.13+dfsg1-4ubuntu3.2","perl-base@5.38.2-3.2build2.1","golang.org/x/net@v0.23.0","golang.org/x/net@v0.23.0","stdlib@v1.22.12"].
Измените условия в ClusterPolicy, чтобы разрешить образы с уязвимостями высокого риска, но с CVSS score меньше 10.0.
conditions:
- all:
- key: "{{ scanner.result.Results[].Vulnerabilities[].Severity }}"
operator: AllNotIn
value: ["CRITICAL"]
message: |
The image contains high-risk vulnerabilities, please fix them before proceeding.
Severity levels: {{ scanner.result.Results[].Vulnerabilities[].Severity }}
- key: "{{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `10.0`][] | length(@) }}"
operator: Equals
value: 0
message: |
The image contains high-risk vulnerabilities, please fix them before proceeding.
High-risk vulnerabilities (CVSS > 10.0): {{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `10.0`].CVSS.redhat.V3Score[] }}.
Severity levels: {{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `10.0`].Severity[] }}.
PkgIDs: {{ scanner.result.Results[].Vulnerabilities[?CVSS.redhat.V3Score > `10.0`].PkgID[] }}.
Затем снова создайте Pod, чтобы проверить политику.
$ kubectl run -n $NAMESPACE vuln-image --image=${IMAGE} -- sleep 3600
Pod будет создан успешно.
Шаг 10: (Необязательно) Требовать, чтобы результаты сканирования уязвимостей были не старше 168 часов
TIP
Если вы хотите добавить в политику дополнительные условия, можно продолжить чтение следующего материала.
Поскольку Cosign Vulnerability Scan Record Attestation включает поле scanFinishedOn,
а trivy соответствует спецификации, мы можем использовать это поле, чтобы определить, были ли результаты сканирования уязвимостей получены не более 168 часов назад.
Нам нужно только добавить условие в ClusterPolicy, чтобы проверить, находится ли поле scanFinishedOn в пределах 168 часов.
conditions:
- all:
- key: "{{ time_since('','{{metadata.scanFinishedOn}}','') }}"
operator: LessThanOrEquals
value: "168h"
message: "The vulnerability scan results must be within 168 hours, not {{ metadata.scanFinishedOn }}"
Здесь это не демонстрируется; заинтересованные читатели могут попробовать сами.
Шаг 11: Очистка ресурсов
Удалите Pod, созданные на предыдущих шагах.
$ export NAMESPACE=<policy>
$ kubectl delete pod -n $NAMESPACE vuln-image
Удалите политику.
$ kubectl delete clusterpolicy reject-high-risk-image
Ожидаемые результаты
После выполнения этого руководства:
- У вас будет рабочая конфигурация Tekton Chains для сканирования уязвимостей и Kyverno для проверки уязвимостей
- Ваши container images автоматически будут включать результаты сканирования уязвимостей в своих аттестациях
- Только образы с приемлемым уровнем уязвимостей смогут быть развернуты в указанном namespace
- Образы с уязвимостями высокого риска будут автоматически блокироваться политиками Kyverno
- Вы реализуете базовый control безопасности цепочки поставки, проверяя статус уязвимостей ваших container images
Это руководство служит основой для внедрения безопасности цепочки поставки в ваши CI/CD pipeline. В production-среде следует:
- Настроить корректную изоляцию namespace и control доступа
- Реализовать безопасное управление ключами для signing keys
- Настроить мониторинг и оповещения о нарушениях политик
- Регулярно обновлять signing keys и security policies
Ссылки