Documentation ¶
Index ¶
- Constants
- Variables
- func GenerateCertificate(key APIKey, options ...CertificateOption) (tls.Certificate, error)
- type API
- type APIKey
- type AuditEvent
- type AuditStream
- type CertificateOption
- type Client
- func (c *Client) APIs(ctx context.Context) ([]API, error)
- func (c *Client) AssignPolicy(ctx context.Context, policy string, identity Identity) error
- func (c *Client) AuditLog(ctx context.Context) (*AuditStream, error)
- func (c *Client) CreateEnclave(ctx context.Context, name string) error
- func (c *Client) CreateKey(ctx context.Context, name string) error
- func (c *Client) CreatePolicy(ctx context.Context, name string, policy *Policy) error
- func (c *Client) CreateSecret(ctx context.Context, name string, value []byte, options *SecretOptions) error
- func (c *Client) Decrypt(ctx context.Context, name string, ciphertext, context []byte) ([]byte, error)
- func (c *Client) DeleteEnclave(ctx context.Context, name string) error
- func (c *Client) DeleteIdentity(ctx context.Context, identity Identity) error
- func (c *Client) DeleteKey(ctx context.Context, name string) error
- func (c *Client) DeletePolicy(ctx context.Context, name string) error
- func (c *Client) DeleteSecret(ctx context.Context, name string) error
- func (c *Client) DescribeCluster(ctx context.Context) (*ClusterInfo, error)
- func (c *Client) DescribeEnclave(ctx context.Context, name string) (*EnclaveInfo, error)
- func (c *Client) DescribeIdentity(ctx context.Context, identity Identity) (*IdentityInfo, error)
- func (c *Client) DescribeKey(ctx context.Context, name string) (*KeyInfo, error)
- func (c *Client) DescribePolicy(ctx context.Context, name string) (*PolicyInfo, error)
- func (c *Client) DescribeSecret(ctx context.Context, name string) (*SecretInfo, error)
- func (c *Client) DescribeSelf(ctx context.Context) (*IdentityInfo, *Policy, error)
- func (c *Client) Enclave(name string) *Enclave
- func (c *Client) Encrypt(ctx context.Context, name string, plaintext, context []byte) ([]byte, error)
- func (c *Client) ErrorLog(ctx context.Context) (*ErrorStream, error)
- func (c *Client) ExpandCluster(ctx context.Context, endpoint string) error
- func (c *Client) GenerateKey(ctx context.Context, name string, context []byte) (DEK, error)
- func (c *Client) GetPolicy(ctx context.Context, name string) (*Policy, error)
- func (c *Client) ImportKey(ctx context.Context, name string, req *ImportKeyRequest) error
- func (c *Client) IsReady(ctx context.Context) (bool, error)
- func (c *Client) ListEnclaves(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (c *Client) ListIdentities(ctx context.Context, prefix string, n int) ([]Identity, string, error)
- func (c *Client) ListKeys(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (c *Client) ListPolicies(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (c *Client) ListSecrets(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (c *Client) Metrics(ctx context.Context) (Metric, error)
- func (c *Client) ReadSecret(ctx context.Context, name string) ([]byte, *SecretInfo, error)
- func (c *Client) ShrinkCluster(ctx context.Context, endpoint string) error
- func (c *Client) Status(ctx context.Context) (State, error)
- func (c *Client) Version(ctx context.Context) (string, error)
- type ClusterInfo
- type ConnError
- type CreateIdentityRequest
- type DEK
- type Enclave
- func (e *Enclave) AssignPolicy(ctx context.Context, policy string, identity Identity) error
- func (e *Enclave) CreateIdentity(ctx context.Context, identity Identity, req *CreateIdentityRequest) error
- func (e *Enclave) CreateKey(ctx context.Context, name string) error
- func (e *Enclave) CreatePolicy(ctx context.Context, name string, policy *Policy) error
- func (e *Enclave) CreateSecret(ctx context.Context, name string, value []byte, options *SecretOptions) error
- func (e *Enclave) Decrypt(ctx context.Context, name string, ciphertext, context []byte) ([]byte, error)
- func (e *Enclave) DeleteIdentity(ctx context.Context, identity Identity) error
- func (e *Enclave) DeleteKey(ctx context.Context, name string) error
- func (e *Enclave) DeletePolicy(ctx context.Context, name string) error
- func (e *Enclave) DeleteSecret(ctx context.Context, name string) error
- func (e *Enclave) DescribeIdentity(ctx context.Context, identity Identity) (*IdentityInfo, error)
- func (e *Enclave) DescribeKey(ctx context.Context, name string) (*KeyInfo, error)
- func (e *Enclave) DescribePolicy(ctx context.Context, name string) (*PolicyInfo, error)
- func (e *Enclave) DescribeSecret(ctx context.Context, name string) (*SecretInfo, error)
- func (e *Enclave) DescribeSelf(ctx context.Context) (*IdentityInfo, *Policy, error)
- func (e *Enclave) Encrypt(ctx context.Context, name string, plaintext, context []byte) ([]byte, error)
- func (e *Enclave) GenerateKey(ctx context.Context, name string, context []byte) (DEK, error)
- func (e *Enclave) GetPolicy(ctx context.Context, name string) (*Policy, error)
- func (e *Enclave) ImportKey(ctx context.Context, name string, req *ImportKeyRequest) error
- func (e *Enclave) ListIdentities(ctx context.Context, prefix string, n int) ([]Identity, string, error)
- func (e *Enclave) ListKeys(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (e *Enclave) ListPolicies(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (e *Enclave) ListSecrets(ctx context.Context, prefix string, n int) ([]string, string, error)
- func (e *Enclave) Metrics(ctx context.Context) (Metric, error)
- func (e *Enclave) ReadSecret(ctx context.Context, name string) ([]byte, *SecretInfo, error)
- type EnclaveInfo
- type Error
- type ErrorEvent
- type ErrorStream
- type Identity
- type IdentityInfo
- type ImportKeyRequest
- type KeyAlgorithm
- type KeyInfo
- type ListIter
- type Metric
- type Policy
- type PolicyInfo
- type Rule
- type SecretInfo
- type SecretOptions
- type SecretType
- type State
Examples ¶
Constants ¶
const ( AES256 = iota ChaCha20 )
All valid cryptographic algorithms that can be used with keys.
Variables ¶
var ( // ErrNotAllowed is returned by a KES server when a client has // not sufficient permission to perform the API operation. ErrNotAllowed = NewError(http.StatusForbidden, "not authorized: insufficient permissions") ErrPartialWrite = NewError(http.StatusServiceUnavailable, "change committed but not replicated") // ErrKeyNotFound is returned by a KES server when a client tries to // access or use a cryptographic key which does not exist. ErrKeyNotFound = NewError(http.StatusNotFound, "key does not exist") // ErrKeyExists is returned by a KES server when a client tries // to create a cryptographic key which already exists. ErrKeyExists = NewError(http.StatusBadRequest, "key already exists") // ErrSecretNotFound is returned by a KES server when a client tries to // access a secret which does not exist. ErrSecretNotFound = NewError(http.StatusNotFound, "secret does not exist") // ErrSecretVersionNotFound is returned by a KES server when a client tries to // access a secret version which does not exist. ErrSecretVersionNotFound = NewError(http.StatusNotFound, "secret version does not exist") // ErrKeyExists is returned by a KES server when a client tries // to create a secret which already exists. ErrSecretExists = NewError(http.StatusNotFound, "secret already exists") // ErrPolicyExists is returned by a KES server when a client tries // to create a policy which already exists. ErrPolicyExists = NewError(http.StatusBadRequest, "policy already exists") // ErrPolicyNotFound is returned by a KES server when a client // tries to access a policy which does not exist. ErrPolicyNotFound = NewError(http.StatusNotFound, "policy does not exist") // ErrIdentityExists is returned by a KES server when a client tries // to create an identity which already exists. ErrIdentityExists = NewError(http.StatusBadRequest, "identity already exists") // ErrPolicyNotFound is returned by a KES server when a client // tries to access a policy which does not exist. ErrIdentityNotFound = NewError(http.StatusNotFound, "identity does not exist") // ErrDecrypt is returned by a KES server when it fails to decrypt // a ciphertext. It may occur when a client uses the wrong key or // the ciphertext has been (maliciously) modified. ErrDecrypt = NewError(http.StatusBadRequest, "decryption failed: ciphertext is not authentic") // ErrEnclaveExists is returned by a KES server when a client tries // to create an enclave that already exists. ErrEnclaveExists = NewError(http.StatusBadRequest, "enclave already exists") // ErrEnclaveNotFound is returned by a KES server when a client tries // to access an enclave which does not exist. ErrEnclaveNotFound = NewError(http.StatusNotFound, "enclave does not exist") )
KES server API errors
Functions ¶
func GenerateCertificate ¶
func GenerateCertificate(key APIKey, options ...CertificateOption) (tls.Certificate, error)
GenerateCertificate generates a new tls.Certificate from the APIKey's private and public key. The certificate can be customized by specifying one or multiple CertificateOptions.
By default, the returned certificate is valid for 90 days.
Example ¶
key, err := kes.GenerateAPIKey(nil) if err != nil { log.Fatal(err) } certificate, err := kes.GenerateCertificate(key) if err != nil { log.Fatal(err) } _ = &tls.Config{ Certificates: []tls.Certificate{certificate}, }
Output:
Types ¶
type API ¶
type API struct { Method string // The HTTP method Path string // The API path without its arguments. For example: "/v1/status" MaxBody int64 // The max. size of request bodies accepted Timeout time.Duration // Amount of time after which request will time out }
API describes a KES server API.
func (API) MarshalJSON ¶ added in v0.2.0
MarshalJSON returns the API's JSON representation.
func (*API) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON unmarshal the JSON data into API.
type APIKey ¶
type APIKey interface { // Public returns the public key that coresponds to // the public key. Public() crypto.PublicKey // Private returns the private key that correspons // to the public key. Private() crypto.PrivateKey // Identity returns the Identity of the public key. // // The identity is the cryptographic fingerprint of // the raw DER-encoded public key as present in a // corresponding X509 cerificate. Identity() Identity // String returns the APIKey's textual representation. String() string }
APIKey is an object that can generate a private/public key pair.
func GenerateAPIKey ¶
GenerateAPIKey generates a new random API key. If rand is nil, crypto/rand.Reader is used.
func ParseAPIKey ¶
ParseAPIKey parses a formatted APIKey and returns the value it represents.
Example ¶
key, err := kes.ParseAPIKey("kes:v1:AGaV6VXHasF0FnaB60WdCOeTZ8eTIDikL4zlN16c8NAs") if err != nil { log.Fatal(err) } fmt.Println(key)
Output: kes:v1:AGaV6VXHasF0FnaB60WdCOeTZ8eTIDikL4zlN16c8NAs
type AuditEvent ¶
type AuditEvent struct { Timestamp time.Time // The point in time when the KES server received the request APIPath string // The API called by the client. May contain API arguments ClientIP net.IP // The client's IP address ClientIdentity Identity // The client's KES identity StatusCode int // The response status code sent to the client ResponseTime time.Duration // Time it took to process the request }
AuditEvent is the event a KES server generates when it response to a request.
type AuditStream ¶
type AuditStream struct {
// contains filtered or unexported fields
}
AuditStream iterates over a stream of AuditEvents. Close the AuditStream to release associated resources.
func NewAuditStream ¶
func NewAuditStream(r io.Reader) *AuditStream
NewAuditStream returns a new AuditStream that reads from r.
Example ¶
reader := strings.NewReader(AuditStream) stream := kes.NewAuditStream(reader) defer stream.Close() for stream.Next() { event := stream.Event() fmt.Println(event.Timestamp) } if err := stream.Close(); err != nil { panic(err) // TODO: error handling }
Output: 2023-03-24 12:37:33 +0000 UTC 2023-03-24 12:38:02 +0000 UTC 2023-03-24 12:39:02 +0000 UTC
func (*AuditStream) Close ¶
func (s *AuditStream) Close() (err error)
Close closes the AuditStream and releases any associated resources.
func (*AuditStream) Event ¶
func (s *AuditStream) Event() AuditEvent
Event returns the most recent AuditEvent, generated by Next.
func (*AuditStream) Next ¶
func (s *AuditStream) Next() bool
Next advances the stream to the next AuditEvent and returns true if there is another one. It returns false if there are no more AuditEvents or when the AuditStream encountered an error.
type CertificateOption ¶
type CertificateOption func(*x509.Certificate)
CertificateOption is a function modifying the passed *x509.Certificate.
type Client ¶
type Client struct { // Endpoints contains one or multiple KES server // endpoints. For example: https://127.0.0.1:7373 // // Each endpoint must be a HTTPS endpoint and // should point to different KES server replicas // with a common configuration. // // Multiple endpoints should only be specified // when multiple KES servers should be used, e.g. // for high availability, but no round-robin DNS // is used. Endpoints []string // HTTPClient is the HTTP client. // // The HTTP client uses its http.RoundTripper // to send requests resp. receive responses. // // It must not be modified concurrently. HTTPClient http.Client // contains filtered or unexported fields }
Client is a KES client. Usually, a new client is instantiated via the NewClient or NewClientWithConfig functions.
In general, a client just requires:
- a KES server endpoint
- a X.509 certificate for authentication
However, custom transport protocols, timeouts, connection pooling, etc. can be specified via a custom http.RoundTripper. For example:
client := &Client{ Endpoints: []string{"https:127.0.0.1:7373"}, HTTPClient: http.Client{ Transport: &http.Transport{ // specify custom behavior... TLSClientConfig: &tls.Config{ Certificates: []tls.Certificates{clientCert}, }, }, }, }
A custom transport protocol can be used via a custom implemention of the http.RoundTripper interface.
func NewClient ¶
func NewClient(endpoint string, key APIKey, options ...CertificateOption) (*Client, error)
NewClient returns a new KES client that uses an API key for authentication.
Example ¶
const ( Endpoint = "https://play.min.io:7373" APIKey = "kes:v1:AD9E7FSYWrMD+VjhI6q545cYT9YOyFxZb7UnjEepYDRc" ) key, err := kes.ParseAPIKey(APIKey) if err != nil { log.Fatalf("Invalid API key '%s': %v", APIKey, err) } client, err := kes.NewClient(Endpoint, key) if err != nil { log.Fatalf("Failed to create client for '%s': %v", Endpoint, err) } _ = client fmt.Println("Identity:", key.Identity())
Output: Identity: 3ecfcdf38fcbe141ae26a1030f81e96b753365a46760ae6b578698a97c59fd22
func NewClientWithConfig ¶
NewClientWithConfig returns a new KES client with the given KES server endpoint that uses the given TLS config for mTLS authentication.
Therefore, the config.Certificates must contain a TLS certificate that is valid for client authentication.
NewClientWithConfig uses an http.Transport with reasonable defaults.
Example ¶
const ( Endpoint = "https://play.min.io:7373" ) const ( PrivateKey = "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEID9E7FSYWrMD+VjhI6q545cYT9YOyFxZb7UnjEepYDRc\n-----END PRIVATE KEY-----" Certificate = "-----BEGIN CERTIFICATE-----\nMIIBKDCB26ADAgECAhB6vebGMUfKnmBKyqoApRSOMAUGAytlcDAbMRkwFwYDVQQDDBByb290QHBsYXkubWluLmlvMB4XDTIwMDQzMDE1MjIyNVoXDTI1MDQyOTE1MjIyNVowGzEZMBcGA1UEAwwQcm9vdEBwbGF5Lm1pbi5pbzAqMAUGAytlcAMhALzn735WfmSH/ghKs+4iPWziZMmWdiWr/sqvqeW+WwSxozUwMzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAFBgMrZXADQQDZOrGKb2ATkDlu2pTcP3LyhSBDpYh7V4TvjRkBTRgjkacCzwFLm+mh+7US8V4dBpIDsJ4uuWoF0y6vbLVGIlkG\n-----END CERTIFICATE-----" ) cert, err := tls.X509KeyPair([]byte(Certificate), []byte(PrivateKey)) if err != nil { log.Fatalf("Failed to certificate/private key: %v", err) } cert.Leaf, _ = x509.ParseCertificate(cert.Certificate[0]) client := kes.NewClientWithConfig(Endpoint, &tls.Config{ MinVersion: tls.VersionTLS12, Certificates: []tls.Certificate{cert}, }) _ = client h := sha256.Sum256(cert.Leaf.RawSubjectPublicKeyInfo) fmt.Println("Identity:", hex.EncodeToString(h[:]))
Output: Identity: 3ecfcdf38fcbe141ae26a1030f81e96b753365a46760ae6b578698a97c59fd22
func (*Client) APIs ¶
APIs returns a list of all API endpoints supported by the KES server.
It returns ErrNotAllowed if the client does not have sufficient permissions to fetch the server APIs.
func (*Client) AssignPolicy ¶
AssignPolicy assigns the policy to the identity. The KES admin identity cannot be assigned to any policy.
AssignPolicy returns PolicyNotFound if no such policy exists.
func (*Client) AuditLog ¶
func (c *Client) AuditLog(ctx context.Context) (*AuditStream, error)
AuditLog returns a stream of audit events produced by the KES server. The stream does not contain any events that happened in the past.
It returns ErrNotAllowed if the client does not have sufficient permissions to subscribe to the audit log.
func (*Client) CreateEnclave ¶
CreateEnclave creates a new enclave with the given identity as enclave admin. Only the KES system admin can create new enclaves.
It returns ErrEnclaveExists if the enclave already exists.
func (*Client) CreateKey ¶
CreateKey creates a new cryptographic key. The key will be generated by the KES server.
It returns ErrKeyExists if a key with the same name already exists.
func (*Client) CreatePolicy ¶ added in v0.2.0
CreatePolicy creates a new policy.
It returns ErrPolicyExists if such a policy already exists.
func (*Client) CreateSecret ¶
func (c *Client) CreateSecret(ctx context.Context, name string, value []byte, options *SecretOptions) error
CreateSecret creates a new secret with the given name.
It returns ErrSecretExists if a secret with the same name already exists.
func (*Client) Decrypt ¶
func (c *Client) Decrypt(ctx context.Context, name string, ciphertext, context []byte) ([]byte, error)
Decrypt decrypts the ciphertext with the named key at the KES server. The exact same context, used during Encrypt, must be provided.
Decrypt returns ErrKeyNotFound if no such key exists. It returns ErrDecrypt when the ciphertext has been modified or a different context value is provided.
func (*Client) DeleteEnclave ¶
DeleteEnclave delete the specified enclave. Only the KES system admin can delete enclaves.
It returns ErrEnclaveNotFound if the enclave does not exist.
func (*Client) DeleteIdentity ¶
DeleteIdentity removes the identity. Once removed, any operation issued by this identity will fail with ErrNotAllowed.
The KES admin identity cannot be removed.
func (*Client) DeleteKey ¶
DeleteKey deletes the key from a KES server. It returns ErrKeyNotFound if no such key exists.
func (*Client) DeletePolicy ¶
DeletePolicy deletes the policy with the given name. Any assigned identities will be removed as well.
It returns ErrPolicyNotFound if no such policy exists.
func (*Client) DeleteSecret ¶
DeleteSecret deletes the secret with the given name.
It returns ErrSecretNotFound if no such secret exists.
func (*Client) DescribeCluster ¶ added in v0.2.0
func (c *Client) DescribeCluster(ctx context.Context) (*ClusterInfo, error)
DescribeCluster returns the KeyCluster for the current cluster.
func (*Client) DescribeEnclave ¶
DescribeEnclave returns an EnclaveInfo describing the specified enclave. Only the KES system admin can create fetch enclave descriptions.
It returns ErrEnclaveNotFound if the enclave does not exists.
func (*Client) DescribeIdentity ¶
DescribeIdentity returns an IdentityInfo describing the given identity.
func (*Client) DescribeKey ¶
DescribeKey returns the KeyInfo for the given key. It returns ErrKeyNotFound if no such key exists.
func (*Client) DescribePolicy ¶
DescribePolicy returns the PolicyInfo for the given policy. It returns ErrPolicyNotFound if no such policy exists.
func (*Client) DescribeSecret ¶
DescribeSecret returns the SecretInfo for the given secret.
It returns ErrSecretNotFound if no such secret exists.
func (*Client) DescribeSelf ¶
DescribeSelf returns an IdentityInfo describing the identity making the API request. It also returns the assigned policy, if any.
DescribeSelf allows an application to obtain identity and policy information about itself.
func (*Client) Enclave ¶
Enclave returns a new Enclave with the given name.
Example ¶
const ( Endpoint = "https://play.min.io:7373" APIKey = "kes:v1:AD9E7FSYWrMD+VjhI6q545cYT9YOyFxZb7UnjEepYDRc" ) key, err := kes.ParseAPIKey(APIKey) if err != nil { log.Fatalf("Invalid API key '%s': %v", APIKey, err) } client, err := kes.NewClient(Endpoint, key) if err != nil { log.Fatalf("Failed to create client for '%s': %v", Endpoint, err) } enclave := client.Enclave("my-enclave") _ = enclave fmt.Println("Identity:", key.Identity())
Output: Identity: 3ecfcdf38fcbe141ae26a1030f81e96b753365a46760ae6b578698a97c59fd22
func (*Client) Encrypt ¶
func (c *Client) Encrypt(ctx context.Context, name string, plaintext, context []byte) ([]byte, error)
Encrypt encrypts the given plaintext with the named key at the KES server. The optional context is cryptographically bound to the returned ciphertext. The exact same context must be provided when decrypting the ciphertext again.
Encrypt returns ErrKeyNotFound if no such key exists at the KES server.
func (*Client) ErrorLog ¶
func (c *Client) ErrorLog(ctx context.Context) (*ErrorStream, error)
ErrorLog returns a stream of error events produced by the KES server. The stream does not contain any events that happened in the past.
It returns ErrNotAllowed if the client does not have sufficient permissions to subscribe to the error log.
func (*Client) ExpandCluster ¶ added in v0.2.0
ExpandCluster expands a KES cluster by adding a new node with the given endpoint.
func (*Client) GenerateKey ¶
GenerateKey returns a new generated data encryption key (DEK). A DEK has a plaintext and ciphertext representation.
The former should be used for cryptographic operations, like encrypting some data.
The later is the result of encrypting the plaintext with the named key at the KES server. It should be stored at a durable location but does not need to stay secret. The ciphertext can only be decrypted with the named key at the KES server.
The context is cryptographically bound to the ciphertext and the same context value must be provided when decrypting the ciphertext via Decrypt. Therefore, an application must either remember the context or must be able to re-generate it.
GenerateKey returns ErrKeyNotFound if no key with the given name exists.
func (*Client) GetPolicy ¶
GetPolicy returns the policy with the given name. It returns ErrPolicyNotFound if no such policy exists.
func (*Client) ImportKey ¶
ImportKey imports the given key into a KES server. It returns ErrKeyExists if a key with the same key already exists.
func (*Client) IsReady ¶ added in v0.2.0
IsReady reports whether the server is ready to serve requests.
Since the readiness endpoint requires authentication, unless disabled at the server, it may fail with ErrNotAllowed even though the server might be ready to handle requests.
func (*Client) ListEnclaves ¶ added in v0.2.0
ListEnclaves returns a paginated list of enclave names from the server, starting at the specified prefix. If n > 0, it returns at most n names. Otherwise, the server determines the page size.
ListEnclaves also returns a continuation token for fetching the next batch. When the listing reaches the end, the continuation token will be empty.
The ListIter type can be used as a convenient way to iterate over a paginated list.
func (*Client) ListIdentities ¶
func (c *Client) ListIdentities(ctx context.Context, prefix string, n int) ([]Identity, string, error)
ListIdentities returns a paginated list of identities from the server, starting at the specified prefix. If n > 0, it returns at most n identities. Otherwise, the server determines the page size.
ListIdentities also returns a continuation token for fetching the next batch. When the listing reaches the end, the continuation token will be empty.
The ListIter type can be used as a convenient way to iterate over a paginated list.
func (*Client) ListKeys ¶
ListKeys returns a paginated list of key names from the server, starting at the specified prefix. If n > 0, it returns at most n names. Otherwise, the server determines the page size.
ListKeys also returns a continuation token for fetching the next batch. When the listing reaches the end, the continuation token will be empty.
The ListIter type can be used as a convenient way to iterate over a paginated list.
func (*Client) ListPolicies ¶
ListPolicies returns a paginated list of policy names from the server, starting at the specified prefix. If n > 0, it returns at most n names. Otherwise, the server determines the page size.
ListPolicies also returns a continuation token for fetching the next batch. When the listing reaches the end, the continuation token will be empty.
The ListIter type can be used as a convenient way to iterate over a paginated list.
func (*Client) ListSecrets ¶
ListSecrets returns a paginated list of secret names from the server, starting at the specified prefix. If n > 0, it returns at most n names. Otherwise, the server determines the page size.
ListSecrets also returns a continuation token for fetching the next batch. When the listing reaches the end, the continuation token will be empty.
The ListIter type can be used as a convenient way to iterate over a paginated list.
func (*Client) Metrics ¶
Metrics returns a KES server metric snapshot.
It returns ErrNotAllowed if the client does not have sufficient permissions to fetch server metrics.
func (*Client) ReadSecret ¶
ReadSecret returns the secret with the given name.
It returns ErrSecretNotFound if no such secret exists.
func (*Client) ShrinkCluster ¶ added in v0.2.0
ShrinkCluster shrinks a KES cluster by removingt the new node with the given endpoint from the cluster.
type ClusterInfo ¶ added in v0.2.0
ClusterInfo describes a KES cluster consisting of one or multiple nodes controlled by one leader node.
type ConnError ¶
type ConnError struct { Host string // The host that couldn't be reached Err error // The underlying error, if any. }
ConnError is a network connection error. It is returned by a Client or Enclave when a request fails due to a network or connection issue. For example, a temporary DNS error.
Calling code may check whether a returned error is of type ConnError:
if cErr, ok := kes.IsConnError(err) { // TODO: handle connection error }
func IsConnError ¶
IsConnError reports whether err is or wraps a ConnError. In this case, it returns the ConnError.
type CreateIdentityRequest ¶ added in v0.2.0
CreateIdentityRequest is the request type for creating a new identity at a KES server.
type DEK ¶
DEK is a data encryption key. It has a plaintext and a ciphertext representation.
Applications should use the plaintext for cryptographic operations and store the ciphertext at a durable location.
If the DEK is used to e.g. encrypt some data then it's safe to store the DEK's ciphertext representation next to the encrypted data. The ciphertext representation does not need to stay secret.
type Enclave ¶
type Enclave struct { // Name is the name of the KES server enclave. Name string // Endpoints contains one or multiple KES server // endpoints. For example: https://127.0.0.1:7373 // // Multiple endpoints should only be specified // when multiple KES servers should be used, e.g. // for high availability, but no round-robin DNS // is used. Endpoints []string // HTTPClient is the HTTP client. // // The HTTP client uses its http.RoundTripper // to send requests resp. receive responses. // // It must not be modified concurrently. HTTPClient http.Client // contains filtered or unexported fields }
An Enclave is an isolated area within a KES server. It stores cryptographic keys, policies and other related information securely.
A KES server contains at least one Enclave and, depending upon its persistence layer, may be able to hold many Enclaves.
With Enclaves, a KES server implements multi-tenancy.
func NewEnclave ¶
func NewEnclave(endpoint, name string, key APIKey, options ...CertificateOption) (*Enclave, error)
NewEnclave returns a new Enclave that uses an API key for authentication.
For obtaining an Enclave from a Client refer to Client.Enclave.
func NewEnclaveWithConfig ¶
NewEnclaveWithConfig returns a new Enclave with the given name and KES server endpoint that uses the given TLS config for mTLS authentication.
Therefore, the config.Certificates must contain a TLS certificate that is valid for client authentication.
NewClientWithConfig uses an http.Transport with reasonable defaults.
For getting an Enclave from a Client refer to Client.Enclave.
func (*Enclave) AssignPolicy ¶
AssignPolicy assigns the policy to the identity. The KES admin identity cannot be assigned to any policy.
AssignPolicy returns PolicyNotFound if no such policy exists.
func (*Enclave) CreateIdentity ¶ added in v0.2.0
func (e *Enclave) CreateIdentity(ctx context.Context, identity Identity, req *CreateIdentityRequest) error
CreateIdentity returns an IdentityInfo describing the given identity.
func (*Enclave) CreateKey ¶
CreateKey creates a new cryptographic key. The key will be generated by the KES server.
It returns ErrKeyExists if a key with the same name already exists.
func (*Enclave) CreatePolicy ¶ added in v0.2.0
CreatePolicy creates a new policy.
It returns ErrPolicyExists if such a policy already exists.
func (*Enclave) CreateSecret ¶
func (e *Enclave) CreateSecret(ctx context.Context, name string, value []byte, options *SecretOptions) error
CreateSecret creates a new secret with the given name.
It returns ErrSecretExists if a secret with the same name already exists.
func (*Enclave) Decrypt ¶
func (e *Enclave) Decrypt(ctx context.Context, name string, ciphertext, context []byte) ([]byte, error)
Decrypt decrypts the ciphertext with the named key at the KES server. The exact same context, used during Encrypt, must be provided.
Decrypt returns ErrKeyNotFound if no such key exists. It returns ErrDecrypt when the ciphertext has been modified or a different context value is provided.
func (*Enclave) DeleteIdentity ¶
DeleteIdentity removes the identity. Once removed, any operation issued by this identity will fail with ErrNotAllowed.
The KES admin identity cannot be removed.
func (*Enclave) DeleteKey ¶
DeleteKey deletes the key from a KES server. It returns ErrKeyNotFound if no such key exists.
func (*Enclave) DeletePolicy ¶
DeletePolicy deletes the policy with the given name. Any assigned identities will be removed as well.
It returns ErrPolicyNotFound if no such policy exists.
func (*Enclave) DeleteSecret ¶
DeleteSecret deletes the secret with the given name.
It returns ErrSecretNotFound if no such secret exists.
func (*Enclave) DescribeIdentity ¶
DescribeIdentity returns an IdentityInfo describing the given identity.
func (*Enclave) DescribeKey ¶
DescribeKey returns the KeyInfo for the given key.
It returns ErrKeyNotFound if no such key exists.
func (*Enclave) DescribePolicy ¶
DescribePolicy returns the PolicyInfo for the given policy. It returns ErrPolicyNotFound if no such policy exists.
func (*Enclave) DescribeSecret ¶
DescribeSecret returns the SecretInfo for the given secret.
It returns ErrSecretNotFound if no such secret exists.
func (*Enclave) DescribeSelf ¶
DescribeSelf returns an IdentityInfo describing the identity making the API request. It also returns the assigned policy, if any.
DescribeSelf allows an application to obtain identity and policy information about itself.
func (*Enclave) Encrypt ¶
func (e *Enclave) Encrypt(ctx context.Context, name string, plaintext, context []byte) ([]byte, error)
Encrypt encrypts the given plaintext with the named key at the KES server. The optional context is cryptographically bound to the returned ciphertext. The exact same context must be provided when decrypting the ciphertext again.
Encrypt returns ErrKeyNotFound if no such key exists at the KES server.
func (*Enclave) GenerateKey ¶
GenerateKey returns a new generated data encryption key (DEK). A DEK has a plaintext and ciphertext representation.
The former should be used for cryptographic operations, like encrypting some data.
The later is the result of encrypting the plaintext with the named key at the KES server. It should be stored at a durable location but does not need to stay secret. The ciphertext can only be decrypted with the named key at the KES server.
The context is cryptographically bound to the ciphertext and the same context value must be provided when decrypting the ciphertext via Decrypt. Therefore, an application must either remember the context or must be able to re-generate it.
GenerateKey returns ErrKeyNotFound if no key with the given name exists.
func (*Enclave) GetPolicy ¶
GetPolicy returns the policy with the given name. It returns ErrPolicyNotFound if no such policy exists.
func (*Enclave) ImportKey ¶
ImportKey imports the given key into a KES server. It returns ErrKeyExists if a key with the same key already exists.
func (*Enclave) ListIdentities ¶
func (e *Enclave) ListIdentities(ctx context.Context, prefix string, n int) ([]Identity, string, error)
ListIdentities lists all identites that match the given pattern.
The pattern matching happens on the server side. If pattern is empty ListIdentities returns all identities.
func (*Enclave) ListKeys ¶
ListKeys lists all names of cryptographic keys that match the given pattern. It returns a KeyIterator that iterates over all matched key names.
The pattern matching happens on the server side. If pattern is empty the KeyIterator iterates over all key names.
func (*Enclave) ListPolicies ¶
ListPolicies lists all policy names that match the given pattern.
The pattern matching happens on the server side. If pattern is empty ListPolicies returns all policy names.
func (*Enclave) ListSecrets ¶
ListSecrets returns a SecretIter that iterates over all secrets matching the pattern.
The '*' pattern matches any secret. If pattern is empty the SecretIter iterates over all secrets names.
func (*Enclave) Metrics ¶ added in v0.2.0
Metrics returns a KES server metric snapshot.
It returns ErrNotAllowed if the client does not have sufficient permissions to fetch server metrics.
func (*Enclave) ReadSecret ¶
ReadSecret returns the secret with the given name.
It returns ErrSecretNotFound if no such secret exists.
type EnclaveInfo ¶
type EnclaveInfo struct { Name string CreatedAt time.Time // Point in time when the enclave has been created CreatedBy Identity // Identity that created the enclave }
EnclaveInfo describes a KES enclave.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error is a KES server API error.
type ErrorEvent ¶
type ErrorEvent struct {
Message string // The logged error message
}
ErrorEvent is the event a KES server generates when it encounters and logs an error.
type ErrorStream ¶
type ErrorStream struct {
// contains filtered or unexported fields
}
ErrorStream iterates over a stream of ErrorEvents. Close the ErrorStream to release associated resources.
func NewErrorStream ¶
func NewErrorStream(r io.Reader) *ErrorStream
NewErrorStream returns a new ErrorStream that reads from r.
Example ¶
reader := strings.NewReader(ErrorStream) stream := kes.NewErrorStream(reader) defer stream.Close() for stream.Next() { event := stream.Event() fmt.Println(event.Message) } if err := stream.Close(); err != nil { panic(err) // TODO: error handling }
Output: 2023/03/24 14:46:10 aws: secret was not encrypted with '4f9147d9-a676-47cd-ad3f-3485abf9123d' 2023/03/24 14:46:17 aws: the CMK 'ff8e2c25-b259-4f74-a001-c7b62d17e0a4' does not exist 2023/03/24 14:46:25 aws: the CMK '8fc17745-9647-4797-b170-afd8b52ed7c0' cannot be used for decryption
func (*ErrorStream) Close ¶
func (s *ErrorStream) Close() error
Close closes the ErrorStream and releases any associated resources.
func (*ErrorStream) Event ¶
func (s *ErrorStream) Event() ErrorEvent
Event returns the most recent ErrorEvent, generated by Next.
func (*ErrorStream) Message ¶
func (s *ErrorStream) Message() string
Message returns the current error message or the ErrorEvent. It is a short-hand for Event().Message.
func (*ErrorStream) Next ¶
func (s *ErrorStream) Next() bool
Next advances the stream to the next ErrorEvent and returns true if there is another one. It returns false if there are no more ErrorEvents or when the ErrorStream encountered an error.
type Identity ¶
type Identity string
An Identity should uniquely identify a client and is computed from the X.509 certificate presented by the client during the TLS handshake using an IdentityFunc.
const IdentityUnknown Identity = ""
IdentityUnknown is the identity returned by an IdentityFunc if it cannot map a particular X.509 certificate to an actual identity.
type IdentityInfo ¶
type IdentityInfo struct { Identity Identity IsAdmin bool // Indicates whether the identity has admin privileges Policy string // Name of the associated policy CreatedAt time.Time // Point in time when the identity was created CreatedBy Identity // Identity that created the identity ExpiresAt time.Time TTL time.Duration }
IdentityInfo describes a KES identity.
type ImportKeyRequest ¶ added in v0.2.0
type ImportKeyRequest struct { Key []byte Cipher KeyAlgorithm }
ImportKeyRequest is the request type for importing a key into a KES server.
type KeyAlgorithm ¶
type KeyAlgorithm uint
KeyAlgorithm is an enum representing the algorithm a cryptographic key can be used with.
func (KeyAlgorithm) MarshalText ¶
func (a KeyAlgorithm) MarshalText() ([]byte, error)
MarshalText returns the KeyAlgorithm's text representation. In contrast to String, it represents KeyAlgorithmUndefined as empty string and returns an error if the KeyAlgorithm isn't valid.
func (KeyAlgorithm) String ¶
func (a KeyAlgorithm) String() string
String returns the KeyAlgorithm's string representation.
func (*KeyAlgorithm) UnmarshalText ¶
func (a *KeyAlgorithm) UnmarshalText(text []byte) error
UnmarshalText parses text as KeyAlgorithm text representation.
type KeyInfo ¶
type KeyInfo struct { Name string // Name of the cryptographic key Algorithm KeyAlgorithm // Cryptographic algorithm the key can be used with CreatedAt time.Time // Point in time when the key was created CreatedBy Identity // Identity that created the key }
KeyInfo describes a cryptographic key at a KES server.
func (*KeyInfo) MarshalJSON ¶
MarshalJSON returns the KeyInfo's JSON representation.
func (*KeyInfo) UnmarshalJSON ¶
UnmarshalJSON parses text as KeyInfo JSON representation.
type ListIter ¶ added in v0.2.0
type ListIter[T any] struct { // NextFunc is a function that retrieves the next batch of items // from the paginated list. It takes a context, a token to continue // from, and the maximum number of items to fetch. It returns the // fetched items, a token to continue from for the next batch, and // any error encountered. NextFunc func(context.Context, string, int) ([]T, string, error) // contains filtered or unexported fields }
ListIter is a struct that represents an iterator over a paginated list of items. It is generic over some item type T.
Example ¶
const ( Endpoint = "https://play.min.io:7373" APIKey = "kes:v1:AD9E7FSYWrMD+VjhI6q545cYT9YOyFxZb7UnjEepYDRc" ) key, err := kes.ParseAPIKey(APIKey) if err != nil { log.Fatalf("Invalid API key '%s': %v", APIKey, err) } client, err := kes.NewClient(Endpoint, key) if err != nil { log.Fatalf("Failed to create client for '%s': %v", Endpoint, err) } ctx := context.TODO() iter := kes.ListIter[string]{ NextFunc: client.ListKeys, } for name, err := iter.Next(ctx); err != io.EOF; name, err = iter.Next(ctx) { if err != nil { log.Fatalf("Failed to list keys: %v", err) } fmt.Println(name) }
Output:
func (*ListIter[T]) Next ¶ added in v0.2.0
Next retrieves the next item from the paginated list. It uses the provided context when fetching the next page. If the ListIter has encountered an error previously or reached the end of the list, it returns the encountered error or io.EOF.
func (*ListIter[T]) SeekTo ¶ added in v0.2.0
SeekTo seeks to a specific position in the paginated list. It updates the iterator's state to start fetching items from the specified prefix and returns the subsequent item.
If the iterator has encountered an error previously, it returns the error without modifying the state. It returns io.EOF when seeking beyond the end of the list.
Example ¶
const ( Endpoint = "https://play.min.io:7373" APIKey = "kes:v1:AD9E7FSYWrMD+VjhI6q545cYT9YOyFxZb7UnjEepYDRc" ) key, err := kes.ParseAPIKey(APIKey) if err != nil { log.Fatalf("Invalid API key '%s': %v", APIKey, err) } client, err := kes.NewClient(Endpoint, key) if err != nil { log.Fatalf("Failed to create client for '%s': %v", Endpoint, err) } ctx := context.TODO() iter := kes.ListIter[string]{ NextFunc: client.ListKeys, } for name, err := iter.SeekTo(ctx, "my-key"); err != io.EOF; name, err = iter.Next(ctx) { if err != nil { log.Fatalf("Failed to list keys: %v", err) } fmt.Println(name) }
Output:
type Metric ¶
type Metric struct { RequestOK uint64 `json:"kes_http_request_success"` // Requests that succeeded RequestErr uint64 `json:"kes_http_request_error"` // Requests that failed with a well-defined error RequestFail uint64 `json:"kes_http_request_failure"` // Requests that failed unexpectedly due to an internal error RequestActive uint64 `json:"kes_http_request_active"` // Requests that are currently active and haven't completed yet AuditEvents uint64 `json:"kes_log_audit_events"` // Number of generated audit events ErrorEvents uint64 `json:"kes_log_error_events"` // Number of generated error events // Histogram of the KES server response latency. // It shows how fast the server can handle requests. // // The KES server response latency is the time // it takes to reply with a response once a request // has been received. // // The histogram consists of n time buckets. Each // time bucket contains the number of responses // that took the time T or less. For example: // // 10ms │ 50ms │ 100ms │ 250ms │ 500ms │ ... // ─────┼──────┼───────┼───────┼───────┼──── // 100 │ 115 │ 121 │ 126 │ 130 │ // // Here, there were 100 responses that took // 10ms or less to generate. There were also // 115 responses that took 50ms or less. // // So, there were 15 responses in the window // >10ms and <=50ms. // LatencyHistogram map[time.Duration]uint64 `json:"kes_http_response_time"` UpTime time.Duration `json:"kes_system_up_time"` // The time the KES server has been up and running // The number of logical CPU cores available on the system. // // The number of available CPU cores may be larger than // the number of cores usable by the server. // // If CPUs == UsableCPUs then the server can use the entire // computing power available on the system. CPUs int `json:"kes_system_num_cpu"` // The number of logical CPU cores usable by the server. // // The number of usable CPU cores may be smaller than // the number of available CPUs on the system. For // instance, a set of CPU cores may be reserved for // other tasks. UsableCPUs int `json:"kes_system_num_cpu_used"` // The number of concurrent co-routines/threads that currently exists. // // It may not correspond to the number of OS threads. Threads int `json:"kes_system_num_threads"` // HeapAlloc is the number of bytes currently allocated on the heap memory. // // It increases as the server allocates objects living on the heap and // decreases as allocated objects get freed. HeapAlloc uint64 `json:"kes_system_mem_heap_used"` // HeapObjects is the number of currently allocated objects on th heap memory. // // Similar to HeapAlloc, it increases as objects are allocated and decreases // as they get freed. HeapObjects uint64 `json:"kes_system_mem_heap_objects"` // StackAlloc is the number of bytes currently used on the OS stack memory. // // It increases as the server starts more co-routines / threads, invokes // functions, etc. and decreases as spawned co-routines / threads terminate. StackAlloc uint64 `json:"kes_system_mem_stack_used"` }
Metric is a KES server metric snapshot.
type Policy ¶
type Policy struct { Allow map[string]Rule // Set of allow rules Deny map[string]Rule // Set of deny rules CreatedAt time.Time CreatedBy Identity }
A Policy represents a set of rules that determine whether an HTTP request is accepted or rejected. It consists of two sets of rules: allow rules and deny rules.
If any rule from the deny set matches an incoming HTTP request, the request is rejected. Conversely, if any rule from the allow set matches, the request is accepted. If no rule matches, the request is also rejected. Therefore, an empty Policy, without any rules, rejects any request.
A rule set is defined by a collection of API path patterns. An API path pattern consists of the KES server API path and an optional resource pattern. For example, "/v1/key/describe/my-key*" consists of the "/v1/key/describe" API path and the resource pattern "my-key*".
When matching API path patterns:
- If the resource pattern does not end with an asterisk ('*') character, the API path pattern only matches requests with an URL path equal to the pattern.
- If the resource pattern ends with an asterisk ('*') character, the API path pattern matches if the API path pattern (without the asterisk) is a prefix of the URL path.
An API path pattern cannot contain more than one asterisk character. API path patterns can be viewed as a subset of glob patterns.
Here's an example defining a policy:
policy := Policy{ Allow: map[string]kes.Rule{ "/v1/status": {}, "/v1/key/describe/my-key*": {}, "/v1/key/generate/my-key*": {}, "/v1/key/decrypt/my-key*": {}, }, }
func (*Policy) IsSubset ¶ added in v0.2.0
IsSubset reports whether the Policy p is a subset of o. If it is then any request allowed by p is also allowed by o and any request rejected by o is also rejected by p.
Usually, p is a subset of o when it contains less or less generic allow rules and/or more or more generic deny rules.
Two policies, A and B, are equivalent, but not necessarily equal, if:
A.IsSubset(B) && B.IsSubset(A)
type PolicyInfo ¶
type PolicyInfo struct { Name string `json:"name"` // Name of the policy CreatedAt time.Time `json:"created_at,omitempty"` // Point in time when the policy was created CreatedBy Identity `json:"created_by,omitempty"` // Identity that created the policy }
PolicyInfo describes a KES policy.
type Rule ¶ added in v0.2.0
type Rule struct{}
A Rule controls HTTP requests and is part of a policy.
type SecretInfo ¶
type SecretInfo struct { Name string // The name of the secret Type SecretType // The type of secret CreatedAt time.Time // Point in time when the secret was created CreatedBy Identity // Identity that created the secret }
SecretInfo describes a secret at a KES server.
func (*SecretInfo) MarshalJSON ¶
func (s *SecretInfo) MarshalJSON() ([]byte, error)
MarshalJSON returns the SecretInfo JSON representation.
func (*SecretInfo) UnmarshalJSON ¶
func (s *SecretInfo) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the given JSON data into the SecretInfo.
type SecretOptions ¶
type SecretOptions struct { // Type specifies the type of the Secret. // Its default vaule is SecretGeneric. Type SecretType }
SecretOptions is a struct containing customization options for secret - like the Secret type.
type SecretType ¶
type SecretType uint
SecretType is an enum representing the type of a Secret.
const (
SecretGeneric SecretType = iota
)
All valid secret types.
func (SecretType) MarshalText ¶
func (s SecretType) MarshalText() ([]byte, error)
MarshalText returns the SecretType text representation. In contrast to String, it returns an error if s is not a valid SecretType.
func (SecretType) String ¶
func (s SecretType) String() string
String returns the SecretType string representation.
func (*SecretType) UnmarshalText ¶
func (s *SecretType) UnmarshalText(text []byte) error
UnmarshalText decodes the given SecretType text representation into s. It returns an error if text is not a valid SecretType.
type State ¶
type State struct { Version string // KES server version OS string // OS running the KES server Arch string // CPU architecture the KES server is running on UpTime time.Duration // Time the KES server has been up and running CPUs int // Number of available logical CPU cores UsableCPUs int // Number of usbale logical CPU cores HeapAlloc uint64 // Number of bytes currently allocated on the heap StackAlloc uint64 // Number of bytes currently allocated on the stack KeyStoreLatency time.Duration // The latency of the KES key store. Zero when the key store is not accessible KeyStoreReachable bool // Indicates whether the key store is reachable KeystoreAvailable bool // Indicates whether the key store is available and reachable }
State is a KES server status snapshot.
func (State) MarshalJSON ¶ added in v0.2.0
MarshalJSON returns the State's JSON representation.
func (*State) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON unmarshal the JSON data into State.