365 lines
16 KiB
Go
365 lines
16 KiB
Go
package iamauth
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewBearerToken(t *testing.T) {
|
|
cases := map[string]struct {
|
|
tokenStr string
|
|
config Config
|
|
expToken BearerToken
|
|
expError string
|
|
}{
|
|
"valid token": {
|
|
tokenStr: validBearerTokenJson,
|
|
expToken: validBearerTokenParsed,
|
|
},
|
|
"valid token with role": {
|
|
tokenStr: validBearerTokenWithRoleJson,
|
|
config: Config{
|
|
EnableIAMEntityDetails: true,
|
|
GetEntityMethodHeader: "X-Consul-IAM-GetEntity-Method",
|
|
GetEntityURLHeader: "X-Consul-IAM-GetEntity-URL",
|
|
GetEntityHeadersHeader: "X-Consul-IAM-GetEntity-Headers",
|
|
GetEntityBodyHeader: "X-Consul-IAM-GetEntity-Body",
|
|
},
|
|
expToken: validBearerTokenWithRoleParsed,
|
|
},
|
|
|
|
"empty json": {
|
|
tokenStr: `{}`,
|
|
expError: "unexpected end of JSON input",
|
|
},
|
|
"missing iam_request_method field": {
|
|
tokenStr: tokenJsonMissingMethodField,
|
|
expError: "iam_http_request_method must be POST",
|
|
},
|
|
"missing iam_request_url field": {
|
|
tokenStr: tokenJsonMissingUrlField,
|
|
expError: "url is invalid",
|
|
},
|
|
"missing iam_request_headers field": {
|
|
tokenStr: tokenJsonMissingHeadersField,
|
|
expError: "unexpected end of JSON input",
|
|
},
|
|
"missing iam_request_body field": {
|
|
tokenStr: tokenJsonMissingBodyField,
|
|
expError: "iam_request_body error",
|
|
},
|
|
"invalid json": {
|
|
tokenStr: `{`,
|
|
expError: "unexpected end of JSON input",
|
|
},
|
|
}
|
|
for name, c := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
token, err := NewBearerToken(c.tokenStr, &c.config)
|
|
t.Logf("token = %+v", token)
|
|
if c.expError != "" {
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), c.expError)
|
|
require.Nil(t, token)
|
|
} else {
|
|
require.NoError(t, err)
|
|
c.expToken.config = &c.config
|
|
require.Equal(t, &c.expToken, token)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseRequestBody(t *testing.T) {
|
|
cases := map[string]struct {
|
|
body string
|
|
allowedValues url.Values
|
|
expValues url.Values
|
|
expError string
|
|
}{
|
|
"one allowed field": {
|
|
body: "Action=GetCallerIdentity&Version=1234",
|
|
allowedValues: url.Values{"Version": []string{"1234"}},
|
|
expValues: url.Values{
|
|
"Action": []string{"GetCallerIdentity"},
|
|
"Version": []string{"1234"},
|
|
},
|
|
},
|
|
"many allowed fields": {
|
|
body: "Action=GetRole&RoleName=my-role&Version=1234",
|
|
allowedValues: url.Values{
|
|
"Action": []string{"GetUser", "GetRole"},
|
|
"UserName": nil,
|
|
"RoleName": nil,
|
|
"Version": nil,
|
|
},
|
|
expValues: url.Values{
|
|
"Action": []string{"GetRole"},
|
|
"RoleName": []string{"my-role"},
|
|
"Version": []string{"1234"},
|
|
},
|
|
},
|
|
"action only": {
|
|
body: "Action=GetRole",
|
|
allowedValues: nil,
|
|
expValues: url.Values{"Action": []string{"GetRole"}},
|
|
},
|
|
|
|
"empty body": {
|
|
expValues: url.Values{},
|
|
expError: `missing field "Action"`,
|
|
},
|
|
"disallowed field": {
|
|
body: "Action=GetRole&Version=1234&Extra=Abc",
|
|
allowedValues: url.Values{"Action": nil, "Version": nil},
|
|
expError: `unexpected field "Extra"`,
|
|
},
|
|
"mismatched action": {
|
|
body: "Action=GetRole",
|
|
allowedValues: url.Values{"Action": []string{"GetUser"}},
|
|
expError: `unexpected value Action=[GetRole]`,
|
|
},
|
|
"mismatched field": {
|
|
body: "Action=GetRole&Extra=1234",
|
|
allowedValues: url.Values{"Action": nil, "Extra": []string{"abc"}},
|
|
expError: `unexpected value Extra=[1234]`,
|
|
},
|
|
"multi-valued field": {
|
|
body: "Action=GetRole&Action=GetUser",
|
|
allowedValues: url.Values{"Action": []string{"GetRole", "GetUser"}},
|
|
// only one value is allowed.
|
|
expError: `unexpected value Action=[GetRole GetUser]`,
|
|
},
|
|
"empty action": {
|
|
body: "Action=",
|
|
allowedValues: nil,
|
|
expError: `missing field "Action"`,
|
|
},
|
|
"missing action": {
|
|
body: "Version=1234",
|
|
allowedValues: url.Values{"Action": []string{"GetRole"}},
|
|
expError: `missing field "Action"`,
|
|
},
|
|
}
|
|
for name, c := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
values, err := parseRequestBody(c.body, c.allowedValues)
|
|
if c.expError != "" {
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), c.expError)
|
|
require.Nil(t, values)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.Equal(t, c.expValues, values)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateGetCallerIdentityBody(t *testing.T) {
|
|
cases := map[string]struct {
|
|
body string
|
|
expError string
|
|
}{
|
|
"valid": {"Action=GetCallerIdentity&Version=1234", ""},
|
|
"valid 2": {"Action=GetCallerIdentity", ""},
|
|
"empty action": {
|
|
"Action=",
|
|
`iam_request_body error: missing field "Action"`,
|
|
},
|
|
"invalid action": {
|
|
"Action=GetRole",
|
|
`iam_request_body error: unexpected value Action=[GetRole]`,
|
|
},
|
|
"missing action": {
|
|
"Version=1234",
|
|
`iam_request_body error: missing field "Action"`,
|
|
},
|
|
"empty": {
|
|
"",
|
|
`iam_request_body error: missing field "Action"`,
|
|
},
|
|
}
|
|
for name, c := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
token := &BearerToken{getCallerIdentityBody: c.body}
|
|
err := token.validateGetCallerIdentityBody()
|
|
if c.expError != "" {
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), c.expError)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateIAMEntityBody(t *testing.T) {
|
|
cases := map[string]struct {
|
|
body string
|
|
expReqType string
|
|
expError string
|
|
}{
|
|
"valid role": {
|
|
body: "Action=GetRole&RoleName=my-role&Version=1234",
|
|
expReqType: "GetRole",
|
|
},
|
|
"valid role without version": {
|
|
body: "Action=GetRole&RoleName=my-role",
|
|
expReqType: "GetRole",
|
|
},
|
|
"valid user": {
|
|
body: "Action=GetUser&UserName=my-role&Version=1234",
|
|
expReqType: "GetUser",
|
|
},
|
|
"valid user without version": {
|
|
body: "Action=GetUser&UserName=my-role",
|
|
expReqType: "GetUser",
|
|
},
|
|
|
|
"invalid action": {
|
|
body: "Action=GetCallerIdentity",
|
|
expError: `unexpected value Action=[GetCallerIdentity]`,
|
|
},
|
|
"role missing action": {
|
|
body: "RoleName=my-role&Version=1234",
|
|
expError: `missing field "Action"`,
|
|
},
|
|
"user missing action": {
|
|
body: "UserName=my-role&Version=1234",
|
|
expError: `missing field "Action"`,
|
|
},
|
|
"empty": {
|
|
body: "",
|
|
expError: `missing field "Action"`,
|
|
},
|
|
"empty action": {
|
|
body: "Action=",
|
|
expError: `missing field "Action"`,
|
|
},
|
|
"role with user name": {
|
|
body: "Action=GetRole&UserName=my-role&Version=1234",
|
|
expError: `invalid request body`,
|
|
},
|
|
"user with role name": {
|
|
body: "Action=GetUser&RoleName=my-role&Version=1234",
|
|
expError: `invalid request body`,
|
|
},
|
|
}
|
|
for name, c := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
token := &BearerToken{
|
|
config: &Config{},
|
|
getIAMEntityBody: c.body,
|
|
}
|
|
reqType, err := token.validateIAMEntityBody()
|
|
if c.expError != "" {
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), c.expError)
|
|
require.Equal(t, "", reqType)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.Equal(t, c.expReqType, reqType)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var (
|
|
validBearerTokenJson = `{
|
|
"iam_http_request_method":"POST",
|
|
"iam_request_body":"QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==",
|
|
"iam_request_headers":"eyJBdXRob3JpemF0aW9uIjpbIkFXUzQtSE1BQy1TSEEyNTYgQ3JlZGVudGlhbD1mYWtlLzIwMjIwMzIyL3VzLWVhc3QtMS9zdHMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWNvbnRlbnQtbGVuZ3RoO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT1lZmMzMjBiOTcyZDA3YjM4YjY1ZWIyNDI1NjgwNWUwMzE0OWRhNTg2ZDgwNGY4YzYzNjRjZTk4ZGViZTA4MGIxIl0sIkNvbnRlbnQtTGVuZ3RoIjpbIjQzIl0sIkNvbnRlbnQtVHlwZSI6WyJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9dXRmLTgiXSwiVXNlci1BZ2VudCI6WyJhd3Mtc2RrLWdvLzEuNDIuMzQgKGdvMS4xNy41OyBkYXJ3aW47IGFtZDY0KSJdLCJYLUFtei1EYXRlIjpbIjIwMjIwMzIyVDIxMTEwM1oiXSwiWC1BbXotU2VjdXJpdHktVG9rZW4iOlsiZmFrZSJdfQ==",
|
|
"iam_request_url":"aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8="
|
|
}`
|
|
|
|
validBearerTokenParsed = BearerToken{
|
|
getCallerIdentityMethod: "POST",
|
|
getCallerIdentityURL: "https://sts.amazonaws.com/",
|
|
getCallerIdentityHeader: http.Header{
|
|
"Authorization": []string{"AWS4-HMAC-SHA256 Credential=fake/20220322/us-east-1/sts/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date;x-amz-security-token, Signature=efc320b972d07b38b65eb24256805e03149da586d804f8c6364ce98debe080b1"},
|
|
"Content-Length": []string{"43"},
|
|
"Content-Type": []string{"application/x-www-form-urlencoded; charset=utf-8"},
|
|
"User-Agent": []string{"aws-sdk-go/1.42.34 (go1.17.5; darwin; amd64)"},
|
|
"X-Amz-Date": []string{"20220322T211103Z"},
|
|
"X-Amz-Security-Token": []string{"fake"},
|
|
},
|
|
getCallerIdentityBody: "Action=GetCallerIdentity&Version=2011-06-15",
|
|
parsedCallerIdentityURL: &url.URL{
|
|
Scheme: "https",
|
|
Host: "sts.amazonaws.com",
|
|
Path: "/",
|
|
},
|
|
}
|
|
|
|
validBearerTokenWithRoleJson = `{"iam_http_request_method":"POST","iam_request_body":"QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==","iam_request_headers":"eyJBdXRob3JpemF0aW9uIjpbIkFXUzQtSE1BQy1TSEEyNTYgQ3JlZGVudGlhbD1mYWtlLWtleS1pZC8yMDIyMDMyMi9mYWtlLXJlZ2lvbi9zdHMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWNvbnRlbnQtbGVuZ3RoO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1jb25zdWwtaWFtLWdldGVudGl0eS1ib2R5O3gtY29uc3VsLWlhbS1nZXRlbnRpdHktaGVhZGVyczt4LWNvbnN1bC1pYW0tZ2V0ZW50aXR5LW1ldGhvZDt4LWNvbnN1bC1pYW0tZ2V0ZW50aXR5LXVybCwgU2lnbmF0dXJlPTU2MWFjMzFiNWFkMDFjMTI0YzU0YzE2OGY3NmVhNmJmZDY0NWI4ZWM1MzQ1ZjgzNTc3MjljOWFhMGI0NzEzMzciXSwiQ29udGVudC1MZW5ndGgiOlsiNDMiXSwiQ29udGVudC1UeXBlIjpbImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDsgY2hhcnNldD11dGYtOCJdLCJVc2VyLUFnZW50IjpbImF3cy1zZGstZ28vMS40Mi4zNCAoZ28xLjE3LjU7IGRhcndpbjsgYW1kNjQpIl0sIlgtQW16LURhdGUiOlsiMjAyMjAzMjJUMjI1NzQyWiJdLCJYLUNvbnN1bC1JYW0tR2V0ZW50aXR5LUJvZHkiOlsiQWN0aW9uPUdldFJvbGVcdTAwMjZSb2xlTmFtZT1teS1yb2xlXHUwMDI2VmVyc2lvbj0yMDEwLTA1LTA4Il0sIlgtQ29uc3VsLUlhbS1HZXRlbnRpdHktSGVhZGVycyI6WyJ7XCJBdXRob3JpemF0aW9uXCI6W1wiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPWZha2Uta2V5LWlkLzIwMjIwMzIyL3VzLWVhc3QtMS9pYW0vYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWNvbnRlbnQtbGVuZ3RoO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGUsIFNpZ25hdHVyZT1hYTJhMTlkMGEzMDVkNzRiYmQwMDk3NzZiY2E4ODBlNTNjZmE5OTFlNDgzZTQwMzk0NzE4MWE0MWNjNDgyOTQwXCJdLFwiQ29udGVudC1MZW5ndGhcIjpbXCI1MFwiXSxcIkNvbnRlbnQtVHlwZVwiOltcImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDsgY2hhcnNldD11dGYtOFwiXSxcIlVzZXItQWdlbnRcIjpbXCJhd3Mtc2RrLWdvLzEuNDIuMzQgKGdvMS4xNy41OyBkYXJ3aW47IGFtZDY0KVwiXSxcIlgtQW16LURhdGVcIjpbXCIyMDIyMDMyMlQyMjU3NDJaXCJdfSJdLCJYLUNvbnN1bC1JYW0tR2V0ZW50aXR5LU1ldGhvZCI6WyJQT1NUIl0sIlgtQ29uc3VsLUlhbS1HZXRlbnRpdHktVXJsIjpbImh0dHBzOi8vaWFtLmFtYXpvbmF3cy5jb20vIl19","iam_request_url":"aHR0cDovLzEyNy4wLjAuMTo2MzY5Ni9zdHMv"}`
|
|
|
|
validBearerTokenWithRoleParsed = BearerToken{
|
|
getCallerIdentityMethod: "POST",
|
|
getCallerIdentityURL: "http://127.0.0.1:63696/sts/",
|
|
getCallerIdentityHeader: http.Header{
|
|
"Authorization": []string{"AWS4-HMAC-SHA256 Credential=fake-key-id/20220322/fake-region/sts/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date;x-consul-iam-getentity-body;x-consul-iam-getentity-headers;x-consul-iam-getentity-method;x-consul-iam-getentity-url, Signature=561ac31b5ad01c124c54c168f76ea6bfd645b8ec5345f8357729c9aa0b471337"},
|
|
"Content-Length": []string{"43"},
|
|
"Content-Type": []string{"application/x-www-form-urlencoded; charset=utf-8"},
|
|
"User-Agent": []string{"aws-sdk-go/1.42.34 (go1.17.5; darwin; amd64)"},
|
|
"X-Amz-Date": []string{"20220322T225742Z"},
|
|
"X-Consul-Iam-Getentity-Body": []string{"Action=GetRole&RoleName=my-role&Version=2010-05-08"},
|
|
"X-Consul-Iam-Getentity-Headers": []string{`{"Authorization":["AWS4-HMAC-SHA256 Credential=fake-key-id/20220322/us-east-1/iam/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=aa2a19d0a305d74bbd009776bca880e53cfa991e483e403947181a41cc482940"],"Content-Length":["50"],"Content-Type":["application/x-www-form-urlencoded; charset=utf-8"],"User-Agent":["aws-sdk-go/1.42.34 (go1.17.5; darwin; amd64)"],"X-Amz-Date":["20220322T225742Z"]}`},
|
|
"X-Consul-Iam-Getentity-Method": []string{"POST"},
|
|
"X-Consul-Iam-Getentity-Url": []string{"https://iam.amazonaws.com/"},
|
|
},
|
|
getCallerIdentityBody: "Action=GetCallerIdentity&Version=2011-06-15",
|
|
|
|
// Fields parsed from headers above
|
|
getIAMEntityMethod: "POST",
|
|
getIAMEntityURL: "https://iam.amazonaws.com/",
|
|
getIAMEntityHeader: http.Header{
|
|
"Authorization": []string{"AWS4-HMAC-SHA256 Credential=fake-key-id/20220322/us-east-1/iam/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=aa2a19d0a305d74bbd009776bca880e53cfa991e483e403947181a41cc482940"},
|
|
"Content-Length": []string{"50"},
|
|
"Content-Type": []string{"application/x-www-form-urlencoded; charset=utf-8"},
|
|
"User-Agent": []string{"aws-sdk-go/1.42.34 (go1.17.5; darwin; amd64)"},
|
|
"X-Amz-Date": []string{"20220322T225742Z"},
|
|
},
|
|
getIAMEntityBody: "Action=GetRole&RoleName=my-role&Version=2010-05-08",
|
|
entityRequestType: "GetRole",
|
|
|
|
parsedCallerIdentityURL: &url.URL{
|
|
Scheme: "http",
|
|
Host: "127.0.0.1:63696",
|
|
Path: "/sts/",
|
|
},
|
|
parsedIAMEntityURL: &url.URL{
|
|
Scheme: "https",
|
|
Host: "iam.amazonaws.com",
|
|
Path: "/",
|
|
},
|
|
}
|
|
|
|
tokenJsonMissingMethodField = `{
|
|
"iam_request_body":"QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==",
|
|
"iam_request_headers":"eyJBdXRob3JpemF0aW9uIjpbIkFXUzQtSE1BQy1TSEEyNTYgQ3JlZGVudGlhbD1mYWtlLzIwMjIwMzIyL3VzLWVhc3QtMS9zdHMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWNvbnRlbnQtbGVuZ3RoO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT1lZmMzMjBiOTcyZDA3YjM4YjY1ZWIyNDI1NjgwNWUwMzE0OWRhNTg2ZDgwNGY4YzYzNjRjZTk4ZGViZTA4MGIxIl0sIkNvbnRlbnQtTGVuZ3RoIjpbIjQzIl0sIkNvbnRlbnQtVHlwZSI6WyJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9dXRmLTgiXSwiVXNlci1BZ2VudCI6WyJhd3Mtc2RrLWdvLzEuNDIuMzQgKGdvMS4xNy41OyBkYXJ3aW47IGFtZDY0KSJdLCJYLUFtei1EYXRlIjpbIjIwMjIwMzIyVDIxMTEwM1oiXSwiWC1BbXotU2VjdXJpdHktVG9rZW4iOlsiZmFrZSJdfQ==",
|
|
"iam_request_url":"aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8="
|
|
}`
|
|
|
|
tokenJsonMissingBodyField = `{
|
|
"iam_http_request_method":"POST",
|
|
"iam_request_headers":"eyJBdXRob3JpemF0aW9uIjpbIkFXUzQtSE1BQy1TSEEyNTYgQ3JlZGVudGlhbD1mYWtlLzIwMjIwMzIyL3VzLWVhc3QtMS9zdHMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWNvbnRlbnQtbGVuZ3RoO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT1lZmMzMjBiOTcyZDA3YjM4YjY1ZWIyNDI1NjgwNWUwMzE0OWRhNTg2ZDgwNGY4YzYzNjRjZTk4ZGViZTA4MGIxIl0sIkNvbnRlbnQtTGVuZ3RoIjpbIjQzIl0sIkNvbnRlbnQtVHlwZSI6WyJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9dXRmLTgiXSwiVXNlci1BZ2VudCI6WyJhd3Mtc2RrLWdvLzEuNDIuMzQgKGdvMS4xNy41OyBkYXJ3aW47IGFtZDY0KSJdLCJYLUFtei1EYXRlIjpbIjIwMjIwMzIyVDIxMTEwM1oiXSwiWC1BbXotU2VjdXJpdHktVG9rZW4iOlsiZmFrZSJdfQ==",
|
|
"iam_request_url":"aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8="
|
|
}`
|
|
|
|
tokenJsonMissingHeadersField = `{
|
|
"iam_http_request_method":"POST",
|
|
"iam_request_body":"QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==",
|
|
"iam_request_url":"aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8="
|
|
}`
|
|
|
|
tokenJsonMissingUrlField = `{
|
|
"iam_http_request_method":"POST",
|
|
"iam_request_body":"QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==",
|
|
"iam_request_headers":"eyJBdXRob3JpemF0aW9uIjpbIkFXUzQtSE1BQy1TSEEyNTYgQ3JlZGVudGlhbD1mYWtlLzIwMjIwMzIyL3VzLWVhc3QtMS9zdHMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWNvbnRlbnQtbGVuZ3RoO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT1lZmMzMjBiOTcyZDA3YjM4YjY1ZWIyNDI1NjgwNWUwMzE0OWRhNTg2ZDgwNGY4YzYzNjRjZTk4ZGViZTA4MGIxIl0sIkNvbnRlbnQtTGVuZ3RoIjpbIjQzIl0sIkNvbnRlbnQtVHlwZSI6WyJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9dXRmLTgiXSwiVXNlci1BZ2VudCI6WyJhd3Mtc2RrLWdvLzEuNDIuMzQgKGdvMS4xNy41OyBkYXJ3aW47IGFtZDY0KSJdLCJYLUFtei1EYXRlIjpbIjIwMjIwMzIyVDIxMTEwM1oiXSwiWC1BbXotU2VjdXJpdHktVG9rZW4iOlsiZmFrZSJdfQ=="
|
|
}`
|
|
)
|