zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/test/blackbox/annotations.bats (about) 1 # Note: Intended to be run as "make run-blackbox-tests" or "make run-blackbox-ci" 2 # Makefile target installs & checks all necessary tooling 3 # Extra tools that are not covered in Makefile target needs to be added in verify_prerequisites() 4 5 load helpers_zot 6 7 function verify_prerequisites { 8 if [ ! $(command -v curl) ]; then 9 echo "you need to install curl as a prerequisite to running the tests" >&3 10 return 1 11 fi 12 13 if [ ! $(command -v jq) ]; then 14 echo "you need to install jq as a prerequisite to running the tests" >&3 15 return 1 16 fi 17 18 if [ ! $(command -v podman) ]; then 19 echo "you need to install podman as a prerequisite to running the tests" >&3 20 return 1 21 fi 22 23 return 0 24 } 25 26 function setup_file() { 27 export COSIGN_PASSWORD="" 28 # Verify prerequisites are available 29 if ! $(verify_prerequisites); then 30 exit 1 31 fi 32 # Download test data to folder common for the entire suite, not just this file 33 skopeo --insecure-policy copy --format=oci docker://ghcr.io/project-zot/golang:1.20 oci:${TEST_DATA_DIR}/golang:1.20 34 # Setup zot server 35 local zot_root_dir=${BATS_FILE_TMPDIR}/zot 36 local zot_config_file=${BATS_FILE_TMPDIR}/zot_config.json 37 mkdir -p ${zot_root_dir} 38 zot_port=$(get_free_port) 39 echo ${zot_port} > ${BATS_FILE_TMPDIR}/zot.port 40 cat > ${zot_config_file}<<EOF 41 { 42 "distSpecVersion": "1.1.0-dev", 43 "storage": { 44 "rootDirectory": "${zot_root_dir}" 45 }, 46 "http": { 47 "address": "0.0.0.0", 48 "port": "${zot_port}" 49 }, 50 "log": { 51 "level": "debug", 52 "output": "${BATS_FILE_TMPDIR}/zot.log" 53 }, 54 "extensions":{ 55 "search": { 56 "enable": "true" 57 }, 58 "lint": { 59 "enable": "true", 60 "mandatoryAnnotations": ["org.opencontainers.image.licenses", "org.opencontainers.image.vendor"] 61 } 62 } 63 } 64 EOF 65 cat > ${BATS_FILE_TMPDIR}/stacker.yaml<<EOF 66 \${{IMAGE_NAME}}: 67 from: 68 type: docker 69 url: docker://\${{IMAGE_NAME}}:\${{IMAGE_TAG}} 70 annotations: 71 org.opencontainers.image.title: \${{IMAGE_NAME}} 72 org.opencontainers.image.description: \${{DESCRIPTION}} 73 org.opencontainers.image.licenses: \${{LICENSES}} 74 org.opencontainers.image.vendor: \${{VENDOR}} 75 EOF 76 cat > ${BATS_FILE_TMPDIR}/Dockerfile<<EOF 77 FROM public.ecr.aws/t0x7q1g8/centos:7 78 CMD ["/bin/sh", "-c", "echo 'It works!'"] 79 EOF 80 zot_serve ${ZOT_PATH} ${zot_config_file} 81 wait_zot_reachable ${zot_port} 82 } 83 84 function teardown() { 85 # conditionally printing on failure is possible from teardown but not from from teardown_file 86 cat ${BATS_FILE_TMPDIR}/zot.log 87 } 88 89 function teardown_file() { 90 zot_stop_all 91 run rm -rf ${HOME}/.config/notation 92 } 93 94 @test "build image with podman and specify annotations" { 95 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 96 run podman build -f ${BATS_FILE_TMPDIR}/Dockerfile -t 127.0.0.1:${zot_port}/annotations:latest . --format oci --annotation org.opencontainers.image.vendor="CentOS" --annotation org.opencontainers.image.licenses="GPLv2" 97 [ "$status" -eq 0 ] 98 run podman push 127.0.0.1:${zot_port}/annotations:latest --tls-verify=false --format=oci 99 [ "$status" -eq 0 ] 100 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"annotations\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 101 [ "$status" -eq 0 ] 102 103 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ] 104 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].Vendor') = '"CentOS"' ] 105 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].Licenses') = '"GPLv2"' ] 106 } 107 108 @test "build image with stacker and specify annotations" { 109 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 110 run stacker --oci-dir ${BATS_FILE_TMPDIR}/stackeroci --stacker-dir ${BATS_FILE_TMPDIR}/.stacker --roots-dir ${BATS_FILE_TMPDIR}/roots build -f ${BATS_FILE_TMPDIR}/stacker.yaml --substitute IMAGE_NAME="ghcr.io/project-zot/golang" --substitute IMAGE_TAG="1.20" --substitute DESCRIPTION="mydesc" --substitute VENDOR="CentOs" --substitute LICENSES="GPLv2" --substitute COMMIT= --substitute OS=$OS --substitute ARCH=$ARCH 111 [ "$status" -eq 0 ] 112 run stacker --oci-dir ${BATS_FILE_TMPDIR}/stackeroci --stacker-dir ${BATS_FILE_TMPDIR}/.stacker --roots-dir ${BATS_FILE_TMPDIR}/roots publish -f ${BATS_FILE_TMPDIR}/stacker.yaml --substitute IMAGE_NAME="ghcr.io/project-zot/golang" --substitute IMAGE_TAG="1.20" --substitute DESCRIPTION="mydesc" --substitute VENDOR="CentOs" --substitute LICENSES="GPLv2" --url docker://127.0.0.1:${zot_port} --tag 1.20 --skip-tls 113 [ "$status" -eq 0 ] 114 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"ghcr.io/project-zot/golang\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses Description }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 115 [ "$status" -eq 0 ] 116 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"ghcr.io/project-zot/golang"' ] 117 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].Description') = '"mydesc"' ] 118 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].Vendor') = '"CentOs"' ] 119 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].Licenses') = '"GPLv2"' ] 120 } 121 122 @test "sign/verify with cosign (only tag-based signatures)" { 123 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 124 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"annotations\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 125 [ "$status" -eq 0 ] 126 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ] 127 local digest=$(echo "${lines[-1]}" | jq -r '.data.ImageList.Results[0].Manifests[0].Digest') 128 129 run cosign initialize 130 [ "$status" -eq 0 ] 131 run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test" 132 [ "$status" -eq 0 ] 133 run cosign sign --key ${BATS_FILE_TMPDIR}/cosign-sign-test.key localhost:${zot_port}/annotations:latest --yes 134 [ "$status" -eq 0 ] 135 run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test.pub localhost:${zot_port}/annotations:latest 136 [ "$status" -eq 0 ] 137 local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"') 138 [[ "$sigName" == *"${digest}"* ]] 139 } 140 141 @test "sign/verify with cosign (only referrers)" { 142 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 143 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"annotations\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 144 [ "$status" -eq 0 ] 145 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ] 146 local digest=$(echo "${lines[-1]}" | jq -r '.data.ImageList.Results[0].Manifests[0].Digest') 147 148 export COSIGN_OCI_EXPERIMENTAL=1 149 export COSIGN_EXPERIMENTAL=1 150 run cosign initialize 151 [ "$status" -eq 0 ] 152 run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-experimental" 153 [ "$status" -eq 0 ] 154 run cosign sign --registry-referrers-mode=oci-1-1 --key ${BATS_FILE_TMPDIR}/cosign-sign-test-experimental.key localhost:${zot_port}/annotations:latest --yes 155 [ "$status" -eq 0 ] 156 run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-experimental.pub localhost:${zot_port}/annotations:latest 157 [ "$status" -eq 0 ] 158 local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"') 159 [[ "$sigName" == *"${digest}"* ]] 160 unset COSIGN_OCI_EXPERIMENTAL 161 unset COSIGN_EXPERIMENTAL 162 } 163 164 @test "sign/verify with cosign (tag and referrers)" { 165 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 166 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"annotations\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 167 [ "$status" -eq 0 ] 168 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ] 169 local digest=$(echo "${lines[-1]}" | jq -r '.data.ImageList.Results[0].Manifests[0].Digest') 170 171 export COSIGN_OCI_EXPERIMENTAL=1 172 export COSIGN_EXPERIMENTAL=1 173 run cosign initialize 174 [ "$status" -eq 0 ] 175 176 run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-tag-1" 177 [ "$status" -eq 0 ] 178 run cosign sign --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-1.key localhost:${zot_port}/annotations:latest --yes 179 [ "$status" -eq 0 ] 180 181 run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-1" 182 [ "$status" -eq 0 ] 183 run cosign sign --registry-referrers-mode=oci-1-1 --key ${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-1.key localhost:${zot_port}/annotations:latest --yes 184 [ "$status" -eq 0 ] 185 186 run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-tag-2" 187 [ "$status" -eq 0 ] 188 run cosign sign --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-2.key localhost:${zot_port}/annotations:latest --yes 189 [ "$status" -eq 0 ] 190 191 run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-1.pub localhost:${zot_port}/annotations:latest 192 [ "$status" -eq 0 ] 193 local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"') 194 [[ "$sigName" == *"${digest}"* ]] 195 run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-2.pub localhost:${zot_port}/annotations:latest 196 [ "$status" -eq 0 ] 197 local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"') 198 [[ "$sigName" == *"${digest}"* ]] 199 run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-1.pub localhost:${zot_port}/annotations:latest 200 [ "$status" -eq 0 ] 201 local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"') 202 [[ "$sigName" == *"${digest}"* ]] 203 204 run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-2" 205 [ "$status" -eq 0 ] 206 run cosign sign --registry-referrers-mode=oci-1-1 --key ${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-2.key localhost:${zot_port}/annotations:latest --yes 207 [ "$status" -eq 0 ] 208 run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-2.pub localhost:${zot_port}/annotations:latest 209 [ "$status" -eq 0 ] 210 local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"') 211 [[ "$sigName" == *"${digest}"* ]] 212 213 unset COSIGN_OCI_EXPERIMENTAL 214 unset COSIGN_EXPERIMENTAL 215 } 216 217 @test "sign/verify with notation" { 218 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 219 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"annotations\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 220 [ "$status" -eq 0 ] 221 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ] 222 [ "$status" -eq 0 ] 223 224 run notation cert generate-test "notation-sign-test" 225 [ "$status" -eq 0 ] 226 227 local trust_policy_file=${HOME}/.config/notation/trustpolicy.json 228 229 cat >${trust_policy_file} <<EOF 230 { 231 "version": "1.0", 232 "trustPolicies": [ 233 { 234 "name": "notation-sign-test", 235 "registryScopes": [ "*" ], 236 "signatureVerification": { 237 "level" : "strict" 238 }, 239 "trustStores": [ "ca:notation-sign-test" ], 240 "trustedIdentities": [ 241 "*" 242 ] 243 } 244 ] 245 } 246 EOF 247 248 run notation sign --key "notation-sign-test" --insecure-registry localhost:${zot_port}/annotations:latest 249 [ "$status" -eq 0 ] 250 run notation verify --insecure-registry localhost:${zot_port}/annotations:latest 251 [ "$status" -eq 0 ] 252 run notation list --insecure-registry localhost:${zot_port}/annotations:latest 253 [ "$status" -eq 0 ] 254 } 255 256 @test "sign/verify with notation( NOTATION_EXPERIMENTAL=1 and --allow-referrers-api )" { 257 zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port` 258 run curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageList(repo: \"annotations\") { Results { RepoName Tag Manifests {Digest ConfigDigest Size Layers { Size Digest }} Vendor Licenses }}}"}' http://localhost:${zot_port}/v2/_zot/ext/search 259 [ "$status" -eq 0 ] 260 [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ] 261 [ "$status" -eq 0 ] 262 263 run notation cert generate-test "notation-sign-test-experimental" 264 [ "$status" -eq 0 ] 265 266 local trust_policy_file=${HOME}/.config/notation/trustpolicy.json 267 268 cat >${trust_policy_file} <<EOF 269 { 270 "version": "1.0", 271 "trustPolicies": [ 272 { 273 "name": "notation-sign-test-experimental", 274 "registryScopes": [ "*" ], 275 "signatureVerification": { 276 "level" : "strict" 277 }, 278 "trustStores": [ "ca:notation-sign-test-experimental" ], 279 "trustedIdentities": [ 280 "*" 281 ] 282 } 283 ] 284 } 285 EOF 286 287 export NOTATION_EXPERIMENTAL=1 288 run notation sign --allow-referrers-api --key "notation-sign-test-experimental" --insecure-registry localhost:${zot_port}/annotations:latest 289 [ "$status" -eq 0 ] 290 run notation verify --allow-referrers-api --insecure-registry localhost:${zot_port}/annotations:latest 291 [ "$status" -eq 0 ] 292 run notation list --allow-referrers-api --insecure-registry localhost:${zot_port}/annotations:latest 293 [ "$status" -eq 0 ] 294 unset NOTATION_EXPERIMENTAL 295 }