zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/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",
    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      tags=( $(oras repo tags --plain-http localhost:${zot_port}/annotations) )
   140      [ "$status" -eq 0 ]
   141      local sigdes=$(oras manifest fetch --descriptor localhost:${zot_port}/annotations:${tags[1]} | jq  .digest | tr -d \")
   142      [ "$status" -eq 0 ]
   143      run oras manifest fetch --plain-http localhost:${zot_port}/annotations@${sigdes}
   144      [ "$status" -eq 0 ]
   145  }
   146  
   147  @test "sign/verify with cosign (only referrers)" {
   148      zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port`
   149      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
   150      [ "$status" -eq 0 ]
   151      [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ]
   152      local digest=$(echo "${lines[-1]}" | jq -r '.data.ImageList.Results[0].Manifests[0].Digest')
   153  
   154      export COSIGN_OCI_EXPERIMENTAL=1
   155      export COSIGN_EXPERIMENTAL=1
   156      run cosign initialize
   157      [ "$status" -eq 0 ]
   158      run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-experimental"
   159      [ "$status" -eq 0 ]
   160      run cosign sign --registry-referrers-mode=oci-1-1 --key ${BATS_FILE_TMPDIR}/cosign-sign-test-experimental.key localhost:${zot_port}/annotations:latest --yes
   161      [ "$status" -eq 0 ]
   162      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-experimental.pub localhost:${zot_port}/annotations:latest
   163      [ "$status" -eq 0 ]
   164      local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"')
   165      [[ "$sigName" == *"${digest}"* ]]
   166      unset COSIGN_OCI_EXPERIMENTAL
   167      unset COSIGN_EXPERIMENTAL
   168  }
   169  
   170  @test "sign/verify with cosign (tag and referrers)" {
   171      zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port`
   172      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
   173      [ "$status" -eq 0 ]
   174      [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ]
   175      local digest=$(echo "${lines[-1]}" | jq -r '.data.ImageList.Results[0].Manifests[0].Digest')
   176  
   177      export COSIGN_OCI_EXPERIMENTAL=1
   178      export COSIGN_EXPERIMENTAL=1
   179      run cosign initialize
   180      [ "$status" -eq 0 ]
   181  
   182      run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-tag-1"
   183      [ "$status" -eq 0 ]
   184      run cosign sign --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-1.key localhost:${zot_port}/annotations:latest --yes
   185      [ "$status" -eq 0 ]
   186  
   187      run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-1"
   188      [ "$status" -eq 0 ]
   189      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
   190      [ "$status" -eq 0 ]
   191  
   192      run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-tag-2"
   193      [ "$status" -eq 0 ]
   194      run cosign sign --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-2.key localhost:${zot_port}/annotations:latest --yes
   195      [ "$status" -eq 0 ]
   196  
   197      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-1.pub localhost:${zot_port}/annotations:latest
   198      [ "$status" -eq 0 ]
   199      local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"')
   200      [[ "$sigName" == *"${digest}"* ]]
   201      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-tag-2.pub localhost:${zot_port}/annotations:latest
   202      [ "$status" -eq 0 ]
   203      local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"')
   204      [[ "$sigName" == *"${digest}"* ]]
   205      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-1.pub localhost:${zot_port}/annotations:latest
   206      [ "$status" -eq 0 ]
   207      local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"')
   208      [[ "$sigName" == *"${digest}"* ]]
   209  
   210      run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-2"
   211      [ "$status" -eq 0 ]
   212      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
   213      [ "$status" -eq 0 ]
   214      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-test-referrers-2.pub localhost:${zot_port}/annotations:latest
   215      [ "$status" -eq 0 ]
   216      local sigName=$(echo "${lines[-1]}" | jq '.[].critical.image."docker-manifest-digest"')
   217      [[ "$sigName" == *"${digest}"* ]]
   218  
   219      unset COSIGN_OCI_EXPERIMENTAL
   220      unset COSIGN_EXPERIMENTAL
   221  }
   222  
   223  @test "sign/verify with notation" {
   224      zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port`
   225      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
   226      [ "$status" -eq 0 ]
   227      [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ]
   228      [ "$status" -eq 0 ]
   229  
   230      run notation cert generate-test "notation-sign-test"
   231      [ "$status" -eq 0 ]
   232  
   233      local trust_policy_file=${HOME}/.config/notation/trustpolicy.json
   234  
   235      cat >${trust_policy_file} <<EOF
   236  {
   237      "version": "1.0",
   238      "trustPolicies": [
   239          {
   240              "name": "notation-sign-test",
   241              "registryScopes": [ "*" ],
   242              "signatureVerification": {
   243                  "level" : "strict"
   244              },
   245              "trustStores": [ "ca:notation-sign-test" ],
   246              "trustedIdentities": [
   247                  "*"
   248              ]
   249          }
   250      ]
   251  }
   252  EOF
   253  
   254      run notation sign --key "notation-sign-test" --insecure-registry localhost:${zot_port}/annotations:latest
   255      [ "$status" -eq 0 ]
   256      run notation verify --insecure-registry localhost:${zot_port}/annotations:latest
   257      [ "$status" -eq 0 ]
   258      run notation list --insecure-registry localhost:${zot_port}/annotations:latest
   259      [ "$status" -eq 0 ]
   260  }
   261  
   262  @test "sign/verify with notation( NOTATION_EXPERIMENTAL=1 and --allow-referrers-api )" {
   263      zot_port=`cat ${BATS_FILE_TMPDIR}/zot.port`
   264      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
   265      [ "$status" -eq 0 ]
   266      [ $(echo "${lines[-1]}" | jq '.data.ImageList.Results[0].RepoName') = '"annotations"' ]
   267      [ "$status" -eq 0 ]
   268  
   269      run notation cert generate-test "notation-sign-test-experimental"
   270      [ "$status" -eq 0 ]
   271  
   272      local trust_policy_file=${HOME}/.config/notation/trustpolicy.json
   273  
   274      cat >${trust_policy_file} <<EOF
   275  {
   276      "version": "1.0",
   277      "trustPolicies": [
   278          {
   279              "name": "notation-sign-test-experimental",
   280              "registryScopes": [ "*" ],
   281              "signatureVerification": {
   282                  "level" : "strict"
   283              },
   284              "trustStores": [ "ca:notation-sign-test-experimental" ],
   285              "trustedIdentities": [
   286                  "*"
   287              ]
   288          }
   289      ]
   290  }
   291  EOF
   292  
   293      export NOTATION_EXPERIMENTAL=1
   294      run notation sign --allow-referrers-api --key "notation-sign-test-experimental" --insecure-registry localhost:${zot_port}/annotations:latest
   295      [ "$status" -eq 0 ]
   296      run notation verify --allow-referrers-api --insecure-registry localhost:${zot_port}/annotations:latest
   297      [ "$status" -eq 0 ]
   298      run notation list --allow-referrers-api --insecure-registry localhost:${zot_port}/annotations:latest
   299      [ "$status" -eq 0 ]
   300      unset NOTATION_EXPERIMENTAL
   301  }