Skip to content

Commit

Permalink
kms: add more APIs and request/response types.
Browse files Browse the repository at this point in the history
This commit adds support for more KMS APIs, like
creating and deleting enclaves and secret keys.

It also adds the generic `ListRequest` and `ListResponse`
types.

Signed-off-by: Andreas Auernhammer <[email protected]>
  • Loading branch information
aead committed Dec 4, 2023
1 parent 286d0a0 commit c977f0e
Show file tree
Hide file tree
Showing 10 changed files with 1,796 additions and 260 deletions.
421 changes: 402 additions & 19 deletions kms/client.go

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions kms/crypto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2023 - MinIO, Inc. All rights reserved.
// Use of this source code is governed by the AGPLv3
// license that can be found in the LICENSE file.

package kms

import (
"fmt"
"strconv"
)

// SecretKeyType defines the type of a secret key. Secret keys with
// different types are not compatible since they may differ in the
// encryption algorithm, key length, cipher mode, etc.
type SecretKeyType uint

// Supported secret key types.
const (
// AES256 represents the AES-256-GCM secret key type.
AES256 SecretKeyType = iota + 1

// ChaCha20 represents the ChaCha20-Poly1305 secret key type.
ChaCha20
)

// String returns the string representation of the SecretKeyType.
func (s SecretKeyType) String() string {
switch s {
case AES256:
return "AES256"
case ChaCha20:
return "ChaCha20"
default:
return "!INVALID:" + strconv.Itoa(int(s))
}
}

func secretKeyTypeFromString(s string) (SecretKeyType, error) {
switch s {
case "AES256":
return AES256, nil
case "ChaCha20":
return ChaCha20, nil
default:
return 0, fmt.Errorf("kms: key type '%s' is not supported", s)
}
}
22 changes: 21 additions & 1 deletion kms/internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,29 @@ package api
const (
PathStatus = "/v1/status"

PathEnclaveCreate = "/v1/enclave/create/"
PathEnclaveDescribe = "/v1/enclave/describe/"
PathEnclaveDelete = "/v1/enclave/delete/"
PathEnclaveList = "/v1/enclave/list/"

PathSecretKeyCreate = "/v1/key/create/"
PathSecretKeyDescribe = "/v1/key/describe/"
PathSecretKeyDelete = "/v1/key/delete/"
PathSecretKeyList = "/v1/key/list/"
PathSecretKeyGenerate = "/v1/key/generate/"
PathSecretKeyEncrypt = "/v1/key/encrypt/"
PathSecretKeyDecrypt = "/v1/key/decrypt/"

PathClusterStatus = "/v1/cluster/status"
PathClusterStatus = "/v1/cluster/status"
PathClusterAdd = "/v1/cluster/add/"
PathClusterRemove = "/v1/cluster/remove/"
PathClusterBackup = "/v1/cluster/backup"
PathClusterRestore = "/v1/cluster/restore"
PathClusterEdit = "/v1/cluster/edit"
)

// API query parameters supported by KMS servers.
const (
QueryListContinue = "continue"
QueryListLimit = "limit"
)
75 changes: 75 additions & 0 deletions kms/iter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2023 - MinIO, Inc. All rights reserved.
// Use of this source code is governed by the AGPLv3
// license that can be found in the LICENSE file.

package kms

import (
"context"
"io"
)

// Iter is an iterator over elements of type T. It turns
// a paginated listing provided by the NextFn into a
// continuous stream of items.
type Iter[T any] struct {
// NextFn is a function that returns the next page from
// a paginated list.
NextFn func(context.Context, *ListRequest) (*ListResponse[T], error)

items []T
prefix string
continueAt string
limit int
err error
}

// SeekTo seeks to a specific position within the stream and returns the item
// at this position.
func (i *Iter[T]) SeekTo(ctx context.Context, req *ListRequest) (item T, err error) {
if i.err != nil && i.err != io.EOF {
return item, i.err
}

i.prefix = req.Prefix
i.continueAt = req.ContinueAt
i.limit = req.Limit

i.items, i.err = nil, nil
return i.Next(ctx)
}

// Next returns the next item from the stream or io.EOF at the end.
// The context is used when Next has to fetch the next page of the
// paginated listing.
func (i *Iter[T]) Next(ctx context.Context) (item T, err error) {
if len(i.items) == 0 {
if i.err != nil {
return item, i.err
}

resp, err := i.NextFn(ctx, &ListRequest{
Prefix: i.prefix,
ContinueAt: i.continueAt,
Limit: i.limit,
})
if err != nil {
i.err = err
i.items = nil
return item, i.err
}

i.items, i.continueAt = resp.Items, resp.ContinueAt
if len(i.items) == 0 {
i.err = io.EOF
return item, i.err
}
if i.continueAt == "" {
i.err = io.EOF
}
}

item = i.items[0]
i.items = i.items[1:]
return item, nil
}
Loading

0 comments on commit c977f0e

Please sign in to comment.