Verifying container image security

When it comes to inspecting and transporting images, skopeo is a useful tool as it does not need a docker or a daemon. It can be used easily in continuous integration (CI) pipelines to copy images between two registries, provide credentials for secured registries, or to promote images from a development registry into production.

About this task

IBM Cloud Pak® for Business Automation provides container images in the IBM® Entitled Registry that are signed following the approach from Red Hat. You can use the signature to verify that the images come from IBM when they are pulled onto the system. For more information about the signature verification, see https://developers.redhat.com/blog/2019/10/29/verifying-signatures-of-red-hat-container-images/.

To inspect the Cloud Pak container images and to convert them if necessary, you can use the skopeo tool. Skopeo is a utility run on the command line that provides various operations with container images and registries.

The following sections can be used to verify the Cloud Pak for Business Automation signature on the container images.

Creating a public key to pull images from IBM Cloud

The Cloud Pak for Business Automation container images on IBM Entitled Registry are signed by Digicert and can be verified with the following steps.

  1. Create a file icp4a-pubkey.gpg and add the following public key in the GNU Privacy Guard (GPG) format.
    -----BEGIN PGP PUBLIC KEY BLOCK-----
    
    mQENBF0UBwABCADAk2QMLvahhx2owpDyasQo0E36I7VM/YdK1J9lAAgsHBJFvn/P
    0PznCfnnFAw2cCj49ftYBN8orxJOSkuQE3p3hz/g21C9jrsrqwoNfNbo5WRUsIxA
    0hL9ywV8EvuOLAKdNY0ACOBHv2g82KSa/bZMg3bPA3Ir1jZZ3jjQrAzwAzvhp2Bo
    v5FwU0xYqm9DwCb/d4yYaEJ28jFWrwGdRnVHuoohu5PyUoQMpt4rwiU1yb3CabaN
    EpGo4ZF2/07sVdhSv1ieqfQMa/rC6XcFALygt/vxzQDeSkPlxWb8wBqzq/sgI5Jb
    wG6I55f3EMP67d/vWzA62FNbXk8DWMRLzWDHABEBAAG0BWljcDRhiQE5BBMBCAAj
    BQJdFAcAAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQcjTsJWhPPpnT
    hgf/ZYjAuPqiiHtJkmm1Nrw5HSCKHMsiHwUc1y5lb+J+xxfz7B3Jm07r/R82h6zI
    ZNnUTpgWzbEM7NazSAPcfL/KQXd3jw713hIXr2D4wzyMnvVAPJz0U/FUXDkZeTil
    U04PT4T9BF5b+kIh560TuouY4bot2QFhuBMnKasLMMrXx1PXbySH9OHWc5bnx3J6
    j+/d7TMj7MsdVgraoqmPtM68fOQUXyn0FCsx2M4kQRllGp7Wv0rIXVVh5lbT7VFs
    OP+8LBBj1DEfCuffQc/21jO4DkC3nalWhXW5jAcAnTLlzKWsAxm/YJLfRYzeAOHa
    mgv9nt/uDfwf0GasJw0cEeNq0A==
    =9hbX
    -----END PGP PUBLIC KEY BLOCK-----
  2. Optional: If you want to verify the icp4a-pubkey.gpg file, create a file icp4a.pem and add the following public certificate in the PEM format.
    -----BEGIN CERTIFICATE-----
    MIIFdDCCBFygAwIBAgIQDofrKzCsbdRrg6R+pu8vWTANBgkqhkiG9w0BAQsFADBy
    MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
    d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQg
    SUQgQ29kZSBTaWduaW5nIENBMB4XDTE5MDYyNzAwMDAwMFoXDTIxMDcwMTEyMDAw
    MFowgbAxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazEPMA0GA1UEBxMG
    QXJtb25rMTQwMgYDVQQKEytJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVz
    IENvcnBvcmF0aW9uMREwDwYDVQQLEwhJQk0gQ0NTUzE0MDIGA1UEAxMrSW50ZXJu
    YXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjCCASIwDQYJKoZI
    hvcNAQEBBQADggEPADCCAQoCggEBAMCTZAwu9qGHHajCkPJqxCjQTfojtUz9h0rU
    n2UACCwcEkW+f8/Q/OcJ+ecUDDZwKPj1+1gE3yivEk5KS5ATeneHP+DbUL2Ouyur
    Cg181ujlZFSwjEDSEv3LBXwS+44sAp01jQAI4Ee/aDzYpJr9tkyDds8DcivWNlne
    ONCsDPADO+GnYGi/kXBTTFiqb0PAJv93jJhoQnbyMVavAZ1GdUe6iiG7k/JShAym
    3ivCJTXJvcJpto0SkajhkXb/TuxV2FK/WJ6p9Axr+sLpdwUAvKC3+/HNAN5KQ+XF
    ZvzAGrOr+yAjklvAbojnl/cQw/rt3+9bMDrYU1teTwNYxEvNYMcCAwEAAaOCAcUw
    ggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB0GA1UdDgQWBBRh
    HPobjHmPzyDJZsLVBlf/zImp5jAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYI
    KwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDovL2NybDMuZGlnaWNlcnQu
    Y29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGGL2h0dHA6Ly9jcmw0LmRp
    Z2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMEwGA1UdIARFMEMwNwYJ
    YIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNv
    bS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcBAQR4MHYwJAYIKwYBBQUHMAGGGGh0
    dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcwAoZCaHR0cDovL2NhY2Vy
    dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRENvZGVTaWduaW5n
    Q0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBACCmH7YUx2O/
    3s599Fk1I8kOJvtkGTccrsrwOEumDiS3BWQJbUKqilr2IhGUA2c1O/zfi0uA3Oem
    Fm3a4wwgtrvme7AkWJNgIdH9FeHGOVan6mB5E318UJ7WJGErPiqk0Xoq0bFGfsoh
    oDSX8INKi2hiEa0Aurt+3FZr0IoJkPyscUSoK/mWZx3dUI1+hXozLhfWZjKnC9wj
    9pa6OKHqvS0Xfl/VQyzX59d3w4bzcalb+kK5N7/dbBlcopvWF5jCOD+WZxkn2Xhe
    aGrTT9LluqInVZ7UR5lQ4iDC7v09i37MoeBZiV20xMHUSVTj4F1ecSdthphymute
    GOc/2vekRHo=
    -----END CERTIFICATE-----
  3. Optional: If you want to verify the icp4a-pubkey.gpg file, create a file icp4a-issuer.pem and add the following issuer public certificate in the PEM format.
    -----BEGIN CERTIFICATE-----
    MIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0BAQsFADBl
    MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
    d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
    b3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQswCQYDVQQG
    EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
    cnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBT
    aWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8O
    Ea9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq
    8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRp
    wsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6scKKrzn/p
    fMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3
    jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg0A9kczye
    n6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNV
    HQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUHAQEEbTBr
    MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUH
    MAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ
    RFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2lj
    ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6
    Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmww
    TwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
    d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsq
    CqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgP
    MA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06GsTvMGHX
    fgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5jDhNLrddf
    RHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8Al
    EeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIysjaKJAL+
    L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8
    B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHv
    -----END CERTIFICATE-----
  4. Optional: Run the following commands to verify the GPG key and its issuer with the icp4a.pem and icp4a-issuer.pem files.
    Table 1. Commands to verify certificate issuance and validity
    Command Description
    openssl x509 -text -in icp4a.pem
    Displays the IBM Cloud Pak for Business Automation public certificate. Verify that the "Subject" line is IBM, and the "Issuer" is www.digicert.com. The icp4a.pem certificate is signed by Digicert.
    gpg2 -v --list-packets icp4a-pubkey.gpg
    Displays the GPG public key. Verify that pkey[0] is the same as the "Modulus" of icp4a.pem. The command validates that icp4a-pubkey.gpg is the public key (in GPG format) for IBM Cloud Pak for Business Automation.
    openssl ocsp -no_nonce \ 
    -issuer icp4a-issuer.pem \ 
    -cert icp4a.pem \ 
    -VAfile icp4a-issuer.pem \ 
    -text -url http://ocsp.digicert.com
    Verifies that the certificate icp4a.pem comes from Digicert by using the Online Certificate Status Protocol (OCSP).

