mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 09:01:31 +00:00
feat: ListAccountAliases
This commit is contained in:
@@ -17,7 +17,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
The platform serves **397 operations** across the AWS APIs below. Every page names the operations its service implements from the pinned model, generated from the dispatch tables on each build rather than written by hand.
|
||||
The platform serves **398 operations** across the AWS APIs below. Every page names the operations its service implements from the pinned model, generated from the dispatch tables on each build rather than written by hand.
|
||||
|
||||
| Service | Operations |
|
||||
|---|---:|
|
||||
@@ -27,8 +27,8 @@ The platform serves **397 operations** across the AWS APIs below. Every page nam
|
||||
| [ECS](/coverage/ecs) | 31 |
|
||||
| [EKS](/coverage/eks) | 36 |
|
||||
| [ELBv2](/coverage/elbv2) | 36 |
|
||||
| [IAM](/coverage/iam) | 79 |
|
||||
| [IAM](/coverage/iam) | 80 |
|
||||
| [RDS](/coverage/rds) | 26 |
|
||||
| [S3](/coverage/s3) | 26 |
|
||||
| [STS](/coverage/sts) | 5 |
|
||||
| **Total** | **397** |
|
||||
| **Total** | **398** |
|
||||
|
||||
@@ -2862,6 +2862,7 @@
|
||||
"GetUser",
|
||||
"GetUserPolicy",
|
||||
"ListAccessKeys",
|
||||
"ListAccountAliases",
|
||||
"ListAttachedGroupPolicies",
|
||||
"ListAttachedRolePolicies",
|
||||
"ListAttachedUserPolicies",
|
||||
@@ -2943,6 +2944,7 @@
|
||||
"GetUser",
|
||||
"GetUserPolicy",
|
||||
"ListAccessKeys",
|
||||
"ListAccountAliases",
|
||||
"ListAttachedGroupPolicies",
|
||||
"ListAttachedRolePolicies",
|
||||
"ListAttachedUserPolicies",
|
||||
@@ -3042,7 +3044,6 @@
|
||||
"GetServiceLastAccessedDetails",
|
||||
"GetServiceLastAccessedDetailsWithEntities",
|
||||
"GetServiceLinkedRoleDeletionStatus",
|
||||
"ListAccountAliases",
|
||||
"ListDelegationRequests",
|
||||
"ListMFADeviceTags",
|
||||
"ListMFADevices",
|
||||
|
||||
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **79 operations** in the IAM `2010-05-08` API model.
|
||||
Spinifex implements **80 operations** in the IAM `2010-05-08` API model.
|
||||
|
||||
### Scope
|
||||
|
||||
@@ -67,6 +67,7 @@ All IAM operations are account-scoped. The root user of an account bypasses poli
|
||||
| `GetUser` |
|
||||
| `GetUserPolicy` |
|
||||
| `ListAccessKeys` |
|
||||
| `ListAccountAliases` |
|
||||
| `ListAttachedGroupPolicies` |
|
||||
| `ListAttachedRolePolicies` |
|
||||
| `ListAttachedUserPolicies` |
|
||||
|
||||
@@ -957,7 +957,7 @@ spot-price: On owned hardware there is no spot-to-on-demand price differential,
|
||||
|
||||
## iam
|
||||
|
||||
`2010-05-08` — 79 of 180 modelled operations implemented (43.9%), 0 stubbed, 19 not applicable, 0 registered outside the pinned model.
|
||||
`2010-05-08` — 80 of 180 modelled operations implemented (44.4%), 0 stubbed, 19 not applicable, 0 registered outside the pinned model.
|
||||
|
||||
### Not implemented
|
||||
|
||||
@@ -1006,7 +1006,6 @@ spot-price: On owned hardware there is no spot-to-on-demand price differential,
|
||||
- `GetServerCertificate`
|
||||
- `GetServiceLastAccessedDetails`
|
||||
- `GetServiceLastAccessedDetailsWithEntities`
|
||||
- `ListAccountAliases`
|
||||
- `ListDelegationRequests`
|
||||
- `ListMFADeviceTags`
|
||||
- `ListMFADevices`
|
||||
|
||||
@@ -323,6 +323,9 @@ var iamActions = map[string]iamAction{
|
||||
"GetAccountSummary": iamHandler(func(accountID string, input *iam.GetAccountSummaryInput, gw *GatewayConfig) (any, error) {
|
||||
return gateway_iam.GetAccountSummary(accountID, input, gw.IAMService)
|
||||
}),
|
||||
"ListAccountAliases": iamHandler(func(accountID string, input *iam.ListAccountAliasesInput, gw *GatewayConfig) (any, error) {
|
||||
return gateway_iam.ListAccountAliases(accountID, input, gw.IAMService)
|
||||
}),
|
||||
}
|
||||
|
||||
func (gw *GatewayConfig) IAM_Request(w http.ResponseWriter, r *http.Request) error {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gateway_iam
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
)
|
||||
@@ -10,3 +11,17 @@ import (
|
||||
func GetAccountSummary(accountID string, input *iam.GetAccountSummaryInput, svc handlers_iam.IAMService) (*iam.GetAccountSummaryOutput, error) {
|
||||
return svc.GetAccountSummary(accountID, input)
|
||||
}
|
||||
|
||||
func ListAccountAliases(accountID string, input *iam.ListAccountAliasesInput, svc handlers_iam.IAMService) (*iam.ListAccountAliasesOutput, error) {
|
||||
p, err := newPager(input.Marker, input.MaxItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := svc.ListAccountAliases(accountID, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.AccountAliases, out.Marker = paginate(p, out.AccountAliases, aws.StringValue)
|
||||
out.IsTruncated = aws.Bool(out.Marker != nil)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ var iamScopes = map[string]resourceScope{
|
||||
"ListOpenIDConnectProviders": {source: sourceAccount},
|
||||
"ListGroups": {source: sourceAccount},
|
||||
"GetAccountSummary": {source: sourceAccount},
|
||||
"ListAccountAliases": {source: sourceAccount},
|
||||
}
|
||||
|
||||
// HasScope reports whether action has an explicit IAM scope-table entry.
|
||||
|
||||
@@ -132,6 +132,38 @@ func TestListUsers_RejectsBadPagingBeforeListing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// listAliasesStub counts calls so a rejected page proves the service never ran.
|
||||
type listAliasesStub struct {
|
||||
handlers_iam.IAMService
|
||||
|
||||
calls int
|
||||
}
|
||||
|
||||
func (s *listAliasesStub) ListAccountAliases(_ string, _ *iam.ListAccountAliasesInput) (*iam.ListAccountAliasesOutput, error) {
|
||||
s.calls++
|
||||
return &iam.ListAccountAliasesOutput{AccountAliases: []*string{}}, nil
|
||||
}
|
||||
|
||||
func TestListAccountAliases_RejectsBadPagingBeforeListing(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input *iam.ListAccountAliasesInput
|
||||
}{
|
||||
{"MaxItems zero", &iam.ListAccountAliasesInput{MaxItems: aws.Int64(0)}},
|
||||
{"MaxItems above 1000", &iam.ListAccountAliasesInput{MaxItems: aws.Int64(1001)}},
|
||||
{"undecodable Marker", &iam.ListAccountAliasesInput{Marker: aws.String("not a marker!")}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
svc := &listAliasesStub{}
|
||||
_, err := gateway_iam.ListAccountAliases(testAccountID, tc.input, svc)
|
||||
require.Error(t, err)
|
||||
assert.True(t, awserrors.IsErrorCode(err, awserrors.ErrorValidationError), "got %v", err)
|
||||
assert.Zero(t, svc.calls)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListUsers_MaxItemsBoundsAccepted(t *testing.T) {
|
||||
svc := &listStub{users: []string{"a", "b"}}
|
||||
assert.Len(t, listUsers(t, svc, nil, 1).Users, 1)
|
||||
|
||||
@@ -242,6 +242,10 @@ func (svc *echoIAMService) GetAccountSummary(accountID string, input *iam.GetAcc
|
||||
return echoIAMCall[iam.GetAccountSummaryInput, iam.GetAccountSummaryOutput](svc, accountID, input)
|
||||
}
|
||||
|
||||
func (svc *echoIAMService) ListAccountAliases(accountID string, input *iam.ListAccountAliasesInput) (*iam.ListAccountAliasesOutput, error) {
|
||||
return echoIAMCall[iam.ListAccountAliasesInput, iam.ListAccountAliasesOutput](svc, accountID, input)
|
||||
}
|
||||
|
||||
func (svc *echoIAMService) GetInstanceProfile(accountID string, input *iam.GetInstanceProfileInput) (*iam.GetInstanceProfileOutput, error) {
|
||||
if _, ok := svc.wantOutput.(*iam.GetInstanceProfileOutput); !ok {
|
||||
return &iam.GetInstanceProfileOutput{InstanceProfile: &iam.InstanceProfile{}}, nil
|
||||
|
||||
@@ -10,11 +10,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/mulgadc/spinifex/spinifex/arn"
|
||||
"github.com/mulgadc/spinifex/spinifex/awserrors"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// flexMockIAMService is a configurable mock with per-method overrides. It
|
||||
@@ -125,6 +128,9 @@ func (m *flexMockIAMService) GetAccountSummary(accountID string, input *iam.GetA
|
||||
}
|
||||
return &iam.GetAccountSummaryOutput{}, nil
|
||||
}
|
||||
func (m *flexMockIAMService) ListAccountAliases(_ string, _ *iam.ListAccountAliasesInput) (*iam.ListAccountAliasesOutput, error) {
|
||||
return &iam.ListAccountAliasesOutput{}, nil
|
||||
}
|
||||
func (m *flexMockIAMService) CreateGroup(_ string, _ *iam.CreateGroupInput) (*iam.CreateGroupOutput, error) {
|
||||
return &iam.CreateGroupOutput{}, nil
|
||||
}
|
||||
@@ -282,6 +288,40 @@ func TestIAMRequest_GetAccountSummary_Success(t *testing.T) {
|
||||
assert.Contains(t, xmlStr, "<value>2</value>")
|
||||
}
|
||||
|
||||
// realAliasesIAMService answers ListAccountAliases from the real service, which
|
||||
// needs no storage, so the test sees the response the gateway actually sends.
|
||||
type realAliasesIAMService struct {
|
||||
flexMockIAMService
|
||||
}
|
||||
|
||||
func (realAliasesIAMService) ListAccountAliases(accountID string, input *iam.ListAccountAliasesInput) (*iam.ListAccountAliasesOutput, error) {
|
||||
return (&handlers_iam.IAMServiceImpl{}).ListAccountAliases(accountID, input)
|
||||
}
|
||||
|
||||
// AWS answers an account with no alias with an empty AccountAliases list and
|
||||
// IsTruncated false, and no Marker.
|
||||
func TestIAMRequest_ListAccountAliases_Empty(t *testing.T) {
|
||||
server := httptest.NewServer(setupIAMRequestHandler(&realAliasesIAMService{}))
|
||||
defer server.Close()
|
||||
client := iam.New(session.Must(session.NewSession(&aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials("test", "test", ""),
|
||||
DisableSSL: aws.Bool(true),
|
||||
Endpoint: aws.String(server.URL),
|
||||
MaxRetries: aws.Int(0),
|
||||
Region: aws.String("us-east-1"),
|
||||
})))
|
||||
|
||||
out, err := client.ListAccountAliases(&iam.ListAccountAliasesInput{})
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, out.AccountAliases)
|
||||
assert.False(t, aws.BoolValue(out.IsTruncated))
|
||||
assert.Nil(t, out.Marker)
|
||||
|
||||
_, err = client.ListAccountAliases(&iam.ListAccountAliasesInput{MaxItems: aws.Int64(1001)})
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), awserrors.ErrorValidationError)
|
||||
}
|
||||
|
||||
// AWS answers GetRole for a never-used role with an empty <RoleLastUsed/>
|
||||
// element; a nil-field struct must still marshal to that element, not vanish.
|
||||
func TestIAMRequest_GetRole_EmptyRoleLastUsed(t *testing.T) {
|
||||
|
||||
@@ -151,4 +151,8 @@ type IAMService interface {
|
||||
// GetAccountSummary returns account-wide IAM usage counts plus AWS-parity
|
||||
// quota values as a SummaryMap. Read-only and account-scoped.
|
||||
GetAccountSummary(accountID string, input *iam.GetAccountSummaryInput) (*iam.GetAccountSummaryOutput, error)
|
||||
|
||||
// ListAccountAliases lists the account's aliases. Spinifex has no account
|
||||
// aliases, so every account has none.
|
||||
ListAccountAliases(accountID string, input *iam.ListAccountAliasesInput) (*iam.ListAccountAliasesOutput, error)
|
||||
}
|
||||
|
||||
@@ -2666,6 +2666,12 @@ func (s *IAMServiceImpl) GetAccountSummary(accountID string, _ *iam.GetAccountSu
|
||||
return &iam.GetAccountSummaryOutput{SummaryMap: summary}, nil
|
||||
}
|
||||
|
||||
// ListAccountAliases returns no aliases, which is what AWS returns for an account
|
||||
// that has none. Spinifex does not serve CreateAccountAlias.
|
||||
func (s *IAMServiceImpl) ListAccountAliases(_ string, _ *iam.ListAccountAliasesInput) (*iam.ListAccountAliasesOutput, error) {
|
||||
return &iam.ListAccountAliasesOutput{AccountAliases: []*string{}}, nil
|
||||
}
|
||||
|
||||
// countOIDCProviders counts the account's OIDC providers. AWS also counts SAML
|
||||
// providers under Providers; Spinifex has none.
|
||||
func (s *IAMServiceImpl) countOIDCProviders(ctx context.Context, accountID string) (int64, error) {
|
||||
|
||||
Reference in New Issue
Block a user