...
1 package live
2
3 import (
4 "context"
5 "errors"
6
7 capb "github.com/letsencrypt/boulder/ca/proto"
8 "github.com/letsencrypt/boulder/core"
9 berrors "github.com/letsencrypt/boulder/errors"
10 "github.com/letsencrypt/boulder/ocsp/responder"
11 rapb "github.com/letsencrypt/boulder/ra/proto"
12 "github.com/letsencrypt/boulder/semaphore"
13 "golang.org/x/crypto/ocsp"
14 "google.golang.org/grpc"
15 )
16
17 type ocspGenerator interface {
18 GenerateOCSP(ctx context.Context, in *rapb.GenerateOCSPRequest, opts ...grpc.CallOption) (*capb.OCSPResponse, error)
19 }
20
21 type Source struct {
22 ra ocspGenerator
23 sem *semaphore.Weighted
24 }
25
26 func New(ra ocspGenerator, maxInflight int64, maxWaiters int) *Source {
27 return &Source{
28 ra: ra,
29 sem: semaphore.NewWeighted(maxInflight, maxWaiters),
30 }
31 }
32
33 func (s *Source) Response(ctx context.Context, req *ocsp.Request) (*responder.Response, error) {
34 err := s.sem.Acquire(ctx, 1)
35 if err != nil {
36 return nil, err
37 }
38 defer s.sem.Release(1)
39 if ctx.Err() != nil {
40 return nil, ctx.Err()
41 }
42
43 resp, err := s.ra.GenerateOCSP(ctx, &rapb.GenerateOCSPRequest{
44 Serial: core.SerialToString(req.SerialNumber),
45 })
46 if err != nil {
47 if errors.Is(err, berrors.NotFound) {
48 return nil, responder.ErrNotFound
49 }
50 return nil, err
51 }
52 parsed, err := ocsp.ParseResponse(resp.Response, nil)
53 if err != nil {
54 return nil, err
55 }
56 return &responder.Response{
57 Raw: resp.Response,
58 Response: parsed,
59 }, nil
60 }
61
View as plain text