Skip to content

Commit ef6c915

Browse files
author
Mitali Rawat
committed
add request ID to ReqContext in Op and include SKI in error logs
1 parent 5ca1df9 commit ef6c915

26 files changed

+1547
-18
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ require (
6060
github.com/google/certificate-transparency-go v1.1.4 // indirect
6161
github.com/google/go-querystring v1.1.0 // indirect
6262
github.com/google/s2a-go v0.1.7 // indirect
63+
github.com/google/uuid v1.6.0 // indirect
6364
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
6465
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
6566
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
117117
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
118118
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
119119
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
120+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
121+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
120122
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
121123
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
122124
github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=

server/server.go

+54-18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"crypto/tls"
1010
"crypto/x509"
1111
"encoding/gob"
12+
"encoding/json"
1213
"errors"
1314
"fmt"
1415
"io"
@@ -30,6 +31,7 @@ import (
3031
textbook_rsa "github.com/cloudflare/gokeyless/server/internal/rsa"
3132

3233
"github.com/cloudflare/cfssl/log"
34+
"github.com/google/uuid"
3335
)
3436

3537
// Server is a Keyless Server capable of performing opaque key operations.
@@ -284,6 +286,37 @@ func makeErrResponse(pkt *protocol.Packet, err protocol.Error) response {
284286
return response{id: pkt.ID, op: protocol.MakeErrorOp(err)}
285287
}
286288

289+
func addOperationRequestID(op *protocol.Operation) string {
290+
reqContext := make(map[string]interface{})
291+
var reqID string
292+
var gen bool
293+
294+
if len(op.ReqContext) > 0 {
295+
if err := json.Unmarshal(op.ReqContext, &reqContext); err == nil {
296+
if v, ok := reqContext["request_id"]; ok {
297+
return v.(string)
298+
} else {
299+
gen = true
300+
}
301+
} else {
302+
log.Errorf("malformed operation.ReqContext %v, ignoring error", op.ReqContext)
303+
}
304+
}
305+
306+
if len(op.ReqContext) == 0 || gen {
307+
reqID = uuid.New().String()
308+
reqContext["request_id"] = reqID
309+
b, err := json.Marshal(reqContext)
310+
if err == nil {
311+
op.ReqContext = b
312+
} else {
313+
log.Errorf("error marshaling operation.ReqContext %v, ignoring error", reqContext)
314+
reqID = ""
315+
}
316+
}
317+
return reqID
318+
}
319+
287320
func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
288321
spanCtx, err := tracing.SpanContextFromBinary(pkt.Operation.JaegerSpan)
289322
if err != nil {
@@ -292,14 +325,17 @@ func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
292325
span, ctx := opentracing.StartSpanFromContext(context.Background(), "operation execution", ext.RPCServerOption(spanCtx))
293326
defer span.Finish()
294327
tracing.SetOperationSpanTags(span, &pkt.Operation)
328+
reqID := addOperationRequestID(&pkt.Operation)
329+
span.SetTag("request_id", reqID)
295330

296-
log.Debugf("connection %s: limited=false opcode=%s id=%d sni=%s ip=%s ski=%v",
331+
log.Debugf("connection %s: limited=false opcode=%s id=%d sni=%s ip=%s ski=%v request-id=%s",
297332
connName,
298333
pkt.Operation.Opcode,
299334
pkt.Header.ID,
300335
pkt.Operation.SNI,
301336
pkt.Operation.ServerIP,
302-
pkt.Operation.SKI)
337+
pkt.Operation.SKI,
338+
reqID)
303339

304340
var opts crypto.SignerOpts
305341
switch pkt.Operation.Opcode {
@@ -362,10 +398,10 @@ func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
362398
key, err := s.keys.Get(ctx, &pkt.Operation)
363399
logKeyLoadDuration(loadStart)
364400
if err != nil {
365-
log.Errorf("failed to load key with sni=%s ip=%s ski=%v: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, err)
401+
log.Errorf("failed to load key with sni=%s ski=%v request-id=%s: %v", pkt.Operation.SNI, pkt.Operation.SKI, reqID, err)
366402
return makeErrResponse(pkt, protocol.ErrInternal)
367403
} else if key == nil {
368-
log.Errorf("failed to load key with sni=%s ip=%s ski=%v: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, protocol.ErrKeyNotFound)
404+
log.Errorf("failed to load key with sni=%s ski=%v request-id=%s: %v", pkt.Operation.SNI, pkt.Operation.SKI, reqID, protocol.ErrKeyNotFound)
369405
return makeErrResponse(pkt, protocol.ErrKeyNotFound)
370406
}
371407

@@ -376,14 +412,14 @@ func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
376412

377413
sig, err := key.Sign(rand.Reader, pkt.Operation.Payload, crypto.Hash(0))
378414
if err != nil {
379-
log.Errorf("Connection: %s: Signing error: %v", connName, protocol.ErrCrypto, err)
415+
log.Errorf("Connection: %s: sni=%s ski=%v request-id=%s: Signing error: %v: request-id:%s:", connName, pkt.Operation.SNI, pkt.Operation.SKI, reqID, protocol.ErrCrypto, err, reqID)
380416
// This indicates that a remote keyserver is being used
381417
var remoteConfigurationErr RemoteConfigurationErr
382418
if errors.As(err, &remoteConfigurationErr) {
383-
log.Errorf("Connection %v: %s: Signing error: %v\n", connName, protocol.ErrRemoteConfiguration, err)
419+
log.Errorf("Connection %v: sni=%s ski=%v request-id=%s: %s: Signing error: %v request-id:%s\n", connName, pkt.Operation.SNI, pkt.Operation.SKI, reqID, protocol.ErrRemoteConfiguration, err, reqID)
384420
return makeErrResponse(pkt, protocol.ErrRemoteConfiguration)
385421
} else {
386-
log.Errorf("Connection %v: %s: Signing error: %v\n", connName, protocol.ErrCrypto, err)
422+
log.Errorf("Connection %v: sni=%s ski=%v request-id=%s: %s: Signing error: %v request-id:%s\n", connName, pkt.Operation.SNI, pkt.Operation.SKI, reqID, protocol.ErrCrypto, err, reqID)
387423
return makeErrResponse(pkt, protocol.ErrCrypto)
388424
}
389425
}
@@ -394,37 +430,37 @@ func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
394430
key, err := s.keys.Get(ctx, &pkt.Operation)
395431
logKeyLoadDuration(loadStart)
396432
if err != nil {
397-
log.Errorf("failed to load key with sni=%s ip=%s ski=%v: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, err)
433+
log.Errorf("failed to load key with sni=%s ip=%s ski=%v request-id=%s: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, err)
398434
return makeErrResponse(pkt, protocol.ErrInternal)
399435
} else if key == nil {
400-
log.Errorf("failed to load key with sni=%s ip=%s ski=%v: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, protocol.ErrKeyNotFound)
436+
log.Errorf("failed to load key with sni=%s ip=%s ski=%v request-id=%s: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, protocol.ErrKeyNotFound)
401437
return makeErrResponse(pkt, protocol.ErrKeyNotFound)
402438
}
403439

404440
if _, ok := key.Public().(*rsa.PublicKey); !ok {
405-
log.Errorf("Connection %v: %s: Key is not RSA", connName, protocol.ErrCrypto)
441+
log.Errorf("Connection %v: sni=%s request-id=%s: %s: Key is not RSA", connName, pkt.Operation.SNI, reqID, protocol.ErrCrypto)
406442
return makeErrResponse(pkt, protocol.ErrCrypto)
407443
}
408444

409445
if rsaKey, ok := key.(*rsa.PrivateKey); ok {
410446
// Decrypt without removing padding; that's the client's responsibility.
411447
ptxt, err := textbook_rsa.Decrypt(rsaKey, pkt.Operation.Payload)
412448
if err != nil {
413-
log.Errorf("connection %v: %v", connName, err)
449+
log.Errorf("connection %v: sni=%s ip=%s ski=%v request-id=%s: %v", connName, pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, err)
414450
return makeErrResponse(pkt, protocol.ErrCrypto)
415451
}
416452
return makeRespondResponse(pkt, ptxt)
417453
}
418454

419455
rsaKey, ok := key.(crypto.Decrypter)
420456
if !ok {
421-
log.Errorf("Connection %v: %s: Key is not Decrypter", connName, protocol.ErrCrypto)
457+
log.Errorf("Connection %v: sni=%s request-id=%s: %s: Key is not Decrypter", connName, pkt.Operation.SNI, reqID, protocol.ErrCrypto)
422458
return makeErrResponse(pkt, protocol.ErrCrypto)
423459
}
424460

425461
ptxt, err := rsaKey.Decrypt(nil, pkt.Operation.Payload, nil)
426462
if err != nil {
427-
log.Errorf("Connection %v: %s: Decryption error: %v", connName, protocol.ErrCrypto, err)
463+
log.Errorf("Connection %v: sni=%s ip=%s ski=%v request-id=%s: %s: Decryption error: %v", connName, pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, protocol.ErrCrypto, err)
428464
return makeErrResponse(pkt, protocol.ErrCrypto)
429465
}
430466

@@ -457,10 +493,10 @@ func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
457493
key, err := s.keys.Get(ctx, &pkt.Operation)
458494
logKeyLoadDuration(loadStart)
459495
if err != nil {
460-
log.Errorf("failed to load key with sni=%s ip=%s ski=%v: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, err)
496+
log.Errorf("failed to load key with sni=%s ip=%s ski=%v request-id=%s: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, err)
461497
return makeErrResponse(pkt, protocol.ErrInternal)
462498
} else if key == nil {
463-
log.Errorf("failed to load key with sni=%s ip=%s ski=%v: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, protocol.ErrKeyNotFound)
499+
log.Errorf("failed to load key with sni=%s ip=%s ski=%v request-id=%s: %v", pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, protocol.ErrKeyNotFound)
464500
return makeErrResponse(pkt, protocol.ErrKeyNotFound)
465501
}
466502

@@ -490,17 +526,17 @@ func (s *Server) unlimitedDo(pkt *protocol.Packet, connName string) response {
490526
}
491527
if err != nil {
492528
if attempts > 1 {
493-
log.Debugf("Connection %v: failed sign attempt: %s, %d attempt(s) left", connName, err, attempts-1)
529+
log.Debugf("Connection %v sni=%s ip=%s ski=%v request-id=%s : failed sign attempt: %s, %d attempt(s) left", connName, pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, err, attempts-1)
494530
continue
495531
} else {
496532
tracing.LogError(span, err)
497533
// This indicates that a remote keyserver is being used
498534
var remoteConfigurationErr RemoteConfigurationErr
499535
if errors.As(err, &remoteConfigurationErr) {
500-
log.Errorf("Connection %v: %s: Signing error: %v\n", connName, protocol.ErrRemoteConfiguration, err)
536+
log.Errorf("Connection %v sni=%s ip=%s ski=%v request-id=%s : %s: Signing error: %v\n", connName, pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, protocol.ErrRemoteConfiguration, err)
501537
return makeErrResponse(pkt, protocol.ErrRemoteConfiguration)
502538
} else {
503-
log.Errorf("Connection %v: %s: Signing error: %v\n", connName, protocol.ErrCrypto, err)
539+
log.Errorf("Connection %v sni=%s ip=%s ski=%v request-id=%s : %s: Signing error: %v\n", connName, pkt.Operation.SNI, pkt.Operation.ServerIP, pkt.Operation.SKI, reqID, protocol.ErrCrypto, err)
504540
return makeErrResponse(pkt, protocol.ErrCrypto)
505541
}
506542
}

server/utils_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package server
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/json"
6+
"testing"
7+
8+
"github.com/cloudflare/gokeyless/protocol"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestRequestID(t *testing.T) {
13+
require := require.New(t)
14+
15+
r := make([]byte, 20)
16+
_, err := rand.Read(r)
17+
require.NoError(err)
18+
19+
// empty byte array in ReqContext
20+
op := protocol.Operation{
21+
Opcode: protocol.OpECDSASignSHA224,
22+
Payload: r,
23+
ReqContext: []byte{},
24+
}
25+
reqID := addOperationRequestID(&op)
26+
require.NotEqual(reqID, "")
27+
28+
// nil byte array
29+
op.ReqContext = nil
30+
reqID = addOperationRequestID(&op)
31+
require.NotEqual(reqID, "")
32+
33+
// Operation.ReqContext contains a map and request id
34+
rc := map[string]interface{}{"request_id": "b76dfaf1-a852-4dc2-98ff-0ba1947a82b6"}
35+
b, err := json.Marshal(rc)
36+
require.NoError(err)
37+
op.ReqContext = b
38+
reqID = addOperationRequestID(&op)
39+
require.Equal(reqID, "b76dfaf1-a852-4dc2-98ff-0ba1947a82b6")
40+
}

vendor/github.com/google/uuid/CHANGELOG.md

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/google/uuid/CONTRIBUTING.md

+26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/google/uuid/CONTRIBUTORS

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/google/uuid/LICENSE

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/google/uuid/README.md

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)