forked from rigup/ephemeral-iam
/
config.go
162 lines (143 loc) · 4.8 KB
/
config.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
// Copyright 2021 Workrise Technologies Inc.
//
// 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 appconfig
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"sync"
"github.com/spf13/viper"
archutil "github.com/replit/ephemeral-iam/internal/appconfig/arch_util"
util "github.com/replit/ephemeral-iam/internal/eiamutil"
errorsutil "github.com/replit/ephemeral-iam/internal/errors"
)
// The configuration key names.
const (
AuthProxyAddress = "authproxy.proxyaddress"
AuthProxyPort = "authproxy.proxyport"
AuthProxyVerbose = "authproxy.verbose"
AuthProxyLogDir = "authproxy.logdir"
AuthProxyCertFile = "authproxy.certfile"
AuthProxyKeyFile = "authproxy.keyfile"
DefaultServiceAccounts = "serviceaccounts"
CloudSQLProxyPath = "binarypaths.cloudsqlproxy"
GcloudPath = "binarypaths.gcloud"
KubectlPath = "binarypaths.kubectl"
GithubAuth = "github.auth"
GithubTokens = "github.tokens" //nolint:gosec // Not hardcoded credentials
LoggingFormat = "logging.format"
LoggingLevel = "logging.level"
LoggingLevelTruncation = "logging.disableleveltruncation"
LoggingPadLevelText = "logging.padleveltext"
)
var (
configDir string
once sync.Once
binPaths = map[string]string{
CloudSQLProxyPath: "cloud_sql_proxy",
GcloudPath: "gcloud",
KubectlPath: "kubectl",
}
)
// InitConfig performs the initiatization of the users configuration file.
func InitConfig() error {
viper.SetConfigName("config")
viper.AddConfigPath(GetConfigDir())
viper.AutomaticEnv()
viper.SetConfigType("yml")
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
return errorsutil.New("Failed to initialize configuration", err)
}
initConfig()
}
// Instantiate logger now that the config is loaded.
util.Logger = util.NewLogger()
// Find the paths to gcloud, kubectl, and cloud_sql_proxy and write them to the config.
if err := getBinPaths(); err != nil {
return err
}
return nil
}
func initConfig() {
viper.SetDefault(AuthProxyAddress, "127.0.0.1")
viper.SetDefault(AuthProxyPort, "8084")
viper.SetDefault(AuthProxyVerbose, false)
viper.SetDefault(AuthProxyLogDir, filepath.Join(GetConfigDir(), "log"))
viper.SetDefault(AuthProxyCertFile, filepath.Join(GetConfigDir(), "server.pem"))
viper.SetDefault(AuthProxyKeyFile, filepath.Join(GetConfigDir(), "server.key"))
viper.SetDefault(GithubAuth, false)
viper.SetDefault(LoggingFormat, "text")
viper.SetDefault(LoggingLevel, "info")
viper.SetDefault(LoggingLevelTruncation, true)
viper.SetDefault(LoggingPadLevelText, true)
if err := viper.SafeWriteConfig(); err != nil {
if _, ok := err.(viper.ConfigFileAlreadyExistsError); !ok {
log.Fatalf("failed to write config file %s/config.yml: %v", GetConfigDir(), err)
}
}
}
func getBinPaths() error {
updated := false
for configKey, binName := range binPaths {
if viper.GetString(configKey) == "" {
updated = true
binPath, err := CheckCommandExists(binName)
if err != nil {
if configKey != CloudSQLProxyPath {
// Exit if kubectl or gcloud aren't installed, but continue if cloud_sql_proxy isn't.
return err
}
util.Logger.Debug("Could not find path to cloud_sql_proxy binary")
}
viper.Set(configKey, binPath)
}
}
if updated {
if err := viper.WriteConfig(); err != nil {
return errorsutil.New("Failed to write binary paths to configuration file", err)
}
}
return nil
}
// CheckCommandExists tries to find the location of a given binary.
func CheckCommandExists(command string) (string, error) {
cmdPath, err := exec.LookPath(command)
if err != nil {
return "", err
}
return cmdPath, nil
}
// GetConfigDir returns the directory to use for the ephemeral-iam configurations.
func GetConfigDir() string {
once.Do(func() {
dir, err := getConfigDir()
errorsutil.CheckError(err)
configDir = dir
})
return configDir
}
func getConfigDir() (string, error) {
userHomeDir, err := os.UserHomeDir()
if err != nil {
return "", errorsutil.New("Failed to get user's home directory", err)
}
confPath := filepath.Join(userHomeDir, archutil.ConfigPath)
if err = os.MkdirAll(confPath, 0o755); err != nil {
return "", errorsutil.New(fmt.Sprintf("Failed to create config directory: %s", confPath), err)
}
return confPath, nil
}