kes

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2023 License: AGPL-3.0 Imports: 34 Imported by: 7

README

KES SDK for Go

Go Reference license

Usage

Import the kes package into your codebase by adding this import statement to one of your .go source files:

import "github.com/minio/kes-go"

License

Use of the KES SDK is governed by the AGPLv3 license that can be found in the LICENSE file.

Documentation

Index

Examples

Constants

View Source
const (
	AES256 = iota
	ChaCha20
)

All valid cryptographic algorithms that can be used with keys.

Variables

View Source
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

func (a API) MarshalJSON() ([]byte, error)

MarshalJSON returns the API's JSON representation.

func (*API) UnmarshalJSON added in v0.2.0

func (a *API) UnmarshalJSON(data []byte) error

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

func GenerateAPIKey(rand io.Reader) (APIKey, error)

GenerateAPIKey generates a new random API key. If rand is nil, crypto/rand.Reader is used.

func ParseAPIKey

func ParseAPIKey(s string) (APIKey, error)

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.

func (*AuditStream) WriteTo

func (s *AuditStream) WriteTo(w io.Writer) (int64, error)

WriteTo writes the entire AuditEvent stream to w. It returns the number of bytes written to w and the first error encountered, if any.

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

func NewClientWithConfig(endpoint string, config *tls.Config) *Client

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

func (c *Client) APIs(ctx context.Context) ([]API, error)

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

func (c *Client) AssignPolicy(ctx context.Context, policy string, identity Identity) error

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

func (c *Client) CreateEnclave(ctx context.Context, name string) error

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

func (c *Client) CreateKey(ctx context.Context, name string) error

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

func (c *Client) CreatePolicy(ctx context.Context, name string, policy *Policy) error

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

func (c *Client) DeleteEnclave(ctx context.Context, name string) error

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

func (c *Client) DeleteIdentity(ctx context.Context, identity Identity) error

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

func (c *Client) DeleteKey(ctx context.Context, name string) error

DeleteKey deletes the key from a KES server. It returns ErrKeyNotFound if no such key exists.

func (*Client) DeletePolicy

func (c *Client) DeletePolicy(ctx context.Context, name string) error

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

func (c *Client) DeleteSecret(ctx context.Context, name string) error

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

func (c *Client) DescribeEnclave(ctx context.Context, name string) (*EnclaveInfo, error)

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

func (c *Client) DescribeIdentity(ctx context.Context, identity Identity) (*IdentityInfo, error)

DescribeIdentity returns an IdentityInfo describing the given identity.

func (*Client) DescribeKey

func (c *Client) DescribeKey(ctx context.Context, name string) (*KeyInfo, error)

DescribeKey returns the KeyInfo for the given key. It returns ErrKeyNotFound if no such key exists.

func (*Client) DescribePolicy

func (c *Client) DescribePolicy(ctx context.Context, name string) (*PolicyInfo, error)

DescribePolicy returns the PolicyInfo for the given policy. It returns ErrPolicyNotFound if no such policy exists.

func (*Client) DescribeSecret

func (c *Client) DescribeSecret(ctx context.Context, name string) (*SecretInfo, error)

DescribeSecret returns the SecretInfo for the given secret.

It returns ErrSecretNotFound if no such secret exists.

func (*Client) DescribeSelf

func (c *Client) DescribeSelf(ctx context.Context) (*IdentityInfo, *Policy, error)

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

func (c *Client) Enclave(name string) *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

func (c *Client) ExpandCluster(ctx context.Context, endpoint string) error

ExpandCluster expands a KES cluster by adding a new node with the given endpoint.

func (*Client) GenerateKey

func (c *Client) GenerateKey(ctx context.Context, name string, context []byte) (DEK, error)

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

func (c *Client) GetPolicy(ctx context.Context, name string) (*Policy, error)

GetPolicy returns the policy with the given name. It returns ErrPolicyNotFound if no such policy exists.

func (*Client) ImportKey

func (c *Client) ImportKey(ctx context.Context, name string, req *ImportKeyRequest) error

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

func (c *Client) IsReady(ctx context.Context) (bool, error)

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

