| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /*
- Copyright © The ESO Authors
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- https://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package server
- import (
- "log"
- "time"
- "google.golang.org/grpc"
- "google.golang.org/grpc/credentials"
- "google.golang.org/grpc/keepalive"
- )
- // Options holds configuration options for creating a gRPC server.
- type Options struct {
- EnableTLS bool
- Verbose bool
- }
- // ServerOptions is kept as a compatibility alias for existing callers.
- //
- //nolint:revive // Compatibility alias for the previous exported API.
- type ServerOptions = Options
- // NewGRPCServer creates a new gRPC server with standard configuration.
- func NewGRPCServer(opts Options) (*grpc.Server, error) {
- var grpcOpts []grpc.ServerOption
- // Add keepalive parameters for better connection diagnostics
- grpcOpts = append(grpcOpts,
- grpc.KeepaliveParams(keepalive.ServerParameters{
- MaxConnectionIdle: 15 * time.Minute,
- MaxConnectionAge: 30 * time.Minute,
- MaxConnectionAgeGrace: 5 * time.Minute,
- Time: 5 * time.Minute,
- Timeout: 1 * time.Minute,
- }),
- grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
- MinTime: 5 * time.Second, // Allow pings every 5s (client sends every 10s)
- PermitWithoutStream: true,
- }),
- )
- if opts.Verbose {
- log.Printf("[CONFIG] Keepalive configured: idle=15m, age=30m, time=5m, timeout=1m, minPing=5s")
- }
- // Add connection tap handler for verbose mode
- if opts.Verbose {
- grpcOpts = append(grpcOpts, grpc.InTapHandle(ConnectionTapHandler))
- log.Printf("[CONFIG] Connection tap handler enabled")
- }
- // Add RPC interceptors: metrics and logging
- grpcOpts = append(grpcOpts, grpc.ChainUnaryInterceptor(
- MetricsUnaryInterceptor(),
- LoggingUnaryInterceptor(opts.Verbose),
- ))
- log.Printf("[CONFIG] RPC metrics and logging interceptors enabled")
- // Configure TLS if enabled
- if opts.EnableTLS {
- log.Printf("[TLS] Loading TLS configuration...")
- tlsConfig, err := LoadTLSConfig(DefaultTLSConfig())
- if err != nil {
- return nil, err
- }
- // Log TLS configuration details
- log.Printf("[TLS] Configuration loaded successfully")
- log.Printf("[TLS] Min TLS version: 0x%04x (%s)", tlsConfig.MinVersion, TLSVersionName(tlsConfig.MinVersion))
- log.Printf("[TLS] Max TLS version: 0x%04x (%s)", tlsConfig.MaxVersion, TLSVersionName(tlsConfig.MaxVersion))
- log.Printf("[TLS] Client auth required: %v", tlsConfig.ClientAuth == 4) // tls.RequireAndVerifyClientCert
- if tlsConfig.ClientCAs != nil {
- subjects := tlsConfig.ClientCAs.Subjects()
- log.Printf("[TLS] Client CA pool has %d certificate(s)", len(subjects))
- if opts.Verbose {
- for i, subject := range subjects {
- log.Printf("[TLS] CA %d: %s", i, string(subject))
- }
- }
- } else {
- log.Printf("[TLS] WARNING: No client CA pool configured")
- }
- if len(tlsConfig.Certificates) > 0 {
- log.Printf("[TLS] Server has %d certificate(s)", len(tlsConfig.Certificates))
- for i, cert := range tlsConfig.Certificates {
- if len(cert.Certificate) > 0 {
- log.Printf("[TLS] Cert %d: raw certificate data present", i)
- }
- }
- } else {
- log.Printf("[TLS] WARNING: No server certificates configured")
- }
- grpcOpts = append(grpcOpts, grpc.Creds(credentials.NewTLS(tlsConfig)))
- log.Printf("[TLS] mTLS enabled for provider server")
- } else {
- log.Printf("[SECURITY] WARNING: TLS DISABLED - NOT SUITABLE FOR PRODUCTION")
- log.Printf("[SECURITY] All traffic will be transmitted in PLAINTEXT")
- }
- return grpc.NewServer(grpcOpts...), nil
- }
|