mirror of
https://github.com/ccfos/nightingale.git
synced 2026-03-02 22:19:10 +00:00
Compare commits
1 Commits
update-wor
...
prom-mtls
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02474818c0 |
@@ -293,11 +293,15 @@ func DatasourceCheck(c *gin.Context, ds models.Datasource) error {
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 TLS 配置(支持 mTLS)
|
||||
tlsConfig, err := ds.HTTPJson.TLS.TLSConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TLS config: %v", err)
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: ds.HTTPJson.TLS.SkipTlsVerify,
|
||||
},
|
||||
TLSClientConfig: tlsConfig,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -169,8 +168,15 @@ func (rt *Router) dsProxy(c *gin.Context) {
|
||||
|
||||
transport, has := transportGet(dsId, ds.UpdatedAt)
|
||||
if !has {
|
||||
// 使用 TLS 配置(支持 mTLS)
|
||||
tlsConfig, err := ds.HTTPJson.TLS.TLSConfig()
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "failed to create TLS config: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: ds.HTTPJson.TLS.SkipTlsVerify},
|
||||
TLSClientConfig: tlsConfig,
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: time.Duration(ds.HTTPJson.DialTimeout) * time.Millisecond,
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -144,6 +147,72 @@ func (h HTTP) ParseUrl() (target *url.URL, err error) {
|
||||
|
||||
type TLS struct {
|
||||
SkipTlsVerify bool `json:"skip_tls_verify"`
|
||||
// mTLS 配置
|
||||
CACert string `json:"ca_cert"` // CA 证书内容 (PEM 格式)
|
||||
ClientCert string `json:"client_cert"` // 客户端证书内容 (PEM 格式)
|
||||
ClientKey string `json:"client_key"` // 客户端密钥内容 (PEM 格式)
|
||||
ClientKeyPassword string `json:"client_key_password"` // 密钥密码(可选)
|
||||
ServerName string `json:"server_name"` // TLS ServerName(可选,用于证书验证)
|
||||
MinVersion string `json:"min_version"` // TLS 最小版本 (1.0, 1.1, 1.2, 1.3)
|
||||
MaxVersion string `json:"max_version"` // TLS 最大版本
|
||||
}
|
||||
|
||||
// TLSConfig 从证书内容创建 tls.Config
|
||||
// 证书内容为 PEM 格式字符串
|
||||
func (t *TLS) TLSConfig() (*tls.Config, error) {
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: t.SkipTlsVerify,
|
||||
}
|
||||
|
||||
// 设置 ServerName
|
||||
if t.ServerName != "" {
|
||||
tlsConfig.ServerName = t.ServerName
|
||||
}
|
||||
|
||||
// 设置 TLS 版本
|
||||
if t.MinVersion != "" {
|
||||
if v, ok := tlsVersionMap[t.MinVersion]; ok {
|
||||
tlsConfig.MinVersion = v
|
||||
}
|
||||
}
|
||||
if t.MaxVersion != "" {
|
||||
if v, ok := tlsVersionMap[t.MaxVersion]; ok {
|
||||
tlsConfig.MaxVersion = v
|
||||
}
|
||||
}
|
||||
|
||||
// 如果配置了客户端证书,则加载 mTLS 配置
|
||||
clientCert := strings.TrimSpace(t.ClientCert)
|
||||
clientKey := strings.TrimSpace(t.ClientKey)
|
||||
caCert := strings.TrimSpace(t.CACert)
|
||||
|
||||
if clientCert != "" && clientKey != "" {
|
||||
// 加载客户端证书和密钥
|
||||
cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load client certificate: %w", err)
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
|
||||
// 加载 CA 证书
|
||||
if caCert != "" {
|
||||
caCertPool := x509.NewCertPool()
|
||||
if !caCertPool.AppendCertsFromPEM([]byte(caCert)) {
|
||||
return nil, fmt.Errorf("failed to parse CA certificate")
|
||||
}
|
||||
tlsConfig.RootCAs = caCertPool
|
||||
}
|
||||
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
// tlsVersionMap TLS 版本映射
|
||||
var tlsVersionMap = map[string]uint16{
|
||||
"1.0": tls.VersionTLS10,
|
||||
"1.1": tls.VersionTLS11,
|
||||
"1.2": tls.VersionTLS12,
|
||||
"1.3": tls.VersionTLS13,
|
||||
}
|
||||
|
||||
func (ds *Datasource) TableName() string {
|
||||
|
||||
@@ -3,7 +3,7 @@ package prom
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/ccfos/nightingale/v6/pkg/tlsx"
|
||||
"github.com/ccfos/nightingale/v6/models"
|
||||
)
|
||||
|
||||
type PromOption struct {
|
||||
@@ -20,7 +20,8 @@ type PromOption struct {
|
||||
|
||||
Headers []string
|
||||
|
||||
tlsx.ClientConfig
|
||||
// TLS 配置(支持 mTLS)
|
||||
TLS models.TLS
|
||||
}
|
||||
|
||||
func (po *PromOption) Equal(target PromOption) bool {
|
||||
@@ -52,10 +53,6 @@ func (po *PromOption) Equal(target PromOption) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if po.InsecureSkipVerify != target.InsecureSkipVerify {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(po.Headers) != len(target.Headers) {
|
||||
return false
|
||||
}
|
||||
@@ -66,6 +63,29 @@ func (po *PromOption) Equal(target PromOption) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// 比较 TLS 配置
|
||||
if po.TLS.SkipTlsVerify != target.TLS.SkipTlsVerify {
|
||||
return false
|
||||
}
|
||||
if po.TLS.CACert != target.TLS.CACert {
|
||||
return false
|
||||
}
|
||||
if po.TLS.ClientCert != target.TLS.ClientCert {
|
||||
return false
|
||||
}
|
||||
if po.TLS.ClientKey != target.TLS.ClientKey {
|
||||
return false
|
||||
}
|
||||
if po.TLS.ServerName != target.TLS.ServerName {
|
||||
return false
|
||||
}
|
||||
if po.TLS.MinVersion != target.TLS.MinVersion {
|
||||
return false
|
||||
}
|
||||
if po.TLS.MaxVersion != target.TLS.MaxVersion {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -101,11 +101,7 @@ func (pc *PromClientMap) loadFromDatabase() {
|
||||
DialTimeout: ds.HTTPJson.DialTimeout,
|
||||
MaxIdleConnsPerHost: ds.HTTPJson.MaxIdleConnsPerHost,
|
||||
Headers: header,
|
||||
}
|
||||
|
||||
if strings.HasPrefix(ds.HTTPJson.Url, "https") {
|
||||
po.UseTLS = true
|
||||
po.InsecureSkipVerify = ds.HTTPJson.TLS.SkipTlsVerify
|
||||
TLS: ds.HTTPJson.TLS,
|
||||
}
|
||||
|
||||
if internalAddr != "" && !pc.ctx.IsCenter {
|
||||
@@ -149,7 +145,10 @@ func (pc *PromClientMap) loadFromDatabase() {
|
||||
}
|
||||
|
||||
func (pc *PromClientMap) newReaderClientFromPromOption(po PromOption) (api.Client, error) {
|
||||
tlsConfig, _ := po.TLSConfig()
|
||||
tlsConfig, err := po.TLS.TLSConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create TLS config: %v", err)
|
||||
}
|
||||
|
||||
return api.NewClient(api.Config{
|
||||
Address: po.Url,
|
||||
@@ -166,7 +165,10 @@ func (pc *PromClientMap) newReaderClientFromPromOption(po PromOption) (api.Clien
|
||||
}
|
||||
|
||||
func (pc *PromClientMap) newWriterClientFromPromOption(po PromOption) (api.Client, error) {
|
||||
tlsConfig, _ := po.TLSConfig()
|
||||
tlsConfig, err := po.TLS.TLSConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create TLS config: %v", err)
|
||||
}
|
||||
|
||||
return api.NewClient(api.Config{
|
||||
Address: po.WriteAddr,
|
||||
|
||||
Reference in New Issue
Block a user