From 5674313b75c63ded3620c9d91445505a4efb318a Mon Sep 17 00:00:00 2001 From: Johannes Schicktanz Date: Fri, 17 Jun 2022 12:23:41 +0200 Subject: [PATCH] signing server cmd updates (#88) --- ...-archive_signatures_sign_signing-server.md | 5 +- go.mod | 2 +- go.sum | 4 +- pkg/commands/componentarchive/remote/get.go | 6 +- .../componentarchive/signature/add_digests.go | 9 ++- .../signature/check_digests.go | 6 +- .../componentarchive/signature/sign/rsa.go | 2 +- .../componentarchive/signature/sign/sign.go | 20 ++++-- .../signature/sign/signing_server.go | 17 +++-- .../componentarchive/signature/verify/rsa.go | 2 +- .../signature/verify/verify.go | 6 +- .../signature/verify/x509_certificate.go | 2 +- pkg/commands/ctf/add.go | 2 +- pkg/commands/ctf/push.go | 2 +- pkg/componentarchive/archive.go | 2 +- pkg/signatures/signing_server.go | 68 +++++++++++++++---- pkg/signatures/util.go | 5 +- .../bindings-go/apis/v2/signatures/const.go | 25 +++++++ .../bindings-go/apis/v2/signatures/rsa.go | 25 ++++--- .../bindings-go/apis/v2/signatures/types.go | 24 +++---- vendor/modules.txt | 2 +- 21 files changed, 157 insertions(+), 79 deletions(-) create mode 100644 vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/const.go diff --git a/docs/reference/component-cli_component-archive_signatures_sign_signing-server.md b/docs/reference/component-cli_component-archive_signatures_sign_signing-server.md index 7effa8ed..fdc7104d 100644 --- a/docs/reference/component-cli_component-archive_signatures_sign_signing-server.md +++ b/docs/reference/component-cli_component-archive_signatures_sign_signing-server.md @@ -11,12 +11,15 @@ component-cli component-archive signatures sign signing-server BASE_URL COMPONEN ``` --allow-plain-http allows the fallback to http if the oci registry does not support https --cc-config string path to the local concourse config file - --config string config file which contains the signing server configuration + --client-cert string [OPTIONAL] path to a file containing the client certificate in PEM format for authenticating to the server --force [OPTIONAL] force overwrite of already existing component descriptors -h, --help help for signing-server --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --private-key string [OPTIONAL] path to a file containing the private key for the provided client certificate in PEM format --recursive [OPTIONAL] recursively sign and upload all referenced component descriptors --registry-config string path to the dockerconfig.json with the oci registry authentication information + --root-ca-certs string [OPTIONAL] path to a file containing additional root ca certificates in PEM format. if empty, the system root ca certificate pool is used + --server-url string url where the signing server is running, e.g. https://localhost:8080 --signature-name string name of the signature --skip-access-types strings [OPTIONAL] comma separated list of access types that will not be digested and signed --upload-base-url string target repository context to upload the signed cd diff --git a/go.mod b/go.mod index 581b2e60..2d4b540b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/containerd/containerd v1.5.5 github.com/docker/cli v20.10.0-rc1+incompatible github.com/drone/envsubst v1.0.2 - github.com/gardener/component-spec/bindings-go v0.0.64 + github.com/gardener/component-spec/bindings-go v0.0.65 github.com/gardener/image-vector v0.10.0 github.com/ghodss/yaml v1.0.0 github.com/go-logr/logr v0.4.0 diff --git a/go.sum b/go.sum index 23d05b1d..d49b6202 100644 --- a/go.sum +++ b/go.sum @@ -290,8 +290,8 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gardener/component-spec/bindings-go v0.0.52/go.mod h1:kQFMTWowNAp9tOp6aImQa/NoLzfvX29jN5Qgud9rpQU= -github.com/gardener/component-spec/bindings-go v0.0.64 h1:5OrwY3D7NjH+nnXCVhUtAvE56/LaMKO2av1Z5aK6/Pw= -github.com/gardener/component-spec/bindings-go v0.0.64/go.mod h1:hwdDN2xZhFxv1vdamShz3/29Nqjx4UQlpxjyBZAZh4M= +github.com/gardener/component-spec/bindings-go v0.0.65 h1:HHczHWEJUXYcaKr+UWGvXFTHYONeSdlIqlj0T73POiw= +github.com/gardener/component-spec/bindings-go v0.0.65/go.mod h1:hwdDN2xZhFxv1vdamShz3/29Nqjx4UQlpxjyBZAZh4M= github.com/gardener/image-vector v0.10.0 h1:Ysg3hxfiGUG/doajiZ0nQuUaJYwfO5BZCOcijL3tRuo= github.com/gardener/image-vector v0.10.0/go.mod h1:32SHGcbmmueeK9VkawsFcEbsoENXQPIuuYiFBUP+vMQ= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= diff --git a/pkg/commands/componentarchive/remote/get.go b/pkg/commands/componentarchive/remote/get.go index 7cbeefd9..45eace40 100644 --- a/pkg/commands/componentarchive/remote/get.go +++ b/pkg/commands/componentarchive/remote/get.go @@ -116,13 +116,13 @@ func (o *ShowOptions) Complete(args []string) error { } if len(o.BaseUrl) == 0 { - return errors.New("the base url must be defined") + return errors.New("the base url must be provided") } if len(o.ComponentName) == 0 { - return errors.New("a component name must be defined") + return errors.New("a component name must be provided") } if len(o.Version) == 0 { - return errors.New("a component's Version must be defined") + return errors.New("a component version must be provided") } return nil } diff --git a/pkg/commands/componentarchive/signature/add_digests.go b/pkg/commands/componentarchive/signature/add_digests.go index 3e7f6f16..80f27698 100644 --- a/pkg/commands/componentarchive/signature/add_digests.go +++ b/pkg/commands/componentarchive/signature/add_digests.go @@ -138,17 +138,16 @@ func (o *AddDigestsOptions) Complete(args []string) error { } if len(o.BaseUrl) == 0 { - return errors.New("the base url must be defined") + return errors.New("a base url must be provided") } if len(o.ComponentName) == 0 { - return errors.New("a component name must be defined") + return errors.New("a component name must be provided") } if len(o.Version) == 0 { - return errors.New("a component version must be defined") + return errors.New("a component version must be provided") } - if o.UploadBaseUrl == "" { - return errors.New("upload-base-url must be defined") + return errors.New("a upload base url must be provided") } return nil diff --git a/pkg/commands/componentarchive/signature/check_digests.go b/pkg/commands/componentarchive/signature/check_digests.go index 19c056fe..2eeb74d9 100644 --- a/pkg/commands/componentarchive/signature/check_digests.go +++ b/pkg/commands/componentarchive/signature/check_digests.go @@ -99,13 +99,13 @@ func (o *CheckDigestsOptions) Complete(args []string) error { } if len(o.BaseUrl) == 0 { - return errors.New("the base url must be defined") + return errors.New("a base url must be provided") } if len(o.ComponentName) == 0 { - return errors.New("a component name must be defined") + return errors.New("a component name must be provided") } if len(o.Version) == 0 { - return errors.New("a component's Version must be defined") + return errors.New("a component version must be provided") } return nil } diff --git a/pkg/commands/componentarchive/signature/sign/rsa.go b/pkg/commands/componentarchive/signature/sign/rsa.go index ba4f3c0c..6399edcd 100644 --- a/pkg/commands/componentarchive/signature/sign/rsa.go +++ b/pkg/commands/componentarchive/signature/sign/rsa.go @@ -67,7 +67,7 @@ func (o *RSASignOptions) Complete(args []string) error { } if o.PathToPrivateKey == "" { - return errors.New("a path to private key file must be given as flag") + return errors.New("a path to a private key file must be provided") } return nil diff --git a/pkg/commands/componentarchive/signature/sign/sign.go b/pkg/commands/componentarchive/signature/sign/sign.go index 42a7211c..0c92b212 100644 --- a/pkg/commands/componentarchive/signature/sign/sign.go +++ b/pkg/commands/componentarchive/signature/sign/sign.go @@ -21,6 +21,7 @@ import ( ociopts "github.com/gardener/component-cli/ociclient/options" "github.com/gardener/component-cli/pkg/commands/constants" + "github.com/gardener/component-cli/pkg/components" "github.com/gardener/component-cli/pkg/logger" "github.com/gardener/component-cli/pkg/signatures" ) @@ -62,6 +63,8 @@ type GenericSignOptions struct { // OciOptions contains all exposed options to configure the oci client. OciOptions ociopts.Options + + SignedRef string } //Complete validates the arguments and flags from the command line @@ -81,20 +84,27 @@ func (o *GenericSignOptions) Complete(args []string) error { } if len(o.BaseUrl) == 0 { - return errors.New("the base url must be defined") + return errors.New("a base url must be provided") } if len(o.ComponentName) == 0 { - return errors.New("a component name must be defined") + return errors.New("a component name must be provided") } if len(o.Version) == 0 { - return errors.New("a component's Version must be defined") + return errors.New("a component version must be provided") } if o.UploadBaseUrlForSigned == "" { - return errors.New("upload-base-url must be defined") + return errors.New("a upload base url must be provided") } if o.SignatureName == "" { return errors.New("a signature name must be provided") } + + signedRef, err := components.OCIRef(cdv2.NewOCIRegistryRepository(o.UploadBaseUrlForSigned, ""), o.ComponentName, o.Version) + if err != nil { + return fmt.Errorf("invalid reference for signed component descriptor: %w", err) + } + o.SignedRef = signedRef + return nil } @@ -171,5 +181,7 @@ func (o *GenericSignOptions) SignAndUploadWithSigner(ctx context.Context, log lo return fmt.Errorf("unable to upload component descriptor: %w", err) } } + + log.Info(fmt.Sprintf("Successfully uploaded signed component descriptor at %s", o.SignedRef)) return nil } diff --git a/pkg/commands/componentarchive/signature/sign/signing_server.go b/pkg/commands/componentarchive/signature/sign/signing_server.go index 7b76a140..97ae479a 100644 --- a/pkg/commands/componentarchive/signature/sign/signing_server.go +++ b/pkg/commands/componentarchive/signature/sign/signing_server.go @@ -20,8 +20,10 @@ import ( ) type SigningServerSignOptions struct { - // SigningServerConfigPath path to the config file containing signing server configuration - SigningServerConfigPath string + ServerURL string + ClientCertPath string + PrivateKeyPath string + RootCACertsPath string GenericSignOptions } @@ -51,7 +53,7 @@ func NewSigningServerSignCommand(ctx context.Context) *cobra.Command { } func (o *SigningServerSignOptions) Run(ctx context.Context, log logr.Logger, fs vfs.FileSystem) error { - signer, err := signatures.NewSigningServerSignerFromConfigFile(o.SigningServerConfigPath) + signer, err := signatures.NewSigningServerSigner(o.ServerURL, o.ClientCertPath, o.PrivateKeyPath, o.RootCACertsPath) if err != nil { return fmt.Errorf("unable to create signing server signer: %w", err) } @@ -63,8 +65,8 @@ func (o *SigningServerSignOptions) Complete(args []string) error { return err } - if o.SigningServerConfigPath == "" { - return errors.New("a config file which contains the signing server configuration must be given as flag") + if o.ServerURL == "" { + return errors.New("a server url must be provided") } return nil @@ -72,5 +74,8 @@ func (o *SigningServerSignOptions) Complete(args []string) error { func (o *SigningServerSignOptions) AddFlags(fs *pflag.FlagSet) { o.GenericSignOptions.AddFlags(fs) - fs.StringVar(&o.SigningServerConfigPath, "config", "", "config file which contains the signing server configuration") + fs.StringVar(&o.ServerURL, "server-url", "", "url where the signing server is running, e.g. https://localhost:8080") + fs.StringVar(&o.ClientCertPath, "client-cert", "", "[OPTIONAL] path to a file containing the client certificate in PEM format for authenticating to the server") + fs.StringVar(&o.PrivateKeyPath, "private-key", "", "[OPTIONAL] path to a file containing the private key for the provided client certificate in PEM format") + fs.StringVar(&o.RootCACertsPath, "root-ca-certs", "", "[OPTIONAL] path to a file containing additional root ca certificates in PEM format. if empty, the system root ca certificate pool is used") } diff --git a/pkg/commands/componentarchive/signature/verify/rsa.go b/pkg/commands/componentarchive/signature/verify/rsa.go index da44027b..6544136c 100644 --- a/pkg/commands/componentarchive/signature/verify/rsa.go +++ b/pkg/commands/componentarchive/signature/verify/rsa.go @@ -68,7 +68,7 @@ func (o *RSAVerifyOptions) Complete(args []string) error { return err } if o.PathToPublicKey == "" { - return errors.New("a path to public key file must be given as flag") + return errors.New("a path to a public key file must be provided") } return nil diff --git a/pkg/commands/componentarchive/signature/verify/verify.go b/pkg/commands/componentarchive/signature/verify/verify.go index f25cae7f..1896193d 100644 --- a/pkg/commands/componentarchive/signature/verify/verify.go +++ b/pkg/commands/componentarchive/signature/verify/verify.go @@ -71,13 +71,13 @@ func (o *GenericVerifyOptions) Complete(args []string) error { } if len(o.BaseUrl) == 0 { - return errors.New("the base url must be defined") + return errors.New("a base url must be provided") } if len(o.ComponentName) == 0 { - return errors.New("a component name must be defined") + return errors.New("a component name must be provided") } if len(o.Version) == 0 { - return errors.New("a component's version must be defined") + return errors.New("a component version must be provided") } if o.SignatureName == "" { return errors.New("a signature name must be provided") diff --git a/pkg/commands/componentarchive/signature/verify/x509_certificate.go b/pkg/commands/componentarchive/signature/verify/x509_certificate.go index 8bcff5da..ccf029d6 100644 --- a/pkg/commands/componentarchive/signature/verify/x509_certificate.go +++ b/pkg/commands/componentarchive/signature/verify/x509_certificate.go @@ -83,7 +83,7 @@ func (o *X509CertificateVerifyOptions) Complete(args []string) error { } if o.certPath == "" { - return errors.New("a path to a certificate file must be given as flag") + return errors.New("a path to a certificate file must be provided") } return nil diff --git a/pkg/commands/ctf/add.go b/pkg/commands/ctf/add.go index cea64e68..69bc77fe 100644 --- a/pkg/commands/ctf/add.go +++ b/pkg/commands/ctf/add.go @@ -127,7 +127,7 @@ func (o *AddOptions) Complete(args []string) error { // Validate validates push options func (o *AddOptions) Validate() error { if len(o.CTFPath) == 0 { - return errors.New("a path to the component descriptor must be defined") + return errors.New("a path to the component descriptor must be provided") } if len(o.ComponentArchives) == 0 { diff --git a/pkg/commands/ctf/push.go b/pkg/commands/ctf/push.go index 86cb114b..e18fc362 100644 --- a/pkg/commands/ctf/push.go +++ b/pkg/commands/ctf/push.go @@ -153,7 +153,7 @@ func (o *PushOptions) Complete(args []string) error { // Validate validates push options func (o *PushOptions) Validate() error { if len(o.CTFPath) == 0 { - return errors.New("a path to the component descriptor must be defined") + return errors.New("a path to the component descriptor must be provided") } return nil } diff --git a/pkg/componentarchive/archive.go b/pkg/componentarchive/archive.go index 31848ed0..4400fb91 100644 --- a/pkg/componentarchive/archive.go +++ b/pkg/componentarchive/archive.go @@ -55,7 +55,7 @@ func (o *BuilderOptions) Default() { // Validate validates the component archive builder options. func (o *BuilderOptions) Validate() error { if len(o.ComponentArchivePath) == 0 { - return errors.New("a component archive path must be defined") + return errors.New("a component archive path must be provided") } if len(o.Name) != 0 { diff --git a/pkg/signatures/signing_server.go b/pkg/signatures/signing_server.go index 72566576..edda5e3a 100644 --- a/pkg/signatures/signing_server.go +++ b/pkg/signatures/signing_server.go @@ -5,6 +5,8 @@ package signatures import ( "bytes" + "crypto/tls" + "crypto/x509" "encoding/hex" "encoding/pem" "errors" @@ -14,28 +16,42 @@ import ( cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" cdv2signatures "github.com/gardener/component-spec/bindings-go/apis/v2/signatures" - "sigs.k8s.io/yaml" ) const ( - AcceptHeader = "Accept" + // http header + AcceptHeader = "Accept" + HashAlgorithmHeader = "X-Hash-Algorithm" + SignatureAlgorithmHeader = "X-Signature-Algorithm" ) type SigningServerSigner struct { - Url string `json:"url"` - Username string `json:"username"` - Password string `json:"password"` + ServerURL string + ClientCert *tls.Certificate + RootCACerts []byte } -func NewSigningServerSignerFromConfigFile(configFilePath string) (*SigningServerSigner, error) { - configBytes, err := ioutil.ReadFile(configFilePath) - if err != nil { - return nil, fmt.Errorf("unable to read config file: %w", err) +func NewSigningServerSigner(serverURL, clientCertPath, privateKeyPath, rootCACertsPath string) (*SigningServerSigner, error) { + signer := SigningServerSigner{ + ServerURL: serverURL, } - var signer SigningServerSigner - if err := yaml.Unmarshal(configBytes, &signer); err != nil { - return nil, fmt.Errorf("unable to parse config yaml: %w", err) + + if clientCertPath != "" { + clientCert, err := tls.LoadX509KeyPair(clientCertPath, privateKeyPath) + if err != nil { + return nil, fmt.Errorf("unable to load client certificate: %w", err) + } + signer.ClientCert = &clientCert } + + if rootCACertsPath != "" { + rootCACerts, err := ioutil.ReadFile(rootCACertsPath) + if err != nil { + return nil, fmt.Errorf("unable to read root ca certificates file: %w", err) + } + signer.RootCACerts = rootCACerts + } + return &signer, nil } @@ -45,14 +61,36 @@ func (signer *SigningServerSigner) Sign(componentDescriptor cdv2.ComponentDescri return nil, fmt.Errorf("unable to hex decode hash: %w", err) } - req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/sign", signer.Url), bytes.NewBuffer(decodedHash)) + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/sign", signer.ServerURL), bytes.NewBuffer(decodedHash)) if err != nil { return nil, fmt.Errorf("unable to build http request: %w", err) } req.Header.Add(AcceptHeader, cdv2.MediaTypePEM) - req.SetBasicAuth(signer.Username, signer.Password) + req.Header.Add(HashAlgorithmHeader, digest.HashAlgorithm) + req.Header.Add(SignatureAlgorithmHeader, cdv2.RSAPKCS1v15) + + var certPool *x509.CertPool + if len(signer.RootCACerts) > 0 { + certPool = x509.NewCertPool() + if ok := certPool.AppendCertsFromPEM(signer.RootCACerts); !ok { + return nil, fmt.Errorf("unable to append root ca certificates to cert pool") + } + } + + clientCerts := []tls.Certificate{} + if signer.ClientCert != nil { + clientCerts = append(clientCerts, *signer.ClientCert) + } + + client := http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: certPool, + Certificates: clientCerts, + }, + }, + } - client := http.Client{} res, err := client.Do(req) if err != nil { return nil, fmt.Errorf("unable to send http request: %w", err) diff --git a/pkg/signatures/util.go b/pkg/signatures/util.go index 981b5ed7..510d2b85 100644 --- a/pkg/signatures/util.go +++ b/pkg/signatures/util.go @@ -17,7 +17,6 @@ import ( "github.com/gardener/component-cli/pkg/logger" cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" - v2 "github.com/gardener/component-spec/bindings-go/apis/v2" cdv2Sign "github.com/gardener/component-spec/bindings-go/apis/v2/signatures" cdoci "github.com/gardener/component-spec/bindings-go/oci" ocispecv1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -68,7 +67,7 @@ func RecursivelyAddDigestsToCd(cd *cdv2.ComponentDescriptor, repoContext cdv2.OC res := res if _, ok := skipAccessTypes[res.Access.Type]; ok { log := logger.Log.WithValues("componentDescriptor", cd, "resource.name", res.Name, "resource.version", res.Version, "resource.extraIdentity", res.ExtraIdentity) - log.Info(fmt.Sprintf("adding %s digest to resource based on skip-access-type", v2.ExcludeFromSignature)) + log.Info(fmt.Sprintf("adding %s digest to resource based on skip-access-type", cdv2.ExcludeFromSignature)) res.Digest = cdv2.NewExcludeFromSignatureDigest() cd.Resources[i] = res @@ -83,7 +82,7 @@ func RecursivelyAddDigestsToCd(cd *cdv2.ComponentDescriptor, repoContext cdv2.OC return cdsWithHashes, nil } -func UploadCDPreservingLocalOciBlobs(ctx context.Context, cd v2.ComponentDescriptor, targetRepository cdv2.OCIRegistryRepository, ociClient ociclient.ExtendedClient, cache ociCache.Cache, blobResolvers map[string]ctf.BlobResolver, force bool, log logr.Logger) error { +func UploadCDPreservingLocalOciBlobs(ctx context.Context, cd cdv2.ComponentDescriptor, targetRepository cdv2.OCIRegistryRepository, ociClient ociclient.ExtendedClient, cache ociCache.Cache, blobResolvers map[string]ctf.BlobResolver, force bool, log logr.Logger) error { // check if the component descriptor already exists and skip if not forced to overwrite if !force { cdresolver := cdoci.NewResolver(ociClient) diff --git a/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/const.go b/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/const.go new file mode 100644 index 00000000..307ecc34 --- /dev/null +++ b/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/const.go @@ -0,0 +1,25 @@ +// Copyright 2022 Copyright (c) 2022 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package signatures + +import "crypto" + +const ( + SHA256 = "sha256" +) + +var HashFunctions = map[string]crypto.Hash{ + SHA256: crypto.SHA256, +} diff --git a/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/rsa.go b/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/rsa.go index b3a2e9df..9c98f77e 100644 --- a/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/rsa.go +++ b/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/rsa.go @@ -65,15 +65,17 @@ func CreateRSASignerFromKeyFile(pathToPrivateKey, mediaType string) (*RSASigner, // Sign returns the signature for the data for the component descriptor. func (s RSASigner) Sign(componentDescriptor cdv2.ComponentDescriptor, digest cdv2.DigestSpec) (*cdv2.SignatureSpec, error) { + hashfunc, ok := HashFunctions[digest.HashAlgorithm] + if !ok { + return nil, fmt.Errorf("unknown hash algorithm %s", digest.HashAlgorithm) + } + decodedHash, err := hex.DecodeString(digest.Value) if err != nil { return nil, fmt.Errorf("unable to hex decode hash: %w", err) } - // ensure length of hash is correct - if len(decodedHash) != 32 { - return nil, fmt.Errorf("hash to sign has invalid length") - } - signature, err := rsa.SignPKCS1v15(rand.Reader, &s.privateKey, 0, decodedHash) + + signature, err := rsa.SignPKCS1v15(rand.Reader, &s.privateKey, hashfunc, decodedHash) if err != nil { return nil, fmt.Errorf("unable to sign hash: %w", err) } @@ -172,17 +174,20 @@ func (v RSAVerifier) Verify(componentDescriptor cdv2.ComponentDescriptor, signat return fmt.Errorf("invalid signature mediaType %s", signature.Signature.MediaType) } + hashfunc, ok := HashFunctions[signature.Digest.HashAlgorithm] + if !ok { + return fmt.Errorf("unknown hash algorithm %s", signature.Digest.HashAlgorithm) + } + decodedHash, err := hex.DecodeString(signature.Digest.Value) if err != nil { return fmt.Errorf("unable to hex decode hash %s: %w", signature.Digest.Value, err) } - // ensure length of hash is correct - if len(decodedHash) != 32 { - return fmt.Errorf("hash to verify has invalid length") - } - if err := rsa.VerifyPKCS1v15(&v.publicKey, 0, decodedHash, signatureBytes); err != nil { + + if err := rsa.VerifyPKCS1v15(&v.publicKey, hashfunc, decodedHash, signatureBytes); err != nil { return fmt.Errorf("unable to verify signature: %w", err) } + return nil } diff --git a/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/types.go b/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/types.go index ef38f79e..1d8b2081 100644 --- a/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/types.go +++ b/vendor/github.com/gardener/component-spec/bindings-go/apis/v2/signatures/types.go @@ -16,10 +16,8 @@ package signatures import ( "context" - "crypto/sha256" "fmt" "hash" - "strings" cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" ) @@ -44,23 +42,17 @@ type Hasher struct { AlgorithmName string } -const SHA256 = "sha256" - // HasherForName creates a Hasher instance for the algorithmName. func HasherForName(algorithmName string) (*Hasher, error) { - switch strings.ToLower(algorithmName) { - case SHA256: - return &Hasher{ - HashFunction: sha256.New(), - AlgorithmName: SHA256, - }, nil - case strings.ToLower(cdv2.NoDigest): - return &Hasher{ - HashFunction: nil, - AlgorithmName: cdv2.NoDigest, - }, nil + hashfunc, ok := HashFunctions[algorithmName] + if !ok { + return nil, fmt.Errorf("hash algorithm %s not found/implemented", algorithmName) } - return nil, fmt.Errorf("hash algorithm %s not found/implemented", algorithmName) + + return &Hasher{ + HashFunction: hashfunc.New(), + AlgorithmName: algorithmName, + }, nil } type ResourceDigester interface { diff --git a/vendor/modules.txt b/vendor/modules.txt index 6c2eb7de..0cf818f7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -52,7 +52,7 @@ github.com/drone/envsubst/path # github.com/fsnotify/fsnotify v1.4.9 ## explicit; go 1.13 github.com/fsnotify/fsnotify -# github.com/gardener/component-spec/bindings-go v0.0.64 +# github.com/gardener/component-spec/bindings-go v0.0.65 ## explicit; go 1.18 github.com/gardener/component-spec/bindings-go/apis github.com/gardener/component-spec/bindings-go/apis/v2