forked from open-cluster-management-io/sdk-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptions.go
More file actions
152 lines (136 loc) · 7.37 KB
/
Copy pathoptions.go
File metadata and controls
152 lines (136 loc) · 7.37 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package grpc
import (
"crypto/tls"
"fmt"
"math"
"os"
"time"
"github.com/spf13/pflag"
"gopkg.in/yaml.v2"
"k8s.io/klog/v2"
pkgtls "open-cluster-management.io/sdk-go/pkg/tls"
)
type GRPCServerOptions struct {
TLSCertFile string `json:"tls_cert_file" yaml:"tls_cert_file"`
TLSKeyFile string `json:"tls_key_file" yaml:"tls_key_file"`
ClientCAFile string `json:"client_ca_file" yaml:"client_ca_file"`
TLSMinVersion uint16 `json:"tls_min_version" yaml:"tls_min_version"`
TLSMaxVersion uint16 `json:"tls_max_version" yaml:"tls_max_version"`
CipherSuites string `json:"cipher_suites" yaml:"cipher_suites"`
ServerBindPort string `json:"server_bind_port" yaml:"server_bind_port"`
MaxConcurrentStreams uint32 `json:"max_concurrent_streams" yaml:"max_concurrent_streams"`
MaxReceiveMessageSize int `json:"max_receive_message_size" yaml:"max_receive_message_size"`
MaxSendMessageSize int `json:"max_send_message_size" yaml:"max_send_message_size"`
WriteBufferSize int `json:"write_buffer_size" yaml:"write_buffer_size"`
ReadBufferSize int `json:"read_buffer_size" yaml:"read_buffer_size"`
ConnectionTimeout time.Duration `json:"connection_timeout" yaml:"connection_timeout"`
MaxConnectionAge time.Duration `json:"max_connection_age" yaml:"max_connection_age"`
ClientMinPingInterval time.Duration `json:"client_min_ping_interval" yaml:"client_min_ping_interval"`
ServerPingInterval time.Duration `json:"server_ping_interval" yaml:"server_ping_interval"`
ServerPingTimeout time.Duration `json:"server_ping_timeout" yaml:"server_ping_timeout"`
PermitPingWithoutStream bool `json:"permit_ping_without_stream" yaml:"permit_ping_without_stream"`
CertWatchInterval time.Duration `json:"cert_watch_interval" yaml:"cert_watch_interval"`
// cipherSuiteIDs holds the parsed uint16 IDs from CipherSuites, populated by Validate().
cipherSuiteIDs []uint16
}
func LoadGRPCServerOptions(configPath string) (*GRPCServerOptions, error) {
opts := NewGRPCServerOptions()
if _, err := os.Stat(configPath); os.IsNotExist(err) {
klog.Warningf("GRPC server config file %s does not exist. Using default options.", configPath)
return opts, nil
}
grpcServerConfig, err := os.ReadFile(configPath)
if err != nil {
return nil, err
}
if err := yaml.Unmarshal(grpcServerConfig, opts); err != nil {
return nil, err
}
if err := opts.Validate(); err != nil {
return nil, err
}
return opts, nil
}
func NewGRPCServerOptions() *GRPCServerOptions {
return &GRPCServerOptions{
ClientCAFile: "/var/run/secrets/hub/grpc/ca/ca-bundle.crt",
TLSCertFile: "/var/run/secrets/hub/grpc/serving-cert/tls.crt",
TLSKeyFile: "/var/run/secrets/hub/grpc/serving-cert/tls.key",
TLSMinVersion: tls.VersionTLS12,
TLSMaxVersion: tls.VersionTLS13,
ServerBindPort: "8090",
MaxConcurrentStreams: math.MaxUint32,
MaxReceiveMessageSize: 1024 * 1024 * 4,
MaxSendMessageSize: math.MaxInt32,
ConnectionTimeout: 120 * time.Second,
MaxConnectionAge: time.Duration(math.MaxInt64),
ClientMinPingInterval: 5 * time.Second,
ServerPingInterval: 30 * time.Second,
ServerPingTimeout: 10 * time.Second,
WriteBufferSize: 32 * 1024,
ReadBufferSize: 32 * 1024,
CertWatchInterval: 1 * time.Minute, // Default: 1 minute
}
}
func (o *GRPCServerOptions) AddFlags(flags *pflag.FlagSet) {
flags.StringVar(&o.ServerBindPort, "grpc-server-bindport", o.ServerBindPort, "gPRC server bind port")
flags.Uint32Var(&o.MaxConcurrentStreams, "grpc-max-concurrent-streams", o.MaxConcurrentStreams, "gPRC max concurrent streams")
flags.IntVar(&o.MaxReceiveMessageSize, "grpc-max-receive-message-size", o.MaxReceiveMessageSize, "gPRC max receive message size")
flags.IntVar(&o.MaxSendMessageSize, "grpc-max-send-message-size", o.MaxSendMessageSize, "gPRC max send message size")
flags.DurationVar(&o.ConnectionTimeout, "grpc-connection-timeout", o.ConnectionTimeout, "gPRC connection timeout")
flags.DurationVar(&o.MaxConnectionAge, "grpc-max-connection-age", o.MaxConnectionAge, "A duration for the maximum amount of time connection may exist before closing")
flags.DurationVar(&o.ClientMinPingInterval, "grpc-client-min-ping-interval", o.ClientMinPingInterval, "Server will terminate the connection if the client pings more than once within this duration")
flags.DurationVar(&o.ServerPingInterval, "grpc-server-ping-interval", o.ServerPingInterval, "Duration after which the server pings the client if no activity is detected")
flags.DurationVar(&o.ServerPingTimeout, "grpc-server-ping-timeout", o.ServerPingTimeout, "Duration the client waits for a response after sending a keepalive ping")
flags.BoolVar(&o.PermitPingWithoutStream, "permit-ping-without-stream", o.PermitPingWithoutStream, "Allow keepalive pings even when there are no active streams")
flags.IntVar(&o.WriteBufferSize, "grpc-write-buffer-size", o.WriteBufferSize, "gPRC write buffer size")
flags.IntVar(&o.ReadBufferSize, "grpc-read-buffer-size", o.ReadBufferSize, "gPRC read buffer size")
flags.StringVar(&o.TLSCertFile, "grpc-tls-cert-file", o.TLSCertFile, "The path to the tls.crt file")
flags.StringVar(&o.TLSKeyFile, "grpc-tls-key-file", o.TLSKeyFile, "The path to the tls.key file")
flags.StringVar(&o.ClientCAFile, "grpc-client-ca-file", o.ClientCAFile, "The path to the client ca file, must specify if using mtls authentication type")
flags.DurationVar(&o.CertWatchInterval, "grpc-cert-watch-interval", o.CertWatchInterval, "Certificate watch interval for polling certificate file changes")
}
// Validate checks option ranges and cross-field constraints.
func (o *GRPCServerOptions) Validate() error {
// Enforce sane floor for TLS for security posture.
if o.TLSMinVersion < tls.VersionTLS12 {
return fmt.Errorf("tls_min_version (%d) is lower than TLS 1.2 (771); minimum supported is TLS 1.2", o.TLSMinVersion)
}
if o.TLSMinVersion > o.TLSMaxVersion {
return fmt.Errorf("tls_min_version (%d) must be <= tls_max_version (%d)", o.TLSMinVersion, o.TLSMaxVersion)
}
// Validate certificate watch interval to prevent time.NewTicker panic
if o.CertWatchInterval <= 30*time.Second {
return fmt.Errorf("cert_watch_interval (%v) must be greater than 30 seconds", o.CertWatchInterval)
}
return o.parseCipherSuiteIDs()
}
// ApplyTLSFlags overrides TLS settings loaded from the config file with values
// from --tls-min-version and --tls-cipher-suites command-line flags.
// Called after LoadGRPCServerOptions so flags take precedence over the config file.
func (o *GRPCServerOptions) ApplyTLSFlags(minVersion, cipherSuites string) error {
if minVersion != "" {
ver, err := pkgtls.ParseTLSVersion(minVersion)
if err != nil {
return fmt.Errorf("invalid --tls-min-version: %w", err)
}
o.TLSMinVersion = ver
}
if cipherSuites != "" {
o.CipherSuites = cipherSuites
}
return o.Validate()
}
// parseCipherSuiteIDs converts the CipherSuites IANA names into uint16 IDs
// using the shared pkg/tls parsing utilities.
func (o *GRPCServerOptions) parseCipherSuiteIDs() error {
if o.CipherSuites == "" {
return nil
}
ids, unsupported := pkgtls.ParseCipherSuites(o.CipherSuites)
if len(unsupported) > 0 {
return fmt.Errorf("unrecognized cipher suite: %s", unsupported[0])
}
o.cipherSuiteIDs = ids
return nil
}