Initial commit (code only without large binaries)
This commit is contained in:
75
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_auth.go
Normal file
75
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_auth.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 认证类型
|
||||
type SSLClientAuthType = int
|
||||
|
||||
const (
|
||||
SSLClientAuthTypeNoClientCert SSLClientAuthType = 0
|
||||
SSLClientAuthTypeRequestClientCert SSLClientAuthType = 1
|
||||
SSLClientAuthTypeRequireAnyClientCert SSLClientAuthType = 2
|
||||
SSLClientAuthTypeVerifyClientCertIfGiven SSLClientAuthType = 3
|
||||
SSLClientAuthTypeRequireAndVerifyClientCert SSLClientAuthType = 4
|
||||
)
|
||||
|
||||
// 所有的客户端认证类型
|
||||
func AllSSLClientAuthTypes() []maps.Map {
|
||||
return []maps.Map{
|
||||
{
|
||||
"name": "不需要客户端证书",
|
||||
"type": SSLClientAuthTypeNoClientCert,
|
||||
"requireCA": false,
|
||||
},
|
||||
{
|
||||
"name": "请求客户端证书",
|
||||
"type": SSLClientAuthTypeRequestClientCert,
|
||||
"requireCA": true,
|
||||
},
|
||||
{
|
||||
"name": "需要客户端证书,但不校验",
|
||||
"type": SSLClientAuthTypeRequireAnyClientCert,
|
||||
"requireCA": true,
|
||||
},
|
||||
{
|
||||
"name": "有客户端证书的时候才校验",
|
||||
"type": SSLClientAuthTypeVerifyClientCertIfGiven,
|
||||
"requireCA": true,
|
||||
},
|
||||
{
|
||||
"name": "校验客户端提供的证书",
|
||||
"type": SSLClientAuthTypeRequireAndVerifyClientCert,
|
||||
"requireCA": true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 查找单个认证方式的名称
|
||||
func FindSSLClientAuthTypeName(authType SSLClientAuthType) string {
|
||||
for _, m := range AllSSLClientAuthTypes() {
|
||||
if m.GetInt("type") == authType {
|
||||
return m.GetString("name")
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 认证类型和tls包内类型的映射
|
||||
func GoSSLClientAuthType(authType SSLClientAuthType) tls.ClientAuthType {
|
||||
switch authType {
|
||||
case SSLClientAuthTypeNoClientCert:
|
||||
return tls.NoClientCert
|
||||
case SSLClientAuthTypeRequestClientCert:
|
||||
return tls.RequestClientCert
|
||||
case SSLClientAuthTypeRequireAnyClientCert:
|
||||
return tls.RequireAnyClientCert
|
||||
case SSLClientAuthTypeVerifyClientCertIfGiven:
|
||||
return tls.VerifyClientCertIfGiven
|
||||
case SSLClientAuthTypeRequireAndVerifyClientCert:
|
||||
return tls.RequireAndVerifyClientCert
|
||||
}
|
||||
return tls.NoClientCert
|
||||
}
|
||||
200
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_cert_config.go
Normal file
200
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_cert_config.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SSLCertConfig SSL证书
|
||||
type SSLCertConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Description string `yaml:"description" json:"description"` // 说明
|
||||
CertData []byte `yaml:"certData" json:"certData"` // 证书数据
|
||||
KeyData []byte `yaml:"keyData" json:"keyData"` // 密钥数据
|
||||
ServerName string `yaml:"serverName" json:"serverName"` // 证书使用的主机名,在请求TLS服务器时需要
|
||||
IsCA bool `yaml:"isCA" json:"isCA"` // 是否为CA证书
|
||||
IsACME bool `yaml:"isACME" json:"isACME"` // 是否通过ACME协议免费申请
|
||||
|
||||
// 以下是从证书中分析所得
|
||||
TimeBeginAt int64 `yaml:"timeBeginAt" json:"timeBeginAt"`
|
||||
TimeEndAt int64 `yaml:"timeEndAt" json:"timeEndAt"`
|
||||
DNSNames []string `yaml:"dnsNames" json:"dnsNames"`
|
||||
CommonNames []string `yaml:"commonNames" json:"commonNames"`
|
||||
|
||||
// OCSP
|
||||
OCSP []byte `yaml:"ocsp" json:"ocsp"`
|
||||
OCSPExpiresAt int64 `yaml:"ocspExpiresAt" json:"ocspExpiresAt"`
|
||||
OCSPError string `yaml:"ocspError" json:"ocspError"`
|
||||
|
||||
cert *tls.Certificate
|
||||
caCerts []*x509.Certificate
|
||||
timeBegin time.Time
|
||||
timeEnd time.Time
|
||||
}
|
||||
|
||||
// Init 校验
|
||||
func (this *SSLCertConfig) Init(ctx context.Context) error {
|
||||
// 如果没有指定数据, 则从ctx中读取数据
|
||||
if ctx != nil && len(this.CertData) < 128 {
|
||||
var dataMapOne = ctx.Value("DataMap")
|
||||
if dataMapOne != nil && !reflect.ValueOf(dataMapOne).IsNil() {
|
||||
dataMap, ok := dataMapOne.(*shared.DataMap)
|
||||
if !ok {
|
||||
return errors.New("SSLCertConfig.init(): invalid 'DataMap' in context")
|
||||
}
|
||||
if dataMap != nil { // 再次检查是否为nil
|
||||
this.KeyData = dataMap.Read(this.KeyData)
|
||||
this.CertData = dataMap.Read(this.CertData)
|
||||
this.OCSP = dataMap.Read(this.OCSP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var commonNames []string // 发行组织
|
||||
var dnsNames []string // 域名
|
||||
|
||||
this.caCerts = []*x509.Certificate{}
|
||||
|
||||
// 分析证书
|
||||
if this.IsCA { // CA证书
|
||||
var data = this.CertData
|
||||
|
||||
var index = -1
|
||||
this.cert = &tls.Certificate{
|
||||
Certificate: [][]byte{},
|
||||
}
|
||||
for {
|
||||
index++
|
||||
|
||||
block, rest := pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
this.cert.Certificate = append(this.cert.Certificate, block.Bytes)
|
||||
data = rest
|
||||
c, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c == nil {
|
||||
return errors.New("no available certificates in file")
|
||||
}
|
||||
this.caCerts = append(this.caCerts, c)
|
||||
|
||||
for _, dnsName := range c.DNSNames {
|
||||
if !lists.ContainsString(dnsNames, dnsName) {
|
||||
dnsNames = append(dnsNames, dnsName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ipAddress := range c.IPAddresses {
|
||||
if ipAddress == nil {
|
||||
continue
|
||||
}
|
||||
var ipAddressString = ipAddress.String()
|
||||
if !lists.ContainsString(dnsNames, ipAddressString) {
|
||||
dnsNames = append(dnsNames, ipAddressString)
|
||||
}
|
||||
}
|
||||
|
||||
commonNames = append(commonNames, c.Issuer.CommonName)
|
||||
|
||||
if index == 0 {
|
||||
this.timeBegin = c.NotBefore
|
||||
this.timeEnd = c.NotAfter
|
||||
}
|
||||
|
||||
if len(rest) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else { // 证书+私钥
|
||||
cert, err := tls.X509KeyPair(this.CertData, this.KeyData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load certificate '%s' failed: %w", strconv.FormatInt(this.Id, 10), err)
|
||||
}
|
||||
|
||||
for index, data := range cert.Certificate {
|
||||
c, err := x509.ParseCertificate(data)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if cert.Leaf == nil {
|
||||
cert.Leaf = c
|
||||
}
|
||||
|
||||
for _, dnsName := range c.DNSNames {
|
||||
if !lists.ContainsString(dnsNames, dnsName) {
|
||||
dnsNames = append(dnsNames, dnsName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ipAddress := range c.IPAddresses {
|
||||
if ipAddress == nil {
|
||||
continue
|
||||
}
|
||||
var ipAddressString = ipAddress.String()
|
||||
if !lists.ContainsString(dnsNames, ipAddressString) {
|
||||
dnsNames = append(dnsNames, ipAddressString)
|
||||
}
|
||||
}
|
||||
|
||||
commonNames = append(commonNames, c.Issuer.CommonName)
|
||||
|
||||
if index == 0 {
|
||||
this.timeBegin = c.NotBefore
|
||||
this.timeEnd = c.NotAfter
|
||||
}
|
||||
}
|
||||
|
||||
this.cert = &cert
|
||||
}
|
||||
|
||||
// 赋值分析结果
|
||||
this.DNSNames = dnsNames
|
||||
this.CommonNames = commonNames
|
||||
this.TimeBeginAt = this.timeBegin.Unix()
|
||||
this.TimeEndAt = this.timeEnd.Unix()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MatchDomain 校验是否匹配某个域名
|
||||
func (this *SSLCertConfig) MatchDomain(domain string) bool {
|
||||
if len(this.DNSNames) == 0 {
|
||||
return false
|
||||
}
|
||||
return configutils.MatchDomains(this.DNSNames, domain)
|
||||
}
|
||||
|
||||
// CertObject 获取证书对象
|
||||
func (this *SSLCertConfig) CertObject() *tls.Certificate {
|
||||
return this.cert
|
||||
}
|
||||
|
||||
func (this *SSLCertConfig) CACerts() []*x509.Certificate {
|
||||
return this.caCerts
|
||||
}
|
||||
|
||||
// TimeBegin 开始时间
|
||||
func (this *SSLCertConfig) TimeBegin() time.Time {
|
||||
return this.timeBegin
|
||||
}
|
||||
|
||||
// TimeEnd 结束时间
|
||||
func (this *SSLCertConfig) TimeEnd() time.Time {
|
||||
return this.timeEnd
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package sslconfigs_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSSLCertConfig_MatchDomain(t *testing.T) {
|
||||
var a = assert.NewAssertion(t)
|
||||
|
||||
var cert = &sslconfigs.SSLCertConfig{
|
||||
DNSNames: []string{"a.com", "b.com"},
|
||||
}
|
||||
a.IsTrue(cert.MatchDomain("a.com"))
|
||||
a.IsFalse(cert.MatchDomain("z.com"))
|
||||
}
|
||||
|
||||
/**func TestSSLCertConfig_DNSNames(t *testing.T) {
|
||||
var config = sslconfigs.SSLCertConfig{}
|
||||
config.CertData = []byte(`YOUR CERT DATA`)
|
||||
config.KeyData = []byte(`YOUR KEY DATA`)
|
||||
|
||||
err := config.Init(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(config.DNSNames)
|
||||
}**/
|
||||
6
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_cert_ref.go
Normal file
6
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_cert_ref.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package sslconfigs
|
||||
|
||||
type SSLCertRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
CertId int64 `yaml:"certId" json:"certId"`
|
||||
}
|
||||
143
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_consts.go
Normal file
143
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_consts.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
var AllTlsVersions = []TLSVersion{ /**"SSL 3.0",**/ "TLS 1.0", "TLS 1.1", "TLS 1.2", "TLS 1.3"}
|
||||
|
||||
var AllTLSCipherSuites = []TLSCipherSuite{
|
||||
"TLS_RSA_WITH_RC4_128_SHA",
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_AES_128_GCM_SHA256",
|
||||
"TLS_AES_256_GCM_SHA384",
|
||||
"TLS_CHACHA20_POLY1305_SHA256",
|
||||
}
|
||||
|
||||
var TLSModernCipherSuites = []string{
|
||||
"TLS_AES_128_GCM_SHA256",
|
||||
"TLS_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_AES_256_GCM_SHA384",
|
||||
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
}
|
||||
|
||||
var TLSIntermediateCipherSuites = []string{
|
||||
"TLS_AES_128_GCM_SHA256",
|
||||
"TLS_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_AES_256_GCM_SHA384",
|
||||
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
}
|
||||
|
||||
func (this *SSLPolicy) convertMinVersion() {
|
||||
switch this.MinVersion {
|
||||
case "SSL 3.0":
|
||||
this.minVersion = tls.VersionSSL30
|
||||
case "TLS 1.0":
|
||||
this.minVersion = tls.VersionTLS10
|
||||
case "TLS 1.1":
|
||||
this.minVersion = tls.VersionTLS11
|
||||
case "TLS 1.2":
|
||||
this.minVersion = tls.VersionTLS12
|
||||
case "TLS 1.3":
|
||||
this.minVersion = tls.VersionTLS13
|
||||
default:
|
||||
this.minVersion = tls.VersionTLS10
|
||||
}
|
||||
}
|
||||
|
||||
func (this *SSLPolicy) initCipherSuites() {
|
||||
// cipher suites
|
||||
suites := []uint16{}
|
||||
for _, suite := range this.CipherSuites {
|
||||
switch suite {
|
||||
case "TLS_RSA_WITH_RC4_128_SHA":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_RC4_128_SHA)
|
||||
case "TLS_RSA_WITH_3DES_EDE_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA)
|
||||
case "TLS_RSA_WITH_AES_128_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_AES_128_CBC_SHA)
|
||||
case "TLS_RSA_WITH_AES_256_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_AES_256_CBC_SHA)
|
||||
case "TLS_RSA_WITH_AES_128_CBC_SHA256":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_AES_128_CBC_SHA256)
|
||||
case "TLS_RSA_WITH_AES_128_GCM_SHA256":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_AES_128_GCM_SHA256)
|
||||
case "TLS_RSA_WITH_AES_256_GCM_SHA384":
|
||||
suites = append(suites, tls.TLS_RSA_WITH_AES_256_GCM_SHA384)
|
||||
case "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA)
|
||||
case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
|
||||
case "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
|
||||
case "TLS_ECDHE_RSA_WITH_RC4_128_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA)
|
||||
case "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
|
||||
case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
|
||||
case "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
|
||||
case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
|
||||
case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
|
||||
case "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
||||
case "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
|
||||
case "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
|
||||
case "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||
case "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305":
|
||||
suites = append(suites, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305)
|
||||
case "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305":
|
||||
suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305)
|
||||
case "TLS_AES_128_GCM_SHA256":
|
||||
suites = append(suites, tls.TLS_AES_128_GCM_SHA256)
|
||||
case "TLS_AES_256_GCM_SHA384":
|
||||
suites = append(suites, tls.TLS_AES_256_GCM_SHA384)
|
||||
case "TLS_CHACHA20_POLY1305_SHA256":
|
||||
suites = append(suites, tls.TLS_CHACHA20_POLY1305_SHA256)
|
||||
}
|
||||
}
|
||||
this.cipherSuites = suites
|
||||
}
|
||||
63
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_hsts.go
Normal file
63
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_hsts.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HSTS设置
|
||||
// 参考: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
|
||||
type HSTSConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
MaxAge int `yaml:"maxAge" json:"maxAge"` // 单位秒
|
||||
IncludeSubDomains bool `yaml:"includeSubDomains" json:"includeSubDomains"`
|
||||
Preload bool `yaml:"preload" json:"preload"`
|
||||
Domains []string `yaml:"domains" json:"domains"`
|
||||
|
||||
hasDomains bool
|
||||
headerValue string
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HSTSConfig) Init() error {
|
||||
this.hasDomains = len(this.Domains) > 0
|
||||
this.headerValue = this.asHeaderValue()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断是否匹配域名
|
||||
func (this *HSTSConfig) Match(domain string) bool {
|
||||
if !this.hasDomains {
|
||||
return true
|
||||
}
|
||||
return configutils.MatchDomains(this.Domains, domain)
|
||||
}
|
||||
|
||||
// Header Key
|
||||
func (this *HSTSConfig) HeaderKey() string {
|
||||
return "Strict-Transport-Security"
|
||||
}
|
||||
|
||||
// 取得当前的Header值
|
||||
func (this *HSTSConfig) HeaderValue() string {
|
||||
return this.headerValue
|
||||
}
|
||||
|
||||
// 转换为Header值
|
||||
func (this *HSTSConfig) asHeaderValue() string {
|
||||
b := strings.Builder{}
|
||||
b.WriteString("max-age=")
|
||||
if this.MaxAge > 0 {
|
||||
b.WriteString(strconv.Itoa(this.MaxAge))
|
||||
} else {
|
||||
b.WriteString("31536000") // 1 year
|
||||
}
|
||||
if this.IncludeSubDomains {
|
||||
b.WriteString("; includeSubDomains")
|
||||
}
|
||||
if this.Preload {
|
||||
b.WriteString("; preload")
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
60
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_hsts_test.go
Normal file
60
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_hsts_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHSTSConfig(t *testing.T) {
|
||||
h := &HSTSConfig{}
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(h.HeaderValue())
|
||||
|
||||
h.IncludeSubDomains = true
|
||||
err = h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(h.HeaderValue())
|
||||
|
||||
h.Preload = true
|
||||
err = h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(h.HeaderValue())
|
||||
|
||||
h.IncludeSubDomains = false
|
||||
err = h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(h.HeaderValue())
|
||||
|
||||
h.MaxAge = 86400
|
||||
err = h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(h.HeaderValue())
|
||||
|
||||
a := assert.NewAssertion(t)
|
||||
a.IsTrue(h.Match("abc.com"))
|
||||
|
||||
h.Domains = []string{"abc.com"}
|
||||
err = h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsTrue(h.Match("abc.com"))
|
||||
|
||||
h.Domains = []string{"1.abc.com"}
|
||||
err = h.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsFalse(h.Match("abc.com"))
|
||||
}
|
||||
261
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_policy.go
Normal file
261
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_policy.go
Normal file
@@ -0,0 +1,261 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"golang.org/x/net/http2"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TLSVersion TLS Version
|
||||
type TLSVersion = string
|
||||
|
||||
// TLSCipherSuite Cipher Suites
|
||||
type TLSCipherSuite = string
|
||||
|
||||
// SSLPolicy SSL配置
|
||||
type SSLPolicy struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||||
|
||||
CertRefs []*SSLCertRef `yaml:"certRefs" json:"certRefs"`
|
||||
Certs []*SSLCertConfig `yaml:"certs" json:"certs"`
|
||||
ClientAuthType SSLClientAuthType `yaml:"clientAuthType" json:"clientAuthType"` // 客户端认证类型
|
||||
ClientCARefs []*SSLCertRef `yaml:"clientCARefs" json:"clientCARefs"` // 客户端认证CA证书引用
|
||||
ClientCACerts []*SSLCertConfig `yaml:"clientCACerts" json:"clientCACerts"` // 客户端认证CA
|
||||
|
||||
MinVersion TLSVersion `yaml:"minVersion" json:"minVersion"` // 支持的最小版本
|
||||
CipherSuitesIsOn bool `yaml:"cipherSuitesIsOn" json:"cipherSuitesIsOn"` // 是否自定义加密算法套件
|
||||
CipherSuites []TLSCipherSuite `yaml:"cipherSuites" json:"cipherSuites"` // 加密算法套件
|
||||
|
||||
HSTS *HSTSConfig `yaml:"hsts" json:"hsts"` // HSTS配置
|
||||
HTTP2Enabled bool `yaml:"http2Enabled" json:"http2Enabled"` // 是否启用HTTP/2
|
||||
HTTP3Enabled bool `yaml:"http3Enabled" json:"http3Enabled"` // 是否启用HTTP/3
|
||||
|
||||
OCSPIsOn bool `yaml:"ocspIsOn" json:"ocspIsOn"` // 是否启用OCSP
|
||||
|
||||
nameMapping map[string]*tls.Certificate // dnsName => cert
|
||||
|
||||
minVersion uint16
|
||||
cipherSuites []uint16
|
||||
|
||||
clientCAPool *x509.CertPool
|
||||
|
||||
tlsConfig *tls.Config
|
||||
|
||||
ocspExpiresAt int64 // OCSP最早过期时间
|
||||
}
|
||||
|
||||
// Init 校验配置
|
||||
func (this *SSLPolicy) Init(ctx context.Context) error {
|
||||
this.nameMapping = map[string]*tls.Certificate{}
|
||||
|
||||
// certs
|
||||
var certs = []tls.Certificate{}
|
||||
for _, cert := range this.Certs {
|
||||
err := cert.Init(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if this.OCSPIsOn && len(cert.OCSP) > 0 && cert.OCSPExpiresAt > time.Now().Unix() {
|
||||
if this.ocspExpiresAt == 0 || cert.OCSPExpiresAt < this.ocspExpiresAt {
|
||||
this.ocspExpiresAt = cert.OCSPExpiresAt
|
||||
}
|
||||
cert.CertObject().OCSPStaple = cert.OCSP
|
||||
}
|
||||
certs = append(certs, *cert.CertObject())
|
||||
for _, dnsName := range cert.DNSNames {
|
||||
this.nameMapping[dnsName] = cert.CertObject()
|
||||
}
|
||||
}
|
||||
|
||||
// CA certs
|
||||
this.clientCAPool = x509.NewCertPool()
|
||||
|
||||
for _, cert := range this.ClientCACerts {
|
||||
err := cert.Init(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certs = append(certs, *cert.CertObject())
|
||||
for _, dnsName := range cert.DNSNames {
|
||||
this.nameMapping[dnsName] = cert.CertObject()
|
||||
}
|
||||
|
||||
for _, caCert := range cert.CACerts() {
|
||||
this.clientCAPool.AddCert(caCert)
|
||||
}
|
||||
}
|
||||
|
||||
// min version
|
||||
this.convertMinVersion()
|
||||
|
||||
// cipher suite categories
|
||||
this.initCipherSuites()
|
||||
|
||||
// hsts
|
||||
if this.HSTS != nil {
|
||||
err := this.HSTS.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// tls config
|
||||
this.tlsConfig = &tls.Config{}
|
||||
cipherSuites := this.TLSCipherSuites()
|
||||
if !this.CipherSuitesIsOn || len(cipherSuites) == 0 {
|
||||
cipherSuites = nil
|
||||
}
|
||||
|
||||
var nextProto = []string{}
|
||||
if this.HTTP2Enabled {
|
||||
nextProto = []string{http2.NextProtoTLS}
|
||||
}
|
||||
this.tlsConfig = &tls.Config{
|
||||
Certificates: certs,
|
||||
MinVersion: this.TLSMinVersion(),
|
||||
CipherSuites: cipherSuites,
|
||||
GetCertificate: nil,
|
||||
ClientAuth: GoSSLClientAuthType(this.ClientAuthType),
|
||||
ClientCAs: this.CAPool(),
|
||||
NextProtos: nextProto,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TLSMinVersion 取得最小版本
|
||||
func (this *SSLPolicy) TLSMinVersion() uint16 {
|
||||
return this.minVersion
|
||||
}
|
||||
|
||||
// TLSCipherSuites 套件
|
||||
func (this *SSLPolicy) TLSCipherSuites() []uint16 {
|
||||
return this.cipherSuites
|
||||
}
|
||||
|
||||
// MatchDomain 校验是否匹配某个域名
|
||||
func (this *SSLPolicy) MatchDomain(domain string) (cert *tls.Certificate, ok bool) {
|
||||
cert, ok = this.nameMapping[domain]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
for name, cert := range this.nameMapping {
|
||||
if configutils.MatchDomain(name, domain) {
|
||||
return cert, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// FirstCert 取得第一个证书
|
||||
func (this *SSLPolicy) FirstCert() *tls.Certificate {
|
||||
for _, cert := range this.Certs {
|
||||
return cert.CertObject()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CAPool CA证书Pool,用于TLS对客户端进行认证
|
||||
func (this *SSLPolicy) CAPool() *x509.CertPool {
|
||||
return this.clientCAPool
|
||||
}
|
||||
|
||||
func (this *SSLPolicy) TLSConfig() *tls.Config {
|
||||
return this.tlsConfig
|
||||
}
|
||||
|
||||
// ContainsCert 检查是否包括某个证书
|
||||
func (this *SSLPolicy) ContainsCert(certId int64) bool {
|
||||
for _, cert := range this.Certs {
|
||||
if cert.Id == certId {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// UpdateCertOCSP 修改某个证书的OCSP
|
||||
func (this *SSLPolicy) UpdateCertOCSP(certId int64, ocsp []byte, expiresAt int64) {
|
||||
var nowTime = time.Now().Unix()
|
||||
|
||||
for _, cert := range this.Certs {
|
||||
if cert.Id == certId {
|
||||
cert.OCSP = ocsp
|
||||
cert.OCSPExpiresAt = expiresAt
|
||||
cert.CertObject().OCSPStaple = cert.OCSP
|
||||
|
||||
// 修改tlsConfig中的cert
|
||||
for index, certObj := range this.tlsConfig.Certificates {
|
||||
if this.certIsEqual(*cert.CertObject(), certObj) {
|
||||
if len(cert.OCSP) > 0 && cert.OCSPExpiresAt > nowTime {
|
||||
this.tlsConfig.Certificates[index].OCSPStaple = ocsp
|
||||
|
||||
// 重置过期时间
|
||||
if this.ocspExpiresAt == 0 || cert.OCSPExpiresAt < this.ocspExpiresAt {
|
||||
this.ocspExpiresAt = cert.OCSPExpiresAt
|
||||
}
|
||||
} else {
|
||||
this.tlsConfig.Certificates[index].OCSPStaple = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckOCSP 检查OCSP过期时间
|
||||
func (this *SSLPolicy) CheckOCSP() {
|
||||
if !this.OCSPIsOn || this.ocspExpiresAt == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var nowTime = time.Now().Unix()
|
||||
if this.ocspExpiresAt > nowTime {
|
||||
return
|
||||
}
|
||||
this.ocspExpiresAt = 0
|
||||
|
||||
for _, cert := range this.Certs {
|
||||
if cert.OCSPExpiresAt > 0 && cert.OCSPExpiresAt < nowTime+1 {
|
||||
// 重置OCSP
|
||||
cert.OCSP = nil
|
||||
cert.OCSPExpiresAt = 0
|
||||
for index, certObj := range this.tlsConfig.Certificates {
|
||||
if this.certIsEqual(*cert.CertObject(), certObj) {
|
||||
this.tlsConfig.Certificates[index].OCSPStaple = nil
|
||||
}
|
||||
}
|
||||
} else if len(cert.OCSP) > 0 && cert.OCSPExpiresAt > nowTime && (this.ocspExpiresAt == 0 || cert.OCSPExpiresAt < this.ocspExpiresAt) {
|
||||
// 重置过期时间
|
||||
this.ocspExpiresAt = cert.OCSPExpiresAt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OcspExpiresAt OCSP最近过期时间
|
||||
func (this *SSLPolicy) OcspExpiresAt() int64 {
|
||||
return this.ocspExpiresAt
|
||||
}
|
||||
|
||||
func (this *SSLPolicy) certIsEqual(cert1 tls.Certificate, cert2 tls.Certificate) bool {
|
||||
var b1 = cert1.Certificate
|
||||
var b2 = cert2.Certificate
|
||||
if len(b1) != len(b2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for index, b := range b1 {
|
||||
if !bytes.Equal(b, b2[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package sslconfigs
|
||||
|
||||
type SSLPolicyRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
SSLPolicyId int64 `yaml:"sslPolicyId" json:"sslPolicyId"`
|
||||
}
|
||||
134
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_policy_test.go
Normal file
134
EdgeCommon/pkg/serverconfigs/sslconfigs/ssl_policy_test.go
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package sslconfigs_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSSLPolicy_MatchDomain(t *testing.T) {
|
||||
var a = assert.NewAssertion(t)
|
||||
|
||||
var policy = &sslconfigs.SSLPolicy{}
|
||||
policy.Certs = []*sslconfigs.SSLCertConfig{
|
||||
{
|
||||
Id: 1,
|
||||
DNSNames: []string{"a.com", "b.com"},
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
DNSNames: []string{"c.com", "d.com"},
|
||||
},
|
||||
{
|
||||
Id: 3,
|
||||
DNSNames: []string{"e.com", "f.com"},
|
||||
},
|
||||
}
|
||||
|
||||
{
|
||||
_, ok := policy.MatchDomain("c.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSLPolicy_CheckOCSP(t *testing.T) {
|
||||
var certData = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIEcTCCA9qgAwIBAgIDbhMuMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJD
|
||||
TjESMBAGA1UECBMJR3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UE
|
||||
ChMHVGVuY2VudDEMMAoGA1UECxMDV1hHMRMwEQYDVQQDEwpNbXBheW1jaENBMR8w
|
||||
HQYJKoZIhvcNAQkBFhBtbXBheW1jaEB0ZW5jZW50MB4XDTE2MTIxMjA5NDAwM1oX
|
||||
DTI2MTIxMDA5NDAwM1owgaExCzAJBgNVBAYTAkNOMRIwEAYDVQQIEwlHdWFuZ2Rv
|
||||
bmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdUZW5jZW50MQ4wDAYDVQQL
|
||||
EwVNTVBheTE2MDQGA1UEAxQt5YyX5Lqs5LiJ55m+5YWt5Y2B6KGM5LqS6IGU56eR
|
||||
5oqA5pyJ6ZmQ5YWs5Y+4MREwDwYDVQQEEwgxNzIyNzc0NDCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBAN2/1axdFhLKgMAGpkM9kpBfz88IvVYLFLaRrsIO
|
||||
aM4RLDup5ye0GrOvQtq8gvPFbn+GuekyBfoVRNHW1OSv/uQfDYd5tcmAy/0BDZSL
|
||||
OfPHaYOS2fj2y9KvLZTFTMBszG9kwV/FFlHgK4SJKbikdqTPd9vnt6Yr7FyfTIws
|
||||
K9RQ77vetOTduWZttON+RK/Tlz6AepiVfl9LZ/XOVveYI/6TfEbI6uUoeXrlSKCf
|
||||
w8/yfo69tcZV0g9yjSnVYDvgp6BFXJ1QK1CnJB4Dnol8XoBgUIrUyJqO+LvPr2Qy
|
||||
wsnyONc15AJK/23vebDGGvTvYtu47qRywISD4ioW15YBK1UCAwEAAaOCAUYwggFC
|
||||
MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHSJDRVMtQ0EgR2VuZXJhdGUgQ2Vy
|
||||
dGlmaWNhdGUiMB0GA1UdDgQWBBQVQCAalLY0TuS+z80biOcWb0QkzjCBvwYDVR0j
|
||||
BIG3MIG0gBQ+BSb2ImK0FVuIzWR+sNRip+WGdKGBkKSBjTCBijELMAkGA1UEBhMC
|
||||
Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
|
||||
BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
|
||||
MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudIIJALtUlyu8AOhXMA4GA1Ud
|
||||
DwEB/wQEAwIGwDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQUF
|
||||
AAOBgQA/Zr9PIRE8c3mAnb0lmx/DToFJrUB4Sr51szjiX5XiKymBoC2hnwJvI+7B
|
||||
EkRdNv4S7rvu33GS7BcZvjEwyrZdA9ZRIQz1MiaBIXdayIkkUCxaStB1junI8Jfc
|
||||
dG6S+JIMJU8y0tG53vEG2JRw8Mmm1qloAxs1Zl92UtlZoiHHCQ==
|
||||
-----END CERTIFICATE-----
|
||||
`)
|
||||
var keyData = []byte(`-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdv9WsXRYSyoDA
|
||||
BqZDPZKQX8/PCL1WCxS2ka7CDmjOESw7qecntBqzr0LavILzxW5/hrnpMgX6FUTR
|
||||
1tTkr/7kHw2HebXJgMv9AQ2Uiznzx2mDktn49svSry2UxUzAbMxvZMFfxRZR4CuE
|
||||
iSm4pHakz3fb57emK+xcn0yMLCvUUO+73rTk3blmbbTjfkSv05c+gHqYlX5fS2f1
|
||||
zlb3mCP+k3xGyOrlKHl65Uign8PP8n6OvbXGVdIPco0p1WA74KegRVydUCtQpyQe
|
||||
A56JfF6AYFCK1Miajvi7z69kMsLJ8jjXNeQCSv9t73mwxhr072LbuO6kcsCEg+Iq
|
||||
FteWAStVAgMBAAECggEAVkqTfMqQj2lsJs2vn5TzVulh9cAB5dzUB6OzbOKsmBwI
|
||||
qYMZZ9LnXSsDihk3oGMg99FWwU9tEf9602mVWRS/zMfkvOZ4/lv3hZIGVdrEB4B/
|
||||
J+talU58zJTM2QraLjtoZqS/t2P7porkhGPX73lYjhQKIXIPfkOza+u1nwqFV84Z
|
||||
YowiRTowuBHAAduW7W5uv4MaGG6P9w/JzR4zHCUjc5rnh/3a3+TN6KRxkXDh+1yi
|
||||
6wg0S54qtTyAEIeGMjIqhzUgN0fxlhyMgtROi8h3DN/tvBoOCT9jGFeTsBcfk6Ib
|
||||
p4sMDo/OcC1NXsENsccVprH297jKmwV0vZFGUebPAQKBgQD9bfrWU0TvLlLILJmT
|
||||
52HRy6HCddKV6SdCBF04Rz3a5L32epKREql6l8KewHo05wlty90UL4sltHwZo9h6
|
||||
QuukNMMuLvaye2qOAkuFw1x5qD4R2VvbQsPDHoJt0zOzzF77/Faob+3NSHk9Yt3h
|
||||
s7/LrU9vDfoPVROMatJR01XzFQKBgQDf/5kofDYQ/qcddosktkgxIyZBFuE4C/s+
|
||||
nhiXl/Kd5Q+AP2o6kPsl5o4Jz2s3zBrmyRb733Zhb/rx/gbebTvqLjrTpyxXovmQ
|
||||
8ecKeAS+IlrvAEDDT4c6ecAXR4zHZER00g0zbL4sX+fpKzON+jL6poA/el4MQySR
|
||||
/DLJUx1nQQKBgQCLNQFG/2BrPXfNaupFWyDZW9CT/6JYJEUjN0B5bHCmr2VFYdjm
|
||||
hWjA5WHLUBEQxCPiwsvCjccSRAyzDNQZfG7xuOXJlZR/P9ms/ce8Ry6hyO+nYEzb
|
||||
qNXddQHSD+RjjAxUwCxdw3XNgFTQimE03EarO5zZdMT57RKa3AaBWePpbQKBgQCq
|
||||
D4fcMNFrfaqqt8FUEgAlLiZw7En5Hz+Ufrr0/Kt6LNnj6EFiTYgfcjcMQ6mHJzKV
|
||||
XL5SY4mg2D+RUectH4mJdae74QPNVTJcVQuv6wbOw45+PZbtsYddYenwwqWjDADd
|
||||
IExdaoXHctjDMcVmWTozCg38I48biC5Pl0WHi86bAQKBgGBK6XUJPRYOsQFshunq
|
||||
edxSbZBiYFDUj6SfOdaTSuU61KOWRTXJyuOBaB77usmZdwOrB4vy1XUT1uuPWKlx
|
||||
SKmNoe/mk2xYiGdKvFDRRHh25zCxDWsQ2nMQfUFczTZ9wBwGs40wzm36fSgHZybq
|
||||
Z3NIV2eNt6YBwkC69DzdazXT
|
||||
-----END PRIVATE KEY-----
|
||||
`)
|
||||
|
||||
var policy = &sslconfigs.SSLPolicy{
|
||||
OCSPIsOn: true,
|
||||
}
|
||||
|
||||
var nowTime = time.Now().Unix()
|
||||
|
||||
policy.Certs = append(policy.Certs, &sslconfigs.SSLCertConfig{
|
||||
Id: 1,
|
||||
CertData: certData,
|
||||
KeyData: keyData,
|
||||
OCSP: []byte("ocsp"),
|
||||
OCSPExpiresAt: nowTime + 1,
|
||||
})
|
||||
policy.Certs = append(policy.Certs, &sslconfigs.SSLCertConfig{
|
||||
Id: 1,
|
||||
CertData: certData,
|
||||
KeyData: keyData,
|
||||
OCSP: []byte("ocsp"),
|
||||
OCSPExpiresAt: nowTime + 3,
|
||||
})
|
||||
policy.Certs = append(policy.Certs, &sslconfigs.SSLCertConfig{
|
||||
Id: 1,
|
||||
CertData: certData,
|
||||
KeyData: keyData,
|
||||
OCSP: []byte("ocsp"),
|
||||
OCSPExpiresAt: nowTime + 2,
|
||||
})
|
||||
|
||||
err := policy.Init(context.TODO())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(policy.OcspExpiresAt(), policy.OcspExpiresAt() == nowTime+1)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
policy.CheckOCSP()
|
||||
t.Log(policy.OcspExpiresAt(), policy.OcspExpiresAt() == nowTime+2)
|
||||
}
|
||||
Reference in New Issue
Block a user