Skip to content

Commit af404e0

Browse files
committed
kes: add support for API key authentication
This commit adds support for KES<->KES authentication via API keys. Now, a KES edge server can authenticate to a KES server (stateful) via API keys - not just via TLS private key / certificate files.
1 parent ffbbe40 commit af404e0

File tree

4 files changed

+48
-8
lines changed

4 files changed

+48
-8
lines changed

internal/keystore/kes/kes.go

+30-8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ type Config struct {
3030
// If empty, the default enclave is used.
3131
Enclave string
3232

33+
// APIKey is an API key to authenticate to the
34+
// KES server. Either an API key or a mTLS private
35+
// key and certificate can be used for authentication.
36+
APIKey kes.APIKey
37+
3338
// PrivateKey is a path to a file containing
3439
// a X.509 private key for mTLS authentication.
3540
PrivateKey string
@@ -50,17 +55,34 @@ func Connect(ctx context.Context, config *Config) (*Conn, error) {
5055
if len(config.Endpoints) == 0 {
5156
return nil, errors.New("kes: no endpoints provided")
5257
}
53-
if config.Certificate == "" {
54-
return nil, errors.New("kes: no certificate provided")
55-
}
56-
if config.PrivateKey == "" {
57-
return nil, errors.New("kes: no private key provided")
58+
if config.APIKey != nil && (config.PrivateKey != "" || config.Certificate != "") {
59+
return nil, errors.New("kes: ambiguous configuration: API key as well as mTLS private key and certificate provided")
5860
}
5961

60-
cert, err := https.CertificateFromFile(config.Certificate, config.PrivateKey, "")
61-
if err != nil {
62-
return nil, err
62+
var (
63+
err error
64+
cert tls.Certificate
65+
)
66+
switch {
67+
case config.APIKey != nil:
68+
cert, err = kes.GenerateCertificate(config.APIKey)
69+
if err != nil {
70+
}
71+
case config.PrivateKey != "" || config.Certificate != "":
72+
if config.Certificate == "" {
73+
return nil, errors.New("kes: no certificate provided")
74+
}
75+
if config.PrivateKey == "" {
76+
return nil, errors.New("kes: no private key provided")
77+
}
78+
cert, err = https.CertificateFromFile(config.Certificate, config.PrivateKey, "")
79+
if err != nil {
80+
return nil, err
81+
}
82+
default:
83+
return nil, errors.New("kes: no API key nor private key and certificate provided")
6384
}
85+
6486
var rootCAs *x509.CertPool
6587
if config.CAPath != "" {
6688
rootCAs, err = https.CertPoolFromFile(config.CAPath)

keserv/config.go

+16
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,10 @@ type KESConfig struct {
337337
// the default enclave name will be used.
338338
Enclave Env[string]
339339

340+
// APIKey is an API key to authenticate to the
341+
// KES server.
342+
APIKey Env[string]
343+
340344
// CertificateFile is a path to a mTLS client
341345
// certificate file used to authenticate to
342346
// the KES server.
@@ -362,9 +366,19 @@ func (c *KESConfig) Connect(ctx context.Context) (kms.Conn, error) {
362366
for _, endpoint := range c.Endpoints {
363367
endpoints = append(endpoints, endpoint.Value)
364368
}
369+
370+
var key kes.APIKey
371+
if c.APIKey.Value != "" {
372+
k, err := kes.ParseAPIKey(c.APIKey.Value)
373+
if err != nil {
374+
return nil, err
375+
}
376+
key = k
377+
}
365378
return kesstore.Connect(ctx, &kesstore.Config{
366379
Endpoints: endpoints,
367380
Enclave: c.Enclave.Value,
381+
APIKey: key,
368382
Certificate: c.CertificateFile.Value,
369383
PrivateKey: c.PrivateKeyFile.Value,
370384
CAPath: c.CAPath.Value,
@@ -373,6 +387,7 @@ func (c *KESConfig) Connect(ctx context.Context) (kms.Conn, error) {
373387

374388
func (c *KESConfig) toYAML(yml *serverConfigYAML) {
375389
yml.KeyStore.KES.Endpoint = c.Endpoints
390+
yml.KeyStore.KES.APIKey = c.APIKey
376391
yml.KeyStore.KES.TLS.Certificate = c.CertificateFile
377392
yml.KeyStore.KES.TLS.PrivateKey = c.PrivateKeyFile
378393
yml.KeyStore.KES.TLS.CAPath = c.CAPath
@@ -381,6 +396,7 @@ func (c *KESConfig) toYAML(yml *serverConfigYAML) {
381396
func (c *KESConfig) fromYAML(yml *serverConfigYAML) {
382397
c.Endpoints = yml.KeyStore.KES.Endpoint
383398
c.Enclave = yml.KeyStore.KES.Enclave
399+
c.APIKey = yml.KeyStore.KES.APIKey
384400
c.CertificateFile = yml.KeyStore.KES.TLS.Certificate
385401
c.PrivateKeyFile = yml.KeyStore.KES.TLS.PrivateKey
386402
c.CAPath = yml.KeyStore.KES.TLS.CAPath

keserv/yml.go

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ type serverConfigYAML struct {
6464
KES struct {
6565
Endpoint []Env[string] `yaml:"endpoint,omitempty"`
6666
Enclave Env[string] `yaml:"enclave,omitempty"`
67+
APIKey Env[string] `yaml:"api_key,omitempty"`
6768
TLS struct {
6869
Certificate Env[string] `yaml:"cert,omitempty"`
6970
PrivateKey Env[string] `yaml:"key,omitempty"`

server-config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ keystore:
189189
endpoint:
190190
- "" # The endpoint (or list of endpoints) to the KES server(s)
191191
enclave: "" # An optional enclave name. If empty, the default enclave will be used
192+
api_key: "" # The KES API key to authenticate to KES server
192193
tls: # The KES mTLS authentication credentials - i.e. client certificate.
193194
cert: "" # Path to the TLS client certificate for mTLS authentication
194195
key: "" # Path to the TLS client private key for mTLS authentication

0 commit comments

Comments
 (0)