Verifying a container image signature

If you pull the images from the IBM Entitled Registry with skopeo, you can enable the container image signature verification. The icp4a-pubkey.gpg file that you created can be used to verify the images under a certain repository and path.

In the following example, images are pulled from "cp.icr.io/cp/cp4a" and verified with the GPG public key that is in the "icp4a-pubkey.gpg" file. All images are rejected, except the signed images in the cp4a folder.

{
  "default": [
    {
      "type": "reject"
    }
  ],
  "transports": {
    "docker": {
      "cp.icr.io/cp/cp4a": [
        {
          "type": "signedBy",
          "keyType": "GPGKeys",
          "keyPath": "icp4a-pubkey.gpg"
        }
      ]
    }
  }
}
Note: If "cp.icr.io" is specified, all of the images that are not signed under this folder are rejected. The skopeo command has the useful option "--policy mypolicy.json", which sets a specific policy file instead of using the default /etc/containers/policy.json file.

Configuring the image source in a deployment

You can apply a security policy to specify the source of an image and whether to trust it even after they are deployed. For more information, see https://docs.openshift.com/container-platform/4.5/security/container_security/security-deploy.html#security-deploy-image-sources_security-deploy.

You can use a MachineConfig object to inject the needed configuration files into the nodes. The needed files are the GPG public key file and the policy.json file. The following example includes a /etc/pki/icp4a-pubkey.gpg file and a /etc/containers/policy.json file inline in the URL encoded format.

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: worker
  name: test-image-signature
