From c1c2e73475f4333267aa855d758800dae0255278 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Tue, 27 Feb 2024 17:04:21 +0100 Subject: [PATCH] Add `X-Request-Id` to all requests made by our CA clients --- ca/acmeClient.go | 3 +++ ca/client.go | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ca/acmeClient.go b/ca/acmeClient.go index bb3b1d84..3ef2f191 100644 --- a/ca/acmeClient.go +++ b/ca/acmeClient.go @@ -48,6 +48,7 @@ func NewACMEClient(endpoint string, contact []string, opts ...ClientOption) (*AC return nil, errors.Wrapf(err, "creating GET request %s failed", endpoint) } req.Header.Set("User-Agent", UserAgent) + enforceRequestID(req) resp, err := ac.client.Do(req) if err != nil { return nil, errors.Wrapf(err, "client GET %s failed", endpoint) @@ -109,6 +110,7 @@ func (c *ACMEClient) GetNonce() (string, error) { return "", errors.Wrapf(err, "creating GET request %s failed", c.dir.NewNonce) } req.Header.Set("User-Agent", UserAgent) + enforceRequestID(req) resp, err := c.client.Do(req) if err != nil { return "", errors.Wrapf(err, "client GET %s failed", c.dir.NewNonce) @@ -188,6 +190,7 @@ func (c *ACMEClient) post(payload []byte, url string, headerOps ...withHeaderOpt } req.Header.Set("Content-Type", "application/jose+json") req.Header.Set("User-Agent", UserAgent) + enforceRequestID(req) resp, err := c.client.Do(req) if err != nil { return nil, errors.Wrapf(err, "client POST %s failed", c.dir.NewOrder) diff --git a/ca/client.go b/ca/client.go index ac13e1fe..5e2d98c8 100644 --- a/ca/client.go +++ b/ca/client.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/pkg/errors" + "github.com/rs/xid" "github.com/smallstep/certificates/api" "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/provisioner" @@ -83,8 +84,7 @@ func (c *uaClient) GetWithContext(ctx context.Context, u string) (*http.Response if err != nil { return nil, errors.Wrapf(err, "create GET %s request failed", u) } - req.Header.Set("User-Agent", UserAgent) - return c.Client.Do(req) + return c.Do(req) } func (c *uaClient) Post(u, contentType string, body io.Reader) (*http.Response, error) { @@ -97,12 +97,24 @@ func (c *uaClient) PostWithContext(ctx context.Context, u, contentType string, b return nil, errors.Wrapf(err, "create POST %s request failed", u) } req.Header.Set("Content-Type", contentType) - req.Header.Set("User-Agent", UserAgent) - return c.Client.Do(req) + return c.Do(req) +} + +// requestIDHeader is the header name used for propagating request IDs from +// the CA client to the CA and back again. +const requestIDHeader = "X-Request-Id" + +// enforceRequestID checks if the X-Request-Id HTTP header is filled. If it's +// empty, it'll generate a new request ID and set the header. +func enforceRequestID(r *http.Request) { + if r.Header.Get(requestIDHeader) == "" { + r.Header.Set(requestIDHeader, xid.New().String()) + } } func (c *uaClient) Do(req *http.Request) (*http.Response, error) { req.Header.Set("User-Agent", UserAgent) + enforceRequestID(req) return c.Client.Do(req) }