diff --git a/README.md b/README.md index 871b584..80fa1f8 100644 --- a/README.md +++ b/README.md @@ -21,26 +21,23 @@ Alternatively, you can also build from source by cloning the repo and running `g `incert` supports the following flags: ```shell - -ca-certs-file string - The path to the local CA certificates file - -ca-certs-image-url string - The URL of an image to extract the CA certificates from - -dest-image-url string - The URL of the image to push the modified image to - -image-cert-path string - The path to the certificate file in the image (optional) (default "/etc/ssl/certs/ca-certificates.crt") - -image-url string - The URL of the image to append the CA certificates to - -output-certs-path string - Output the (appended) certificates file from the image to a local file (optional) - -owner-group-id int - The group ID of the owner of the certificate file in the image (optional) - -owner-user-id int - The user ID of the owner of the certificate file in the image (optional) - -platform string - The platform to build the image for (default "linux/amd64") - -replace-certs - Replace the certificates in the certificate file instead of appending them +Appends CA certificates to Docker images and pushes the modified image to a specified registry. + +Usage: + incert [flags] + +Flags: + --ca-certs-file string The path to the local CA certificates file + --ca-certs-image-url string The URL of an image to extract the CA certificates from + --dest-image-url string The URL of the image to push the modified image to + -h, --help help for incert + --image-cert-path string The path to the certificate file in the image (optional) (default "/etc/ssl/certs/ca-certificates.crt") + --image-url string The URL of the image to append the CA certificates to + --output-certs-path string Output the (appended) certificates file from the image to a local file (optional) + --owner-group-id int The group ID of the owner of the certificate file in the image (optional) + --owner-user-id int The user ID of the owner of the certificate file in the image (optional) + --platform string The platform to build the image for (default "linux/amd64") + --replace-certs Replace the certificates in the certificate file instead of appending them ``` ## Example @@ -48,7 +45,7 @@ Alternatively, you can also build from source by cloning the repo and running `g To append a corporate CA certificate to an image, use the following command: ```bash -$ incert -image-url=mycompany/myimage:latest -ca-certs-file=/path/to/cacerts.pem -dest-image-url=myregistry/myimage:latest +$ incert --image-url=mycompany/myimage:latest --ca-certs-file=/path/to/cacerts.pem --dest-image-url=myregistry/myimage:latest ``` This will append the certificates in `/path/to/cacerts.pem` to the `mycompany/myimage:latest` image and push the modified image to `myregistry/myimage:latest`. diff --git a/go.mod b/go.mod index 6787e8a..03e92cd 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,10 @@ go 1.23.0 toolchain go1.23.5 -require github.com/google/go-containerregistry v0.20.3 +require ( + github.com/google/go-containerregistry v0.20.3 + github.com/spf13/cobra v1.8.1 +) require ( github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect @@ -17,6 +20,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/spf13/pflag v1.0.5 // indirect github.com/vbatts/tar-split v0.11.6 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.29.0 // indirect diff --git a/go.sum b/go.sum index 004eb77..3adfd26 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,44 @@ +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -25,19 +47,41 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/main.go b/main.go index 7e83948..caff88e 100644 --- a/main.go +++ b/main.go @@ -9,13 +9,15 @@ import ( "archive/tar" "bytes" "encoding/pem" - "flag" + "errors" "fmt" "io" "log" "os" "strings" + "github.com/spf13/cobra" + "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -38,37 +40,61 @@ var ( ) func init() { - flag.StringVar(&imageURL, "image-url", "", "The URL of the image to append the CA certificates to") - flag.StringVar(&caCertFile, "ca-certs-file", "", "The path to the local CA certificates file") - flag.StringVar(&caCertsImageURL, "ca-certs-image-url", "", "The URL of an image to extract the CA certificates from") - flag.StringVar(&destImageURL, "dest-image-url", "", "The URL of the image to push the modified image to") - flag.StringVar(&platformStr, "platform", "linux/amd64", "The platform to build the image for") - - flag.StringVar(&imageCertPath, "image-cert-path", "/etc/ssl/certs/ca-certificates.crt", "The path to the certificate file in the image (optional)") - flag.IntVar(&ownerUserID, "owner-user-id", 0, "The user ID of the owner of the certificate file in the image (optional)") - flag.IntVar(&ownerGroupID, "owner-group-id", 0, "The group ID of the owner of the certificate file in the image (optional)") - flag.StringVar(&outputCerts, "output-certs-path", "", "Output the (appended) certificates file from the image to a local file (optional)") - flag.BoolVar(&replaceCerts, "replace-certs", false, "Replace the certificates in the certificate file instead of appending them") + rootCmd.Flags().StringVar(&imageURL, "image-url", "", "The URL of the image to append the CA certificates to") + rootCmd.Flags().StringVar(&caCertFile, "ca-certs-file", "", "The path to the local CA certificates file") + rootCmd.Flags().StringVar(&caCertsImageURL, "ca-certs-image-url", "", "The URL of an image to extract the CA certificates from") + rootCmd.Flags().StringVar(&destImageURL, "dest-image-url", "", "The URL of the image to push the modified image to") + rootCmd.Flags().StringVar(&platformStr, "platform", "linux/amd64", "The platform to build the image for") + + rootCmd.Flags().StringVar(&imageCertPath, "image-cert-path", "/etc/ssl/certs/ca-certificates.crt", "The path to the certificate file in the image (optional)") + rootCmd.Flags().IntVar(&ownerUserID, "owner-user-id", 0, "The user ID of the owner of the certificate file in the image (optional)") + rootCmd.Flags().IntVar(&ownerGroupID, "owner-group-id", 0, "The group ID of the owner of the certificate file in the image (optional)") + rootCmd.Flags().StringVar(&outputCerts, "output-certs-path", "", "Output the (appended) certificates file from the image to a local file (optional)") + rootCmd.Flags().BoolVar(&replaceCerts, "replace-certs", false, "Replace the certificates in the certificate file instead of appending them") + + _ = rootCmd.MarkFlagRequired("image-url") + _ = rootCmd.MarkFlagRequired("dest-image-url") } -func usage() { - flag.Usage() - os.Exit(1) +func main() { + if err := rootCmd.Execute(); err != nil { + os.Exit(1) + } } -func main() { +var rootCmd = &cobra.Command{ + Use: "incert", + Short: "Appends CA certificates to Docker images and pushes the modified image to a specified registry.", + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + return do(cmd, args) + }, +} +// Fetch the remote image +func fetchImage(imageURL string, platform v1.Platform) (v1.Image, error) { + ref, err := name.ParseReference(imageURL) + if err != nil { + return nil, err + } + img, err := remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain), remote.WithPlatform((platform))) + if err != nil { + return nil, err + } + return img, nil +} + +func do(_ *cobra.Command, _ []string) error { var platform v1.Platform - flag.Parse() - if imageURL == "" || destImageURL == "" || (caCertFile == "" && caCertsImageURL == "") { - usage() + if caCertFile == "" && caCertsImageURL == "" { + return errors.New("either --ca-certs-file or --ca-certs-image-url must be provided") } if platformStr != "" { p, err := v1.ParsePlatform(platformStr) if err != nil { - log.Fatalf("Failed to parse platform: %s", err) + return fmt.Errorf("Failed to parse platform: %s", err) } platform = *p } @@ -76,61 +102,51 @@ func main() { // Get the cert bytes caCertBytes, err := getCertBytes(platform) if err != nil { - log.Fatalf("Failed to get certificate bytes: %s", err) + return fmt.Errorf("Failed to get certificate bytes: %s", err) } // Sanity check to make sure the caCertBytes are actually a list of pem-encoded certificates block, _ := pem.Decode(caCertBytes) if block == nil || block.Type != "CERTIFICATE" { - log.Fatalf("Failed to find any certificates in %s", caCertFile) + return fmt.Errorf("Failed to find any certificates in %s", caCertFile) } img, err := fetchImage(imageURL, platform) if err != nil { - log.Fatalf("Failed to fetch image %s: %s\n", imageURL, err) + return fmt.Errorf("Failed to fetch image %s: %s\n", imageURL, err) } newImg, err := newImage(img, caCertBytes) if err != nil { - log.Fatalf("Failed to create new image: %s\n", err) + return fmt.Errorf("Failed to create new image: %s\n", err) } if outputCerts != "" { if err := os.WriteFile(outputCerts, caCertBytes, 0644); err != nil { - log.Fatalf("Failed to write certificates to file %s: %s.\n", outputCerts, err) + return fmt.Errorf("Failed to write certificates to file %s: %s.\n", outputCerts, err) } } newRef, err := name.ParseReference(destImageURL) if err != nil { - log.Fatalf("Failed to parse destination image URL %s: %s\n", destImageURL, err) + return fmt.Errorf("Failed to parse destination image URL %s: %s\n", destImageURL, err) } // Push the modified image back to the registry err = remote.Write(newRef, newImg, remote.WithAuthFromKeychain(authn.DefaultKeychain)) if err != nil { - log.Fatalf("Failed to push modified image %s: %s\n", newRef.String(), err) + return fmt.Errorf("Failed to push modified image %s: %s\n", newRef.String(), err) } fmt.Fprintf(os.Stderr, "Successfully appended CA certificates to image %s\n", newRef.String()) h, err := newImg.Digest() if err != nil { - log.Fatalf("Failed to get digest of image %s: %s\n", newRef.String(), err) + return fmt.Errorf("Failed to get digest of image %s: %s\n", newRef.String(), err) } + fmt.Printf("%s@sha256:%s\n", newRef.String(), h.Hex) -} -// Fetch the remote image -func fetchImage(imageURL string, platform v1.Platform) (v1.Image, error) { - ref, err := name.ParseReference(imageURL) - if err != nil { - return nil, err - } - img, err := remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain), remote.WithPlatform((platform))) - if err != nil { - return nil, err - } - return img, nil + return nil } func getCertBytes(platform v1.Platform) ([]byte, error) { @@ -139,21 +155,22 @@ func getCertBytes(platform v1.Platform) ([]byte, error) { // Read the contents of the local CA certificates file caCertBytes, err := os.ReadFile(caCertFile) if err != nil { - log.Fatalf("Failed to read CA certificates file %s: %s\n", caCertFile, err) + return []byte{}, fmt.Errorf("Failed to read CA certificates file %s: %s\n", caCertFile, err) } // Sanity check to make sure the caCertBytes are actually a list of pem-encoded certificates block, _ := pem.Decode(caCertBytes) if block == nil || block.Type != "CERTIFICATE" { - log.Fatalf("Failed to find any certificates in %s", caCertFile) + return []byte{}, fmt.Errorf("Failed to find any certificates in %s", caCertFile) } return caCertBytes, nil } else { // Fetch the remote image and its manifest img, err := fetchImage(caCertsImageURL, platform) if err != nil { - log.Fatalf("Failed to fetch image %s: %s\n", caCertsImageURL, err) + return []byte{}, fmt.Errorf("Failed to fetch image %s: %s\n", caCertsImageURL, err) } + return extractCACerts(img) } } @@ -173,6 +190,7 @@ func extractCACerts(img v1.Image) ([]byte, error) { return io.ReadAll(tr) } } + return nil, fmt.Errorf("failed to find %s in remote image", imageCertPath) } @@ -191,7 +209,7 @@ func newImage(old v1.Image, caCertBytes []byte) (v1.Image, error) { // Create a new tar file with the modified ca-certificates file buf := bytes.Buffer{} newTar := tar.NewWriter(&buf) - newTar.WriteHeader(&tar.Header{ + _ = newTar.WriteHeader(&tar.Header{ Name: imageCertPath, Mode: 0644, Size: int64(len(newCaCertBytes)),