Skip to content

Commit 260b7eb

Browse files
authored
Parse http headers as array of strings instead as string (#64)
1 parent e728839 commit 260b7eb

File tree

6 files changed

+44
-40
lines changed

6 files changed

+44
-40
lines changed

internal/capability/http/http.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ func (httpCapability *HttpCapability) Execute(
6767
return cacao.NewVariables(), err
6868
}
6969

70-
for key, httpCapability := range command.Headers {
71-
request.Header.Add(key, httpCapability)
70+
for key, httpHeaders := range command.Headers {
71+
for _, httpHeader := range httpHeaders {
72+
request.Header.Add(key, httpHeader)
73+
}
7274
}
7375
if target.ID != "" {
7476
if err := verifyAuthInfoMatchesAgentTarget(&target, &authentication); err != nil {

models/cacao/cacao.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ type ExtensionDefinition struct {
155155
}
156156

157157
type Command struct {
158-
Type string `bson:"type" json:"type" validate:"required"`
159-
Command string `bson:"command" json:"command" validate:"required"`
160-
Description string `bson:"description,omitempty" json:"description,omitempty"`
161-
CommandB64 string `bson:"command_b64,omitempty" json:"command_b64,omitempty"`
162-
Version string `bson:"version,omitempty" json:"version,omitempty"`
163-
PlaybookActivity string `bson:"playbook_activity,omitempty" json:"playbook_activity,omitempty"`
164-
Headers map[string]string `bson:"headers,omitempty" json:"headers,omitempty"`
165-
Content string `bson:"content,omitempty" json:"content,omitempty"`
166-
ContentB64 string `bson:"content_b64,omitempty" json:"content_b64,omitempty"`
158+
Type string `bson:"type" json:"type" validate:"required"`
159+
Command string `bson:"command" json:"command" validate:"required"`
160+
Description string `bson:"description,omitempty" json:"description,omitempty"`
161+
CommandB64 string `bson:"command_b64,omitempty" json:"command_b64,omitempty"`
162+
Version string `bson:"version,omitempty" json:"version,omitempty"`
163+
PlaybookActivity string `bson:"playbook_activity,omitempty" json:"playbook_activity,omitempty"`
164+
Headers map[string][]string `bson:"headers,omitempty" json:"headers,omitempty"`
165+
Content string `bson:"content,omitempty" json:"content,omitempty"`
166+
ContentB64 string `bson:"content_b64,omitempty" json:"content_b64,omitempty"`
167167
}
168168

169169
type Step struct {

test/integration/capability/http/http_integration_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestHttpConnection(t *testing.T) {
1616
expectedCommand := cacao.Command{
1717
Type: "http-api",
1818
Command: "GET https://httpbin.org/",
19-
Headers: map[string]string{"accept": "application/json"},
19+
Headers: map[string][]string{"accept": {"application/json"}},
2020
}
2121

2222
var variable1 = cacao.Variable{
@@ -56,7 +56,7 @@ func TestHttpOAuth2(t *testing.T) {
5656
expectedCommand := cacao.Command{
5757
Type: "http-api",
5858
Command: "GET https://httpbin.org/bearer",
59-
Headers: map[string]string{"accept": "application/json"},
59+
Headers: map[string][]string{"accept": {"application/json"}},
6060
}
6161

6262
var variable1 = cacao.Variable{
@@ -102,7 +102,7 @@ func TestHttpBasicAuth(t *testing.T) {
102102
expectedCommand := cacao.Command{
103103
Type: "http-api",
104104
Command: "GET https://httpbin.org/hidden-basic-auth/username_test/password_test",
105-
Headers: map[string]string{"accept": "application/json"},
105+
Headers: map[string][]string{"accept": {"application/json"}},
106106
}
107107

108108
var variable1 = cacao.Variable{

test/unittest/capability/openc2/openc2_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func TestOpenC2Request(t *testing.T) {
3838
command := cacao.Command{
3939
Type: "http-api",
4040
Command: "POST / HTTP/1.1",
41-
Headers: map[string]string{"accept": "application/json"},
41+
Headers: map[string][]string{"accept": {"application/json"}},
4242
}
4343

4444
cacaoVariable := cacao.Variable{

test/unittest/utils/http/http_test.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestHttpGetConnection(t *testing.T) {
4444
command := cacao.Command{
4545
Type: "http-api",
4646
Command: "GET / HTTP/1.1",
47-
Headers: map[string]string{"accept": "application/json"},
47+
Headers: map[string][]string{"accept": {"application/json"}},
4848
}
4949
httpOptions := http.HttpOptions{
5050
Command: &command,
@@ -72,7 +72,7 @@ func TestHttpPostConnection(t *testing.T) {
7272
command := cacao.Command{
7373
Type: "http-api",
7474
Command: "POST / HTTP/1.1",
75-
Headers: map[string]string{"accept": "application/json"},
75+
Headers: map[string][]string{"accept": {"application/json"}},
7676
}
7777
httpOptions := http.HttpOptions{
7878
Command: &command,
@@ -99,7 +99,7 @@ func TestHttpPutConnection(t *testing.T) {
9999
command := cacao.Command{
100100
Type: "http-api",
101101
Command: "PUT / HTTP/1.1",
102-
Headers: map[string]string{"accept": "application/json"},
102+
Headers: map[string][]string{"accept": {"application/json"}},
103103
}
104104
httpOptions := http.HttpOptions{
105105
Command: &command,
@@ -125,7 +125,7 @@ func TestHttpDeleteConnection(t *testing.T) {
125125
command := cacao.Command{
126126
Type: "http-api",
127127
Command: "DELETE / HTTP/1.1",
128-
Headers: map[string]string{"accept": "application/json"},
128+
Headers: map[string][]string{"accept": {"application/json"}},
129129
}
130130
httpOptions := http.HttpOptions{
131131
Command: &command,
@@ -153,7 +153,7 @@ func TestHttpStatus200(t *testing.T) {
153153
command := cacao.Command{
154154
Type: "http-api",
155155
Command: "GET / HTTP/1.1",
156-
Headers: map[string]string{"accept": "application/json"},
156+
Headers: map[string][]string{"accept": {"application/json"}},
157157
}
158158
httpOptions := http.HttpOptions{
159159
Command: &command,
@@ -186,7 +186,7 @@ func TestHttpBearerToken(t *testing.T) {
186186
command := cacao.Command{
187187
Type: "http-api",
188188
Command: "GET / HTTP/1.1",
189-
Headers: map[string]string{"accept": "application/json"},
189+
Headers: map[string][]string{"accept": {"application/json"}},
190190
}
191191
httpOptions := http.HttpOptions{
192192
Command: &command,
@@ -219,7 +219,7 @@ func TestHttpBasicAuth(t *testing.T) {
219219

220220
target := cacao.AgentTarget{
221221
Address: map[cacao.NetAddressType][]string{
222-
"url": []string{url},
222+
"url": {url},
223223
},
224224
AuthInfoIdentifier: "d0c7e6a0-f7fe-464e-9935-e6b3443f5b91",
225225
}
@@ -234,7 +234,7 @@ func TestHttpBasicAuth(t *testing.T) {
234234
command := cacao.Command{
235235
Type: "http-api",
236236
Command: "GET / HTTP/1.1",
237-
Headers: map[string]string{"accept": "application/json"},
237+
Headers: map[string][]string{"accept": {"application/json"}},
238238
}
239239
httpOptions := http.HttpOptions{
240240
Command: &command,
@@ -281,7 +281,7 @@ func TestHttpPostWithContentConnection(t *testing.T) {
281281
command := cacao.Command{
282282
Type: "http-api",
283283
Command: "POST / HTTP/1.1",
284-
Headers: map[string]string{"accept": "application/json"},
284+
Headers: map[string][]string{"accept": {"application/json"}},
285285
ContentB64: base64EncodedBody,
286286
}
287287
httpOptions := http.HttpOptions{
@@ -313,7 +313,7 @@ func TestHttpPathDnameParser(t *testing.T) {
313313
command := cacao.Command{
314314
Type: "http-api",
315315
Command: "POST /url HTTP/1.1",
316-
Headers: map[string]string{"accept": "application/json"},
316+
Headers: map[string][]string{"accept": {"application/json"}},
317317
}
318318
httpOptions := http.HttpOptions{
319319
Target: &target,
@@ -335,7 +335,7 @@ func TestHttpPathDnamePortParser(t *testing.T) {
335335
command := cacao.Command{
336336
Type: "http-api",
337337
Command: "POST /url HTTP/1.1",
338-
Headers: map[string]string{"accept": "application/json"},
338+
Headers: map[string][]string{"accept": {"application/json"}},
339339
}
340340
httpOptions := http.HttpOptions{
341341
Target: &target,
@@ -357,7 +357,7 @@ func TestHttpPathDnameRandomPortParser(t *testing.T) {
357357
command := cacao.Command{
358358
Type: "http-api",
359359
Command: "POST /url HTTP/1.1",
360-
Headers: map[string]string{"accept": "application/json"},
360+
Headers: map[string][]string{"accept": {"application/json"}},
361361
}
362362
httpOptions := http.HttpOptions{
363363
Target: &target,
@@ -379,7 +379,7 @@ func TestHttpPathIpv4Parser(t *testing.T) {
379379
command := cacao.Command{
380380
Type: "http-api",
381381
Command: "POST / HTTP/1.1",
382-
Headers: map[string]string{"accept": "application/json"},
382+
Headers: map[string][]string{"accept": {"application/json"}},
383383
}
384384
httpOptions := http.HttpOptions{
385385
Target: &target,
@@ -403,7 +403,7 @@ func TestHttpPathParser(t *testing.T) {
403403
command := cacao.Command{
404404
Type: "http-api",
405405
Command: "POST / HTTP/1.1",
406-
Headers: map[string]string{"accept": "application/json"},
406+
Headers: map[string][]string{"accept": {"application/json"}},
407407
}
408408
httpOptions := http.HttpOptions{
409409
Target: &target,
@@ -427,7 +427,7 @@ func TestHttpPathBreakingParser(t *testing.T) {
427427
command := cacao.Command{
428428
Type: "http-api",
429429
Command: "POST / HTTP/1.1",
430-
Headers: map[string]string{"accept": "application/json"},
430+
Headers: map[string][]string{"accept": {"application/json"}},
431431
}
432432
httpOptions := http.HttpOptions{
433433
Target: &target,
@@ -445,7 +445,7 @@ func TestMethodExtract(t *testing.T) {
445445
command := cacao.Command{
446446
Type: "http-api",
447447
Command: "POST /api1/newObject HTTP/1.1",
448-
Headers: map[string]string{"accept": "application/json"},
448+
Headers: map[string][]string{"accept": {"application/json"}},
449449
}
450450
method, err := http.GetMethodFrom(&command)
451451
if err != nil {
@@ -458,7 +458,7 @@ func TestPathExtract(t *testing.T) {
458458
command := cacao.Command{
459459
Type: "http-api",
460460
Command: "POST /api1/newObject HTTP/1.1",
461-
Headers: map[string]string{"accept": "application/json"},
461+
Headers: map[string][]string{"accept": {"application/json"}},
462462
}
463463
path, err := http.GetPathFrom(&command)
464464
if err != nil {
@@ -471,7 +471,7 @@ func TestVersionExtract(t *testing.T) {
471471
command := cacao.Command{
472472
Type: "http-api",
473473
Command: "POST /api1/newObject HTTP/1.1",
474-
Headers: map[string]string{"accept": "application/json"},
474+
Headers: map[string][]string{"accept": {"application/json"}},
475475
}
476476
version, err := http.GetVersionFrom(&command)
477477
if err != nil {
@@ -484,7 +484,7 @@ func TestCommandFailedExtract(t *testing.T) {
484484
command := cacao.Command{
485485
Type: "http-api",
486486
Command: "POST /api1/newObject",
487-
Headers: map[string]string{"accept": "application/json"},
487+
Headers: map[string][]string{"accept": {"application/json"}},
488488
}
489489
version, err := http.GetVersionFrom(&command)
490490
if err == nil {
@@ -501,7 +501,7 @@ func TestDnameWithInvalidPathParser(t *testing.T) {
501501
command := cacao.Command{
502502
Type: "http-api",
503503
Command: "POST /url HTTP/1.1",
504-
Headers: map[string]string{"accept": "application/json"},
504+
Headers: map[string][]string{"accept": {"application/json"}},
505505
}
506506
httpOptions := http.HttpOptions{
507507
Target: &target,
@@ -523,7 +523,7 @@ func TestHttpPathIpv4WithRandomPort(t *testing.T) {
523523
command := cacao.Command{
524524
Type: "http-api",
525525
Command: "POST /url HTTP/1.1",
526-
Headers: map[string]string{"accept": "application/json"},
526+
Headers: map[string][]string{"accept": {"application/json"}},
527527
}
528528
httpOptions := http.HttpOptions{
529529
Target: &target,
@@ -545,7 +545,7 @@ func TestInvalidDname(t *testing.T) {
545545
command := cacao.Command{
546546
Type: "http-api",
547547
Command: "POST /url HTTP/1.1",
548-
Headers: map[string]string{"accept": "application/json"},
548+
Headers: map[string][]string{"accept": {"application/json"}},
549549
}
550550
httpOptions := http.HttpOptions{
551551
Target: &target,
@@ -568,7 +568,7 @@ func TestInvalidIpv4(t *testing.T) {
568568
command := cacao.Command{
569569
Type: "http-api",
570570
Command: "POST /url HTTP/1.1",
571-
Headers: map[string]string{"accept": "application/json"},
571+
Headers: map[string][]string{"accept": {"application/json"}},
572572
}
573573
httpOptions := http.HttpOptions{
574574
Target: &target,

utils/http/http.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ func verifyAuthInfoMatchesAgentTarget(
115115
}
116116

117117
func (httpOptions *HttpOptions) addHeaderTo(request *http.Request) {
118-
for header_key, header_value := range httpOptions.Command.Headers {
119-
request.Header.Add(header_key, header_value)
118+
for headerKey, headerValues := range httpOptions.Command.Headers {
119+
for _, headerValue := range headerValues {
120+
request.Header.Add(headerKey, headerValue)
121+
}
120122
}
121123
}
122124

0 commit comments

Comments
 (0)