auth: enhance OIDC client with TLS and proxy configuration options (#4990)

This commit is contained in:
fatedier
2025-09-25 10:19:19 +08:00
committed by GitHub
parent 7cfa546b55
commit abf4942e8a
6 changed files with 108 additions and 8 deletions

View File

@@ -27,16 +27,19 @@ type Setter interface {
SetNewWorkConn(*msg.NewWorkConn) error
}
func NewAuthSetter(cfg v1.AuthClientConfig) (authProvider Setter) {
func NewAuthSetter(cfg v1.AuthClientConfig) (authProvider Setter, err error) {
switch cfg.Method {
case v1.AuthMethodToken:
authProvider = NewTokenAuth(cfg.AdditionalScopes, cfg.Token)
case v1.AuthMethodOIDC:
authProvider = NewOidcAuthSetter(cfg.AdditionalScopes, cfg.OIDC)
authProvider, err = NewOidcAuthSetter(cfg.AdditionalScopes, cfg.OIDC)
if err != nil {
return nil, err
}
default:
panic(fmt.Sprintf("wrong method: '%s'", cfg.Method))
return nil, fmt.Errorf("unsupported auth method: %s", cfg.Method)
}
return authProvider
return authProvider, nil
}
type Verifier interface {

View File

@@ -16,23 +16,72 @@ package auth
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"net/url"
"os"
"slices"
"github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
v1 "github.com/fatedier/frp/pkg/config/v1"
"github.com/fatedier/frp/pkg/msg"
)
// createOIDCHTTPClient creates an HTTP client with custom TLS and proxy configuration for OIDC token requests
func createOIDCHTTPClient(trustedCAFile string, insecureSkipVerify bool, proxyURL string) (*http.Client, error) {
// Clone the default transport to get all reasonable defaults
transport := http.DefaultTransport.(*http.Transport).Clone()
// Configure TLS settings
if trustedCAFile != "" || insecureSkipVerify {
tlsConfig := &tls.Config{
InsecureSkipVerify: insecureSkipVerify,
}
if trustedCAFile != "" && !insecureSkipVerify {
caCert, err := os.ReadFile(trustedCAFile)
if err != nil {
return nil, fmt.Errorf("failed to read OIDC CA certificate file %q: %w", trustedCAFile, err)
}
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
return nil, fmt.Errorf("failed to parse OIDC CA certificate from file %q", trustedCAFile)
}
tlsConfig.RootCAs = caCertPool
}
transport.TLSClientConfig = tlsConfig
}
// Configure proxy settings
if proxyURL != "" {
parsedURL, err := url.Parse(proxyURL)
if err != nil {
return nil, fmt.Errorf("failed to parse OIDC proxy URL %q: %w", proxyURL, err)
}
transport.Proxy = http.ProxyURL(parsedURL)
} else {
// Explicitly disable proxy to override DefaultTransport's ProxyFromEnvironment
transport.Proxy = nil
}
return &http.Client{Transport: transport}, nil
}
type OidcAuthProvider struct {
additionalAuthScopes []v1.AuthScope
tokenGenerator *clientcredentials.Config
httpClient *http.Client
}
func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClientConfig) *OidcAuthProvider {
func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClientConfig) (*OidcAuthProvider, error) {
eps := make(map[string][]string)
for k, v := range cfg.AdditionalEndpointParams {
eps[k] = []string{v}
@@ -50,14 +99,30 @@ func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClien
EndpointParams: eps,
}
// Create custom HTTP client if needed
var httpClient *http.Client
if cfg.TrustedCaFile != "" || cfg.InsecureSkipVerify || cfg.ProxyURL != "" {
var err error
httpClient, err = createOIDCHTTPClient(cfg.TrustedCaFile, cfg.InsecureSkipVerify, cfg.ProxyURL)
if err != nil {
return nil, fmt.Errorf("failed to create OIDC HTTP client: %w", err)
}
}
return &OidcAuthProvider{
additionalAuthScopes: additionalAuthScopes,
tokenGenerator: tokenGenerator,
}
httpClient: httpClient,
}, nil
}
func (auth *OidcAuthProvider) generateAccessToken() (accessToken string, err error) {
tokenObj, err := auth.tokenGenerator.Token(context.Background())
ctx := context.Background()
if auth.httpClient != nil {
ctx = context.WithValue(ctx, oauth2.HTTPClient, auth.httpClient)
}
tokenObj, err := auth.tokenGenerator.Token(ctx)
if err != nil {
return "", fmt.Errorf("couldn't generate OIDC token for login: %v", err)
}

View File

@@ -228,6 +228,17 @@ type AuthOIDCClientConfig struct {
// AdditionalEndpointParams specifies additional parameters to be sent
// this field will be transfer to map[string][]string in OIDC token generator.
AdditionalEndpointParams map[string]string `json:"additionalEndpointParams,omitempty"`
// TrustedCaFile specifies the path to a custom CA certificate file
// for verifying the OIDC token endpoint's TLS certificate.
TrustedCaFile string `json:"trustedCaFile,omitempty"`
// InsecureSkipVerify disables TLS certificate verification for the
// OIDC token endpoint. Only use this for debugging, not recommended for production.
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
// ProxyURL specifies a proxy to use when connecting to the OIDC token endpoint.
// Supports http, https, socks5, and socks5h proxy protocols.
// If empty, no proxy is used for OIDC connections.
ProxyURL string `json:"proxyURL,omitempty"`
}
type VirtualNetConfig struct {