acl: Fix tag parsing for IAM users and roles in IAM auth method (#12797)
* acl: Fix tag parsing on IAM users and roles in IAM auth method * Add changelog
This commit is contained in:
parent
e62745c82c
commit
1a938e4a49
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
acl: Fix parsing of IAM user and role tags in IAM auth method
|
||||
```
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/hashicorp/consul/internal/iamauth/iamauthtest"
|
||||
"github.com/hashicorp/consul/internal/iamauth/responses"
|
||||
"github.com/hashicorp/consul/internal/iamauth/responsestest"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -18,11 +19,11 @@ func TestValidateLogin(t *testing.T) {
|
|||
var (
|
||||
serverForRoleMismatchedIds = &iamauthtest.Server{
|
||||
GetCallerIdentityResponse: f.ServerForRole.GetCallerIdentityResponse,
|
||||
GetRoleResponse: responsestest.MakeGetRoleResponse(f.RoleARN, "AAAAsomenonmatchingid"),
|
||||
GetRoleResponse: responsestest.MakeGetRoleResponse(f.RoleARN, "AAAAsomenonmatchingid", responses.Tags{}),
|
||||
}
|
||||
serverForUserMismatchedIds = &iamauthtest.Server{
|
||||
GetCallerIdentityResponse: f.ServerForUser.GetCallerIdentityResponse,
|
||||
GetUserResponse: responsestest.MakeGetUserResponse(f.UserARN, "AAAAsomenonmatchingid"),
|
||||
GetUserResponse: responsestest.MakeGetUserResponse(f.UserARN, "AAAAsomenonmatchingid", responses.Tags{}),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ func MakeFixture() Fixture {
|
|||
f.AssumedRoleARN, f.EntityIDWithSession, f.AccountID,
|
||||
),
|
||||
GetRoleResponse: responsestest.MakeGetRoleResponse(
|
||||
f.RoleARN, f.EntityID, toTags(f.RoleTags)...,
|
||||
f.RoleARN, f.EntityID, toTags(f.RoleTags),
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ func MakeFixture() Fixture {
|
|||
f.UserARN, f.EntityID, f.AccountID,
|
||||
),
|
||||
GetUserResponse: responsestest.MakeGetUserResponse(
|
||||
f.UserARN, f.EntityID, toTags(f.UserTags)...,
|
||||
f.UserARN, f.EntityID, toTags(f.UserTags),
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -155,15 +155,15 @@ func (f *Fixture) RoleTagValues() []string { return values(f.RoleTags) }
|
|||
func (f *Fixture) UserTagValues() []string { return values(f.UserTags) }
|
||||
|
||||
// toTags converts the map to a slice of responses.Tag
|
||||
func toTags(tags map[string]string) []responses.Tag {
|
||||
result := []responses.Tag{}
|
||||
func toTags(tags map[string]string) responses.Tags {
|
||||
members := []responses.TagMember{}
|
||||
for k, v := range tags {
|
||||
result = append(result, responses.Tag{
|
||||
members = append(members, responses.TagMember{
|
||||
Key: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
return result
|
||||
return responses.Tags{Members: members}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ type Role struct {
|
|||
Path string `xml:"Path"`
|
||||
RoleId string `xml:"RoleId"`
|
||||
RoleName string `xml:"RoleName"`
|
||||
Tags []Tag `xml:"Tags"`
|
||||
Tags Tags `xml:"Tags"`
|
||||
}
|
||||
|
||||
func (r *Role) EntityPath() string { return r.Path }
|
||||
|
@ -69,7 +69,7 @@ type User struct {
|
|||
Path string `xml:"Path"`
|
||||
UserId string `xml:"UserId"`
|
||||
UserName string `xml:"UserName"`
|
||||
Tags []Tag `xml:"Tags"`
|
||||
Tags Tags `xml:"Tags"`
|
||||
}
|
||||
|
||||
func (u *User) EntityPath() string { return u.Path }
|
||||
|
@ -78,14 +78,18 @@ func (u *User) EntityName() string { return u.UserName }
|
|||
func (u *User) EntityId() string { return u.UserId }
|
||||
func (u *User) EntityTags() map[string]string { return tagsToMap(u.Tags) }
|
||||
|
||||
type Tag struct {
|
||||
type Tags struct {
|
||||
Members []TagMember `xml:"member"`
|
||||
}
|
||||
|
||||
type TagMember struct {
|
||||
Key string `xml:"Key"`
|
||||
Value string `xml:"Value"`
|
||||
}
|
||||
|
||||
func tagsToMap(tags []Tag) map[string]string {
|
||||
func tagsToMap(tags Tags) map[string]string {
|
||||
result := map[string]string{}
|
||||
for _, tag := range tags {
|
||||
for _, tag := range tags.Members {
|
||||
result[tag.Key] = tag.Value
|
||||
}
|
||||
return result
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package responses
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -155,3 +156,138 @@ func TestCanonicalArn(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalXML(t *testing.T) {
|
||||
t.Run("user xml", func(t *testing.T) {
|
||||
var resp GetUserResponse
|
||||
err := xml.Unmarshal([]byte(rawUserXML), &resp)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedParsedUserXML, resp)
|
||||
})
|
||||
t.Run("role xml", func(t *testing.T) {
|
||||
var resp GetRoleResponse
|
||||
err := xml.Unmarshal([]byte(rawRoleXML), &resp)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedParsedRoleXML, resp)
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
rawUserXML = `<GetUserResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||
<GetUserResult>
|
||||
<User>
|
||||
<Path>/</Path>
|
||||
<Arn>arn:aws:iam::000000000000:user/my-user</Arn>
|
||||
<UserName>my-user</UserName>
|
||||
<UserId>AIDAexampleuserid</UserId>
|
||||
<CreateDate>2021-01-01T00:01:02Z</CreateDate>
|
||||
<Tags>
|
||||
<member>
|
||||
<Value>some-value</Value>
|
||||
<Key>some-tag</Key>
|
||||
</member>
|
||||
<member>
|
||||
<Value>another-value</Value>
|
||||
<Key>another-tag</Key>
|
||||
</member>
|
||||
<member>
|
||||
<Value>third-value</Value>
|
||||
<Key>third-tag</Key>
|
||||
</member>
|
||||
</Tags>
|
||||
</User>
|
||||
</GetUserResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>11815b96-cb16-4d33-b2cf-0042fa4db4cd</RequestId>
|
||||
</ResponseMetadata>
|
||||
</GetUserResponse>`
|
||||
|
||||
expectedParsedUserXML = GetUserResponse{
|
||||
XMLName: xml.Name{
|
||||
Space: "https://iam.amazonaws.com/doc/2010-05-08/",
|
||||
Local: "GetUserResponse",
|
||||
},
|
||||
GetUserResult: []GetUserResult{
|
||||
{
|
||||
User: User{
|
||||
Arn: "arn:aws:iam::000000000000:user/my-user",
|
||||
Path: "/",
|
||||
UserId: "AIDAexampleuserid",
|
||||
UserName: "my-user",
|
||||
Tags: Tags{
|
||||
Members: []TagMember{
|
||||
{Key: "some-tag", Value: "some-value"},
|
||||
{Key: "another-tag", Value: "another-value"},
|
||||
{Key: "third-tag", Value: "third-value"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ResponseMetadata: []ResponseMetadata{
|
||||
{RequestId: "11815b96-cb16-4d33-b2cf-0042fa4db4cd"},
|
||||
},
|
||||
}
|
||||
|
||||
rawRoleXML = `<GetRoleResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||
<GetRoleResult>
|
||||
<Role>
|
||||
<Path>/</Path>
|
||||
<AssumeRolePolicyDocument>some-json-document-that-we-ignore</AssumeRolePolicyDocument>
|
||||
<MaxSessionDuration>43200</MaxSessionDuration>
|
||||
<RoleId>AROAsomeuniqueid</RoleId>
|
||||
<RoleLastUsed>
|
||||
<LastUsedDate>2022-01-01T01:02:03Z</LastUsedDate>
|
||||
<Region>us-east-1</Region>
|
||||
</RoleLastUsed>
|
||||
<RoleName>my-role</RoleName>
|
||||
<Arn>arn:aws:iam::000000000000:role/my-role</Arn>
|
||||
<CreateDate>2020-01-01T00:00:01Z</CreateDate>
|
||||
<Tags>
|
||||
<member>
|
||||
<Value>some-value</Value>
|
||||
<Key>some-key</Key>
|
||||
</member>
|
||||
<member>
|
||||
<Value>another-value</Value>
|
||||
<Key>another-key</Key>
|
||||
</member>
|
||||
<member>
|
||||
<Value>a-third-value</Value>
|
||||
<Key>third-key</Key>
|
||||
</member>
|
||||
</Tags>
|
||||
</Role>
|
||||
</GetRoleResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>a9866067-c0e5-4b5e-86ba-429c1151e2fb</RequestId>
|
||||
</ResponseMetadata>
|
||||
</GetRoleResponse>`
|
||||
|
||||
expectedParsedRoleXML = GetRoleResponse{
|
||||
XMLName: xml.Name{
|
||||
Space: "https://iam.amazonaws.com/doc/2010-05-08/",
|
||||
Local: "GetRoleResponse",
|
||||
},
|
||||
GetRoleResult: []GetRoleResult{
|
||||
{
|
||||
Role: Role{
|
||||
Arn: "arn:aws:iam::000000000000:role/my-role",
|
||||
Path: "/",
|
||||
RoleId: "AROAsomeuniqueid",
|
||||
RoleName: "my-role",
|
||||
Tags: Tags{
|
||||
Members: []TagMember{
|
||||
{Key: "some-key", Value: "some-value"},
|
||||
{Key: "another-key", Value: "another-value"},
|
||||
{Key: "third-key", Value: "a-third-value"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ResponseMetadata: []ResponseMetadata{
|
||||
{RequestId: "a9866067-c0e5-4b5e-86ba-429c1151e2fb"},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ func MakeGetCallerIdentityResponse(arn, userId, accountId string) responses.GetC
|
|||
}
|
||||
}
|
||||
|
||||
func MakeGetRoleResponse(arn, id string, tags ...responses.Tag) responses.GetRoleResponse {
|
||||
func MakeGetRoleResponse(arn, id string, tags responses.Tags) responses.GetRoleResponse {
|
||||
if strings.Contains(id, ":") {
|
||||
panic("RoleId in GetRole response must not contain ':'")
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func MakeGetRoleResponse(arn, id string, tags ...responses.Tag) responses.GetRol
|
|||
}
|
||||
}
|
||||
|
||||
func MakeGetUserResponse(arn, id string, tags ...responses.Tag) responses.GetUserResponse {
|
||||
func MakeGetUserResponse(arn, id string, tags responses.Tags) responses.GetUserResponse {
|
||||
if strings.Contains(id, ":") {
|
||||
panic("UserId in GetUser resposne must not contain ':'")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue