fix(storage): deleting manifests with identical digests (#951)

Suppose we push two identical manifests (sharing same digest) but with
different tags, then deleting by digest should throw an error otherwise
we end up deleting all image tags (with gc) or dangling references
(without gc)

This behaviour is controlled via Authorization, added a new policy
action named detectManifestsCollision which enables this behaviour

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>

Co-authored-by: Ramkumar Chinchani <rchincha@cisco.com>
This commit is contained in:
peusebiu
2022-11-18 19:35:28 +02:00
committed by GitHub
parent 4e13619dc8
commit 168d21da1e
22 changed files with 507 additions and 141 deletions
@@ -53,7 +53,6 @@ function setup_file() {
}
}
EOF
git -C ${BATS_FILE_TMPDIR} clone https://github.com/project-zot/helm-charts.git
setup_zot_file_level ${zot_config_file}
wait_zot_reachable "http://127.0.0.1:8080/v2/_catalog"
}
@@ -66,7 +65,6 @@ function teardown_file() {
rm -rf ${oci_data_dir}
}
@test "push image user policy" {
run skopeo --insecure-policy copy --dest-creds test:test --dest-tls-verify=false \
oci:${TEST_DATA_DIR}/golang:1.18 \
@@ -74,7 +72,6 @@ function teardown_file() {
[ "$status" -eq 0 ]
}
@test "pull image anonymous policy" {
local oci_data_dir=${BATS_FILE_TMPDIR}/oci
run skopeo --insecure-policy copy --src-tls-verify=false \
@@ -0,0 +1,109 @@
load helpers_pushpull
function setup_file() {
# Verify prerequisites are available
if ! verify_prerequisites; then
exit 1
fi
# Download test data to folder common for the entire suite, not just this file
skopeo --insecure-policy copy --format=oci docker://ghcr.io/project-zot/golang:1.19 oci:${TEST_DATA_DIR}/golang:1.19
# Setup zot server
local zot_root_dir=${BATS_FILE_TMPDIR}/zot
local zot_config_file=${BATS_FILE_TMPDIR}/zot_config.json
local oci_data_dir=${BATS_FILE_TMPDIR}/oci
local htpasswordFile=${BATS_FILE_TMPDIR}/htpasswd
mkdir -p ${zot_root_dir}
mkdir -p ${oci_data_dir}
echo 'test:$2a$10$EIIoeCnvsIDAJeDL4T1sEOnL2fWOvsq7ACZbs3RT40BBBXg.Ih7V.' >> ${htpasswordFile}
cat > ${zot_config_file}<<EOF
{
"distSpecVersion": "1.0.1",
"storage": {
"rootDirectory": "${zot_root_dir}"
},
"http": {
"address": "127.0.0.1",
"port": "8080",
"auth": {
"htpasswd": {
"path": "${htpasswordFile}"
}
},
"accessControl": {
"**": {
"anonymousPolicy": [
"read",
"create",
"delete",
"detectManifestCollision"
],
"policies": [
{
"users": [
"test"
],
"actions": [
"read",
"create",
"delete"
]
}
]
}
}
},
"log": {
"level": "debug"
}
}
EOF
setup_zot_file_level ${zot_config_file}
wait_zot_reachable "http://127.0.0.1:8080/v2/_catalog"
}
function teardown_file() {
local zot_root_dir=${BATS_FILE_TMPDIR}/zot
local oci_data_dir=${BATS_FILE_TMPDIR}/oci
teardown_zot_file_level
rm -rf ${zot_root_dir}
rm -rf ${oci_data_dir}
}
@test "push 2 images with same manifest with user policy" {
run skopeo --insecure-policy copy --dest-creds test:test --dest-tls-verify=false \
oci:${TEST_DATA_DIR}/golang:1.19 \
docker://127.0.0.1:8080/golang:1.19
[ "$status" -eq 0 ]
run skopeo --insecure-policy copy --dest-creds test:test --dest-tls-verify=false \
oci:${TEST_DATA_DIR}/golang:1.19 \
docker://127.0.0.1:8080/golang:latest
[ "$status" -eq 0 ]
}
@test "skopeo delete image with anonymous policy should fail" {
# skopeo deletes by digest, so it should fail with detectManifestCollision policy
run skopeo --insecure-policy delete --tls-verify=false \
docker://127.0.0.1:8080/golang:1.19
[ "$status" -eq 1 ]
# conflict status code
[[ "$output" == *"409"* ]]
}
@test "regctl delete image with anonymous policy should fail" {
run regctl registry set localhost:8080 --tls disabled
[ "$status" -eq 0 ]
run regctl image delete localhost:8080/golang:1.19 --force-tag-dereference
[ "$status" -eq 1 ]
# conflict status code
[[ "$output" == *"409"* ]]
}
@test "delete image with user policy should work" {
# should work without detectManifestCollision policy
run skopeo --insecure-policy delete --creds test:test --tls-verify=false \
docker://127.0.0.1:8080/golang:1.19
[ "$status" -eq 0 ]
}