github.com/argoproj/argo-cd/v3@v3.2.1/reposerver/server.go (about)

     1  package reposerver
     2  
     3  import (
     4  	"crypto/tls"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
    10  	"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
    11  	"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
    12  	log "github.com/sirupsen/logrus"
    13  	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
    14  	"google.golang.org/grpc"
    15  	"google.golang.org/grpc/credentials"
    16  	"google.golang.org/grpc/health"
    17  	"google.golang.org/grpc/health/grpc_health_v1"
    18  	"google.golang.org/grpc/keepalive"
    19  	"google.golang.org/grpc/reflection"
    20  
    21  	"github.com/argoproj/argo-cd/v3/common"
    22  	versionpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/version"
    23  	"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
    24  	reposervercache "github.com/argoproj/argo-cd/v3/reposerver/cache"
    25  	"github.com/argoproj/argo-cd/v3/reposerver/metrics"
    26  	"github.com/argoproj/argo-cd/v3/reposerver/repository"
    27  	"github.com/argoproj/argo-cd/v3/server/version"
    28  	"github.com/argoproj/argo-cd/v3/util/env"
    29  	"github.com/argoproj/argo-cd/v3/util/git"
    30  	grpc_util "github.com/argoproj/argo-cd/v3/util/grpc"
    31  	tlsutil "github.com/argoproj/argo-cd/v3/util/tls"
    32  )
    33  
    34  // ArgoCDRepoServer is the repo server implementation
    35  type ArgoCDRepoServer struct {
    36  	repoService *repository.Service
    37  	opts        []grpc.ServerOption
    38  }
    39  
    40  // The hostnames to generate self-signed issues with
    41  var tlsHostList = []string{"localhost", "reposerver"}
    42  
    43  // NewServer returns a new instance of the Argo CD Repo server
    44  func NewServer(metricsServer *metrics.MetricsServer, cache *reposervercache.Cache, tlsConfCustomizer tlsutil.ConfigCustomizer, initConstants repository.RepoServerInitConstants, gitCredsStore git.CredsStore) (*ArgoCDRepoServer, error) {
    45  	var tlsConfig *tls.Config
    46  
    47  	// Generate or load TLS server certificates to use with this instance of
    48  	// repository server.
    49  	if tlsConfCustomizer != nil {
    50  		var err error
    51  		certPath := env.StringFromEnv(common.EnvAppConfigPath, common.DefaultAppConfigPath) + "/reposerver/tls/tls.crt"
    52  		keyPath := env.StringFromEnv(common.EnvAppConfigPath, common.DefaultAppConfigPath) + "/reposerver/tls/tls.key"
    53  		tlsConfig, err = tlsutil.CreateServerTLSConfig(certPath, keyPath, tlsHostList)
    54  		if err != nil {
    55  			return nil, fmt.Errorf("error creating server TLS config: %w", err)
    56  		}
    57  		tlsConfCustomizer(tlsConfig)
    58  	}
    59  
    60  	var serverMetricsOptions []grpc_prometheus.ServerMetricsOption
    61  	if os.Getenv(common.EnvEnableGRPCTimeHistogramEnv) == "true" {
    62  		serverMetricsOptions = append(serverMetricsOptions, grpc_prometheus.WithServerHandlingTimeHistogram())
    63  	}
    64  	serverMetrics := grpc_prometheus.NewServerMetrics(serverMetricsOptions...)
    65  	metricsServer.PrometheusRegistry.MustRegister(serverMetrics)
    66  
    67  	serverLog := log.NewEntry(log.StandardLogger())
    68  	streamInterceptors := []grpc.StreamServerInterceptor{
    69  		logging.StreamServerInterceptor(grpc_util.InterceptorLogger(serverLog)),
    70  		serverMetrics.StreamServerInterceptor(),
    71  		recovery.StreamServerInterceptor(recovery.WithRecoveryHandler(grpc_util.LoggerRecoveryHandler(serverLog))),
    72  	}
    73  	unaryInterceptors := []grpc.UnaryServerInterceptor{
    74  		logging.UnaryServerInterceptor(grpc_util.InterceptorLogger(serverLog)),
    75  		serverMetrics.UnaryServerInterceptor(),
    76  		recovery.UnaryServerInterceptor(recovery.WithRecoveryHandler(grpc_util.LoggerRecoveryHandler(serverLog))),
    77  		grpc_util.ErrorSanitizerUnaryServerInterceptor(),
    78  	}
    79  
    80  	serverOpts := []grpc.ServerOption{
    81  		grpc.ChainUnaryInterceptor(unaryInterceptors...),
    82  		grpc.ChainStreamInterceptor(streamInterceptors...),
    83  		grpc.MaxRecvMsgSize(apiclient.MaxGRPCMessageSize),
    84  		grpc.MaxSendMsgSize(apiclient.MaxGRPCMessageSize),
    85  		grpc.KeepaliveEnforcementPolicy(
    86  			keepalive.EnforcementPolicy{
    87  				MinTime: common.GetGRPCKeepAliveEnforcementMinimum(),
    88  			},
    89  		),
    90  		grpc.StatsHandler(otelgrpc.NewServerHandler()),
    91  	}
    92  
    93  	// We do allow for non-TLS servers to be created, in case of mTLS will be
    94  	// implemented by e.g. a sidecar container.
    95  	if tlsConfig != nil {
    96  		serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(tlsConfig)))
    97  	}
    98  	repoService := repository.NewService(metricsServer, cache, initConstants, gitCredsStore, filepath.Join(os.TempDir(), "_argocd-repo"))
    99  	if err := repoService.Init(); err != nil {
   100  		return nil, fmt.Errorf("failed to initialize the repo service: %w", err)
   101  	}
   102  
   103  	return &ArgoCDRepoServer{
   104  		opts:        serverOpts,
   105  		repoService: repoService,
   106  	}, nil
   107  }
   108  
   109  // CreateGRPC creates new configured grpc server
   110  func (a *ArgoCDRepoServer) CreateGRPC() *grpc.Server {
   111  	server := grpc.NewServer(a.opts...)
   112  	versionpkg.RegisterVersionServiceServer(server, version.NewServer(nil, func() (bool, error) {
   113  		return true, nil
   114  	}))
   115  	apiclient.RegisterRepoServerServiceServer(server, a.repoService)
   116  
   117  	healthService := health.NewServer()
   118  	grpc_health_v1.RegisterHealthServer(server, healthService)
   119  
   120  	// Register reflection service on gRPC server.
   121  	reflection.Register(server)
   122  
   123  	return server
   124  }