Сканирование и верификация уязвимостей
В ACP (Alauda Container Platform) можно использовать Tekton Pipeline для сборки и сканирования образа на наличие уязвимостей.
В частности, используйте задачу trivy для генерации результатов сканирования уязвимостей, затем используйте cosign для загрузки аттестации результатов сканирования уязвимостей и, наконец, используйте kyverno для проверки аттестации результатов сканирования уязвимостей.
Обзор функциональности
Этот метод использует инструменты, подобные trivy, для сканирования образа на наличие уязвимостей, а затем использует Kyverno для проверки результатов сканирования уязвимостей:
- Используйте Tekton Task
trivy для сканирования образа на наличие уязвимостей.
- Используйте Tekton Task
cosign для загрузки результатов сканирования уязвимостей в образ.
- Настройте правила Kyverno для проверки результатов сканирования уязвимостей.
- Используйте образ для создания Pod, чтобы проверить результаты сканирования уязвимостей.
Сценарии использования
Следующие сценарии требуют обращения к рекомендациям в этом документе:
- Реализация сканирования и верификации уязвимостей в кластерах Kubernetes с использованием Kyverno
- Применение политик безопасности, разрешающих развертывание только образов с приемлемым уровнем уязвимостей
- Настройка автоматизированного сканирования и верификации уязвимостей в CI/CD-конвейерах
- Обеспечение безопасности образов и соответствия требованиям по уязвимостям в production-средах
- Реализация средств контроля безопасности цепочки поставки для container image путем проверки их состояния уязвимостей
Предварительные требования
- Кластер Kubernetes с установленными Tekton Pipelines, Tekton Chains и Kyverno
- Registry с включенной возможностью push образов
- Установленный и настроенный для доступа к кластеру CLI
kubectl
- Установленный CLI-инструмент
cosign
- Установленный CLI-инструмент
jq
Обзор процесса
Пошаговые инструкции
Шаги 1–3: Базовая настройка
Эти шаги идентичны руководству Quick Start: Signed Provenance. Пожалуйста, выполните в этом руководстве инструкции для:
Шаг 4: Создание примера Pipeline
Это ресурс Pipeline, который используется для сборки образа и генерации cosign-аттестации уязвимостей.
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 и вывод задачи git-clone генерируются непосредственно внутри pipeline.
В production-средах обычно:
- Используют задачу
git-clone для получения исходного кода из вашего repository
- Собирают образ с использованием Containerfile, который уже находится в исходном коде
- Такой подход обеспечивает корректное управление версиями и сохраняет разделение между кодом и конфигурацией pipeline
Пояснение полей YAML
- То же самое, что и в Шаг 4: Создание примера Pipeline, но добавляется следующий контент:
workspaces:
signkey: workspace для private keys и паролей, используемых для подписей образов.
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"}
- То же самое, что и в Шаг 5: Запуск примера Pipeline. Ниже приведены только различия.
workspaces
signkey: имя secret для signing key.
secret.secretName: signing secret, подготовленный на предыдущем шаге Получение 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: семейство OS.
Name: название OS.
Results: результаты сканирования уязвимостей.
Class:
os-pkgs: пакеты OS.
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
- Вы реализуете базовый контроль безопасности цепочки поставки, проверяя состояние уязвимостей ваших container images
Это руководство закладывает основу для внедрения безопасности цепочки поставки в ваши CI/CD-конвейеры. В production-среде следует:
- Настроить надлежащую изоляцию namespace и управление доступом
- Реализовать безопасное управление ключами для signing keys
- Настроить мониторинг и оповещения о нарушениях политик
- Регулярно ротировать signing keys и обновлять политики безопасности
Ссылки