-
Notifications
You must be signed in to change notification settings - Fork 0
/
tls.go
128 lines (108 loc) · 3.37 KB
/
tls.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
package auth
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"os"
)
type TLSConfig struct {
// 值为真表示是服务端 TLS 配置
// 值为假表示是客户端 TLS 配置
IsServerConfig bool
// 是否启用双向 TLS 认证
EnableMutualTLS bool
CertFile string
KeyFile string
CAFile string
ServerName string
}
var (
// server
errNoCertForServerTLSConfig = errors.New("no certificate provided for server (mutual) TLS config")
errNoPKeyForServerTLSConfig = errors.New("no private key provided for server (mutual) TLS config")
errNoCAForServerMuTLSConfig = errors.New("no root certificate provided for server mutual TLS config")
// client
errNoCertForClientMuTLSConfig = errors.New("no certificate provided for client mutual TLS config")
errNoPKeyForClientMuTLSConfig = errors.New("no private key provided for client mutual TLS config")
errNoCAForClientTLSConfig = errors.New("no root certificate provided for client (mutual) TLS config")
)
func SetupTLSConfig(cfg TLSConfig) (tlsConfig *tls.Config, err error) {
// 单向 TLS 认证
// 服务端需要设置: 服务端证书, 服务端私钥, 服务端名字
// 客户端需要设置: 根证书
// 双向 TLS 认证
// 服务端需要设置: 服务端证书, 服务端私钥, 服务端名字, 根证书
// 客户端需要设置: 客户端证书, 客户端私钥, 根证书
tlsConfig = &tls.Config{}
if cfg.IsServerConfig {
// 服务端 TLS 配置
// 不论是否开启双向 TLS 认证
// 服务端都需要提供自己的证书和私钥
if cfg.CertFile == "" {
return nil, errNoCertForServerTLSConfig
}
if cfg.KeyFile == "" {
return nil, errNoPKeyForServerTLSConfig
}
tlsConfig.Certificates = make([]tls.Certificate, 1)
tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
if err != nil {
return nil, err
}
// 不论是否开启双向 TLS 认证都需要设置服务端名字
tlsConfig.ServerName = cfg.ServerName
// 如果启用了双向 TLS 认证还需要提供根证书来认证客户端证书
if cfg.EnableMutualTLS {
if cfg.CAFile == "" {
return nil, errNoCAForServerMuTLSConfig
}
if ca, err := loadCA(cfg.CAFile); err != nil {
return nil, err
} else {
tlsConfig.ClientCAs = ca
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
}
return tlsConfig, nil
} else {
// 服务端 TLS 配置
// 不论是否开启双向 TLS 认证
// 客户端都需要提供根证书
if cfg.CAFile == "" {
return nil, errNoCAForClientTLSConfig
}
if ca, err := loadCA(cfg.CAFile); err != nil {
return nil, err
} else {
tlsConfig.RootCAs = ca
}
// 如果开启了双向 TLS 认证
// 客户端还需要提供自己的证书和私钥
if cfg.EnableMutualTLS {
if cfg.CertFile == "" {
return nil, errNoCertForClientMuTLSConfig
}
if cfg.KeyFile == "" {
return nil, errNoPKeyForClientMuTLSConfig
}
tlsConfig.Certificates = make([]tls.Certificate, 1)
tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
if err != nil {
return nil, err
}
}
return tlsConfig, nil
}
}
func loadCA(CAFile string) (*x509.CertPool, error) {
b, err := os.ReadFile(CAFile)
if err != nil {
return nil, err
}
ca := x509.NewCertPool()
if ok := ca.AppendCertsFromPEM(b); !ok {
return nil, fmt.Errorf("failed to parse root certificate: %q", CAFile)
}
return ca, nil
}