-
Notifications
You must be signed in to change notification settings - Fork 11
AWS managed compute scanner #236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b2914ee
6bf07aa
2d826d3
af49150
92f77cc
20ed6fd
3571fa5
358d68a
bb28c24
6c3932f
34be313
0b3ea0d
91f56af
810cc1e
8200455
6b7c558
9ebdb86
b6cfbe6
50ffdba
4302b5e
46dadc3
257e502
428480b
f88e980
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import type { Credentials } from "@aws-sdk/client-sts"; | ||
| import type { AwsCredentialIdentity } from "@smithy/types"; | ||
| import { EC2Client } from "@aws-sdk/client-ec2"; | ||
| import { EKSClient } from "@aws-sdk/client-eks"; | ||
| import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts"; | ||
|
|
||
| const sourceClient = new STSClient({ region: "us-east-1" }); | ||
|
|
||
| export class AwsCredentials { | ||
| static from(credentials: Credentials) { | ||
| return new AwsCredentials(credentials); | ||
| } | ||
|
|
||
| private constructor(private readonly credentials: Credentials) {} | ||
|
|
||
| toIdentity(): AwsCredentialIdentity { | ||
| if ( | ||
| this.credentials.AccessKeyId == null || | ||
| this.credentials.SecretAccessKey == null | ||
| ) | ||
| throw new Error("Missing required AWS credentials"); | ||
|
|
||
| return { | ||
| accessKeyId: this.credentials.AccessKeyId, | ||
| secretAccessKey: this.credentials.SecretAccessKey, | ||
| sessionToken: this.credentials.SessionToken ?? undefined, | ||
| }; | ||
| } | ||
|
|
||
| ec2(region?: string) { | ||
| return new EC2Client({ region, credentials: this.toIdentity() }); | ||
| } | ||
|
|
||
| eks(region?: string) { | ||
| return new EKSClient({ region, credentials: this.toIdentity() }); | ||
| } | ||
|
|
||
| sts(region?: string) { | ||
| return new STSClient({ region, credentials: this.toIdentity() }); | ||
| } | ||
| } | ||
|
|
||
| export const assumeWorkspaceRole = async (roleArn: string) => | ||
| assumeRole(sourceClient, roleArn); | ||
|
|
||
| export const assumeRole = async ( | ||
| client: STSClient, | ||
| roleArn: string, | ||
| ): Promise<AwsCredentials> => { | ||
| const { Credentials: CustomerCredentials } = await client.send( | ||
| new AssumeRoleCommand({ | ||
| RoleArn: roleArn, | ||
| RoleSessionName: "CtrlplaneScanner", | ||
| }), | ||
| ); | ||
| if (CustomerCredentials == null) | ||
| throw new Error(`Failed to assume AWS role ${roleArn}`); | ||
| return AwsCredentials.from(CustomerCredentials); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,186 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { Cluster, EKSClient } from "@aws-sdk/client-eks"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { STSClient } from "@aws-sdk/client-sts"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { ResourceProviderAws, Workspace } from "@ctrlplane/db/schema"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { KubernetesClusterAPIV1 } from "@ctrlplane/validators/resources"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { DescribeRegionsCommand } from "@aws-sdk/client-ec2"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DescribeClusterCommand, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ListClustersCommand, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from "@aws-sdk/client-eks"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import _ from "lodash"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { isPresent } from "ts-is-present"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { logger } from "@ctrlplane/logger"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ReservedMetadataKey } from "@ctrlplane/validators/conditions"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { AwsCredentials } from "./aws.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { omitNullUndefined } from "../utils.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { assumeRole, assumeWorkspaceRole } from "./aws.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const log = logger.child({ label: "resource-scan/eks" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const convertEksClusterToKubernetesResource = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accountId: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cluster: Cluster, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): KubernetesClusterAPIV1 => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const region = cluster.endpoint?.split(".")[2]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const partition = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cluster.arn?.split(":")[1] ?? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (region?.startsWith("us-gov-") ? "aws-us-gov" : "aws"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const appUrl = `https://${ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| partition === "aws-us-gov" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? `console.${region}.${partition}` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : "console.aws.amazon" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }.com/eks/home?region=${region}#/clusters/${cluster.name}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const version = cluster.version!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [major, minor] = version.split("."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
zacharyblasczyk marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: cluster.name ?? "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| identifier: `aws/${accountId}/eks/${cluster.name}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version: "kubernetes/v1" as const, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| kind: "ClusterAPI" as const, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: cluster.name!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auth: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: "aws/eks" as const, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| region: region!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clusterName: cluster.name!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status: cluster.status ?? "UNKNOWN", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| server: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| certificateAuthorityData: cluster.certificateAuthority?.data, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| endpoint: cluster.endpoint!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: omitNullUndefined({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReservedMetadataKey.Links]: JSON.stringify({ "AWS Console": appUrl }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReservedMetadataKey.ExternalId]: cluster.arn ?? "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReservedMetadataKey.KubernetesFlavor]: "eks", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReservedMetadataKey.KubernetesVersion]: cluster.version, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "aws/arn": cluster.arn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "aws/region": region, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "aws/platform-version": cluster.platformVersion, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "kubernetes/status": cluster.status, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "kubernetes/version-major": major, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "kubernetes/version-minor": minor, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(cluster.tags ?? {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const getAwsRegions = async (credentials: AwsCredentials) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| credentials | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ec2() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .send(new DescribeRegionsCommand({})) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then(({ Regions = [] }) => Regions.map((region) => region.RegionName)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const getClusters = async (client: EKSClient) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .send(new ListClustersCommand({})) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((response) => response.clusters ?? []); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
zacharyblasczyk marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const createEksClusterScannerForRegion = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client: AwsCredentials, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| customerRoleArn: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const accountId = /arn:aws:iam::(\d+):/.exec(customerRoleArn)?.[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (accountId == null) throw new Error("Missing account ID"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return async (region: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const eksClient = client.eks(region); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const clusters = await getClusters(eksClient); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `Found ${clusters.length} clusters for ${customerRoleArn} in region ${region}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return _.chain(clusters) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map((name) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eksClient | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .send(new DescribeClusterCommand({ name })) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then(({ cluster }) => cluster), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .thru((promises) => Promise.all(promises)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .value() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((clusterDetails) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clusterDetails | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(isPresent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map((cluster) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| convertEksClusterToKubernetesResource(accountId, cluster), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+103
to
+117
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Handle API call failures individually to prevent entire region scan from failing. If any Apply this diff to handle errors in cluster descriptions: return _.chain(clusters)
.map((name) =>
eksClient
.send(new DescribeClusterCommand({ name }))
.then(({ cluster }) => cluster)
+ .catch((error) => {
+ log.error(`Failed to describe cluster ${name} in region ${region}: ${error}`);
+ return null; // Skip this cluster and continue
+ }),
)
- .thru((promises) => Promise.all(promises))
+ .thru((promises) => Promise.all(promises))
.value()
.then((clusterDetails) =>
clusterDetails
.filter(isPresent)
.map((cluster) =>
convertEksClusterToKubernetesResource(accountId, cluster),
),
);
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const scanEksClustersByAssumedRole = async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceClient: STSClient, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| customerRoleArn: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = await assumeRole(workspaceClient, customerRoleArn); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const regions = await getAwsRegions(client); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `Scanning ${regions.length} AWS regions for EKS clusters in account ${customerRoleArn}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const regionalClusterScanner = createEksClusterScannerForRegion( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| customerRoleArn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return _.chain(regions) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(isPresent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(regionalClusterScanner) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .thru((promises) => Promise.all(promises)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .value() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((results) => results.flat()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const getEksResources = async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspace: Workspace, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config: ResourceProviderAws, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { awsRoleArn: workspaceRoleArn } = workspace; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (workspaceRoleArn == null) return []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `Scanning for EKS cluters with assumed role arns ${config.awsRoleArns.join(", ")} using role ${workspaceRoleArn}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceId: workspace.id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceRoleArn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const credentials = await assumeWorkspaceRole(workspaceRoleArn); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const workspaceStsClient = credentials.sts(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const resources = await _.chain(config.awsRoleArns) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map((customerRoleArn) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scanEksClustersByAssumedRole(workspaceStsClient, customerRoleArn), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .thru((promises) => Promise.all(promises)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .value() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((results) => results.flat()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((resources) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resources.map((resource) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+164
to
+172
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use Using Apply this diff to use const resources = await _.chain(config.awsRoleArns)
.map((customerRoleArn) =>
scanEksClustersByAssumedRole(workspaceStsClient, customerRoleArn)
+ .then((result) => ({ status: 'fulfilled', value: result }))
+ .catch((error) => {
+ log.error(`Failed to scan EKS clusters for role ${customerRoleArn}: ${error}`);
+ return { status: 'rejected', reason: error };
+ }),
)
- .thru((promises) => Promise.all(promises))
+ .thru((promises) => Promise.allSettled(promises))
.value()
- .then((results) => results.flat())
- .then((resources) =>
+ .then((results) =>
+ results
+ .filter((result) => result.status === 'fulfilled')
+ .flatMap((result) => result.value),
+ )
+ .then((resources) =>
resources.map((resource) => ({
...resource,
workspaceId: workspace.id,
providerId: config.resourceProviderId,
})),
);📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...resource, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceId: workspace.id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| providerId: config.resourceProviderId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const resourceTypes = _.countBy(resources, (resource) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [resource.kind, resource.version].join("/"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info(`Found ${resources.length} resources`, { resourceTypes }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return resources; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.