1 package notmain
2
3 import (
4 "context"
5 "flag"
6 "net/http"
7 "os"
8
9 "github.com/aws/aws-sdk-go-v2/aws"
10 "github.com/aws/aws-sdk-go-v2/config"
11 "github.com/aws/aws-sdk-go-v2/service/s3"
12 awsl "github.com/aws/smithy-go/logging"
13
14 "github.com/letsencrypt/boulder/cmd"
15 "github.com/letsencrypt/boulder/crl/storer"
16 cspb "github.com/letsencrypt/boulder/crl/storer/proto"
17 "github.com/letsencrypt/boulder/features"
18 bgrpc "github.com/letsencrypt/boulder/grpc"
19 "github.com/letsencrypt/boulder/issuance"
20 blog "github.com/letsencrypt/boulder/log"
21 )
22
23 type Config struct {
24 CRLStorer struct {
25 cmd.ServiceConfig
26
27
28
29
30 IssuerCerts []string `validate:"min=1,dive,required"`
31
32
33
34
35
36 S3Endpoint string
37
38
39 S3Bucket string
40
41
42
43 AWSConfigFile string
44
45
46
47 AWSCredsFile string
48
49 Features map[string]bool
50 }
51
52 Syslog cmd.SyslogConfig
53 OpenTelemetry cmd.OpenTelemetryConfig
54 }
55
56
57 type awsLogger struct {
58 blog.Logger
59 }
60
61 func (log awsLogger) Logf(c awsl.Classification, format string, v ...interface{}) {
62 switch c {
63 case awsl.Debug:
64 log.Debugf(format, v...)
65 case awsl.Warn:
66 log.Warningf(format, v...)
67 }
68 }
69
70 func main() {
71 configFile := flag.String("config", "", "File path to the configuration file for this service")
72 flag.Parse()
73 if *configFile == "" {
74 flag.Usage()
75 os.Exit(1)
76 }
77
78 var c Config
79 err := cmd.ReadConfigFile(*configFile, &c)
80 cmd.FailOnError(err, "Reading JSON config file into config structure")
81
82 err = features.Set(c.CRLStorer.Features)
83 cmd.FailOnError(err, "Failed to set feature flags")
84
85 scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.CRLStorer.DebugAddr)
86 defer oTelShutdown(context.Background())
87 logger.Info(cmd.VersionString())
88 clk := cmd.Clock()
89
90 tlsConfig, err := c.CRLStorer.TLS.Load(scope)
91 cmd.FailOnError(err, "TLS config")
92
93 issuers := make([]*issuance.Certificate, 0, len(c.CRLStorer.IssuerCerts))
94 for _, filepath := range c.CRLStorer.IssuerCerts {
95 cert, err := issuance.LoadCertificate(filepath)
96 cmd.FailOnError(err, "Failed to load issuer cert")
97 issuers = append(issuers, cert)
98 }
99
100
101
102
103
104 awsConfig, err := config.LoadDefaultConfig(
105 context.Background(),
106 config.WithSharedConfigFiles([]string{c.CRLStorer.AWSConfigFile}),
107 config.WithSharedCredentialsFiles([]string{c.CRLStorer.AWSCredsFile}),
108 config.WithHTTPClient(new(http.Client)),
109 config.WithLogger(awsLogger{logger}),
110 config.WithClientLogMode(aws.LogRequestEventMessage|aws.LogResponseEventMessage),
111 )
112 cmd.FailOnError(err, "Failed to load AWS config")
113
114 s3opts := make([]func(*s3.Options), 0)
115 if c.CRLStorer.S3Endpoint != "" {
116 s3opts = append(
117 s3opts,
118 s3.WithEndpointResolver(s3.EndpointResolverFromURL(c.CRLStorer.S3Endpoint)),
119 func(o *s3.Options) { o.UsePathStyle = true },
120 )
121 }
122 s3client := s3.NewFromConfig(awsConfig, s3opts...)
123
124 csi, err := storer.New(issuers, s3client, c.CRLStorer.S3Bucket, scope, logger, clk)
125 cmd.FailOnError(err, "Failed to create CRLStorer impl")
126
127 start, err := bgrpc.NewServer(c.CRLStorer.GRPC, logger).Add(
128 &cspb.CRLStorer_ServiceDesc, csi).Build(tlsConfig, scope, clk)
129 cmd.FailOnError(err, "Unable to setup CRLStorer gRPC server")
130
131 cmd.FailOnError(start(), "CRLStorer gRPC service failed")
132 }
133
134 func init() {
135 cmd.RegisterCommand("crl-storer", main, &cmd.ConfigValidator{Config: &Config{}})
136 }
137
View as plain text