Skip to content

Commit 375414c

Browse files
committed
[v18] web: Add web eksAuditLogs to integration configure endpoint
Extend the web endpoint for the webscript for integrations configure access-graph-cloud-sync-iam.sh to add the `eksAuditLogs` query param to configure with EKS audit logs enabled. Add tests for this endpoint as there were none.
1 parent 35f47b9 commit 375414c

File tree

2 files changed

+176
-2
lines changed

2 files changed

+176
-2
lines changed

lib/web/integrations_awsoidc.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"maps"
2626
"net/http"
2727
"slices"
28+
"strconv"
2829
"strings"
2930

3031
"github.com/aws/aws-sdk-go-v2/aws/arn"
@@ -1379,6 +1380,19 @@ func (h *Handler) awsAccessGraphOIDCSync(w http.ResponseWriter, r *http.Request,
13791380
}
13801381
}
13811382

1383+
if eksAuditLogs := queryParams.Get("eksAuditLogs"); eksAuditLogs != "" {
1384+
enabled, err := strconv.ParseBool(eksAuditLogs)
1385+
if err != nil {
1386+
// The error returned by ParseBool contains no more information than this
1387+
// error. As we canot wrap both it and trace.BadParameter, we do the
1388+
// latter as a preferred error type.
1389+
return nil, trace.BadParameter("invalid boolean value for eksAuditLogs %q", eksAuditLogs)
1390+
}
1391+
if enabled {
1392+
argsList = append(argsList, "--eks-audit-logs")
1393+
}
1394+
}
1395+
13821396
script, err := oneoff.BuildScript(oneoff.OneOffScriptParams{
13831397
EntrypointArgs: strings.Join(argsList, " "),
13841398
SuccessMessage: "Success! You can now go back to the Teleport Web UI to complete the Access Graph AWS Sync enrollment.",

lib/web/integrations_awsoidc_test.go

Lines changed: 162 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,173 @@ func TestBuildEC2SSMIAMScript(t *testing.T) {
310310
}
311311
}
312312

313+
func TestBuildAccessGraphCloudSyncIAMScript(t *testing.T) {
314+
t.Parallel()
315+
isBadParamErrFn := func(tt require.TestingT, err error, i ...any) {
316+
require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err)
317+
}
318+
319+
env := newWebPack(t, 1)
320+
321+
// Unauthenticated client for script downloading.
322+
anonymousHTTPClient := env.proxies[0].newClient(t)
323+
pathVars := []string{
324+
"webapi",
325+
"scripts",
326+
"integrations",
327+
"configure",
328+
"access-graph-cloud-sync-iam.sh",
329+
}
330+
endpoint := anonymousHTTPClient.Endpoint(pathVars...)
331+
332+
role := "myRole"
333+
awsAccountID := "123456789012"
334+
sqsUrl := "https://sqs.us-west-2.amazonaws.com/123456789012/queue-name"
335+
cloudTrailS3Bucket := "arn:aws:s3:::bucket-name"
336+
kmsKey1 := "arn:aws:kms:us-west-2:123456789012:key/00000000-1111-2222-3333-444444444444"
337+
kmsKey2 := "arn:aws:kms:us-west-2:123456789012:key/55555555-6666-7777-8888-999999999999"
338+
339+
tests := []struct {
340+
name string
341+
reqRelativeURL string
342+
reqQuery url.Values
343+
errCheck require.ErrorAssertionFunc
344+
expectedTeleportArgs string
345+
}{
346+
{
347+
name: "valid",
348+
reqQuery: url.Values{
349+
"kind": []string{"aws-iam"},
350+
"role": []string{role},
351+
"awsAccountID": []string{awsAccountID},
352+
},
353+
errCheck: require.NoError,
354+
expectedTeleportArgs: "integration configure access-graph aws-iam" +
355+
" --role=" + role +
356+
" --aws-account-id=" + awsAccountID,
357+
},
358+
{
359+
name: "valid with cloud trail",
360+
reqQuery: url.Values{
361+
"kind": []string{"aws-iam"},
362+
"role": []string{role},
363+
"awsAccountID": []string{awsAccountID},
364+
"sqsUrl": []string{sqsUrl},
365+
"cloudTrailS3Bucket": []string{cloudTrailS3Bucket},
366+
"kmsKeysARNs": []string{kmsKey1, kmsKey2},
367+
},
368+
errCheck: require.NoError,
369+
expectedTeleportArgs: "integration configure access-graph aws-iam" +
370+
" --role=" + role +
371+
" --aws-account-id=" + awsAccountID +
372+
" --sqs-queue-url=" + sqsUrl +
373+
" --cloud-trail-bucket=" + cloudTrailS3Bucket +
374+
" --kms-key=" + kmsKey1 +
375+
" --kms-key=" + kmsKey2,
376+
},
377+
{
378+
name: "valid with eks audit logs",
379+
reqQuery: url.Values{
380+
"kind": []string{"aws-iam"},
381+
"role": []string{role},
382+
"awsAccountID": []string{awsAccountID},
383+
"eksAuditLogs": []string{"true"},
384+
},
385+
errCheck: require.NoError,
386+
expectedTeleportArgs: "integration configure access-graph aws-iam" +
387+
" --role=" + role +
388+
" --aws-account-id=" + awsAccountID +
389+
" --eks-audit-logs",
390+
},
391+
{
392+
name: "valid with cloud trail and eks audit logs",
393+
reqQuery: url.Values{
394+
"kind": []string{"aws-iam"},
395+
"role": []string{role},
396+
"awsAccountID": []string{awsAccountID},
397+
"sqsUrl": []string{sqsUrl},
398+
"cloudTrailS3Bucket": []string{cloudTrailS3Bucket},
399+
"kmsKeysARNs": []string{kmsKey1, kmsKey2},
400+
"eksAuditLogs": []string{"true"},
401+
},
402+
errCheck: require.NoError,
403+
expectedTeleportArgs: "integration configure access-graph aws-iam" +
404+
" --role=" + role +
405+
" --aws-account-id=" + awsAccountID +
406+
" --sqs-queue-url=" + sqsUrl +
407+
" --cloud-trail-bucket=" + cloudTrailS3Bucket +
408+
" --kms-key=" + kmsKey1 +
409+
" --kms-key=" + kmsKey2 +
410+
" --eks-audit-logs",
411+
},
412+
{
413+
name: "valid with symbols in role",
414+
reqQuery: url.Values{
415+
"kind": []string{"aws-iam"},
416+
"role": []string{"Test+1=2,3.4@5-6_7"},
417+
"awsAccountID": []string{"123456789012"},
418+
},
419+
errCheck: require.NoError,
420+
expectedTeleportArgs: "integration configure access-graph aws-iam " +
421+
"--role=Test\\+1=2,3.4\\@5-6_7 " +
422+
"--aws-account-id=123456789012",
423+
},
424+
{
425+
name: "missing kind",
426+
reqQuery: url.Values{
427+
"role": []string{"myRole"},
428+
"awsAccountID": []string{"123456789012"},
429+
},
430+
errCheck: isBadParamErrFn,
431+
},
432+
{
433+
name: "missing role",
434+
reqQuery: url.Values{
435+
"kind": []string{"aws-iam"},
436+
"awsAccountID": []string{"123456789012"},
437+
},
438+
errCheck: isBadParamErrFn,
439+
},
440+
{
441+
name: "missing awsAccountID",
442+
reqQuery: url.Values{
443+
"kind": []string{"aws-iam"},
444+
"role": []string{"myRole"},
445+
},
446+
errCheck: isBadParamErrFn,
447+
},
448+
{
449+
name: "trying to inject escape sequence into query params",
450+
reqQuery: url.Values{
451+
"kind": []string{"aws-iam"},
452+
"role": []string{"'; rm -rf /tmp/dir; echo '"},
453+
"awsAccountID": []string{"123456789012"},
454+
},
455+
errCheck: isBadParamErrFn,
456+
},
457+
}
458+
459+
for _, tc := range tests {
460+
t.Run(tc.name, func(t *testing.T) {
461+
resp, err := anonymousHTTPClient.Get(t.Context(), endpoint, tc.reqQuery)
462+
tc.errCheck(t, err)
463+
if err != nil {
464+
return
465+
}
466+
467+
require.Contains(t, string(resp.Bytes()),
468+
fmt.Sprintf("entrypointArgs='%s'\n", tc.expectedTeleportArgs),
469+
)
470+
})
471+
}
472+
}
473+
313474
func TestBuildAWSAppAccessConfigureIAMScript(t *testing.T) {
314475
t.Parallel()
315476
isBadParamErrFn := func(tt require.TestingT, err error, i ...any) {
316477
require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err)
317478
}
318479

319-
ctx := context.Background()
320480
env := newWebPack(t, 1)
321481

322482
// Unauthenticated client for script downloading.
@@ -372,7 +532,7 @@ func TestBuildAWSAppAccessConfigureIAMScript(t *testing.T) {
372532

373533
for _, tc := range tests {
374534
t.Run(tc.name, func(t *testing.T) {
375-
resp, err := anonymousHTTPClient.Get(ctx, endpoint, tc.reqQuery)
535+
resp, err := anonymousHTTPClient.Get(t.Context(), endpoint, tc.reqQuery)
376536
tc.errCheck(t, err)
377537
if err != nil {
378538
return

0 commit comments

Comments
 (0)