aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2022-12-23 17:14:51 -0800
committerMike Crute <mike@crute.us>2022-12-23 17:14:51 -0800
commitd4a56ba3c37ea7141854d0c1196ffee41fbaca6d (patch)
treeaf092b4b879ea02608693f04f8f63c9f19f3bdd8
parent685da24d55cb12e1f8d78a079cb7911424f6ddd4 (diff)
downloadgolib-d4a56ba3c37ea7141854d0c1196ffee41fbaca6d.tar.bz2
golib-d4a56ba3c37ea7141854d0c1196ffee41fbaca6d.tar.xz
golib-d4a56ba3c37ea7141854d0c1196ffee41fbaca6d.zip
secrets: add AWS IAM supportsecrets/v0.3.0
-rw-r--r--secrets/client.go16
-rw-r--r--secrets/noop_client.go17
-rw-r--r--secrets/vault_client.go67
3 files changed, 96 insertions, 4 deletions
diff --git a/secrets/client.go b/secrets/client.go
index 92c46ef..779f28c 100644
--- a/secrets/client.go
+++ b/secrets/client.go
@@ -33,6 +33,12 @@ type ApiKey struct {
33 Key string `json:"key" mapstructure:"key"` 33 Key string `json:"key" mapstructure:"key"`
34} 34}
35 35
36type AWSCredential struct {
37 AccessKeyId string `json:"access_key" mapstructure:"access_key"`
38 SecretAccessKey string `json:"secret_key" mapstructure:"secret_key"`
39 SessionToken string `json:"security_token" mapstructure:"security_token"`
40}
41
36type RSAKey struct { 42type RSAKey struct {
37 Key string `json:"key" mapstructure:"key"` 43 Key string `json:"key" mapstructure:"key"`
38} 44}
@@ -63,9 +69,13 @@ func (k *RSAKey) RSAPrivateKey() (*rsa.PrivateKey, error) {
63// to inject stubs to code that doesn't care about the fact that a 69// to inject stubs to code that doesn't care about the fact that a
64// manager may exist. 70// manager may exist.
65type Client interface { 71type Client interface {
66 DatabaseCredential(context.Context, string) (*Credential, Handle, error) 72 DatabaseCredential(ctx context.Context, suffix string) (*Credential, Handle, error)
67 Secret(context.Context, string, any) (Handle, error) 73 Secret(ctx context.Context, suffix string, out any) (Handle, error)
68 WriteSecret(context.Context, string, any) error 74 RawSecret(ctx context.Context, path string, out any) (Handle, error)
75 AWSIAMUser(ctx context.Context, name string) (*AWSCredential, Handle, error)
76 AWSAssumeRoleSimple(ctx context.Context, name string) (*AWSCredential, Handle, error)
77 AWSAssumeRole(ctx context.Context, name string, sessionName string, ttl time.Duration) (*AWSCredential, Handle, error)
78 WriteSecret(ctx context.Context, suffix string, out any) error
69 Destroy(Handle) error 79 Destroy(Handle) error
70 MakeNonCritical(Handle) error 80 MakeNonCritical(Handle) error
71} 81}
diff --git a/secrets/noop_client.go b/secrets/noop_client.go
index 85bd736..e727e51 100644
--- a/secrets/noop_client.go
+++ b/secrets/noop_client.go
@@ -3,6 +3,7 @@ package secrets
3import ( 3import (
4 "context" 4 "context"
5 "sync" 5 "sync"
6 "time"
6) 7)
7 8
8type NoopHandle struct{} 9type NoopHandle struct{}
@@ -33,6 +34,22 @@ func (c *NoopClient) Secret(ctx context.Context, path string, out any) (Handle,
33 return &NoopHandle{}, nil 34 return &NoopHandle{}, nil
34} 35}
35 36
37func (c *NoopClient) RawSecret(ctx context.Context, path string, out any) (Handle, error) {
38 return &NoopHandle{}, nil
39}
40
41func (c *NoopClient) AWSIAMUser(ctx context.Context, name string) (*AWSCredential, Handle, error) {
42 return &AWSCredential{}, &NoopHandle{}, nil
43}
44
45func (c *NoopClient) AWSAssumeRoleSimple(ctx context.Context, name string) (*AWSCredential, Handle, error) {
46 return &AWSCredential{}, &NoopHandle{}, nil
47}
48
49func (c *NoopClient) AWSAssumeRole(ctx context.Context, name string, sessionName string, ttl time.Duration) (*AWSCredential, Handle, error) {
50 return &AWSCredential{}, &NoopHandle{}, nil
51}
52
36func (c *NoopClient) WriteSecret(ctx context.Context, path string, in any) error { 53func (c *NoopClient) WriteSecret(ctx context.Context, path string, in any) error {
37 return nil 54 return nil
38} 55}
diff --git a/secrets/vault_client.go b/secrets/vault_client.go
index ce26dbe..b84b344 100644
--- a/secrets/vault_client.go
+++ b/secrets/vault_client.go
@@ -289,8 +289,25 @@ func (c *VaultClient) makeHandle(name string, s *api.Secret) Handle {
289 return h 289 return h
290} 290}
291 291
292func (c *VaultClient) writeHandle(ctx context.Context, prefix, suffix string, data map[string]any) (Handle, error) {
293 key := suffix
294 if prefix != "" {
295 key = path.Join(prefix, suffix)
296 }
297
298 s, err := c.logical.WriteWithContext(ctx, key, data)
299 if err != nil {
300 return nil, fmt.Errorf("writeHandle: error writing to Vault: %w", err)
301 }
302
303 return c.makeHandle(key, s), nil
304}
305
292func (c *VaultClient) read(ctx context.Context, prefix, suffix string) (Handle, error) { 306func (c *VaultClient) read(ctx context.Context, prefix, suffix string) (Handle, error) {
293 key := path.Join(prefix, suffix) 307 key := suffix
308 if prefix != "" {
309 key = path.Join(prefix, suffix)
310 }
294 311
295 s, err := c.logical.ReadWithContext(ctx, key) 312 s, err := c.logical.ReadWithContext(ctx, key)
296 if err != nil { 313 if err != nil {
@@ -358,6 +375,54 @@ func (c *VaultClient) Secret(ctx context.Context, suffix string, out any) (Handl
358 return h, nil 375 return h, nil
359} 376}
360 377
378func (c *VaultClient) RawSecret(ctx context.Context, path string, out any) (Handle, error) {
379 h, err := c.read(ctx, "", path)
380 if err != nil {
381 return nil, err
382 }
383
384 if err = mapstructure.Decode(h.(*VaultHandle).secret.Data["data"], out); err != nil {
385 return nil, err
386 }
387
388 return h, nil
389}
390
391func (c *VaultClient) AWSAssumeRoleSimple(ctx context.Context, name string) (*AWSCredential, Handle, error) {
392 return c.AWSAssumeRole(ctx, name, fmt.Sprintf("%s-%d", name, time.Now().UnixNano()), time.Hour)
393}
394
395func (c *VaultClient) AWSAssumeRole(ctx context.Context, name string, sessionName string, ttl time.Duration) (*AWSCredential, Handle, error) {
396 h, err := c.writeHandle(ctx, "aws/sts", name, map[string]any{
397 "role_session_name": sessionName,
398 "ttl": ttl.String(),
399 })
400 if err != nil {
401 return nil, nil, err
402 }
403
404 var d AWSCredential
405 if err = mapstructure.Decode(h.(*VaultHandle).secret.Data, &d); err != nil {
406 return nil, nil, fmt.Errorf("AWSIAMUser: error decoding secret: %w", err)
407 }
408
409 return nil, nil, nil
410}
411
412func (c *VaultClient) AWSIAMUser(ctx context.Context, name string) (*AWSCredential, Handle, error) {
413 h, err := c.read(ctx, "aws/creds", name)
414 if err != nil {
415 return nil, nil, err
416 }
417
418 var d AWSCredential
419 if err = mapstructure.Decode(h.(*VaultHandle).secret.Data, &d); err != nil {
420 return nil, nil, fmt.Errorf("AWSIAMUser: error decoding secret: %w", err)
421 }
422
423 return &d, h, nil
424}
425
361func (c *VaultClient) WriteSecret(ctx context.Context, suffix string, in any) error { 426func (c *VaultClient) WriteSecret(ctx context.Context, suffix string, in any) error {
362 inb, err := json.Marshal(in) 427 inb, err := json.Marshal(in)
363 if err != nil { 428 if err != nil {