This repository has been archived by the owner on Apr 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
secret_manager.go
126 lines (115 loc) · 3.77 KB
/
secret_manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package forester
import (
"cloud.google.com/go/secretmanager/apiv1"
"context"
"google.golang.org/api/iterator"
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
)
const lotwUsername = "lotw_username"
const lotwPassword = "lotw_password"
const qrzUsername = "qrz_username"
const qrzPassword = "qrz_password"
const qrzLogbookAPIKey = "qrz_logbook_api_key"
type SecretStore struct {
ctx context.Context
client *secretmanager.Client
}
func NewSecretStore(ctx context.Context) SecretStore {
client, _ := secretmanager.NewClient(ctx)
return SecretStore{ctx, client}
}
func makeSecretID(scope string, key string) string {
return scope + "_" + key
}
// FetchSecret gets the latest value of the secret for the given logbook and key.
func (s *SecretStore) FetchSecret(logbookID string, key string) (string, error) {
secretID := makeSecretID(logbookID, key)
versionName := "projects/" + projectID + "/secrets/" + secretID + "/versions/latest"
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: versionName,
}
resp, err := s.client.AccessSecretVersion(s.ctx, req)
if err != nil {
return "", err
}
return string(resp.GetPayload().GetData()), nil
}
// SetSecret adds a version to the given secret, possibly creating the secret first. It returns the
// version name, e.g. "/projects/*/secrets/*/versions/n".
func (s *SecretStore) SetSecret(logbookID string, key string, secretValue string) (string, error) {
secretID := makeSecretID(logbookID, key)
projectName := "projects/" + projectID
secretName := projectName + "/secrets/" + secretID
_, err := s.client.GetSecret(s.ctx, &secretmanagerpb.GetSecretRequest{Name: secretName})
if err != nil {
// assume the secret didn't exist and create it
secretName, err = s.createSecret(projectName, secretID)
if err != nil {
return "", err
}
}
newVersion, err := s.addSecretVersion(secretName, secretValue)
if err != nil {
return "", err
}
err = s.deleteAllVersionsExceptLatest(secretName, newVersion)
return newVersion, err
}
// Creates a new secret with no versions. Returns the secret name, e.g. "/projects/*/secrets/*".
func (s *SecretStore) createSecret(projectName string, secretID string) (string, error) {
createResp, err := s.client.CreateSecret(s.ctx, &secretmanagerpb.CreateSecretRequest{
Parent: projectName,
SecretId: secretID,
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_Automatic_{
Automatic: &secretmanagerpb.Replication_Automatic{},
},
},
},
})
if err != nil {
return "", err
}
return createResp.Name, nil
}
// Adds a version to the given secret. Returns the version name, e.g.
// "/projects/*/secrets/*/versions/n".
func (s *SecretStore) addSecretVersion(secretName string, secretValue string) (string, error) {
versionResp, err := s.client.AddSecretVersion(s.ctx, &secretmanagerpb.AddSecretVersionRequest{
Parent: secretName,
Payload: &secretmanagerpb.SecretPayload{
Data: []byte(secretValue),
},
})
if err != nil {
return "", err
}
return versionResp.Name, nil
}
// Destroys all versions of the secret except the given (latest) version name, e.g.
// "/projects/*/secrets/*/versions/n".
func (s *SecretStore) deleteAllVersionsExceptLatest(
secretName string, latestVersionName string) error {
versionItr := s.client.ListSecretVersions(s.ctx,
&secretmanagerpb.ListSecretVersionsRequest{Parent: secretName})
for {
ver, err := versionItr.Next()
if err == iterator.Done {
break
}
if err != nil {
return err
}
if ver.Name == latestVersionName {
// Don't delete the (given) latest
continue
}
ver, err = s.client.DestroySecretVersion(s.ctx,
&secretmanagerpb.DestroySecretVersionRequest{Name: ver.Name, Etag: ver.Etag})
if err != nil {
return err
}
}
return nil
}