-
Notifications
You must be signed in to change notification settings - Fork 0
/
envloader.go
179 lines (154 loc) · 5.94 KB
/
envloader.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2021 Board of Trustees of the University of Illinois.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package envloader
import (
"encoding/base64"
"encoding/json"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/rokwire/logging-library-go/v2/logs"
"github.com/rokwire/logging-library-go/v2/logutils"
)
// -------------------- EnvLoader --------------------
// EnvLoader is an interface to assist with environment variable loading
type EnvLoader interface {
// GetEnvVar returns the environment variable value with the specified key
// If required and key is not found, a fatal log will be generated. Otherwise an empty string is returned
GetEnvVar(key string, required bool) string
// GetAndLogEnvVar returns and logs the environment variable value with the specified key
// If required and key is not found, a fatal log will be generated. Otherwise an empty string is returned
// If sensitive, the value of the environment variable will not be logged
GetAndLogEnvVar(key string, required bool, sensitive bool) string
}
// NewEnvLoader initializes and returns an EnvLoader, using AWSSecretsManagerEnvLoader if configured
func NewEnvLoader(version string, logger *logs.Logger) EnvLoader {
secretName := os.Getenv("APP_SECRET_ARN")
region := os.Getenv("AWS_REGION")
if secretName != "" && region != "" {
return NewAWSSecretsManagerEnvLoader(secretName, region, version, logger)
}
return NewLocalEnvLoader(version, logger)
}
// -------------------- LocalEnvLoader --------------------
// LocalEnvLoader is an EnvLoader implementation which loads variables from the local system environment
type LocalEnvLoader struct {
logger *logs.Logger
version string
}
// GetEnvVar implements EnvLoader
func (l *LocalEnvLoader) GetEnvVar(key string, required bool) string {
value, exist := os.LookupEnv(key)
if !exist {
if required {
l.logger.Fatal("No environment variable " + key)
} else {
l.logger.Error("No environment variable " + key)
}
}
return value
}
// GetAndLogEnvVar implements EnvLoader
func (l *LocalEnvLoader) GetAndLogEnvVar(key string, required bool, sensitive bool) string {
value := l.GetEnvVar(key, required)
logEnvVar(key, value, sensitive, l.version, l.logger)
return value
}
// NewLocalEnvLoader instantiates a new LocalEnvLoader instance
func NewLocalEnvLoader(version string, logger *logs.Logger) *LocalEnvLoader {
return &LocalEnvLoader{version: version, logger: logger}
}
// -------------------- AWSSecretsManagerEnvLoader --------------------
// AWSSecretsManagerEnvLoader is an EnvLoader implementation which loads variables from an AWS SecretsManager secret
type AWSSecretsManagerEnvLoader struct {
logger *logs.Logger
version string
secrets map[string]string
}
// GetEnvVar implements EnvLoader
func (a *AWSSecretsManagerEnvLoader) GetEnvVar(key string, required bool) string {
value, exist := a.secrets[key]
if !exist {
if required {
a.logger.Fatal("No environment variable " + key)
} else {
a.logger.Error("No environment variable " + key)
}
}
return value
}
// GetAndLogEnvVar implements EnvLoader
func (a *AWSSecretsManagerEnvLoader) GetAndLogEnvVar(key string, required bool, sensitive bool) string {
value := a.GetEnvVar(key, required)
logEnvVar(key, value, sensitive, a.version, a.logger)
return value
}
// NewAWSSecretsManagerEnvLoader instantiates a new AWSSecretsManagerEnvLoader instance
func NewAWSSecretsManagerEnvLoader(secretName string, region string, version string, logger *logs.Logger) *AWSSecretsManagerEnvLoader {
if secretName == "" {
logger.Fatal("Secret name cannot be empty")
}
if region == "" {
logger.Fatal("Region cannot be empty")
}
s, err := session.NewSession(&aws.Config{
Region: ®ion,
})
if err != nil {
logger.Fatalf("Error creating AWS session - SecretName: %s, Region: %s, Error: %v", secretName, region, err)
}
svc := secretsmanager.New(s)
input := &secretsmanager.GetSecretValueInput{
SecretId: aws.String(secretName),
VersionStage: aws.String("AWSCURRENT"),
}
result, err := svc.GetSecretValue(input)
if err != nil {
logger.Fatalf("Error loading secrets manager secret - Name: %s, Region: %s, Error: %v", secretName, region, err)
}
var secretConfigs map[string]string
var secretString, decodedBinarySecret string
if result.SecretString != nil {
secretString = *result.SecretString
err := json.Unmarshal([]byte(secretString), &secretConfigs)
if err != nil {
logger.Fatalf("Failed to unmarshal secrets: %v", err)
}
} else {
decodedBinarySecretBytes := make([]byte, base64.StdEncoding.DecodedLen(len(result.SecretBinary)))
len, err := base64.StdEncoding.Decode(decodedBinarySecretBytes, result.SecretBinary)
if err != nil {
logger.Fatalf("Secrets Base64 Decode Error: %v", err)
}
decodedBinarySecret = string(decodedBinarySecretBytes[:len])
err = json.Unmarshal([]byte(decodedBinarySecret), &secretConfigs)
if err != nil {
logger.Fatalf("Failed to unmarshal secrets: %v", err)
}
}
if secretConfigs == nil {
logger.Fatal("Secrets are nil")
}
return &AWSSecretsManagerEnvLoader{secrets: secretConfigs, version: version, logger: logger}
}
func logEnvVar(name string, value string, sensitive bool, version string, logger *logs.Logger) {
if version == "dev" {
if sensitive {
logger.InfoWithFields("ENV_VAR", logutils.Fields{"name": name})
} else {
logger.InfoWithFields("ENV_VAR", logutils.Fields{"name": name, "value": value})
}
}
}