From 4b709310e2a09cf85846a78678eb8ed2eee5de81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 20:15:13 +0000 Subject: [PATCH] rebase: bump github.com/IBM/keyprotect-go-client from 0.7.0 to 0.8.0 Bumps [github.com/IBM/keyprotect-go-client](https://github.com/IBM/keyprotect-go-client) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/IBM/keyprotect-go-client/releases) - [Commits](https://github.com/IBM/keyprotect-go-client/compare/v0.7.0...v0.8.0) --- updated-dependencies: - dependency-name: github.com/IBM/keyprotect-go-client dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +- go.sum | 13 +- .../IBM/keyprotect-go-client/README.md | 57 ++- .../IBM/keyprotect-go-client/import_token.go | 8 +- .../IBM/keyprotect-go-client/key_alias.go | 8 +- .../IBM/keyprotect-go-client/keys.go | 350 +++++++++++++++--- .../IBM/keyprotect-go-client/policy.go | 44 +-- vendor/github.com/google/uuid/hash.go | 4 +- vendor/github.com/google/uuid/null.go | 118 ++++++ vendor/github.com/google/uuid/sql.go | 2 +- vendor/github.com/google/uuid/uuid.go | 55 ++- vendor/github.com/google/uuid/version4.go | 35 +- .../hashicorp/go-retryablehttp/.travis.yml | 12 - .../hashicorp/go-retryablehttp/README.md | 1 + .../hashicorp/go-retryablehttp/client.go | 157 +++++--- .../go-retryablehttp/roundtripper.go | 11 +- vendor/modules.txt | 8 +- 17 files changed, 721 insertions(+), 168 deletions(-) create mode 100644 vendor/github.com/google/uuid/null.go delete mode 100644 vendor/github.com/hashicorp/go-retryablehttp/.travis.yml diff --git a/go.mod b/go.mod index 02e926b94..7ea59ef84 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ceph/ceph-csi go 1.17 require ( - github.com/IBM/keyprotect-go-client v0.7.0 + github.com/IBM/keyprotect-go-client v0.8.0 github.com/aws/aws-sdk-go v1.44.28 github.com/aws/aws-sdk-go-v2/service/sts v1.16.7 github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000 @@ -75,7 +75,7 @@ require ( github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.8 // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.1.2 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -83,7 +83,7 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect - github.com/hashicorp/go-retryablehttp v0.6.6 // indirect + github.com/hashicorp/go-retryablehttp v0.7.0 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect diff --git a/go.sum b/go.sum index 00fc309ed..3114cb5b5 100644 --- a/go.sum +++ b/go.sum @@ -79,8 +79,8 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/zstd v1.4.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/GoogleCloudPlatform/k8s-cloud-provider v1.16.1-0.20210702024009-ea6160c1d0e3/go.mod h1:8XasY4ymP2V/tn2OOV9ZadmiTE1FIB/h3W+yNlPttKw= github.com/IBM/keyprotect-go-client v0.5.1/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= -github.com/IBM/keyprotect-go-client v0.7.0 h1:JstSHD14Lp6ihwQseyPuGcs1AjOBjAmcisP0dTBA6A0= -github.com/IBM/keyprotect-go-client v0.7.0/go.mod h1:SVr2ylV/fhSQPDiUjWirN9fsyWFCNNbt8GIT8hPJVjE= +github.com/IBM/keyprotect-go-client v0.8.0 h1:IgLKSigHRpCCl5cZjBkOYziUZ9zxn6w9iRh+KA8Siww= +github.com/IBM/keyprotect-go-client v0.8.0/go.mod h1:yr8h2noNgU8vcbs+vhqoXp3Lmv73PI0zAc6VMgFvWwM= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= @@ -494,8 +494,9 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= @@ -582,8 +583,9 @@ github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a/go.mod github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY= -github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= @@ -1695,8 +1697,9 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= +gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/vendor/github.com/IBM/keyprotect-go-client/README.md b/vendor/github.com/IBM/keyprotect-go-client/README.md index 2fe0bd79b..e02b8bee6 100644 --- a/vendor/github.com/IBM/keyprotect-go-client/README.md +++ b/vendor/github.com/IBM/keyprotect-go-client/README.md @@ -119,18 +119,18 @@ crkID := key.ID myDEK := []byte{"thisisadataencryptionkey"} // Do some encryption with myDEK // Wrap the DEK so we can safely store it -wrappedDEK, err := client.Wrap(ctx, crkID, myDEK, nil) +wrappedDEK, err := client.Wrap(ctx, crkIDOrAlias, myDEK, nil) // Unwrap the DEK -dek, err := client.Unwrap(ctx, crkID, wrappedDEK, nil) +dek, err := client.Unwrap(ctx, crkIDOrAlias, wrappedDEK, nil) // Do some encryption/decryption using the DEK // Discard the DEK dek = nil ``` Note you can also pass additional authentication data (AAD) to wrap and unwrap calls -to provide another level of protection for your DEK. The AAD is a string array with +to provide another level of protection for your DEK. The AAD is a string array with each element up to 255 chars. For example: ```go @@ -138,11 +138,11 @@ myAAD := []string{"First aad string", "second aad string", "third aad string"} myDEK := []byte{"thisisadataencryptionkey"} // Do some encryption with myDEK // Wrap the DEK so we can safely store it -wrappedDEK, err := client.Wrap(ctx, crkID, myDEK, &myAAD) +wrappedDEK, err := client.Wrap(ctx, crkIDOrAlias, myDEK, &myAAD) // Unwrap the DEK -dek, err := client.Unwrap(ctx, crkID, wrappedDEK, &myAAD) +dek, err := client.Unwrap(ctx, crkIDOrAlias, wrappedDEK, &myAAD) // Do some encryption/decryption using the DEK // Discard the DEK dek = nil @@ -151,7 +151,7 @@ dek = nil Have key protect create a DEK for you: ```go -dek, wrappedDek, err := client.WrapCreateDEK(ctx, crkID, nil) +dek, wrappedDek, err := client.WrapCreateDEK(ctx, crkIDOrAlias, nil) // Do some encrypt/decrypt with the dek // Discard the DEK dek = nil @@ -163,7 +163,7 @@ Can also specify AAD: ```go myAAD := []string{"First aad string", "second aad string", "third aad string"} -dek, wrappedDek, err := client.WrapCreateDEK(ctx, crkID, &myAAD) +dek, wrappedDek, err := client.WrapCreateDEK(ctx, crkIDOrAlias, &myAAD) // Do some encrypt/decrypt with the dek // Discard the DEK dek = nil @@ -171,3 +171,46 @@ dek = nil // Save the wrapped DEK for later. Call Unwrap to use it, make // sure to specify the same AAD. ``` +### Fetching List Key Versions With Parameters. + +```go + +limit := uint32(2) +offset := uint32(0) +totalCount := true + +listkeyVersionsOptions := &kp.ListKeyVersionsOptions{ + Limit : &limit, + Offset : &offset, + TotalCount : &totalCount, +} + +keyVersions, err := client.ListKeyVersions(ctx, "key_id_or_alias", listkeyVersionsOptions) +if err != nil { + fmt.Println(err) +} +fmt.Println(keyVersions) +``` + +### Fetching List Key With Parameters. + +```go + +limit := uint32(5) +offset := uint32(0) +extractable := false +keyStates := []kp.KeyState{kp.KeyState(kp.Active), kp.KeyState(kp.Suspended)} + +listKeysOptions := &kp.ListKeysOptions{ + Limit : &limit, + Offset : &offset, + Extractable : &extractable, + State : keyStates, +} + +keys, err := client.ListKeys(ctx, listKeysOptions) +if err != nil { + fmt.Println(err) +} +fmt.Println(keys) +``` \ No newline at end of file diff --git a/vendor/github.com/IBM/keyprotect-go-client/import_token.go b/vendor/github.com/IBM/keyprotect-go-client/import_token.go index fcdd08599..c39a0c22c 100644 --- a/vendor/github.com/IBM/keyprotect-go-client/import_token.go +++ b/vendor/github.com/IBM/keyprotect-go-client/import_token.go @@ -32,7 +32,13 @@ import ( "time" ) -const importTokenEncAlgo = "RSAES_OAEP_SHA_256" // currently the only one supported +// EncryptionAlgorithm represents the encryption algorithm used for key creation +const ( + // AlgorithmRSAOAEP256 denotes RSA OAEP SHA 256 encryption, supported by KP + AlgorithmRSAOAEP256 string = "RSAES_OAEP_SHA_256" + // AlgorithmRSAOAEP1 denotes RSA OAEP SHA 1 encryption, supported by HPCS + AlgorithmRSAOAEP1 string = "RSAES_OAEP_SHA_1" +) // ImportTokenCreateRequest represents request parameters for creating a // ImportToken. diff --git a/vendor/github.com/IBM/keyprotect-go-client/key_alias.go b/vendor/github.com/IBM/keyprotect-go-client/key_alias.go index fdb63f9e9..e29dcdf5f 100644 --- a/vendor/github.com/IBM/keyprotect-go-client/key_alias.go +++ b/vendor/github.com/IBM/keyprotect-go-client/key_alias.go @@ -33,9 +33,9 @@ type KeyAliases struct { // An alias name acts as an identifier just like key ID // For more information please refer to the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-create-key-alias#create-key-alias-api -func (c *Client) CreateKeyAlias(ctx context.Context, aliasName, keyID string) (*KeyAlias, error) { +func (c *Client) CreateKeyAlias(ctx context.Context, aliasName, idOrAlias string) (*KeyAlias, error) { - req, err := c.newRequest("POST", fmt.Sprintf(requestPath, keyID, aliasName), nil) + req, err := c.newRequest("POST", fmt.Sprintf(requestPath, idOrAlias, aliasName), nil) if err != nil { return nil, err } @@ -56,9 +56,9 @@ func (c *Client) CreateKeyAlias(ctx context.Context, aliasName, keyID string) (* // DeleteKeyAlias deletes an alias name associated with a key // For more information please refer to the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-create-key-alias#delete-key-alias -func (c *Client) DeleteKeyAlias(ctx context.Context, aliasName, keyID string) error { +func (c *Client) DeleteKeyAlias(ctx context.Context, aliasName, idOrAlias string) error { - req, err := c.newRequest("DELETE", fmt.Sprintf(requestPath, keyID, aliasName), nil) + req, err := c.newRequest("DELETE", fmt.Sprintf(requestPath, idOrAlias, aliasName), nil) if err != nil { return err } diff --git a/vendor/github.com/IBM/keyprotect-go-client/keys.go b/vendor/github.com/IBM/keyprotect-go-client/keys.go index d87821951..2080c48ca 100644 --- a/vendor/github.com/IBM/keyprotect-go-client/keys.go +++ b/vendor/github.com/IBM/keyprotect-go-client/keys.go @@ -21,6 +21,7 @@ import ( "log" "net/url" "strconv" + "strings" "time" ) @@ -38,6 +39,17 @@ var ( // PreferReturn designates the value for the "Prefer" header. type PreferReturn int +type KeyState uint32 + +// https://cloud.ibm.com/docs/key-protect?topic=key-protect-key-states +const ( + Active KeyState = iota + 1 + Suspended + Deactivated + _ + Destroyed +) + // Key represents a key as returned by the KP API. type Key struct { ID string `json:"id,omitempty"` @@ -65,6 +77,9 @@ type Key struct { Deleted *bool `json:"deleted,omitempty"` DeletedBy *string `json:"deletedBy,omitempty"` DeletionDate *time.Time `json:"deletionDate,omitempty"` + PurgeAllowed *bool `json:"purgeAllowed,omitempty"` + PurgeAllowedFrom *time.Time `json:"purgeAllowedFrom,omitempty"` + PurgeScheduledOn *time.Time `json:"purgeScheduledOn,omitempty"` DualAuthDelete *DualAuth `json:"dualAuthDelete,omitempty"` } @@ -80,13 +95,27 @@ type Keys struct { Keys []Key `json:"resources"` } +type KeyVersionsMetadata struct { + CollectionType string `json:"collectionType"` + CollectionTotal *uint32 `json:"collectionTotal"` + TotalCount *uint32 `json:"totalCount,omitempty"` +} + +type KeyVersions struct { + Metadata KeyVersionsMetadata `json:"metadata"` + KeyVersion []KeyVersion `json:"resources"` +} + // KeysActionRequest represents request parameters for a key action // API call. type KeysActionRequest struct { - PlainText string `json:"plaintext,omitempty"` - AAD []string `json:"aad,omitempty"` - CipherText string `json:"ciphertext,omitempty"` - Payload string `json:"payload,omitempty"` + PlainText string `json:"plaintext,omitempty"` + AAD []string `json:"aad,omitempty"` + CipherText string `json:"ciphertext,omitempty"` + Payload string `json:"payload,omitempty"` + EncryptedNonce string `json:"encryptedNonce,omitempty"` + IV string `json:"iv,omitempty"` + EncryptionAlgorithm string `json:"encryptionAlgorithm,omitempty"` } type KeyVersion struct { @@ -101,23 +130,14 @@ func (c *Client) CreateKey(ctx context.Context, name string, expiration *time.Ti // CreateImportedKey creates a new KP key from the given key material. func (c *Client) CreateImportedKey(ctx context.Context, name string, expiration *time.Time, payload, encryptedNonce, iv string, extractable bool) (*Key, error) { - key := Key{ - Name: name, - Type: keyType, - Extractable: extractable, - Payload: payload, - } - - if payload != "" && encryptedNonce != "" && iv != "" { - key.EncryptedNonce = encryptedNonce - key.IV = iv - key.EncryptionAlgorithm = importTokenEncAlgo - } - - if expiration != nil { - key.Expiration = expiration - } + key := c.createKeyTemplate(ctx, name, expiration, payload, encryptedNonce, iv, extractable, nil, AlgorithmRSAOAEP256) + return c.createKey(ctx, key) +} +// CreateImportedKeyWithSHA1 creates a new KP key from the given key material +// using RSAES OAEP SHA 1 as encryption algorithm. +func (c *Client) CreateImportedKeyWithSHA1(ctx context.Context, name string, expiration *time.Time, payload, encryptedNonce, iv string, extractable bool, aliases []string) (*Key, error) { + key := c.createKeyTemplate(ctx, name, expiration, payload, encryptedNonce, iv, extractable, aliases, AlgorithmRSAOAEP1) return c.createKey(ctx, key) } @@ -160,25 +180,33 @@ func (c *Client) CreateKeyWithAliases(ctx context.Context, name string, expirati // https://cloud.ibm.com/docs/key-protect?topic=key-protect-import-root-keys#import-root-key-api // https://cloud.ibm.com/docs/key-protect?topic=key-protect-import-standard-keys#import-standard-key-gui func (c *Client) CreateImportedKeyWithAliases(ctx context.Context, name string, expiration *time.Time, payload, encryptedNonce, iv string, extractable bool, aliases []string) (*Key, error) { + key := c.createKeyTemplate(ctx, name, expiration, payload, encryptedNonce, iv, extractable, aliases, AlgorithmRSAOAEP256) + return c.createKey(ctx, key) +} + +func (c *Client) createKeyTemplate(ctx context.Context, name string, expiration *time.Time, payload, encryptedNonce, iv string, extractable bool, aliases []string, encryptionAlgorithm string) Key { key := Key{ Name: name, Type: keyType, Extractable: extractable, Payload: payload, - Aliases: aliases, + } + + if aliases != nil { + key.Aliases = aliases } if !extractable && payload != "" && encryptedNonce != "" && iv != "" { key.EncryptedNonce = encryptedNonce key.IV = iv - key.EncryptionAlgorithm = importTokenEncAlgo + key.EncryptionAlgorithm = encryptionAlgorithm } if expiration != nil { key.Expiration = expiration } - return c.createKey(ctx, key) + return key } func (c *Client) createKey(ctx context.Context, key Key) (*Key, error) { @@ -203,6 +231,36 @@ func (c *Client) createKey(ctx context.Context, key Key) (*Key, error) { return &keysResponse.Keys[0], nil } +// SetKeyRing method transfers a key associated with one key ring to another key ring +// For more information please refer to the link below: +// https://cloud.ibm.com/docs/key-protect?topic=key-protect-grouping-keys#transfer-key-key-ring +func (c *Client) SetKeyRing(ctx context.Context, idOrAlias, newKeyRingID string) (*Key, error) { + if idOrAlias == "" { + return nil, fmt.Errorf("Please provide a valid key ID or alias") + } + + if newKeyRingID == "" { + return nil, fmt.Errorf("Please provide a valid key ring id") + } + + keyRingRequestBody := struct { + KeyRingID string + }{ + KeyRingID: newKeyRingID, + } + + req, err := c.newRequest("PATCH", fmt.Sprintf("keys/%s", idOrAlias), keyRingRequestBody) + if err != nil { + return nil, err + } + + response := Keys{} + if _, err := c.do(ctx, req, &response); err != nil { + return nil, err + } + return &response.Keys[0], nil +} + // GetKeys retrieves a collection of keys that can be paged through. func (c *Client) GetKeys(ctx context.Context, limit int, offset int) (*Keys, error) { if limit == 0 { @@ -228,6 +286,55 @@ func (c *Client) GetKeys(ctx context.Context, limit int, offset int) (*Keys, err return &keys, nil } +//ListKeysOptions struct to add the query parameters for the List Keys function +type ListKeysOptions struct { + Extractable *bool + Limit *uint32 + Offset *uint32 + State []KeyState +} + +// ListKeys retrieves a list of keys that are stored in your Key Protect service instance. +// https://cloud.ibm.com/apidocs/key-protect#getkeys +func (c *Client) ListKeys(ctx context.Context, listKeysOptions *ListKeysOptions) (*Keys, error) { + + req, err := c.newRequest("GET", "keys", nil) + if err != nil { + return nil, err + } + + // extracting the query parameters and encoding the same in the request url + if listKeysOptions != nil { + values := req.URL.Query() + if listKeysOptions.Limit != nil { + values.Set("limit", fmt.Sprint(*listKeysOptions.Limit)) + } + if listKeysOptions.Offset != nil { + values.Set("offset", fmt.Sprint(*listKeysOptions.Offset)) + } + if listKeysOptions.State != nil { + var states []string + for _, i := range listKeysOptions.State { + states = append(states, strconv.Itoa(int(i))) + } + + values.Set("state", strings.Join(states, ",")) + } + if listKeysOptions.Extractable != nil { + values.Set("extractable", fmt.Sprint(*listKeysOptions.Extractable)) + } + req.URL.RawQuery = values.Encode() + } + + keys := Keys{} + _, err = c.do(ctx, req, &keys) + if err != nil { + return nil, err + } + + return &keys, nil +} + // GetKey retrieves a key by ID or alias name. // For more information on Key Alias please refer to the link below // https://cloud.ibm.com/docs/key-protect?topic=key-protect-retrieve-key @@ -245,10 +352,10 @@ func (c *Client) GetKeyMetadata(ctx context.Context, idOrAlias string) (*Key, er return c.getKey(ctx, idOrAlias, "keys/%s/metadata") } -func (c *Client) getKey(ctx context.Context, id string, path string) (*Key, error) { +func (c *Client) getKey(ctx context.Context, idOrAlias string, path string) (*Key, error) { keys := Keys{} - req, err := c.newRequest("GET", fmt.Sprintf(path, id), nil) + req, err := c.newRequest("GET", fmt.Sprintf(path, idOrAlias), nil) if err != nil { return nil, err } @@ -267,10 +374,51 @@ type ForceOpt struct { Force bool } -// DeleteKey deletes a key resource by specifying the ID of the key. -func (c *Client) DeleteKey(ctx context.Context, id string, prefer PreferReturn, callOpts ...CallOpt) (*Key, error) { +// ListKeyVersionsOptions struct to add the query parameters for the ListKeyVersions function +type ListKeyVersionsOptions struct { + Limit *uint32 + Offset *uint32 + TotalCount *bool +} - req, err := c.newRequest("DELETE", fmt.Sprintf("keys/%s", id), nil) +// ListKeyVersions gets all the versions of the key resource by specifying ID of the key and/or optional parameters +// https://cloud.ibm.com/apidocs/key-protect#getkeyversions +func (c *Client) ListKeyVersions(ctx context.Context, idOrAlias string, listKeyVersionsOptions *ListKeyVersionsOptions) (*KeyVersions, error) { + keyVersion := KeyVersions{} + // forming the request + req, err := c.newRequest("GET", fmt.Sprintf("keys/%s/versions", idOrAlias), nil) + if err != nil { + return nil, err + } + + // extracting the query parameters and encoding the same in the request url + if listKeyVersionsOptions != nil { + values := req.URL.Query() + if listKeyVersionsOptions.Limit != nil { + values.Set("limit", fmt.Sprint(*listKeyVersionsOptions.Limit)) + } + if listKeyVersionsOptions.Offset != nil { + values.Set("offset", fmt.Sprint(*listKeyVersionsOptions.Offset)) + } + if listKeyVersionsOptions.TotalCount != nil { + values.Set("totalCount", fmt.Sprint(*listKeyVersionsOptions.TotalCount)) + } + req.URL.RawQuery = values.Encode() + } + + //making a request + _, err = c.do(ctx, req, &keyVersion) + if err != nil { + return nil, err + } + + return &keyVersion, nil +} + +// DeleteKey deletes a key resource by specifying the ID of the key. +func (c *Client) DeleteKey(ctx context.Context, idOrAlias string, prefer PreferReturn, callOpts ...CallOpt) (*Key, error) { + + req, err := c.newRequest("DELETE", fmt.Sprintf("keys/%s", idOrAlias), nil) if err != nil { return nil, err } @@ -301,12 +449,37 @@ func (c *Client) DeleteKey(ctx context.Context, id string, prefer PreferReturn, return nil, nil } +// Purge key method shreds all the metadata and registrations associated with a key that has been +// deleted. The purge operation is allowed to be performed on a key from 4 hours after its deletion +// and its action is irreversible. +// For more information please refer to the link below: +// https://cloud.ibm.com/docs/key-protect?topic=key-protect-delete-keys#delete-keys-key-purge +func (c *Client) PurgeKey(ctx context.Context, idOrAlias string, prefer PreferReturn) (*Key, error) { + req, err := c.newRequest("DELETE", fmt.Sprintf("keys/%s/purge", idOrAlias), nil) + if err != nil { + return nil, err + } + + req.Header.Set("Prefer", preferHeaders[prefer]) + + keys := Keys{} + _, err = c.do(ctx, req, &keys) + if err != nil { + return nil, err + } + if len(keys.Keys) > 0 { + return &keys.Keys[0], nil + } + + return nil, nil +} + // RestoreKey method reverts a delete key status to active key // This method performs restore of any key from deleted state to active state. // For more information please refer to the link below: -// https://cloud.ibm.com/dowcs/key-protect?topic=key-protect-restore-keys -func (c *Client) RestoreKey(ctx context.Context, id string) (*Key, error) { - req, err := c.newRequest("POST", fmt.Sprintf("keys/%s/restore", id), nil) +// https://cloud.ibm.com/docs/key-protect?topic=key-protect-restore-keys +func (c *Client) RestoreKey(ctx context.Context, idOrAlias string) (*Key, error) { + req, err := c.newRequest("POST", fmt.Sprintf("keys/%s/restore", idOrAlias), nil) if err != nil { return nil, err } @@ -322,17 +495,17 @@ func (c *Client) RestoreKey(ctx context.Context, id string) (*Key, error) { } // Wrap calls the wrap action with the given plain text. -func (c *Client) Wrap(ctx context.Context, id string, plainText []byte, additionalAuthData *[]string) ([]byte, error) { - _, ct, err := c.wrap(ctx, id, plainText, additionalAuthData) +func (c *Client) Wrap(ctx context.Context, idOrAlias string, plainText []byte, additionalAuthData *[]string) ([]byte, error) { + _, ct, err := c.wrap(ctx, idOrAlias, plainText, additionalAuthData) return ct, err } // WrapCreateDEK calls the wrap action without plain text. -func (c *Client) WrapCreateDEK(ctx context.Context, id string, additionalAuthData *[]string) ([]byte, []byte, error) { - return c.wrap(ctx, id, nil, additionalAuthData) +func (c *Client) WrapCreateDEK(ctx context.Context, idOrAlias string, additionalAuthData *[]string) ([]byte, []byte, error) { + return c.wrap(ctx, idOrAlias, nil, additionalAuthData) } -func (c *Client) wrap(ctx context.Context, id string, plainText []byte, additionalAuthData *[]string) ([]byte, []byte, error) { +func (c *Client) wrap(ctx context.Context, idOrAlias string, plainText []byte, additionalAuthData *[]string) ([]byte, []byte, error) { keysActionReq := &KeysActionRequest{} if plainText != nil { @@ -347,7 +520,7 @@ func (c *Client) wrap(ctx context.Context, id string, plainText []byte, addition keysActionReq.AAD = *additionalAuthData } - keysAction, err := c.doKeysAction(ctx, id, "wrap", keysActionReq) + keysAction, err := c.doKeysAction(ctx, idOrAlias, "wrap", keysActionReq) if err != nil { return nil, nil, err } @@ -359,8 +532,8 @@ func (c *Client) wrap(ctx context.Context, id string, plainText []byte, addition } // Unwrap is deprecated since it returns only plaintext and doesn't know how to handle rotation. -func (c *Client) Unwrap(ctx context.Context, id string, cipherText []byte, additionalAuthData *[]string) ([]byte, error) { - plainText, _, err := c.UnwrapV2(ctx, id, cipherText, additionalAuthData) +func (c *Client) Unwrap(ctx context.Context, idOrAlias string, cipherText []byte, additionalAuthData *[]string) ([]byte, error) { + plainText, _, err := c.UnwrapV2(ctx, idOrAlias, cipherText, additionalAuthData) if err != nil { return nil, err } @@ -368,7 +541,7 @@ func (c *Client) Unwrap(ctx context.Context, id string, cipherText []byte, addit } // Unwrap with rotation support. -func (c *Client) UnwrapV2(ctx context.Context, id string, cipherText []byte, additionalAuthData *[]string) ([]byte, []byte, error) { +func (c *Client) UnwrapV2(ctx context.Context, idOrAlias string, cipherText []byte, additionalAuthData *[]string) ([]byte, []byte, error) { keysAction := &KeysActionRequest{ CipherText: string(cipherText), @@ -378,7 +551,7 @@ func (c *Client) UnwrapV2(ctx context.Context, id string, cipherText []byte, add keysAction.AAD = *additionalAuthData } - respAction, err := c.doKeysAction(ctx, id, "unwrap", keysAction) + respAction, err := c.doKeysAction(ctx, idOrAlias, "unwrap", keysAction) if err != nil { return nil, nil, err } @@ -390,13 +563,13 @@ func (c *Client) UnwrapV2(ctx context.Context, id string, cipherText []byte, add } // Rotate rotates a CRK. -func (c *Client) Rotate(ctx context.Context, id, payload string) error { +func (c *Client) Rotate(ctx context.Context, idOrAlias, payload string) error { actionReq := &KeysActionRequest{ Payload: payload, } - _, err := c.doKeysAction(ctx, id, "rotate", actionReq) + _, err := c.doKeysAction(ctx, idOrAlias, "rotate", actionReq) if err != nil { return err } @@ -404,12 +577,78 @@ func (c *Client) Rotate(ctx context.Context, id, payload string) error { return nil } +type KeyPayload struct { + payload string + encryptedNonce string + iv string + encryptionAlgorithm string +} + +func NewKeyPayload(payload, encryptedNonce, iv string) KeyPayload { + kp := KeyPayload{ + payload: payload, + encryptedNonce: encryptedNonce, + iv: iv, + } + return kp +} + +// EncryptWithRSA256 sets the encryption algorithm for key create to RSAES_OAEP_SHA_256 +// This is the default algorithm for key creation under Key Protect service +func (kp KeyPayload) WithRSA256() KeyPayload { + kp.encryptionAlgorithm = "RSAES_OAEP_SHA_256" + return kp +} + +// EncryptWithRSA1 sets the encryption algorithm for key create to RSAES_OAEP_SHA_1 +// This algorithm is only supported by the Hyper Protect(HPCS) service +func (kp KeyPayload) WithRSA1() KeyPayload { + kp.encryptionAlgorithm = "RSAES_OAEP_SHA_1" + return kp +} + +// RotateV2 methods supports rotation of a root key with or without payload and also rotate a +// securely imported root key. +func (c *Client) RotateV2(ctx context.Context, idOrAlias string, new_key *KeyPayload) error { + var actionReq *KeysActionRequest + if new_key != nil { + actionReq = &KeysActionRequest{ + Payload: new_key.payload, + EncryptedNonce: new_key.encryptedNonce, + IV: new_key.iv, + EncryptionAlgorithm: new_key.encryptionAlgorithm, + } + } + + _, err := c.doKeysAction(ctx, idOrAlias, "rotate", actionReq) + if err != nil { + return err + } + + return nil +} + +// SyncAssociatedResources method executes the sync request which verifies and updates +// the resources associated with the key. +// For more information please refer to the link below +// https://cloud.ibm.com/docs/key-protect?topic=key-protect-sync-associated-resources +func (c *Client) SyncAssociatedResources(ctx context.Context, idOrAlias string) error { + req, err := c.newRequest("POST", fmt.Sprintf("keys/%s/actions/sync", idOrAlias), nil) + if err != nil { + return err + } + + _, err = c.do(ctx, req, nil) + + return err +} + // Disable a key. The key will not be deleted but it will not be active // and key operations cannot be performed on a disabled key. // For more information can refer to the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-disable-keys -func (c *Client) DisableKey(ctx context.Context, id string) error { - _, err := c.doKeysAction(ctx, id, "disable", nil) +func (c *Client) DisableKey(ctx context.Context, idOrAlias string) error { + _, err := c.doKeysAction(ctx, idOrAlias, "disable", nil) return err } @@ -418,8 +657,8 @@ func (c *Client) DisableKey(ctx context.Context, id string) error { // Note: This does not recover Deleted keys. // For more information can refer to the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-disable-keys#enable-api -func (c *Client) EnableKey(ctx context.Context, id string) error { - _, err := c.doKeysAction(ctx, id, "enable", nil) +func (c *Client) EnableKey(ctx context.Context, idOrAlias string) error { + _, err := c.doKeysAction(ctx, idOrAlias, "enable", nil) return err } @@ -427,8 +666,8 @@ func (c *Client) EnableKey(ctx context.Context, id string) error { // After the key is set to deletion it can be deleted by another user who has Manager access. // For more information refer to the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-delete-dual-auth-keys#set-key-deletion-api -func (c *Client) InitiateDualAuthDelete(ctx context.Context, id string) error { - _, err := c.doKeysAction(ctx, id, "setKeyForDeletion", nil) +func (c *Client) InitiateDualAuthDelete(ctx context.Context, idOrAlias string) error { + _, err := c.doKeysAction(ctx, idOrAlias, "setKeyForDeletion", nil) return err } @@ -436,25 +675,20 @@ func (c *Client) InitiateDualAuthDelete(ctx context.Context, id string) error { // be prevented from getting deleted by unsetting the key for deletion. // For more information refer to the Key Protect docs in the link below: //https://cloud.ibm.com/docs/key-protect?topic=key-protect-delete-dual-auth-keys#unset-key-deletion-api -func (c *Client) CancelDualAuthDelete(ctx context.Context, id string) error { - _, err := c.doKeysAction(ctx, id, "unsetKeyForDeletion", nil) +func (c *Client) CancelDualAuthDelete(ctx context.Context, idOrAlias string) error { + _, err := c.doKeysAction(ctx, idOrAlias, "unsetKeyForDeletion", nil) return err } // doKeysAction calls the KP Client to perform an action on a key. -func (c *Client) doKeysAction(ctx context.Context, id string, action string, keysActionReq *KeysActionRequest) (*KeysActionRequest, error) { +func (c *Client) doKeysAction(ctx context.Context, idOrAlias string, action string, keysActionReq *KeysActionRequest) (*KeysActionRequest, error) { keyActionRsp := KeysActionRequest{} - v := url.Values{} - v.Set("action", action) - - req, err := c.newRequest("POST", fmt.Sprintf("keys/%s", id), keysActionReq) + req, err := c.newRequest("POST", fmt.Sprintf("keys/%s/actions/%s", idOrAlias, action), keysActionReq) if err != nil { return nil, err } - req.URL.RawQuery = v.Encode() - _, err = c.do(ctx, req, &keyActionRsp) if err != nil { return nil, err diff --git a/vendor/github.com/IBM/keyprotect-go-client/policy.go b/vendor/github.com/IBM/keyprotect-go-client/policy.go index 53bb5ea69..4c60970e9 100644 --- a/vendor/github.com/IBM/keyprotect-go-client/policy.go +++ b/vendor/github.com/IBM/keyprotect-go-client/policy.go @@ -59,15 +59,15 @@ type Policies struct { Policies []Policy `json:"resources"` } -// GetPolicy retrieves a policy by Key ID. This function is +// GetPolicy retrieves a policy by Key ID or alias. This function is // deprecated, as it only returns one policy and does not let you // select which policy set it will return. It is kept for backward // compatibility on keys with only one rotation policy. Please update // to use the new GetPolicies or GetPolicy functions. -func (c *Client) GetPolicy(ctx context.Context, id string) (*Policy, error) { +func (c *Client) GetPolicy(ctx context.Context, idOrAlias string) (*Policy, error) { policyresponse := Policies{} - req, err := c.newRequest("GET", fmt.Sprintf("keys/%s/policies", id), nil) + req, err := c.newRequest("GET", fmt.Sprintf("keys/%s/policies", idOrAlias), nil) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (c *Client) GetPolicy(ctx context.Context, id string) (*Policy, error) { // the rotation interval needed. This function is deprecated as it will only // let you set key rotation policies. To set dual auth and other newer policies // on a key, please use the new SetPolicies of SetPolicy functions. -func (c *Client) SetPolicy(ctx context.Context, id string, prefer PreferReturn, rotationInterval int) (*Policy, error) { +func (c *Client) SetPolicy(ctx context.Context, idOrAlias string, prefer PreferReturn, rotationInterval int) (*Policy, error) { policy := Policy{ Type: policyType, @@ -103,7 +103,7 @@ func (c *Client) SetPolicy(ctx context.Context, id string, prefer PreferReturn, policyresponse := Policies{} - req, err := c.newRequest("PUT", fmt.Sprintf("keys/%s/policies", id), &policyRequest) + req, err := c.newRequest("PUT", fmt.Sprintf("keys/%s/policies", idOrAlias), &policyRequest) if err != nil { return nil, err } @@ -118,11 +118,11 @@ func (c *Client) SetPolicy(ctx context.Context, id string, prefer PreferReturn, return &policyresponse.Policies[0], nil } -// GetPolicies retrieves all policies details associated with a Key ID. -func (c *Client) GetPolicies(ctx context.Context, id string) ([]Policy, error) { +// GetPolicies retrieves all policies details associated with a Key ID or alias. +func (c *Client) GetPolicies(ctx context.Context, idOrAlias string) ([]Policy, error) { policyresponse := Policies{} - req, err := c.newRequest("GET", fmt.Sprintf("keys/%s/policies", id), nil) + req, err := c.newRequest("GET", fmt.Sprintf("keys/%s/policies", idOrAlias), nil) if err != nil { return nil, err } @@ -155,10 +155,10 @@ func (c *Client) getPolicy(ctx context.Context, id, policyType string, policyres // GetRotationPolivy method retrieves rotation policy details of a key // For more information can refet the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-set-rotation-policy#view-rotation-policy-api -func (c *Client) GetRotationPolicy(ctx context.Context, id string) (*Policy, error) { +func (c *Client) GetRotationPolicy(ctx context.Context, idOrAlias string) (*Policy, error) { policyresponse := Policies{} - err := c.getPolicy(ctx, id, RotationPolicy, &policyresponse) + err := c.getPolicy(ctx, idOrAlias, RotationPolicy, &policyresponse) if err != nil { return nil, err } @@ -173,10 +173,10 @@ func (c *Client) GetRotationPolicy(ctx context.Context, id string) (*Policy, err // GetDualAuthDeletePolicy method retrieves dual auth delete policy details of a key // For more information can refer the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-set-dual-auth-key-policy#view-dual-auth-key-policy-api -func (c *Client) GetDualAuthDeletePolicy(ctx context.Context, id string) (*Policy, error) { +func (c *Client) GetDualAuthDeletePolicy(ctx context.Context, idOrAlias string) (*Policy, error) { policyresponse := Policies{} - err := c.getPolicy(ctx, id, DualAuthDelete, &policyresponse) + err := c.getPolicy(ctx, idOrAlias, DualAuthDelete, &policyresponse) if err != nil { return nil, err } @@ -188,10 +188,10 @@ func (c *Client) GetDualAuthDeletePolicy(ctx context.Context, id string) (*Polic return &policyresponse.Policies[0], nil } -func (c *Client) setPolicy(ctx context.Context, id, policyType string, policyRequest Policies) (*Policies, error) { +func (c *Client) setPolicy(ctx context.Context, idOrAlias, policyType string, policyRequest Policies) (*Policies, error) { policyresponse := Policies{} - req, err := c.newRequest("PUT", fmt.Sprintf("keys/%s/policies", id), &policyRequest) + req, err := c.newRequest("PUT", fmt.Sprintf("keys/%s/policies", idOrAlias), &policyRequest) if err != nil { return nil, err } @@ -207,10 +207,10 @@ func (c *Client) setPolicy(ctx context.Context, id, policyType string, policyReq return &policyresponse, nil } -// SetRotationPolicy updates the rotation policy associated with a key by specifying key ID and rotation interval. +// SetRotationPolicy updates the rotation policy associated with a key by specifying key ID or alias and rotation interval. // For more information can refer the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-set-rotation-policy#update-rotation-policy-api -func (c *Client) SetRotationPolicy(ctx context.Context, id string, rotationInterval int) (*Policy, error) { +func (c *Client) SetRotationPolicy(ctx context.Context, idOrAlias string, rotationInterval int) (*Policy, error) { policy := Policy{ Type: policyType, Rotation: &Rotation{ @@ -226,7 +226,7 @@ func (c *Client) SetRotationPolicy(ctx context.Context, id string, rotationInter Policies: []Policy{policy}, } - policyresponse, err := c.setPolicy(ctx, id, RotationPolicy, policyRequest) + policyresponse, err := c.setPolicy(ctx, idOrAlias, RotationPolicy, policyRequest) if err != nil { return nil, err } @@ -238,10 +238,10 @@ func (c *Client) SetRotationPolicy(ctx context.Context, id string, rotationInter return &policyresponse.Policies[0], nil } -// SetDualAuthDeletePolicy updates the dual auth delete policy by passing the key ID and enable detail +// SetDualAuthDeletePolicy updates the dual auth delete policy by passing the key ID or alias and enable detail // For more information can refer the Key Protect docs in the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-set-dual-auth-key-policy#create-dual-auth-key-policy-api -func (c *Client) SetDualAuthDeletePolicy(ctx context.Context, id string, enabled bool) (*Policy, error) { +func (c *Client) SetDualAuthDeletePolicy(ctx context.Context, idOrAlias string, enabled bool) (*Policy, error) { policy := Policy{ Type: policyType, DualAuth: &DualAuth{ @@ -257,7 +257,7 @@ func (c *Client) SetDualAuthDeletePolicy(ctx context.Context, id string, enabled Policies: []Policy{policy}, } - policyresponse, err := c.setPolicy(ctx, id, DualAuthDelete, policyRequest) + policyresponse, err := c.setPolicy(ctx, idOrAlias, DualAuthDelete, policyRequest) if err != nil { return nil, err } @@ -273,7 +273,7 @@ func (c *Client) SetDualAuthDeletePolicy(ctx context.Context, id string, enabled // To set rotation policy for the key pass the setRotationPolicy parameter as true and set the rotationInterval detail. // To set dual auth delete policy for the key pass the setDualAuthDeletePolicy parameter as true and set the dualAuthEnable detail. // Both the policies can be set or either of the policies can be set. -func (c *Client) SetPolicies(ctx context.Context, id string, setRotationPolicy bool, rotationInterval int, setDualAuthDeletePolicy, dualAuthEnable bool) ([]Policy, error) { +func (c *Client) SetPolicies(ctx context.Context, idOrAlias string, setRotationPolicy bool, rotationInterval int, setDualAuthDeletePolicy, dualAuthEnable bool) ([]Policy, error) { policies := []Policy{} if setRotationPolicy { rotationPolicy := Policy{ @@ -304,7 +304,7 @@ func (c *Client) SetPolicies(ctx context.Context, id string, setRotationPolicy b policyresponse := Policies{} - req, err := c.newRequest("PUT", fmt.Sprintf("keys/%s/policies", id), &policyRequest) + req, err := c.newRequest("PUT", fmt.Sprintf("keys/%s/policies", idOrAlias), &policyRequest) if err != nil { return nil, err } diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go index b17461631..b404f4bec 100644 --- a/vendor/github.com/google/uuid/hash.go +++ b/vendor/github.com/google/uuid/hash.go @@ -26,8 +26,8 @@ var ( // NewMD5 and NewSHA1. func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { h.Reset() - h.Write(space[:]) - h.Write(data) + h.Write(space[:]) //nolint:errcheck + h.Write(data) //nolint:errcheck s := h.Sum(nil) var uuid UUID copy(uuid[:], s) diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go new file mode 100644 index 000000000..d7fcbf286 --- /dev/null +++ b/vendor/github.com/google/uuid/null.go @@ -0,0 +1,118 @@ +// Copyright 2021 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "database/sql/driver" + "encoding/json" + "fmt" +) + +var jsonNull = []byte("null") + +// NullUUID represents a UUID that may be null. +// NullUUID implements the SQL driver.Scanner interface so +// it can be used as a scan destination: +// +// var u uuid.NullUUID +// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) +// ... +// if u.Valid { +// // use u.UUID +// } else { +// // NULL value +// } +// +type NullUUID struct { + UUID UUID + Valid bool // Valid is true if UUID is not NULL +} + +// Scan implements the SQL driver.Scanner interface. +func (nu *NullUUID) Scan(value interface{}) error { + if value == nil { + nu.UUID, nu.Valid = Nil, false + return nil + } + + err := nu.UUID.Scan(value) + if err != nil { + nu.Valid = false + return err + } + + nu.Valid = true + return nil +} + +// Value implements the driver Valuer interface. +func (nu NullUUID) Value() (driver.Value, error) { + if !nu.Valid { + return nil, nil + } + // Delegate to UUID Value function + return nu.UUID.Value() +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (nu NullUUID) MarshalBinary() ([]byte, error) { + if nu.Valid { + return nu.UUID[:], nil + } + + return []byte(nil), nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (nu *NullUUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(nu.UUID[:], data) + nu.Valid = true + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (nu NullUUID) MarshalText() ([]byte, error) { + if nu.Valid { + return nu.UUID.MarshalText() + } + + return jsonNull, nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (nu *NullUUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + nu.Valid = false + return err + } + nu.UUID = id + nu.Valid = true + return nil +} + +// MarshalJSON implements json.Marshaler. +func (nu NullUUID) MarshalJSON() ([]byte, error) { + if nu.Valid { + return json.Marshal(nu.UUID) + } + + return jsonNull, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (nu *NullUUID) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, jsonNull) { + *nu = NullUUID{} + return nil // valid null UUID + } + err := json.Unmarshal(data, &nu.UUID) + nu.Valid = err == nil + return err +} diff --git a/vendor/github.com/google/uuid/sql.go b/vendor/github.com/google/uuid/sql.go index f326b54db..2e02ec06c 100644 --- a/vendor/github.com/google/uuid/sql.go +++ b/vendor/github.com/google/uuid/sql.go @@ -9,7 +9,7 @@ import ( "fmt" ) -// Scan implements sql.Scanner so UUIDs can be read from databases transparently +// Scan implements sql.Scanner so UUIDs can be read from databases transparently. // Currently, database types that map to string and []byte are supported. Please // consult database-specific driver documentation for matching types. func (uuid *UUID) Scan(src interface{}) error { diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go index 524404cc5..a57207aeb 100644 --- a/vendor/github.com/google/uuid/uuid.go +++ b/vendor/github.com/google/uuid/uuid.go @@ -12,6 +12,7 @@ import ( "fmt" "io" "strings" + "sync" ) // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -33,7 +34,27 @@ const ( Future // Reserved for future definition. ) -var rander = rand.Reader // random function +const randPoolSize = 16 * 16 + +var ( + rander = rand.Reader // random function + poolEnabled = false + poolMu sync.Mutex + poolPos = randPoolSize // protected with poolMu + pool [randPoolSize]byte // protected with poolMu +) + +type invalidLengthError struct{ len int } + +func (err invalidLengthError) Error() string { + return fmt.Sprintf("invalid UUID length: %d", err.len) +} + +// IsInvalidLengthError is matcher function for custom error invalidLengthError +func IsInvalidLengthError(err error) bool { + _, ok := err.(invalidLengthError) + return ok +} // Parse decodes s into a UUID or returns an error. Both the standard UUID // forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and @@ -68,7 +89,7 @@ func Parse(s string) (UUID, error) { } return uuid, nil default: - return uuid, fmt.Errorf("invalid UUID length: %d", len(s)) + return uuid, invalidLengthError{len(s)} } // s is now at least 36 bytes long // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx @@ -112,7 +133,7 @@ func ParseBytes(b []byte) (UUID, error) { } return uuid, nil default: - return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) + return uuid, invalidLengthError{len(b)} } // s is now at least 36 bytes long // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx @@ -243,3 +264,31 @@ func SetRand(r io.Reader) { } rander = r } + +// EnableRandPool enables internal randomness pool used for Random +// (Version 4) UUID generation. The pool contains random bytes read from +// the random number generator on demand in batches. Enabling the pool +// may improve the UUID generation throughput significantly. +// +// Since the pool is stored on the Go heap, this feature may be a bad fit +// for security sensitive applications. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func EnableRandPool() { + poolEnabled = true +} + +// DisableRandPool disables the randomness pool if it was previously +// enabled with EnableRandPool. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func DisableRandPool() { + poolEnabled = false + defer poolMu.Unlock() + poolMu.Lock() + poolPos = randPoolSize +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go index c110465db..7697802e4 100644 --- a/vendor/github.com/google/uuid/version4.go +++ b/vendor/github.com/google/uuid/version4.go @@ -14,11 +14,21 @@ func New() UUID { return Must(NewRandom()) } +// NewString creates a new random UUID and returns it as a string or panics. +// NewString is equivalent to the expression +// +// uuid.New().String() +func NewString() string { + return Must(NewRandom()).String() +} + // NewRandom returns a Random (Version 4) UUID. // // The strength of the UUIDs is based on the strength of the crypto/rand // package. // +// Uses the randomness pool if it was enabled with EnableRandPool. +// // A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being @@ -27,7 +37,10 @@ func New() UUID { // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() (UUID, error) { - return NewRandomFromReader(rander) + if !poolEnabled { + return NewRandomFromReader(rander) + } + return newRandomFromPool() } // NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. @@ -41,3 +54,23 @@ func NewRandomFromReader(r io.Reader) (UUID, error) { uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 return uuid, nil } + +func newRandomFromPool() (UUID, error) { + var uuid UUID + poolMu.Lock() + if poolPos == randPoolSize { + _, err := io.ReadFull(rander, pool[:]) + if err != nil { + poolMu.Unlock() + return Nil, err + } + poolPos = 0 + } + copy(uuid[:], pool[poolPos:(poolPos+16)]) + poolPos += 16 + poolMu.Unlock() + + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml b/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml deleted file mode 100644 index c4fb6d6c8..000000000 --- a/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -language: go - -go: - - 1.12.4 - -branches: - only: - - master - -script: make updatedeps test diff --git a/vendor/github.com/hashicorp/go-retryablehttp/README.md b/vendor/github.com/hashicorp/go-retryablehttp/README.md index 30357c756..8943becf1 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/README.md +++ b/vendor/github.com/hashicorp/go-retryablehttp/README.md @@ -26,6 +26,7 @@ fails so that the full request can be attempted again. See the details. Version 0.6.0 and before are compatible with Go prior to 1.12. From 0.6.1 onward, Go 1.12+ is required. +From 0.6.7 onward, Go 1.13+ is required. Example Use =========== diff --git a/vendor/github.com/hashicorp/go-retryablehttp/client.go b/vendor/github.com/hashicorp/go-retryablehttp/client.go index f1ccd3df3..adbdd92e3 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/client.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/client.go @@ -35,11 +35,12 @@ import ( "net/url" "os" "regexp" + "strconv" "strings" "sync" "time" - "github.com/hashicorp/go-cleanhttp" + cleanhttp "github.com/hashicorp/go-cleanhttp" ) var ( @@ -276,12 +277,16 @@ type Logger interface { Printf(string, ...interface{}) } -// LeveledLogger interface implements the basic methods that a logger library needs +// LeveledLogger is an interface that can be implemented by any logger or a +// logger wrapper to provide leveled logging. The methods accept a message +// string and a variadic number of key-value pairs. For log.Printf style +// formatting where message string contains a format specifier, use Logger +// interface. type LeveledLogger interface { - Error(string, ...interface{}) - Info(string, ...interface{}) - Debug(string, ...interface{}) - Warn(string, ...interface{}) + Error(msg string, keysAndValues ...interface{}) + Info(msg string, keysAndValues ...interface{}) + Debug(msg string, keysAndValues ...interface{}) + Warn(msg string, keysAndValues ...interface{}) } // hookLogger adapts an LeveledLogger to Logger for use by the existing hook functions @@ -357,6 +362,7 @@ type Client struct { ErrorHandler ErrorHandler loggerInit sync.Once + clientInit sync.Once } // NewClient creates a new Client with default settings. @@ -398,21 +404,39 @@ func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bo return false, ctx.Err() } + // don't propagate other errors + shouldRetry, _ := baseRetryPolicy(resp, err) + return shouldRetry, nil +} + +// ErrorPropagatedRetryPolicy is the same as DefaultRetryPolicy, except it +// propagates errors back instead of returning nil. This allows you to inspect +// why it decided to retry or not. +func ErrorPropagatedRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) { + // do not retry on context.Canceled or context.DeadlineExceeded + if ctx.Err() != nil { + return false, ctx.Err() + } + + return baseRetryPolicy(resp, err) +} + +func baseRetryPolicy(resp *http.Response, err error) (bool, error) { if err != nil { if v, ok := err.(*url.Error); ok { // Don't retry if the error was due to too many redirects. if redirectsErrorRe.MatchString(v.Error()) { - return false, nil + return false, v } // Don't retry if the error was due to an invalid protocol scheme. if schemeErrorRe.MatchString(v.Error()) { - return false, nil + return false, v } // Don't retry if the error was due to TLS cert verification failure. if _, ok := v.Err.(x509.UnknownAuthorityError); ok { - return false, nil + return false, v } } @@ -420,12 +444,19 @@ func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bo return true, nil } + // 429 Too Many Requests is recoverable. Sometimes the server puts + // a Retry-After response header to indicate when the server is + // available to start processing request from client. + if resp.StatusCode == http.StatusTooManyRequests { + return true, nil + } + // Check the response code. We retry on 500-range responses to allow // the server time to recover, as 500's are typically not permanent // errors and may relate to outages on the server side. This will catch // invalid response codes as well, like 0 and 999. if resp.StatusCode == 0 || (resp.StatusCode >= 500 && resp.StatusCode != 501) { - return true, nil + return true, fmt.Errorf("unexpected HTTP status %s", resp.Status) } return false, nil @@ -434,7 +465,21 @@ func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bo // DefaultBackoff provides a default callback for Client.Backoff which // will perform exponential backoff based on the attempt number and limited // by the provided minimum and maximum durations. +// +// It also tries to parse Retry-After response header when a http.StatusTooManyRequests +// (HTTP Code 429) is found in the resp parameter. Hence it will return the number of +// seconds the server states it may be ready to process more requests from this client. func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { + if resp != nil { + if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode == http.StatusServiceUnavailable { + if s, ok := resp.Header["Retry-After"]; ok { + if sleep, err := strconv.ParseInt(s[0], 10, 64); err == nil { + return time.Second * time.Duration(sleep) + } + } + } + } + mult := math.Pow(2, float64(attemptNum)) * float64(min) sleep := time.Duration(mult) if float64(sleep) != mult || sleep > max { @@ -490,25 +535,31 @@ func PassthroughErrorHandler(resp *http.Response, err error, _ int) (*http.Respo // Do wraps calling an HTTP method with retries. func (c *Client) Do(req *Request) (*http.Response, error) { - if c.HTTPClient == nil { - c.HTTPClient = cleanhttp.DefaultPooledClient() - } + c.clientInit.Do(func() { + if c.HTTPClient == nil { + c.HTTPClient = cleanhttp.DefaultPooledClient() + } + }) logger := c.logger() if logger != nil { switch v := logger.(type) { - case Logger: - v.Printf("[DEBUG] %s %s", req.Method, req.URL) case LeveledLogger: v.Debug("performing request", "method", req.Method, "url", req.URL) + case Logger: + v.Printf("[DEBUG] %s %s", req.Method, req.URL) } } var resp *http.Response - var err error + var attempt int + var shouldRetry bool + var doErr, checkErr error for i := 0; ; i++ { + attempt++ + var code int // HTTP response code // Always rewind the request body when non-nil. @@ -527,30 +578,30 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if c.RequestLogHook != nil { switch v := logger.(type) { - case Logger: - c.RequestLogHook(v, req.Request, i) case LeveledLogger: c.RequestLogHook(hookLogger{v}, req.Request, i) + case Logger: + c.RequestLogHook(v, req.Request, i) default: c.RequestLogHook(nil, req.Request, i) } } // Attempt the request - resp, err = c.HTTPClient.Do(req.Request) + resp, doErr = c.HTTPClient.Do(req.Request) if resp != nil { code = resp.StatusCode } // Check if we should continue with retries. - checkOK, checkErr := c.CheckRetry(req.Context(), resp, err) + shouldRetry, checkErr = c.CheckRetry(req.Context(), resp, doErr) - if err != nil { + if doErr != nil { switch v := logger.(type) { - case Logger: - v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, err) case LeveledLogger: - v.Error("request failed", "error", err, "method", req.Method, "url", req.URL) + v.Error("request failed", "error", doErr, "method", req.Method, "url", req.URL) + case Logger: + v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, doErr) } } else { // Call this here to maintain the behavior of logging all requests, @@ -558,23 +609,18 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if c.ResponseLogHook != nil { // Call the response logger function if provided. switch v := logger.(type) { - case Logger: - c.ResponseLogHook(v, resp) case LeveledLogger: c.ResponseLogHook(hookLogger{v}, resp) + case Logger: + c.ResponseLogHook(v, resp) default: c.ResponseLogHook(nil, resp) } } } - // Now decide if we should continue. - if !checkOK { - if checkErr != nil { - err = checkErr - } - c.HTTPClient.CloseIdleConnections() - return resp, err + if !shouldRetry { + break } // We do this before drainBody because there's no need for the I/O if @@ -585,7 +631,7 @@ func (c *Client) Do(req *Request) (*http.Response, error) { } // We're going to retry, consume any response to reuse the connection. - if err == nil && resp != nil { + if doErr == nil { c.drainBody(resp.Body) } @@ -596,10 +642,10 @@ func (c *Client) Do(req *Request) (*http.Response, error) { } if logger != nil { switch v := logger.(type) { - case Logger: - v.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain) case LeveledLogger: v.Debug("retrying request", "request", desc, "timeout", wait, "remaining", remain) + case Logger: + v.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain) } } select { @@ -608,21 +654,44 @@ func (c *Client) Do(req *Request) (*http.Response, error) { return nil, req.Context().Err() case <-time.After(wait): } + + // Make shallow copy of http Request so that we can modify its body + // without racing against the closeBody call in persistConn.writeLoop. + httpreq := *req.Request + req.Request = &httpreq + } + + // this is the closest we have to success criteria + if doErr == nil && checkErr == nil && !shouldRetry { + return resp, nil + } + + defer c.HTTPClient.CloseIdleConnections() + + err := doErr + if checkErr != nil { + err = checkErr } if c.ErrorHandler != nil { - c.HTTPClient.CloseIdleConnections() - return c.ErrorHandler(resp, err, c.RetryMax+1) + return c.ErrorHandler(resp, err, attempt) } // By default, we close the response body and return an error without // returning the response if resp != nil { - resp.Body.Close() + c.drainBody(resp.Body) } - c.HTTPClient.CloseIdleConnections() - return nil, fmt.Errorf("%s %s giving up after %d attempts", - req.Method, req.URL, c.RetryMax+1) + + // this means CheckRetry thought the request was a failure, but didn't + // communicate why + if err == nil { + return nil, fmt.Errorf("%s %s giving up after %d attempt(s)", + req.Method, req.URL, attempt) + } + + return nil, fmt.Errorf("%s %s giving up after %d attempt(s): %w", + req.Method, req.URL, attempt, err) } // Try to read the response body so we can reuse this connection. @@ -632,10 +701,10 @@ func (c *Client) drainBody(body io.ReadCloser) { if err != nil { if c.logger() != nil { switch v := c.logger().(type) { - case Logger: - v.Printf("[ERR] error reading response body: %v", err) case LeveledLogger: v.Error("error reading response body", "error", err) + case Logger: + v.Printf("[ERR] error reading response body: %v", err) } } } diff --git a/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go b/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go index b841b4cfe..8f3ee3584 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go @@ -1,7 +1,9 @@ package retryablehttp import ( + "errors" "net/http" + "net/url" "sync" ) @@ -39,5 +41,12 @@ func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { } // Execute the request. - return rt.Client.Do(retryableReq) + resp, err := rt.Client.Do(retryableReq) + // If we got an error returned by standard library's `Do` method, unwrap it + // otherwise we will wind up erroneously re-nesting the error. + if _, ok := err.(*url.Error); ok { + return resp, errors.Unwrap(err) + } + + return resp, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 67c21ce03..e615762c4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,5 +1,5 @@ -# github.com/IBM/keyprotect-go-client v0.7.0 -## explicit; go 1.12 +# github.com/IBM/keyprotect-go-client v0.8.0 +## explicit; go 1.15 github.com/IBM/keyprotect-go-client github.com/IBM/keyprotect-go-client/iam # github.com/PuerkitoBio/purell v1.1.1 @@ -229,7 +229,7 @@ github.com/google/go-cmp/cmp/internal/value # github.com/google/gofuzz v1.1.0 ## explicit; go 1.12 github.com/google/gofuzz -# github.com/google/uuid v1.1.2 +# github.com/google/uuid v1.3.0 ## explicit github.com/google/uuid # github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 @@ -262,7 +262,7 @@ github.com/hashicorp/go-multierror ## explicit; go 1.13 github.com/hashicorp/go-plugin github.com/hashicorp/go-plugin/internal/plugin -# github.com/hashicorp/go-retryablehttp v0.6.6 +# github.com/hashicorp/go-retryablehttp v0.7.0 ## explicit; go 1.13 github.com/hashicorp/go-retryablehttp # github.com/hashicorp/go-rootcerts v1.0.2