spec:
  config:
    ignition:
      version: 2.2.0
    storage:
      files:
        - contents:
            source: >-
              data:,-----BEGIN%20PGP%20PUBLIC%20KEY%20BLOCK-----%0AmQENBF0UBwABCADAk2QMLvahhx2owpDyasQo0E36I7VM%2FYdK1J9lAAgsHBJFvn%2FP%0A0PznCfnnFAw2cCj49ftYBN8orxJOSkuQE3p3hz%2Fg21C9jrsrqwoNfNbo5WRUsIxA%0A0hL9ywV8EvuOLAKdNY0ACOBHv2g82KSa%2FbZMg3bPA3Ir1jZZ3jjQrAzwAzvhp2Bo%0Av5FwU0xYqm9DwCb%2Fd4yYaEJ28jFWrwGdRnVHuoohu5PyUoQMpt4rwiU1yb3CabaN%0AEpGo4ZF2%2F07sVdhSv1ieqfQMa%2FrC6XcFALygt%2FvxzQDeSkPlxWb8wBqzq%2FsgI5Jb%0AwG6I55f3EMP67d%2FvWzA62FNbXk8DWMRLzWDHABEBAAG0BWljcDRhiQE5BBMBCAAj%0ABQJdFAcAAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQcjTsJWhPPpnT%0Ahgf%2FZYjAuPqiiHtJkmm1Nrw5HSCKHMsiHwUc1y5lb%2BJ%2Bxxfz7B3Jm07r%2FR82h6zI%0AZNnUTpgWzbEM7NazSAPcfL%2FKQXd3jw713hIXr2D4wzyMnvVAPJz0U%2FFUXDkZeTil%0AU04PT4T9BF5b%2BkIh560TuouY4bot2QFhuBMnKasLMMrXx1PXbySH9OHWc5bnx3J6%0Aj%2B%2Fd7TMj7MsdVgraoqmPtM68fOQUXyn0FCsx2M4kQRllGp7Wv0rIXVVh5lbT7VFs%0AOP%2B8LBBj1DEfCuffQc%2F21jO4DkC3nalWhXW5jAcAnTLlzKWsAxm%2FYJLfRYzeAOHa%0Amgv9nt%2FuDfwf0GasJw0cEeNq0A%3D%3D%0A%3D9hbX%0A-----END%20PGP%20PUBLIC%20KEY%20BLOCK-----%0A
          filesystem: root
          mode: 420
          path: /etc/pki/icp4a-pubkey.gpg
        - contents:
            source: >-
              data:,%7B%0A%20%20%20%20%22default%22%3A%20%5B%7B%0A%20%20%20%20%20%20%20%20%22type%22%3A%20%22reject%22%0A%20%20%20%20%7D%5D%2C%0A%20%20%20%20%22transports%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22docker%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22cp.stg.icr.io%2Fcp%2Fcp4a%22%3A%20%5B%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%20%22signedBy%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22keyType%22%3A%20%22GPGKeys%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22keyPath%22%3A%20%22%2Fetc%2Fpki%2Ficp4a-pubkey.gpg%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D
          filesystem: root
          mode: 420
          path: /etc/containers/policy.json

With a URL decoder, you can decode the two files into clear text.

Cleaning up local images and caches

Before any test or use of the image signature, you must clean up the container images and the local cache, even if your image pull policy is "always". If an image is cached locally, it is not pulled again and the image signature verification does not take place.

Scanning for vulnerabilities

All of the Cloud Pak container images pass rigorous image vulnerability scans during the development lifecycle, but new vulnerabilities are discovered almost every day. It is likely that most of the vulnerabilities you find are related to the Linux® kernel or to a few embedded packages. IBM tracks these vulnerabilities and provides fixes for them in fix packs or subsequent releases. To find out more, you can contact IBM support.

Signing unsigned images and generating a GPG key pair to pull them

The container images in the Passport Advantage® (PPA) packages are not signed. If you download the PPA packages, you can sign these images with your own private key, and then push them into a local or corporate registry.

  1. Follow the OpenShift Container Platform (OCP) documentation to sign a container image, generate a GPG private key, and a public key "mysignedkey.gpg" that is generated from it. For more information, see Managing Containers: Chapter 3. Signing Container Images.
  2. Edit the /etc/containers/policy.json file on your target OCP image registry to include the GPG public key "mysignedkey.gpg".
    ...
        "docker": {
          "$(oc registry info)": [
            {
              "type": "signedBy",
              "keyType": "GPGKeys",
              "keyPath": "/etc/pki/containers/mysignedkey.gpg"
            }
          ]
        }
    ...
  3. Copy the GPG public key to the registry keyPath location.
    sudo mv mysignedkey.gpg /etc/pki/containers/mysignedkey.gpg
  4. Use the skopeo copy command to create a mirror of the Cloud Pak for Business Automation container image. The command needs the --remove-signatures option.