Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: simplify API usage with higher level methods #7

Merged
merged 1 commit into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.

// Package okms is a client for interacting with OVHcloud KMS REST-API.
package okms

import (
Expand All @@ -16,17 +17,18 @@ import (
"github.com/ovh/okms-sdk-go/types"
)

var _ Client = (*RestAPIClient)(nil)
var _ API = (*Client)(nil)

// Client is the interface abstracting the KMS clients methods.
type Client interface {
// API is the interface abstracting the KMS clients methods.
type API interface {
// RandomApi
DataKeyApi
SignatureApi
EncryptionApi
ServiceKeyApi
// SecretApi
// Ping(ctx context.Context) error
SetCustomHeader(key, value string)
}

// type RandomApi interface {
Expand Down Expand Up @@ -74,18 +76,10 @@ type ServiceKeyApi interface {
// ListServiceKeys returns a page of service keys. The response contains a continuationToken that must be passed to the
// subsequent calls in order to get the next page. The state parameter when no nil is used to query keys having a specific state.
ListServiceKeys(ctx context.Context, continuationToken *string, maxKey *int32, state *types.KeyStates) (*types.ListServiceKeysResponse, error)
// ListAllServiceKeys returns an iterator to go through all the keys without having to deal with pagination.
ListAllServiceKeys(pageSize *int32, state *types.KeyStates) KeyIter
// UpdateServiceKey updates some service key metadata.
UpdateServiceKey(ctx context.Context, keyId uuid.UUID, body types.PatchServiceKeyRequest) (*types.GetServiceKeyResponse, error)
}

// type ServiceKeyApi2 interface {
// GenerateSymmetricKey(ctx context.Context, name string, size types.KeySizes, usage ...types.CryptographicUsages) (*types.GetServiceKeyResponse, error)
// GenerateRSAKeyPair(ctx context.Context, name string, size types.KeySizes, usage ...types.CryptographicUsages) (*types.GetServiceKeyResponse, error)
// GenerateECDSAKeyPair(ctx context.Context, name string, curve types.Curves, usage ...types.CryptographicUsages) (*types.GetServiceKeyResponse, error)
// }

// type SecretApi interface {
// GetSecretsMetadata(ctx context.Context, path string, list bool) (*types.GetMetadataResponse, error)
// PatchSecretMetadata(ctx context.Context, path string, body types.SecretUpdatableMetadata) error
Expand Down
253 changes: 202 additions & 51 deletions client.go

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions datakey.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ import (
"math"

"github.com/google/uuid"
"github.com/ovh/okms-sdk-go/internal/utils"
"github.com/ovh/okms-sdk-go/internal/xcrypto"
)

// DataKeys creates a new datakey provider for the given service key.
func (client *Client) DataKeys(serviceKeyID uuid.UUID) *DataKeyProvider {
return newDataKeyProvider(client, serviceKeyID)
}

// DataKeyProvider is a helper provider that wraps an API client
// and provides helpers functions to repeatedly generate or decrypt datakeys
// protected by the same service key.
Expand All @@ -33,9 +39,9 @@ type DataKeyProvider struct {
keyId uuid.UUID
}

// NewDataKeyProvider creates a new datakey provider for the given service key,
// newDataKeyProvider creates a new datakey provider for the given service key,
// using the given [DataKeyApi] api client.
func NewDataKeyProvider(api DataKeyApi, keyId uuid.UUID) *DataKeyProvider {
func newDataKeyProvider(api DataKeyApi, keyId uuid.UUID) *DataKeyProvider {
return &DataKeyProvider{
api: api,
keyId: keyId,
Expand All @@ -52,8 +58,7 @@ func (sk *DataKeyProvider) GenerateDataKey(ctx context.Context, name string, siz
return nil, nil, errors.New("key size is out of bound")
}
// Let's first ask the KMS to generate a new DK
//nolint:gosec // integer bounds are checked right before
plain, encryptedKey, err := sk.api.GenerateDataKey(ctx, sk.keyId, name, int32(size))
plain, encryptedKey, err := sk.api.GenerateDataKey(ctx, sk.keyId, name, utils.ToInt32(size))
if err != nil {
return nil, nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"errors"
"fmt"

"github.com/ovh/okms-sdk-go/internal/utils"
"github.com/ovh/okms-sdk-go/types"
)

Expand Down Expand Up @@ -204,7 +205,7 @@ func newKmsErrorFromRestResponse(resp types.ErrorResponse) *KmsError {
kmsErr.ErrorId = *resp.ErrorId
}
if resp.ErrorCode != nil {
kmsErr.ErrorCode = ErrorCode(*resp.ErrorCode)
kmsErr.ErrorCode = ErrorCode(utils.ToUint32(*resp.ErrorCode))
}
if resp.Errors != nil {
for _, er := range *resp.Errors {
Expand Down
54 changes: 27 additions & 27 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ func ExampleNewRestAPIClientWithHttp() {
}

// Generate an 256 bits AES key
func ExampleRestAPIClient_CreateImportServiceKey_generateAES() {
var kmsClient *okms.RestAPIClient // Initialize client
func ExampleClient_CreateImportServiceKey_generateAES() {
var kmsClient *okms.Client // Initialize client
kType := types.Oct
kSize := types.N256
ops := []types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}
Expand All @@ -67,13 +67,13 @@ func ExampleRestAPIClient_CreateImportServiceKey_generateAES() {
}

// Generate a 2048 bits RSA key pair
func ExampleRestAPIClient_CreateImportServiceKey_generateRSA() {
var kmsClient *okms.RestAPIClient // Initialize client
func ExampleClient_CreateImportServiceKey_generateRSA() {
var kmsClient *okms.Client // Initialize client
kType := types.RSA
kSize := types.N2048
ops := []types.CryptographicUsages{types.Sign, types.Verify}
// Create a new RSA 2048 key-pair
respAes, err := kmsClient.CreateImportServiceKey(context.Background(), nil, types.CreateImportServiceKeyRequest{
respRSA, err := kmsClient.CreateImportServiceKey(context.Background(), nil, types.CreateImportServiceKeyRequest{
Name: "RSA key-pair example",
Type: &kType,
Size: &kSize,
Expand All @@ -82,17 +82,17 @@ func ExampleRestAPIClient_CreateImportServiceKey_generateRSA() {
if err != nil {
panic(err)
}
fmt.Println("RSA KEY:", respAes.Id)
fmt.Println("RSA KEY:", respRSA.Id)
}

// Generate an ECDSA key pair on the P-256 curve
func ExampleRestAPIClient_CreateImportServiceKey_generateECDSA() {
var kmsClient *okms.RestAPIClient // Initialize client
func ExampleClient_CreateImportServiceKey_generateECDSA() {
var kmsClient *okms.Client // Initialize client
kType := types.EC
curve := types.P256
ops := []types.CryptographicUsages{types.Sign, types.Verify}
// Create a new ECDSA P-256 key-pair
respAes, err := kmsClient.CreateImportServiceKey(context.Background(), nil, types.CreateImportServiceKeyRequest{
respEC, err := kmsClient.CreateImportServiceKey(context.Background(), nil, types.CreateImportServiceKeyRequest{
Name: "ECDSA key-pair example",
Type: &kType,
Curve: &curve,
Expand All @@ -101,23 +101,23 @@ func ExampleRestAPIClient_CreateImportServiceKey_generateECDSA() {
if err != nil {
panic(err)
}
fmt.Println("ECDSA KEY:", respAes.Id)
fmt.Println("ECDSA KEY:", respEC.Id)
}

func ExampleRestAPIClient_Sign() {
var kmsClient *okms.RestAPIClient // Initialize client
data := "Hello World !!!" // Data to sign
func ExampleClient_Sign() {
var kmsClient *okms.Client // Initialize client
data := "Hello World !!!" // Data to sign
signResponse, err := kmsClient.Sign(context.Background(), uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"), types.ES256, false, []byte(data))
if err != nil {
panic(err)
}
fmt.Println("Signature:", signResponse)
}

func ExampleRestAPIClient_Verify() {
var kmsClient *okms.RestAPIClient // Initialize client
var signature string // Base64 encoded signature
data := "Hello World !!!" // Data to sign
func ExampleClient_Verify() {
var kmsClient *okms.Client // Initialize client
var signature string // Base64 encoded signature
data := "Hello World !!!" // Data to sign
result, err := kmsClient.Verify(context.Background(), uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"), types.ES256, false, []byte(data), signature)
if err != nil {
panic(err)
Expand All @@ -126,10 +126,10 @@ func ExampleRestAPIClient_Verify() {
}

func ExampleDataKeyProvider_helpers() {
var kmsClient *okms.RestAPIClient // Initialize client
var kmsClient *okms.Client // Initialize client

data := "Hello World !!!" // Data to encrypt
dkProvider := okms.NewDataKeyProvider(kmsClient, uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"))
dkProvider := kmsClient.DataKeys(uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"))

// Unless you want to use another algorithm than AES-GCM 256 bits, you can use the 2 following helper methods:
encryptedData, encryptedKey, nonce, err := dkProvider.EncryptGCM(context.Background(), "Example DK", []byte(data), []byte("Some additional data"))
Expand All @@ -145,9 +145,9 @@ func ExampleDataKeyProvider_helpers() {
}

func ExampleDataKeyProvider_GenerateDataKey() {
var kmsClient *okms.RestAPIClient // Initialize client
data := "Hello World !!!" // Data to encrypt
dkProvider := okms.NewDataKeyProvider(kmsClient, uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"))
var kmsClient *okms.Client // Initialize client
data := "Hello World !!!" // Data to encrypt
dkProvider := kmsClient.DataKeys(uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"))

// Generate a new datakey
plain, encrypted, err := dkProvider.GenerateDataKey(context.Background(), "Example DK", 256)
Expand Down Expand Up @@ -178,11 +178,11 @@ func ExampleDataKeyProvider_GenerateDataKey() {
}

func ExampleDataKeyProvider_DecryptDataKey() {
var kmsClient *okms.RestAPIClient // Initialize client
var encryptedData []byte // Some encrypted data
var encryptedKey []byte // Encrypted datakey
var nonce []byte // Nonce used for data encryption
dkProvider := okms.NewDataKeyProvider(kmsClient, uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"))
var kmsClient *okms.Client // Initialize client
var encryptedData []byte // Some encrypted data
var encryptedKey []byte // Encrypted datakey
var nonce []byte // Nonce used for data encryption
dkProvider := kmsClient.DataKeys(uuid.MustParse("2dab95dc-d7d3-482b-a07b-6b4dfae89d58"))

// Decrypt data key
plain, err := dkProvider.DecryptDataKey(context.Background(), encryptedKey)
Expand Down
33 changes: 9 additions & 24 deletions examples/datakeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,16 @@ import (
"github.com/ovh/okms-sdk-go/types"
)

func dataKeyEncryptDecrypt(ctx context.Context, kmsClient okms.Client) {
func dataKeyEncryptDecrypt(ctx context.Context, kmsClient *okms.Client) {
// Create a new AES 256 key
respAes, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "AES key example",
Type: ptrTo(types.Oct),
Size: ptrTo(types.N256),
Operations: ptrTo([]types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}),
})
respAes, err := kmsClient.GenerateSymmetricKey(ctx, types.N256, "AES key example", "", types.WrapKey, types.UnwrapKey)
if err != nil {
panic(err)
}

data := "Hello World !!!" // Data to encrypt

dkProvider := okms.NewDataKeyProvider(kmsClient, respAes.Id)
dkProvider := kmsClient.DataKeys(respAes.Id)

// ENCRYPTION

Expand Down Expand Up @@ -108,19 +103,14 @@ func dataKeyEncryptDecrypt(ctx context.Context, kmsClient okms.Client) {
fmt.Println("Decrypted:", string(plainData))
}

func dataKeyEncryptStream(ctx context.Context, kmsClient okms.Client) {
func dataKeyEncryptStream(ctx context.Context, kmsClient *okms.Client) {
// Create a new AES 256 key
respAes, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "AES key example",
Type: ptrTo(types.Oct),
Size: ptrTo(types.N256),
Operations: ptrTo([]types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}),
})
respAes, err := kmsClient.GenerateSymmetricKey(ctx, types.N256, "AES key example", "", types.WrapKey, types.UnwrapKey)
if err != nil {
panic(err)
}

dkProvider := okms.NewDataKeyProvider(kmsClient, respAes.Id)
dkProvider := kmsClient.DataKeys(respAes.Id)

sourceFile, err := os.Open("10GB_Plain_File.txt")
if err != nil {
Expand All @@ -146,19 +136,14 @@ func dataKeyEncryptStream(ctx context.Context, kmsClient okms.Client) {
}
}

func dataKeyDecryptStream(ctx context.Context, kmsClient okms.Client) {
func dataKeyDecryptStream(ctx context.Context, kmsClient *okms.Client) {
// Create a new AES 256 key
respAes, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "AES key example",
Type: ptrTo(types.Oct),
Size: ptrTo(types.N256),
Operations: ptrTo([]types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}),
})
respAes, err := kmsClient.GenerateSymmetricKey(ctx, types.N256, "AES key example", "", types.WrapKey, types.UnwrapKey)
if err != nil {
panic(err)
}

dkProvider := okms.NewDataKeyProvider(kmsClient, respAes.Id)
dkProvider := kmsClient.DataKeys(respAes.Id)

sourceFile, err := os.Create("Encrypted_File.bin")
if err != nil {
Expand Down
9 changes: 2 additions & 7 deletions examples/encrypt_decrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,9 @@ import (
"github.com/ovh/okms-sdk-go/types"
)

func encryptDecrypt(ctx context.Context, kmsClient okms.Client) {
func encryptDecrypt(ctx context.Context, kmsClient *okms.Client) {
// Create a new AES 256 key
respAes, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "AES key example",
Type: ptrTo(types.Oct),
Size: ptrTo(types.N256),
Operations: ptrTo([]types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}),
})
respAes, err := kmsClient.GenerateSymmetricKey(ctx, types.N256, "AES key example", "", types.Encrypt, types.Decrypt)
if err != nil {
panic(err)
}
Expand Down
23 changes: 4 additions & 19 deletions examples/generate_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,23 @@ import (
"github.com/ovh/okms-sdk-go/types"
)

func generateKeys(ctx context.Context, kmsClient okms.Client) {
func generateKeys(ctx context.Context, kmsClient *okms.Client) {
// Create a new AES 256 key
respAes, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "AES key example",
Type: ptrTo(types.Oct),
Size: ptrTo(types.N256),
Operations: ptrTo([]types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}),
})
respAes, err := kmsClient.GenerateSymmetricKey(ctx, types.N256, "AES key example", "", types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey)
if err != nil {
panic(err)
}
fmt.Println("AES KEY:", respAes.Id)

// Create a new RSA 2048 key-pair
respRSA, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "RSA key-pair example",
Type: ptrTo(types.RSA),
Size: ptrTo(types.N2048),
Operations: ptrTo([]types.CryptographicUsages{types.Sign, types.Verify}),
})
respRSA, err := kmsClient.GenerateRSAKeyPair(ctx, types.N2048, "RSA key-pair example", "", types.Sign, types.Verify)
if err != nil {
panic(err)
}
fmt.Println("RSA KEY:", respRSA.Id)

// Create a new ECDSA P-256 key-pair
respECDSA, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "ECDSA key-pair example",
Type: ptrTo(types.EC),
Curve: ptrTo(types.P256),
Operations: ptrTo([]types.CryptographicUsages{types.Sign, types.Verify}),
})
respECDSA, err := kmsClient.GenerateECKeyPair(ctx, types.P256, "ECDSA key-pair example", "", types.Sign, types.Verify)
if err != nil {
panic(err)
}
Expand Down
11 changes: 3 additions & 8 deletions examples/list_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/ovh/okms-sdk-go/types"
)

func listKeys(ctx context.Context, kmsClient okms.Client) {
func listKeys(ctx context.Context, kmsClient *okms.Client) {
it := kmsClient.ListAllServiceKeys(nil, nil)
for it.Next(ctx) {
key, err := it.Value()
Expand All @@ -36,14 +36,9 @@ func listKeys(ctx context.Context, kmsClient okms.Client) {
}
}

func getKey(ctx context.Context, kmsClient okms.Client) {
func getKey(ctx context.Context, kmsClient *okms.Client) {
// Create a new AES 256 key
respAes, err := kmsClient.CreateImportServiceKey(ctx, nil, types.CreateImportServiceKeyRequest{
Name: "AES key example",
Type: ptrTo(types.Oct),
Size: ptrTo(types.N256),
Operations: ptrTo([]types.CryptographicUsages{types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey}),
})
respAes, err := kmsClient.GenerateSymmetricKey(ctx, types.N256, "AES key example", "", types.Encrypt, types.Decrypt, types.WrapKey, types.UnwrapKey)
if err != nil {
panic(err)
}
Expand Down
Loading
Loading