Skip to content

Commit a2d0720

Browse files
committed
Indicate when req/res bodies have been redacted
1 parent 3aea883 commit a2d0720

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

pkg/utils/http_dump_transport.go

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"strings"
1010
)
1111

12+
const redactedString = "[REDACTED]"
13+
1214
type dumpTransport struct {
1315
roundTripper http.RoundTripper
1416
logRequest func([]byte)
@@ -22,7 +24,7 @@ func redactAuthz(req *http.Request) (restore func()) {
2224

2325
origAuthz := req.Header.Get("Authorization")
2426
if origAuthz != "" {
25-
req.Header.Set("Authorization", "[REDACTED]")
27+
req.Header.Set("Authorization", redactedString)
2628
restore = func() {
2729
req.Header.Set("Authorization", origAuthz)
2830
}
@@ -50,31 +52,77 @@ func redactBody(rc io.ReadCloser, rx *regexp.Regexp) (bool, io.ReadCloser, error
5052
return rx.Match(content.Bytes()), io.NopCloser(&content), nil
5153
}
5254

55+
func redactRequestBody(req *http.Request) (restore func()) {
56+
restore = func() {}
57+
58+
redactedReader := io.NopCloser(strings.NewReader(redactedString))
59+
60+
redact, origBody, _ := redactBody(req.Body, regexp.MustCompile(".*"))
61+
62+
if redact {
63+
origLength := req.ContentLength
64+
65+
req.Body = redactedReader
66+
req.ContentLength = int64(len(redactedString))
67+
68+
restore = func() {
69+
req.Body = origBody
70+
req.ContentLength = origLength
71+
}
72+
} else {
73+
req.Body = origBody
74+
}
75+
76+
return
77+
}
78+
79+
func redactResponseBody(res *http.Response) (restore func()) {
80+
restore = func() {}
81+
82+
redactedReader := io.NopCloser(strings.NewReader(redactedString))
83+
84+
redact, origBody, _ := redactBody(res.Body, regexp.MustCompile("{\"protected\":\".*\",\"payload\":\".*\",\"signature\":\".*\"}"))
85+
86+
if redact {
87+
origLength := res.ContentLength
88+
89+
res.Body = redactedReader
90+
res.ContentLength = int64(len(redactedString))
91+
92+
restore = func() {
93+
res.Body = origBody
94+
res.ContentLength = origLength
95+
}
96+
} else {
97+
res.Body = origBody
98+
}
99+
100+
return
101+
}
102+
53103
// dumpRequest logs the contents of a given HTTP request, but first:
54104
// 1. sanitizes the Authorization header
55105
// 2. sanitizes the request body if the request is for authentication
56106
func (d *dumpTransport) dumpRequest(req *http.Request) []byte {
57-
restore := redactAuthz(req)
58-
defer restore()
107+
restoreAuthz := redactAuthz(req)
108+
defer restoreAuthz()
59109

60-
redact := false
61-
var body io.ReadCloser
62110
if strings.Contains(req.URL.Path, "/authn") {
63-
redact, body, _ = redactBody(req.Body, regexp.MustCompile(".*"))
64-
req.Body = body
111+
restoreBody := redactRequestBody(req)
112+
defer restoreBody()
65113
}
66114

67-
dump, _ := httputil.DumpRequestOut(req, !redact)
115+
dump, _ := httputil.DumpRequestOut(req, true)
68116
return dump
69117
}
70118

71119
// dumpResponse logs the contents of a given HTTP response, but first
72120
// sanitizes the response body if it includes a Conjur token.
73121
func (d *dumpTransport) dumpResponse(res *http.Response) []byte {
74-
redact, body, _ := redactBody(res.Body, regexp.MustCompile("{\"protected\":\".*\",\"payload\":\".*\",\"signature\":\".*\"}"))
75-
res.Body = body
122+
restoreBody := redactResponseBody(res)
123+
defer restoreBody()
76124

77-
dump, _ := httputil.DumpResponse(res, !redact)
125+
dump, _ := httputil.DumpResponse(res, true)
78126
return dump
79127
}
80128

pkg/utils/http_dump_transport_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func TestDumpTransport(t *testing.T) {
3737
path: "/authn-xyz/account/login",
3838
body: "some-body",
3939
assert: func(t *testing.T, req *http.Request, dump string) {
40+
assert.Contains(t, dump, redactedString)
4041
assert.NotContains(t, dump, "some-body")
4142

4243
reqBody, err := ioutil.ReadAll(req.Body)
@@ -79,6 +80,7 @@ func TestDumpTransport(t *testing.T) {
7980
description: "Body is redacted if it contains a Conjur token",
8081
body: "{\"protected\":\"abcde\",\"payload\":\"fghijk\",\"signature\":\"lmnop\"}",
8182
assert: func(t *testing.T, res *http.Response, dump string) {
83+
assert.Contains(t, dump, redactedString)
8284
assert.NotContains(t, dump, "{\"protected\":\"abcde\",\"payload\":\"fghijk\",\"signature\":\"lmnop\"}")
8385

8486
reqBody, err := ioutil.ReadAll(res.Body)

0 commit comments

Comments
 (0)