mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-28 03:19:47 +08:00
AWS Roles Anywhere: profile sync summary web api (#58007)
This PR adds the AWS IAM Roles Anywhere Status fields to the already existing endpoint which returns the integration status.
This commit is contained in:
@@ -338,6 +338,26 @@ func collectIntegrationStats(ctx context.Context, req collectIntegrationStatsReq
|
||||
}
|
||||
ret.Integration = uiIg
|
||||
|
||||
integrationStatus := req.integration.GetStatus()
|
||||
|
||||
switch req.integration.GetSubKind() {
|
||||
case types.IntegrationSubKindAWSRolesAnywhere:
|
||||
ret.RolesAnywhereProfileSync = &ui.RolesAnywhereProfileSync{}
|
||||
|
||||
awsRolesAnywhereSpec := req.integration.GetAWSRolesAnywhereIntegrationSpec()
|
||||
if awsRolesAnywhereSpec != nil {
|
||||
ret.RolesAnywhereProfileSync.Enabled = awsRolesAnywhereSpec.ProfileSyncConfig.Enabled
|
||||
}
|
||||
|
||||
if integrationStatus.AWSRolesAnywhere != nil {
|
||||
ret.RolesAnywhereProfileSync.Status = integrationStatus.AWSRolesAnywhere.LastProfileSync.Status
|
||||
ret.RolesAnywhereProfileSync.ErrorMessage = integrationStatus.AWSRolesAnywhere.LastProfileSync.ErrorMessage
|
||||
ret.RolesAnywhereProfileSync.SyncedProfiles = int(integrationStatus.AWSRolesAnywhere.LastProfileSync.SyncedProfiles)
|
||||
ret.RolesAnywhereProfileSync.SyncStartTime = integrationStatus.AWSRolesAnywhere.LastProfileSync.StartTime
|
||||
ret.RolesAnywhereProfileSync.SyncEndTime = integrationStatus.AWSRolesAnywhere.LastProfileSync.EndTime
|
||||
}
|
||||
}
|
||||
|
||||
var nextPage string
|
||||
for {
|
||||
filters := &usertasksv1.ListUserTasksFilters{
|
||||
|
||||
@@ -244,7 +244,7 @@ func (m *mockUserTasksLister) ListUserTasks(ctx context.Context, pageSize int64,
|
||||
return ret, "", nil
|
||||
}
|
||||
|
||||
func TestCollectAWSOIDCAutoDiscoverStats(t *testing.T) {
|
||||
func TestCollectIntegrationStats(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
logger := logtest.NewLogger()
|
||||
|
||||
@@ -505,6 +505,150 @@ func TestCollectAWSOIDCAutoDiscoverStats(t *testing.T) {
|
||||
}
|
||||
require.Equal(t, expectedSummary, gotSummary)
|
||||
})
|
||||
|
||||
t.Run("returns AWS IAM Roles Anywhere Profile Sync status", func(t *testing.T) {
|
||||
syncStartTime := time.Now()
|
||||
syncEndTime := syncStartTime.Add(5 * time.Minute)
|
||||
integrationName := "my-integration"
|
||||
integration, err := types.NewIntegrationAWSRA(
|
||||
types.Metadata{Name: integrationName},
|
||||
&types.AWSRAIntegrationSpecV1{
|
||||
TrustAnchorARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:trust-anchor/12345678-1234-1234-1234-123456789012",
|
||||
ProfileSyncConfig: &types.AWSRolesAnywhereProfileSyncConfig{
|
||||
Enabled: true,
|
||||
ProfileARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:profile/uuid2",
|
||||
ProfileAcceptsRoleSessionName: true,
|
||||
RoleARN: "arn:aws:iam::123456789012:role/SyncRole",
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
integration.SetStatus(types.IntegrationStatusV1{
|
||||
AWSRolesAnywhere: &types.AWSRAIntegrationStatusV1{
|
||||
LastProfileSync: &types.AWSRolesAnywhereProfileSyncIterationSummary{
|
||||
Status: "SUCCESS",
|
||||
SyncedProfiles: 4,
|
||||
StartTime: syncStartTime,
|
||||
EndTime: syncEndTime,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
clt := &mockRelevantAWSRegionsClient{
|
||||
discoveryConfigs: []*discoveryconfig.DiscoveryConfig{},
|
||||
databaseServices: &proto.ListResourcesResponse{},
|
||||
databases: make([]types.Database, 0),
|
||||
}
|
||||
|
||||
deployedDatabaseServicesClient := &mockDeployedDatabaseServices{
|
||||
listErr: trace.AccessDenied("AccessDenied to ECS:ListServices"),
|
||||
}
|
||||
req := collectIntegrationStatsRequest{
|
||||
logger: logger,
|
||||
integration: integration,
|
||||
discoveryConfigLister: clt,
|
||||
databaseGetter: clt,
|
||||
awsOIDCClient: deployedDatabaseServicesClient,
|
||||
userTasksClient: &mockUserTasksLister{},
|
||||
}
|
||||
gotSummary, err := collectIntegrationStats(ctx, req)
|
||||
require.NoError(t, err)
|
||||
expectedSummary := &ui.IntegrationWithSummary{
|
||||
Integration: &ui.Integration{
|
||||
Name: integrationName,
|
||||
SubKind: "aws-ra",
|
||||
AWSRA: &ui.IntegrationAWSRASpec{
|
||||
TrustAnchorARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:trust-anchor/12345678-1234-1234-1234-123456789012",
|
||||
ProfileSyncConfig: ui.AWSRAProfileSync{
|
||||
Enabled: true,
|
||||
ProfileARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:profile/uuid2",
|
||||
RoleARN: "arn:aws:iam::123456789012:role/SyncRole",
|
||||
},
|
||||
},
|
||||
},
|
||||
RolesAnywhereProfileSync: &ui.RolesAnywhereProfileSync{
|
||||
Enabled: true,
|
||||
Status: "SUCCESS",
|
||||
SyncedProfiles: 4,
|
||||
SyncStartTime: syncStartTime,
|
||||
SyncEndTime: syncEndTime,
|
||||
},
|
||||
}
|
||||
require.Equal(t, expectedSummary, gotSummary)
|
||||
})
|
||||
|
||||
t.Run("returns AWS IAM Roles Anywhere Profile Sync status with error message", func(t *testing.T) {
|
||||
syncStartTime := time.Now()
|
||||
syncEndTime := syncStartTime.Add(5 * time.Minute)
|
||||
integrationName := "my-integration"
|
||||
integration, err := types.NewIntegrationAWSRA(
|
||||
types.Metadata{Name: integrationName},
|
||||
&types.AWSRAIntegrationSpecV1{
|
||||
TrustAnchorARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:trust-anchor/12345678-1234-1234-1234-123456789012",
|
||||
ProfileSyncConfig: &types.AWSRolesAnywhereProfileSyncConfig{
|
||||
Enabled: true,
|
||||
ProfileARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:profile/uuid2",
|
||||
ProfileAcceptsRoleSessionName: true,
|
||||
RoleARN: "arn:aws:iam::123456789012:role/SyncRole",
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
integration.SetStatus(types.IntegrationStatusV1{
|
||||
AWSRolesAnywhere: &types.AWSRAIntegrationStatusV1{
|
||||
LastProfileSync: &types.AWSRolesAnywhereProfileSyncIterationSummary{
|
||||
Status: "ERROR",
|
||||
SyncedProfiles: 0,
|
||||
StartTime: syncStartTime,
|
||||
EndTime: syncEndTime,
|
||||
ErrorMessage: "Failed to sync profiles due to access denied error",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
clt := &mockRelevantAWSRegionsClient{
|
||||
discoveryConfigs: []*discoveryconfig.DiscoveryConfig{},
|
||||
databaseServices: &proto.ListResourcesResponse{},
|
||||
databases: make([]types.Database, 0),
|
||||
}
|
||||
|
||||
deployedDatabaseServicesClient := &mockDeployedDatabaseServices{
|
||||
listErr: trace.AccessDenied("AccessDenied to ECS:ListServices"),
|
||||
}
|
||||
req := collectIntegrationStatsRequest{
|
||||
logger: logger,
|
||||
integration: integration,
|
||||
discoveryConfigLister: clt,
|
||||
databaseGetter: clt,
|
||||
awsOIDCClient: deployedDatabaseServicesClient,
|
||||
userTasksClient: &mockUserTasksLister{},
|
||||
}
|
||||
gotSummary, err := collectIntegrationStats(ctx, req)
|
||||
require.NoError(t, err)
|
||||
expectedSummary := &ui.IntegrationWithSummary{
|
||||
Integration: &ui.Integration{
|
||||
Name: integrationName,
|
||||
SubKind: "aws-ra",
|
||||
AWSRA: &ui.IntegrationAWSRASpec{
|
||||
TrustAnchorARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:trust-anchor/12345678-1234-1234-1234-123456789012",
|
||||
ProfileSyncConfig: ui.AWSRAProfileSync{
|
||||
Enabled: true,
|
||||
ProfileARN: "arn:aws:rolesanywhere:eu-west-2:123456789012:profile/uuid2",
|
||||
RoleARN: "arn:aws:iam::123456789012:role/SyncRole",
|
||||
},
|
||||
},
|
||||
},
|
||||
RolesAnywhereProfileSync: &ui.RolesAnywhereProfileSync{
|
||||
Enabled: true,
|
||||
Status: "ERROR",
|
||||
SyncedProfiles: 0,
|
||||
SyncStartTime: syncStartTime,
|
||||
SyncEndTime: syncEndTime,
|
||||
ErrorMessage: "Failed to sync profiles due to access denied error",
|
||||
},
|
||||
}
|
||||
require.Equal(t, expectedSummary, gotSummary)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCollectAutoDiscoveryRules(t *testing.T) {
|
||||
|
||||
@@ -124,6 +124,9 @@ type IntegrationWithSummary struct {
|
||||
AWSRDS ResourceTypeSummary `json:"awsrds"`
|
||||
// AWSEKS contains the summary for the AWS EKS resources for this integration.
|
||||
AWSEKS ResourceTypeSummary `json:"awseks"`
|
||||
|
||||
// RolesAnywhereProfileSync contains the summary for the AWS Roles Anywhere Profile Sync.
|
||||
RolesAnywhereProfileSync *RolesAnywhereProfileSync `json:"rolesAnywhereProfileSync,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceTypeSummary contains the summary of the enrollment rules and found resources by the integration.
|
||||
@@ -150,6 +153,26 @@ type ResourceTypeSummary struct {
|
||||
ECSDatabaseServiceCount int `json:"ecsDatabaseServiceCount,omitempty"`
|
||||
}
|
||||
|
||||
// RolesAnywhereProfileSync contains the summary for the AWS Roles Anywhere Profile Sync.
|
||||
type RolesAnywhereProfileSync struct {
|
||||
// Enabled indicates whether the profile sync is enabled.
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Status is the string representation of the profile sync status.
|
||||
// Either ERROR or SUCCESS.
|
||||
Status string `json:"status,omitempty"`
|
||||
// ErrorMessage is the error message from the last sync when the Status is ERROR.
|
||||
ErrorMessage string `json:"errorMessage,omitempty"`
|
||||
|
||||
// SyncedProfiles is the number of profiles that were imported into Teleport.
|
||||
SyncedProfiles int `json:"syncedProfiles,omitempty"`
|
||||
|
||||
// SyncStartTime is the time when the profile sync started.
|
||||
SyncStartTime time.Time `json:"syncStartTime,omitempty"`
|
||||
// SyncEndTime is the time when the profile sync ended.
|
||||
SyncEndTime time.Time `json:"syncEndTime,omitempty"`
|
||||
}
|
||||
|
||||
// IntegrationDiscoveryRule describes a discovery rule associated with an integration.
|
||||
type IntegrationDiscoveryRule struct {
|
||||
// ResourceType indicates the type of resource that this rule targets.
|
||||
|
||||
Reference in New Issue
Block a user