-
Notifications
You must be signed in to change notification settings - Fork 3
/
config.go
119 lines (98 loc) · 3.75 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
package snowflake
import (
"crypto/rsa"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"strings"
"time"
"github.com/snowflakedb/gosnowflake"
"github.com/youmark/pkcs8"
)
type Config struct {
Account string `json:"account"`
Warehouse string `json:"warehouse"`
DBName string `json:"dbname"`
User string `json:"user"`
Schema string `json:"schema"`
Role string `json:"role"`
Password string `json:"password"`
UseKeyPairAuth bool `json:"useKeyPairAuth"`
PrivateKey string `json:"privateKey"`
PrivateKeyPassphrase string `json:"privateKeyPassphrase"`
Application string `json:"application"`
LoginTimeout time.Duration `json:"loginTimeout"` // default: 5m
KeepSessionAlive bool `json:"keepSessionAlive"`
UseLegacyMappings bool `json:"useLegacyMappings"`
QueryTag string `json:"queryTag"`
}
func (c Config) ConnectionString() (dsn string, err error) {
sc := gosnowflake.Config{
Authenticator: gosnowflake.AuthTypeSnowflake,
User: c.User,
Password: c.Password,
Account: c.Account,
Database: c.DBName,
Warehouse: c.Warehouse,
Schema: c.Schema,
Role: c.Role,
Application: c.Application,
LoginTimeout: c.LoginTimeout,
Params: make(map[string]*string),
}
if c.UseKeyPairAuth {
sc.Authenticator = gosnowflake.AuthTypeJwt
privateKey, err := c.ParsePrivateKey()
if err != nil {
return "", fmt.Errorf("parsing private key: %w", err)
}
sc.PrivateKey = privateKey
}
if c.KeepSessionAlive {
valueTrue := "true"
sc.Params["client_session_keep_alive"] = &valueTrue
}
if c.QueryTag != "" {
sc.Params["query_tag"] = &c.QueryTag
}
dsn, err = gosnowflake.DSN(&sc)
if err != nil {
err = fmt.Errorf("creating dsn: %v", err)
}
return
}
func (c *Config) Parse(configJSON json.RawMessage) error {
return json.Unmarshal(configJSON, c)
}
func (c *Config) ParsePrivateKey() (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(normalisePem(c.PrivateKey)))
if block == nil {
return nil, errors.New("decoding private key failed")
}
var opts [][]byte
if len(c.PrivateKeyPassphrase) > 0 {
opts = append(opts, []byte(c.PrivateKeyPassphrase))
}
rsaPrivateKey, err := pkcs8.ParsePKCS8PrivateKeyRSA(block.Bytes, opts...)
if err != nil {
return nil, fmt.Errorf("parsing private key: %w", err)
}
return rsaPrivateKey, nil
}
// normalisePem formats the content of certificates and keys by adding necessary newlines around specific markers.
func normalisePem(content string) string {
// Remove all existing newline characters and replace them with a space
formattedContent := strings.ReplaceAll(content, "\n", " ")
// Add a newline after specific BEGIN markers
formattedContent = strings.Replace(formattedContent, "-----BEGIN CERTIFICATE-----", "-----BEGIN CERTIFICATE-----\n", 1)
formattedContent = strings.Replace(formattedContent, "-----BEGIN RSA PRIVATE KEY-----", "-----BEGIN RSA PRIVATE KEY-----\n", 1)
formattedContent = strings.Replace(formattedContent, "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----BEGIN ENCRYPTED PRIVATE KEY-----\n", 1)
formattedContent = strings.Replace(formattedContent, "-----BEGIN PRIVATE KEY-----", "-----BEGIN PRIVATE KEY-----\n", 1)
// Add a newline before and after specific END markers
formattedContent = strings.Replace(formattedContent, "-----END CERTIFICATE-----", "\n-----END CERTIFICATE-----\n", 1)
formattedContent = strings.Replace(formattedContent, "-----END RSA PRIVATE KEY-----", "\n-----END RSA PRIVATE KEY-----\n", 1)
formattedContent = strings.Replace(formattedContent, "-----END ENCRYPTED PRIVATE KEY-----", "\n-----END ENCRYPTED PRIVATE KEY-----\n", 1)
formattedContent = strings.Replace(formattedContent, "-----END PRIVATE KEY-----", "\n-----END PRIVATE KEY-----\n", 1)
return formattedContent
}