/
tlsconfig.go
136 lines (117 loc) · 3.88 KB
/
tlsconfig.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
/*
Copyright Idea LCC. All Rights Reserved.
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: [Default license](LICENSE)
*/
package vaultconnector
import (
"crypto/x509"
"encoding/pem"
"fmt"
"regexp"
"strings"
"github.com/anoideaopen/cartridge/cryptocache"
"github.com/pkg/errors"
)
// IsTLSEnabled is a generic function that expects a URL and verifies if it has
// a prefix HTTPS or GRPCS to return true for TLS Enabled URLs or false otherwise
func IsTLSEnabled(url string) bool {
tlsURL := strings.ToLower(url)
if strings.HasPrefix(tlsURL, "https://") || strings.HasPrefix(tlsURL, "grpcs://") {
return true
}
return false
}
// ToAddress is a utility function to trim the GRPC protocol prefix as it is not needed by GO
// if the GRPC protocol is not found, the url is returned unchanged
func ToAddress(url string) string {
if strings.HasPrefix(url, "grpc://") {
return strings.TrimPrefix(url, "grpc://")
}
if strings.HasPrefix(url, "grpcs://") {
return strings.TrimPrefix(url, "grpcs://")
}
return url
}
// AttemptSecured is a utility function which verifies URL and returns if secured connections needs to established
// for protocol 'grpcs' in URL returns true
// for protocol 'grpc' in URL returns false
// for no protocol mentioned, returns !allowInSecure
func AttemptSecured(url string, allowInSecure bool) bool {
ok, err := regexp.MatchString(".*(?i)s://", url)
if ok && err == nil {
return true
}
if strings.Contains(url, "://") {
return false
}
return !allowInSecure
}
// MutualTLSConfig Mutual TLS configurations
type MutualTLSConfig struct {
Pem []string
// Certfiles root certificates for TLS validation (Comma separated path list)
Path string
// Client TLS information
Client TLSKeyPair
}
// TLSKeyPair contains the private key and certificate for TLS encryption
type TLSKeyPair struct {
Key TLSConfig
Cert TLSConfig
}
// TLSConfig TLS configuration used in the sdk's configs.
type TLSConfig struct {
// the following two fields are interchangeable.
// If Path is available, then it will be used to load the cert
// if Pem is available, then it has the raw data of the cert it will be used as-is
// Certificate root certificate path
// If both Path and Pem are available, pem takes the precedence
Path string
// Certificate actual content
Pem string
// bytes from Pem/Path
bytes []byte
}
// Bytes returns the tls certificate as a byte array
func (cfg *TLSConfig) Bytes() []byte {
return cfg.bytes
}
// LoadBytes preloads bytes from Pem/Path
// Pem takes precedence over Path
//
//nolint:nestif
func (cfg *TLSConfig) LoadBytes(cache cryptocache.CryptoCache) error {
if cfg.Pem != "" {
cfg.bytes = []byte(cfg.Pem)
} else if cfg.Path != "" {
cryptoname := strings.Split(cfg.Path, "/")
var err error
if strings.Contains(cfg.Path, "/tls/") {
if len(cryptoname) == 3 { //nolint:gomnd
cfg.bytes, err = cache.GetCrypto(fmt.Sprintf("%s/%s/%s", cryptoname[len(cryptoname)-3], cryptoname[len(cryptoname)-2], cryptoname[len(cryptoname)-1])) // username@org/tls/cryptoname
} else {
cfg.bytes, err = cache.GetCrypto(fmt.Sprintf("%s/%s", cryptoname[len(cryptoname)-2], cryptoname[len(cryptoname)-1])) // tls/cryptoname
}
} else if strings.Contains(cfg.Path, "/tlscacerts/") {
cfg.bytes, err = cache.GetCrypto(cryptoname[len(cryptoname)-1]) // cryptoname
}
if err != nil {
return errors.Wrapf(err, "failed to load pem bytes from path %s", cfg.Path)
}
}
return nil
}
// TLSCert returns the tls certificate as a *x509.Certificate by loading it either from the embedded Pem or Path
func (cfg *TLSConfig) TLSCert() (*x509.Certificate, bool, error) {
block, _ := pem.Decode(cfg.bytes)
if block != nil {
pub, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, false, errors.Wrap(err, "certificate parsing failed")
}
return pub, true, nil
}
// no cert found and there is no error
return nil, false, nil
}