-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
155 lines (124 loc) · 3.54 KB
/
main.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// A module to help with cryptographic requirements like encryption and hashing
package crypto
import (
"context"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"os"
"github.com/hashicorp/vault/api"
auth "github.com/hashicorp/vault/api/auth/approle"
)
// Read Env Vars
var vault_uri string = os.Getenv("VAULT_URI")
var vault_role_id string = os.Getenv("VAULT_ROLE_ID")
var vault_secret_id string = os.Getenv("VAULT_SECRET_ID")
var vault_approle_mountpath string = os.Getenv("VAULT_APPROLE_MOUNTPATH")
var vault_data_key_name string = os.Getenv("VAULT_DATA_KEY_NAME")
var encrypted_data_key string = os.Getenv("ENCRYPTED_DATA_KEY")
// Other Global Variables
var data_key []byte
var dataKeyCache map[string][]byte = map[string][]byte{}
// Vault functions
func getApproleAuth() *auth.AppRoleAuth {
// Check if vault_approle_mountpath has a value
if len(vault_approle_mountpath) == 0 {
vault_approle_mountpath = "approle-batch"
}
secretID := &auth.SecretID{
FromString: vault_secret_id,
}
appRoleAuth, err := auth.NewAppRoleAuth(vault_role_id, secretID, auth.WithMountPath(vault_approle_mountpath))
if err != nil {
return nil
}
return appRoleAuth
}
func getDataKey(encrypted_data_key_ string, clientId string) (data_key_ []byte) {
var cachedKeyPresent bool
if clientId != "" {
data_key_, cachedKeyPresent = dataKeyCache[clientId]
}
if cachedKeyPresent {
return
}
// If clientId is not provided, check if global data key is set (environment variable)
if len(data_key) != 0 && clientId == "" {
data_key_ = data_key
return
}
// If no cache value found, retrieve unencrypted data key value from vault
// Initialize vault client
config := &api.Config{
Address: vault_uri,
}
client, err := api.NewClient(config)
if err != nil {
return nil
}
// Initialize approle auth
appRoleAuth := getApproleAuth()
secret_, err := client.Auth().Login(context.TODO(), appRoleAuth)
if err != nil {
return nil
}
// TODO: make client object a singleton
// Initialize a lifetimewatcher to renew the token when it expires;
// this would make more sense if the above code is reused and not re-initialized everytime
client.NewLifetimeWatcher(&api.LifetimeWatcherInput{
Secret: secret_,
})
// Check if data key is passed as a parameter
var ciphertext string
var isGlobal bool = false
var vaultDataKeyName_ string
if encrypted_data_key_ != "" {
ciphertext = encrypted_data_key_
} else {
ciphertext = encrypted_data_key
isGlobal = true
}
if clientId != "" {
vaultDataKeyName_ = clientId
} else {
vaultDataKeyName_ = vault_data_key_name
}
// Decrypt the encrypted data key
data := map[string]interface{}{
"ciphertext": ciphertext,
}
secret, err := client.Logical().Write("/transit/decrypt/"+vaultDataKeyName_, data)
if err != nil {
return nil
}
// Set data_key_ to plaintext value
data_key_, err = base64.StdEncoding.DecodeString(secret.Data["plaintext"].(string))
if err != nil {
return nil
}
// Set clientId based cache
if clientId != "" {
dataKeyCache[clientId] = data_key_
}
// Set global data_key
if isGlobal {
data_key = data_key_
}
return
}
// Crypto functions
func newCipherAESGCMObject(data_key_b64_str string, clientId string) (gcm cipher.AEAD, err error) {
// Get data key
data_key := getDataKey(data_key_b64_str, clientId)
// Generate new aes cipher using our 32 byte key
c, err := aes.NewCipher(data_key)
if err != nil {
return
}
// GCM or Galois/Counter Mode, is a mode of operation for symmetric key cryptographic block ciphers
gcm, err = cipher.NewGCM(c)
if err != nil {
return
}
return
}