Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

kes: add support for API key authentication #340

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions internal/keystore/kes/kes.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ type Config struct {
// If empty, the default enclave is used.
Enclave string

// APIKey is an API key to authenticate to the
// KES server. Either an API key or a mTLS private
// key and certificate can be used for authentication.
APIKey kes.APIKey

// PrivateKey is a path to a file containing
// a X.509 private key for mTLS authentication.
PrivateKey string
Expand All @@ -50,17 +55,35 @@ func Connect(ctx context.Context, config *Config) (*Conn, error) {
if len(config.Endpoints) == 0 {
return nil, errors.New("kes: no endpoints provided")
}
if config.Certificate == "" {
return nil, errors.New("kes: no certificate provided")
}
if config.PrivateKey == "" {
return nil, errors.New("kes: no private key provided")
if config.APIKey != nil && (config.PrivateKey != "" || config.Certificate != "") {
return nil, errors.New("kes: ambiguous configuration: API key as well as mTLS private key and/or certificate provided")
}

cert, err := https.CertificateFromFile(config.Certificate, config.PrivateKey, "")
if err != nil {
return nil, err
var (
err error
cert tls.Certificate
)
switch {
case config.APIKey != nil:
cert, err = kes.GenerateCertificate(config.APIKey)
if err != nil {
return nil, err
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we return the error here?

case config.PrivateKey != "" || config.Certificate != "":
if config.Certificate == "" {
return nil, errors.New("kes: no certificate provided")
}
if config.PrivateKey == "" {
return nil, errors.New("kes: no private key provided")
}
cert, err = https.CertificateFromFile(config.Certificate, config.PrivateKey, "")
if err != nil {
return nil, err
}
default:
return nil, errors.New("kes: no API key nor private key and certificate provided")
}

var rootCAs *x509.CertPool
if config.CAPath != "" {
rootCAs, err = https.CertPoolFromFile(config.CAPath)
Expand Down
16 changes: 16 additions & 0 deletions keserv/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ type KESConfig struct {
// the default enclave name will be used.
Enclave Env[string]

// APIKey is an API key to authenticate to the
// KES server.
APIKey Env[string]

// CertificateFile is a path to a mTLS client
// certificate file used to authenticate to
// the KES server.
Expand All @@ -389,9 +393,19 @@ func (c *KESConfig) Connect(ctx context.Context) (kms.Conn, error) {
for _, endpoint := range c.Endpoints {
endpoints = append(endpoints, endpoint.Value)
}

var key kes.APIKey
if c.APIKey.Value != "" {
k, err := kes.ParseAPIKey(c.APIKey.Value)
if err != nil {
return nil, err
}
key = k
}
return kesstore.Connect(ctx, &kesstore.Config{
Endpoints: endpoints,
Enclave: c.Enclave.Value,
APIKey: key,
Certificate: c.CertificateFile.Value,
PrivateKey: c.PrivateKeyFile.Value,
CAPath: c.CAPath.Value,
Expand All @@ -400,6 +414,7 @@ func (c *KESConfig) Connect(ctx context.Context) (kms.Conn, error) {

func (c *KESConfig) toYAML(yml *serverConfigYAML) {
yml.KeyStore.KES.Endpoint = c.Endpoints
yml.KeyStore.KES.APIKey = c.APIKey
yml.KeyStore.KES.TLS.Certificate = c.CertificateFile
yml.KeyStore.KES.TLS.PrivateKey = c.PrivateKeyFile
yml.KeyStore.KES.TLS.CAPath = c.CAPath
Expand All @@ -408,6 +423,7 @@ func (c *KESConfig) toYAML(yml *serverConfigYAML) {
func (c *KESConfig) fromYAML(yml *serverConfigYAML) {
c.Endpoints = yml.KeyStore.KES.Endpoint
c.Enclave = yml.KeyStore.KES.Enclave
c.APIKey = yml.KeyStore.KES.APIKey
c.CertificateFile = yml.KeyStore.KES.TLS.Certificate
c.PrivateKeyFile = yml.KeyStore.KES.TLS.PrivateKey
c.CAPath = yml.KeyStore.KES.TLS.CAPath
Expand Down
1 change: 1 addition & 0 deletions keserv/yml.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type serverConfigYAML struct {
KES struct {
Endpoint []Env[string] `yaml:"endpoint,omitempty"`
Enclave Env[string] `yaml:"enclave,omitempty"`
APIKey Env[string] `yaml:"api_key,omitempty"`
TLS struct {
Certificate Env[string] `yaml:"cert,omitempty"`
PrivateKey Env[string] `yaml:"key,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions server-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ keystore:
endpoint:
- "" # The endpoint (or list of endpoints) to the KES server(s)
enclave: "" # An optional enclave name. If empty, the default enclave will be used
api_key: "" # The KES API key to authenticate to KES server
tls: # The KES mTLS authentication credentials - i.e. client certificate.
cert: "" # Path to the TLS client certificate for mTLS authentication
key: "" # Path to the TLS client private key for mTLS authentication
Expand Down