mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 00:06:38 +00:00
Add proxy <-> management authentication
This commit is contained in:
@@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -16,6 +17,9 @@ import (
|
||||
|
||||
const DefaultManagementURL = "https://api.netbird.io:443"
|
||||
|
||||
// envProxyToken is the environment variable name for the proxy access token.
|
||||
const envProxyToken = "NB_PROXY_TOKEN"
|
||||
|
||||
var (
|
||||
Version = "dev"
|
||||
Commit = "unknown"
|
||||
@@ -42,11 +46,12 @@ var (
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "proxy",
|
||||
Short: "NetBird reverse proxy server",
|
||||
Long: "NetBird reverse proxy server for proxying traffic to NetBird networks.",
|
||||
Version: Version,
|
||||
RunE: runServer,
|
||||
Use: "proxy",
|
||||
Short: "NetBird reverse proxy server",
|
||||
Long: "NetBird reverse proxy server for proxying traffic to NetBird networks.",
|
||||
Version: Version,
|
||||
SilenceUsage: true,
|
||||
RunE: runServer,
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -85,6 +90,11 @@ func SetVersionInfo(version, commit, buildDate, goVersion string) {
|
||||
}
|
||||
|
||||
func runServer(cmd *cobra.Command, args []string) error {
|
||||
proxyToken := os.Getenv(envProxyToken)
|
||||
if proxyToken == "" {
|
||||
return fmt.Errorf("proxy token is required: set %s environment variable", envProxyToken)
|
||||
}
|
||||
|
||||
level := "error"
|
||||
if debugLogs {
|
||||
level = "debug"
|
||||
@@ -100,6 +110,7 @@ func runServer(cmd *cobra.Command, args []string) error {
|
||||
Version: Version,
|
||||
ManagementAddress: mgmtAddr,
|
||||
ProxyURL: proxyURL,
|
||||
ProxyToken: proxyToken,
|
||||
CertificateDirectory: certDir,
|
||||
GenerateACMECertificates: acmeCerts,
|
||||
ACMEChallengeAddress: acmeAddr,
|
||||
|
||||
@@ -49,6 +49,13 @@ spec:
|
||||
value: "https://proxy.local"
|
||||
- name: NB_PROXY_CERTIFICATE_DIRECTORY
|
||||
value: "/certs"
|
||||
- name: NB_PROXY_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: netbird-proxy-token
|
||||
key: token
|
||||
- name: NB_PROXY_ALLOW_INSECURE
|
||||
value: "true" # Required for HTTP management connection in dev
|
||||
volumeMounts:
|
||||
- name: tls-certs
|
||||
mountPath: /certs
|
||||
|
||||
48
proxy/internal/grpc/auth.go
Normal file
48
proxy/internal/grpc/auth.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// Package grpc provides gRPC utilities for the proxy client.
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
// EnvProxyAllowInsecure controls whether the proxy token can be sent over non-TLS connections.
|
||||
const EnvProxyAllowInsecure = "NB_PROXY_ALLOW_INSECURE"
|
||||
|
||||
var _ credentials.PerRPCCredentials = (*proxyAuthToken)(nil)
|
||||
|
||||
type proxyAuthToken struct {
|
||||
token string
|
||||
allowInsecure bool
|
||||
}
|
||||
|
||||
func (t proxyAuthToken) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
|
||||
return map[string]string{
|
||||
"authorization": "Bearer " + t.token,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RequireTransportSecurity returns true by default to protect the token in transit.
|
||||
// Set NB_PROXY_ALLOW_INSECURE=true to allow non-TLS connections (not recommended for production).
|
||||
func (t proxyAuthToken) RequireTransportSecurity() bool {
|
||||
return !t.allowInsecure
|
||||
}
|
||||
|
||||
// WithProxyToken returns a DialOption that sets the proxy access token on each outbound RPC.
|
||||
func WithProxyToken(token string) grpc.DialOption {
|
||||
allowInsecure := false
|
||||
if val := os.Getenv(EnvProxyAllowInsecure); val != "" {
|
||||
parsed, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
log.Warnf("invalid value for %s: %v", EnvProxyAllowInsecure, err)
|
||||
} else {
|
||||
allowInsecure = parsed
|
||||
}
|
||||
}
|
||||
return grpc.WithPerRPCCredentials(proxyAuthToken{token: token, allowInsecure: allowInsecure})
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/netbirdio/netbird/proxy/internal/acme"
|
||||
"github.com/netbirdio/netbird/proxy/internal/auth"
|
||||
"github.com/netbirdio/netbird/proxy/internal/debug"
|
||||
proxygrpc "github.com/netbirdio/netbird/proxy/internal/grpc"
|
||||
"github.com/netbirdio/netbird/proxy/internal/health"
|
||||
"github.com/netbirdio/netbird/proxy/internal/proxy"
|
||||
"github.com/netbirdio/netbird/proxy/internal/roundtrip"
|
||||
@@ -76,6 +77,8 @@ type Server struct {
|
||||
DebugEndpointAddress string
|
||||
// HealthAddress is the address for the health probe endpoint (default: "localhost:8080").
|
||||
HealthAddress string
|
||||
// ProxyToken is the access token for authenticating with the management server.
|
||||
ProxyToken string
|
||||
}
|
||||
|
||||
// NotifyStatus sends a status update to management about tunnel connectivity
|
||||
@@ -153,6 +156,7 @@ func (s *Server) ListenAndServe(ctx context.Context, addr string) (err error) {
|
||||
Timeout: 10 * time.Second,
|
||||
PermitWithoutStream: true,
|
||||
}),
|
||||
proxygrpc.WithProxyToken(s.ProxyToken),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create management connection: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user