Skip to content

Commit 72f8ca1

Browse files
Add aws_organizations_delegated_administrator and aws_organizations_delegated_services_for_account tables (#2421) (#2477) (#2496)
Co-authored-by: Muhammad Fuad Bin Abdullah <[email protected]>
1 parent 60d4264 commit 72f8ca1

5 files changed

+404
-0
lines changed

aws/plugin.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ func Plugin(ctx context.Context) *plugin.Plugin {
409409
"aws_organizations_policy": tableAwsOrganizationsPolicy(ctx),
410410
"aws_organizations_policy_target": tableAwsOrganizationsPolicyTarget(ctx),
411411
"aws_organizations_root": tableAwsOrganizationsRoot(ctx),
412+
"aws_organizations_delegated_administrator": tableAwsOrganizationsDelegatedAdministrator(ctx),
413+
"aws_organizations_delegated_services_for_account": tableAwsOrganizationsDelegatedServicesForAccount(ctx),
412414
"aws_pinpoint_app": tableAwsPinpointApp(ctx),
413415
"aws_pipes_pipe": tableAwsPipes(ctx),
414416
"aws_pricing_product": tableAwsPricingProduct(ctx),
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package aws
2+
3+
import (
4+
"context"
5+
6+
"github.com/aws/aws-sdk-go-v2/service/organizations"
7+
8+
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
9+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
10+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
11+
)
12+
13+
func tableAwsOrganizationsDelegatedAdministrator(_ context.Context) *plugin.Table {
14+
return &plugin.Table{
15+
Name: "aws_organizations_delegated_administrator",
16+
Description: "AWS Organizations Delegated Administrator",
17+
List: &plugin.ListConfig{
18+
Hydrate: listOrganizationsDelegatedAdmins,
19+
Tags: map[string]string{"service": "organizations", "action": "ListDelegatedAdministrators"},
20+
},
21+
Columns: awsGlobalRegionColumns([]*plugin.Column{
22+
{
23+
Name: "id",
24+
Description: "The unique identifier (account ID) of the delegated administrator.",
25+
Type: proto.ColumnType_STRING,
26+
},
27+
{
28+
Name: "arn",
29+
Description: "The Amazon Resource Name (ARN) of the delegated administrator.",
30+
Type: proto.ColumnType_STRING,
31+
},
32+
{
33+
Name: "email",
34+
Description: "The email address associated with the delegated administrator account.",
35+
Type: proto.ColumnType_STRING,
36+
},
37+
{
38+
Name: "name",
39+
Description: "The friendly name of the delegated administrator account.",
40+
Type: proto.ColumnType_STRING,
41+
},
42+
{
43+
Name: "status",
44+
Description: "The status of the delegated administrator.",
45+
Type: proto.ColumnType_STRING,
46+
},
47+
{
48+
Name: "joined_method",
49+
Description: "The method by which the account joined the organization.",
50+
Type: proto.ColumnType_STRING,
51+
},
52+
{
53+
Name: "joined_timestamp",
54+
Description: "The date the account became a part of the organization.",
55+
Type: proto.ColumnType_TIMESTAMP,
56+
},
57+
{
58+
Name: "delegation_enabled_date",
59+
Description: "The date when the delegation was enabled.",
60+
Type: proto.ColumnType_TIMESTAMP,
61+
},
62+
63+
// Standard columns for all tables
64+
{
65+
Name: "title",
66+
Description: resourceInterfaceDescription("title"),
67+
Type: proto.ColumnType_STRING,
68+
Transform: transform.FromField("Name"),
69+
},
70+
{
71+
Name: "akas",
72+
Description: resourceInterfaceDescription("akas"),
73+
Type: proto.ColumnType_JSON,
74+
Transform: transform.FromField("Arn").Transform(transform.EnsureStringArray),
75+
},
76+
}),
77+
}
78+
}
79+
80+
func listOrganizationsDelegatedAdmins(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) {
81+
82+
// Get Client
83+
svc, err := OrganizationClient(ctx, d)
84+
if err != nil {
85+
plugin.Logger(ctx).Error("aws_organizations_delegated_administrator.ListDelegatedAdministrators", "client_error", err)
86+
return nil, err
87+
}
88+
89+
// Limiting the result
90+
maxItems := int32(20)
91+
92+
// Reduce the basic request limit down if the user has only requested a small number of rows
93+
if d.QueryContext.Limit != nil {
94+
limit := int32(*d.QueryContext.Limit)
95+
if limit < maxItems {
96+
maxItems = int32(limit)
97+
}
98+
}
99+
100+
params := &organizations.ListDelegatedAdministratorsInput{
101+
MaxResults: &maxItems,
102+
}
103+
104+
paginator := organizations.NewListDelegatedAdministratorsPaginator(svc, params, func(o *organizations.ListDelegatedAdministratorsPaginatorOptions) {
105+
o.Limit = maxItems
106+
o.StopOnDuplicateToken = true
107+
})
108+
109+
for paginator.HasMorePages() {
110+
// apply rate limiting
111+
output, err := paginator.NextPage(ctx)
112+
if err != nil {
113+
plugin.Logger(ctx).Error("aws_organizations_delegated_administrator.ListDelegatedAdministrators", "api_error", err)
114+
return nil, err
115+
}
116+
117+
for _, admin := range output.DelegatedAdministrators {
118+
d.StreamListItem(ctx, admin)
119+
120+
// Context may get cancelled due to manual cancellation or if the limit has been reached
121+
if d.RowsRemaining(ctx) == 0 {
122+
return nil, nil
123+
}
124+
}
125+
}
126+
127+
return nil, nil
128+
129+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package aws
2+
3+
import (
4+
"context"
5+
6+
"github.com/aws/aws-sdk-go-v2/service/organizations"
7+
"github.com/aws/aws-sdk-go-v2/service/organizations/types"
8+
9+
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
10+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
11+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
12+
)
13+
14+
func tableAwsOrganizationsDelegatedServicesForAccount(_ context.Context) *plugin.Table {
15+
16+
return &plugin.Table{
17+
Name: "aws_organizations_delegated_services_for_account",
18+
Description: "AWS Organizations Delegated Services For Account",
19+
List: &plugin.ListConfig{
20+
ParentHydrate: listOrganizationsDelegatedAdmins, // Use Delegated Administrator as parent per recommendation. Referenced table_aws_cloudwatch_log_stream. This function can be found in table_aws_organizations_delegated_administrator
21+
Hydrate: listDelegatedServices,
22+
Tags: map[string]string{"service": "organizations", "action": "ListDelegatedServicesForAccount"},
23+
KeyColumns: []*plugin.KeyColumn{ // Make delegated_account_id optional, user can still query `where` using this column.
24+
{Name: "delegated_account_id", Require: plugin.Optional},
25+
},
26+
},
27+
Columns: awsGlobalRegionColumns([]*plugin.Column{
28+
{
29+
Name: "delegated_account_id",
30+
Description: "The unique identifier (account ID) of the delegated administrator account for which services are listed.",
31+
Type: proto.ColumnType_STRING,
32+
},
33+
{
34+
Name: "service_principal",
35+
Description: "The service principal delegated to the administrator account.",
36+
Type: proto.ColumnType_STRING,
37+
},
38+
{
39+
Name: "delegation_enabled_date",
40+
Description: "The date when the delegation was enabled.",
41+
Type: proto.ColumnType_TIMESTAMP,
42+
},
43+
44+
// Standard columns for all tables
45+
{
46+
Name: "title",
47+
Description: resourceInterfaceDescription("title"),
48+
Type: proto.ColumnType_STRING,
49+
Transform: transform.FromField("ServicePrincipal"),
50+
},
51+
}),
52+
}
53+
}
54+
55+
// Define a struct to hold the DelegatedService and the AccountId used to fetch it.\
56+
type delegatedServiceInfo struct {
57+
types.DelegatedService
58+
DelegatedAccountId string
59+
}
60+
61+
62+
func listDelegatedServices(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
63+
delegatedAccount := h.Item.(types.DelegatedAdministrator) // Get delegated administrator details
64+
65+
delegatedAccountId := d.EqualsQualString("delegated_account_id") // Get delegated_account_id from where statement
66+
67+
// Minimize API calls
68+
if delegatedAccountId != "" {
69+
if delegatedAccountId != *delegatedAccount.Id {
70+
return nil, nil
71+
}
72+
}
73+
74+
// Get Client
75+
svc, err := OrganizationClient(ctx, d)
76+
if err != nil {
77+
plugin.Logger(ctx).Error("aws_organizations_delegated_services_for_account.ListDelegatedServicesForAccount", "client_error", err)
78+
return nil, err
79+
}
80+
81+
// Limiting the result
82+
maxItems := int32(20)
83+
84+
// Reduce the page size if a smaller limit is provided
85+
if d.QueryContext.Limit != nil {
86+
limit := int32(*d.QueryContext.Limit)
87+
if limit < maxItems {
88+
maxItems = limit
89+
}
90+
}
91+
params := &organizations.ListDelegatedServicesForAccountInput{
92+
AccountId: delegatedAccount.Id,
93+
MaxResults: &maxItems,
94+
}
95+
96+
paginator := organizations.NewListDelegatedServicesForAccountPaginator(svc, params, func(o *organizations.ListDelegatedServicesForAccountPaginatorOptions) {
97+
o.Limit = maxItems
98+
o.StopOnDuplicateToken = true
99+
})
100+
101+
for paginator.HasMorePages() {
102+
output, err := paginator.NextPage(ctx)
103+
if err != nil {
104+
plugin.Logger(ctx).Error("aws_organizations_delegated_services_for_account.ListDelegatedServicesForAccount", "api_error", err)
105+
return nil, err
106+
}
107+
108+
for _, service := range output.DelegatedServices {
109+
// Stream a new struct that includes the AccountId used for the API call
110+
d.StreamListItem(ctx, delegatedServiceInfo{
111+
DelegatedService: service,
112+
DelegatedAccountId: *delegatedAccount.Id,
113+
})
114+
115+
// Context may get cancelled due to manual cancellation or if the limit has been reached
116+
if d.RowsRemaining(ctx) == 0 {
117+
return nil, nil
118+
}
119+
}
120+
}
121+
122+
return nil, nil
123+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
title: "Steampipe Table: aws_organizations_delegated_administrator - Query AWS Organizations Delegated Administrators using SQL"
3+
description: "Allows users to query AWS Organizations Delegated Administrators and provides information about each account delegated administrative privileges within an AWS Organization."
4+
folder: "Organizations"
5+
---
6+
7+
# Table: aws_organizations_delegated_administrator - Query AWS Organizations Delegated Administrators using SQL
8+
9+
The AWS Organizations Delegated Administrator is a resource within AWS Organizations service that allows you to query details about your delegated administrator accounts, including their status, the date delegation was enabled, and associated metadata. This is useful for managing and auditing delegated administration within your organization.
10+
11+
## Table Usage Guide
12+
13+
The `aws_organizations_delegated_administrator` table in Steampipe lets you query details of accounts designated as delegated administrators in AWS Organizations. This table allows you, as a DevOps engineer, to identify accounts with specific statuses, view the date delegation was enabled, and gather other relevant account information. The schema outlines various attributes of each delegated administrator account.
14+
15+
**Important Notes:**
16+
* This table returns details about *delegated administrator* accounts, **not** the management account executing the API call.
17+
* The `account_id` column shows the ID of the account that made the API request (typically the management account). To retrieve the ID of the delegated administrator (member account), refer to the `id` column.
18+
19+
## Examples
20+
21+
### Basic info
22+
Retrieve basic information about all delegated administrators in your organization.
23+
24+
```sql+postgres
25+
select
26+
id,
27+
arn,
28+
email,
29+
joined_method,
30+
joined_timestamp,
31+
name,
32+
status,
33+
delegation_enabled_date
34+
from
35+
aws_organizations_delegated_administrator;
36+
```
37+
38+
```sql+sqlite
39+
select
40+
id,
41+
arn,
42+
email,
43+
joined_method,
44+
joined_timestamp,
45+
name,
46+
status,
47+
delegation_enabled_date
48+
from
49+
aws_organizations_delegated_administrator;
50+
```
51+
52+
### List delegated administrators with a specific status
53+
Identify delegated administrators with a particular status (e.g., ACTIVE, SUSPENDED, PENDING_CLOSURE).
54+
55+
```sql+postgres
56+
select
57+
id,
58+
name,
59+
arn,
60+
email,
61+
joined_method,
62+
joined_timestamp,
63+
status,
64+
delegation_enabled_date
65+
from
66+
aws_organizations_delegated_administrator
67+
where
68+
status = 'ACTIVE';
69+
```
70+
71+
```sql+sqlite
72+
select
73+
id,
74+
name,
75+
arn,
76+
email,
77+
joined_method,
78+
joined_timestamp,
79+
status,
80+
delegation_enabled_date
81+
from
82+
aws_organizations_delegated_administrator
83+
where
84+
status = 'ACTIVE';
85+
```

0 commit comments

Comments
 (0)