func (c *Client) ListEnclaves(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (c *Client) ListKeys(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (c *Client) ListPolicies(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (c *Client) ListSecrets(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (c *Client) Metrics(ctx context.Context) (Metric, error)

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

func (c *Client) ReadSecret(ctx context.Context, name string) ([]byte, *SecretInfo, error)

ReadSecret returns the secret with the given name.

It returns ErrSecretNotFound if no such secret exists.

func (*Client) ShrinkCluster added in v0.2.0

func (c *Client) ShrinkCluster(ctx context.Context, endpoint string) error

ShrinkCluster shrinks a KES cluster by removingt the new node with the given endpoint from the cluster.

func (*Client) Status

func (c *Client) Status(ctx context.Context) (State, error)

Status returns the current state of the KES server.

func (*Client) Version

func (c *Client) Version(ctx context.Context) (string, error)

Version tries to fetch the version information from the KES server.

type ClusterInfo added in v0.2.0

type ClusterInfo struct {
	Nodes  map[uint64]string
	Leader uint64
}

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

func IsConnError(err error) (*ConnError, bool)

IsConnError reports whether err is or wraps a ConnError. In this case, it returns the ConnError.

func (*ConnError) Error

func (c *ConnError) Error() string

Error returns the string representation of the ConnError.

func (*ConnError) Temporary deprecated

func (c *ConnError) Temporary() bool

Temporary returns false. It is implemented such that ConnError implements the net.Error interface.

Deprecated: See the net.Error documentation

func (*ConnError) Timeout

func (c *ConnError) Timeout() bool

Timeout reports whether the error is caused by a timeout.

func (*ConnError) Unwrap

func (c *ConnError) Unwrap() error

Unwarp returns the underlying connection error.

type CreateIdentityRequest added in v0.2.0

type CreateIdentityRequest struct {
	Policy string
	Admin  bool
	TTL    time.Duration
}

CreateIdentityRequest is the request type for creating a new identity at a KES server.

type DEK

type DEK struct {
	Plaintext  []byte
	Ciphertext []byte
}

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

func NewEnclaveWithConfig(endpoint, name string, config *tls.Config) *Enclave

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

func (e *Enclave) AssignPolicy(ctx context.Context, policy string, identity Identity) error

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

func (e *Enclave) CreateKey(ctx context.Context, name string) error

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

func (e *Enclave) CreatePolicy(ctx context.Context, name string, policy *Policy) error

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

func (e *Enclave) DeleteIdentity(ctx context.Context, identity Identity) error

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

func (e *Enclave) DeleteKey(ctx context.Context, name string) error

DeleteKey deletes the key from a KES server. It returns ErrKeyNotFound if no such key exists.

func (*Enclave) DeletePolicy

func (e *Enclave) DeletePolicy(ctx context.Context, name string) error

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

func (e *Enclave) DeleteSecret(ctx context.Context, name string) error

DeleteSecret deletes the secret with the given name.

It returns ErrSecretNotFound if no such secret exists.

func (*Enclave) DescribeIdentity

func (e *Enclave) DescribeIdentity(ctx context.Context, identity Identity) (*IdentityInfo, error)

DescribeIdentity returns an IdentityInfo describing the given identity.

func (*Enclave) DescribeKey

func (e *Enclave) DescribeKey(ctx context.Context, name string) (*KeyInfo, error)

DescribeKey returns the KeyInfo for the given key.

It returns ErrKeyNotFound if no such key exists.

func (*Enclave) DescribePolicy

func (e *Enclave) DescribePolicy(ctx context.Context, name string) (*PolicyInfo, error)

DescribePolicy returns the PolicyInfo for the given policy. It returns ErrPolicyNotFound if no such policy exists.

func (*Enclave) DescribeSecret

func (e *Enclave) DescribeSecret(ctx context.Context, name string) (*SecretInfo, error)

DescribeSecret returns the SecretInfo for the given secret.

It returns ErrSecretNotFound if no such secret exists.

func (*Enclave) DescribeSelf

func (e *Enclave) DescribeSelf(ctx context.Context) (*IdentityInfo, *Policy, error)

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

func (e *Enclave) GenerateKey(ctx context.Context, name string, context []byte) (DEK, error)

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

func (e *Enclave) GetPolicy(ctx context.Context, name string) (*Policy, error)

GetPolicy returns the policy with the given name. It returns ErrPolicyNotFound if no such policy exists.

func (*Enclave) ImportKey

func (e *Enclave) ImportKey(ctx context.Context, name string, req *ImportKeyRequest) error

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

func (e *Enclave) ListKeys(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (e *Enclave) ListPolicies(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (e *Enclave) ListSecrets(ctx context.Context, prefix string, n int) ([]string, string, error)

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

func (e *Enclave) Metrics(ctx context.Context) (Metric, error)

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

func (e *Enclave) ReadSecret(ctx context.Context, name string) ([]byte, *SecretInfo, error)

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.

func NewError

func NewError(code int, msg string) Error

NewError returns a new Error with the given HTTP status code and error message.

func (Error) Error

func (e Error) Error() string

func (Error) Status

func (e Error) Status() int

Status returns the HTTP status code of the 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.

func (*ErrorStream) WriteTo

func (s *ErrorStream) WriteTo(w io.Writer) (int64, error)

WriteTo writes the entire ErrorEvent stream to w. It returns the number of bytes written to w and the first error encounterred, if any.

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.

func (Identity) IsUnknown

func (id Identity) IsUnknown() bool

IsUnknown returns true if and only if the identity is IdentityUnknown.

func (Identity) String

func (id Identity) String() string

String returns the string representation of the 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

func (k *KeyInfo) MarshalJSON() ([]byte, error)

MarshalJSON returns the KeyInfo's JSON representation.

func (*KeyInfo) UnmarshalJSON

func (k *KeyInfo) UnmarshalJSON(text []byte) error

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

func (i *ListIter[T]) Next(ctx context.Context) (item T, err error)

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

func (i *ListIter[T]) SeekTo(ctx context.Context, prefix string) (item T, err error)

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.

func (*Metric) RequestN

func (m *Metric) RequestN() uint64

RequestN returns the total number of received requests.

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

func (p *Policy) IsSubset(o *Policy) bool

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)

func (*Policy) Verify added in v0.2.0

func (p *Policy) Verify(r *http.Request) error

Verify reports whether the given HTTP request is allowed. It returns no error if:

(1) No deny pattern matches the URL path *AND*
(2) At least one allow pattern matches the URL path.

Otherwise, Verify returns ErrNotAllowed.

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

func (s State) MarshalJSON() ([]byte, error)

MarshalJSON returns the State's JSON representation.

func (*State) UnmarshalJSON added in v0.2.0

func (s *State) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshal the JSON data into State.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL