diff --git a/CHANGELOG.md b/CHANGELOG.md index 06954004..2091949b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,189 @@ +# [0.89.0-alpha.22](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.21...0.89.0-alpha.22) (2023-07-19) + + +### Features + +* collect provider errors ([cccc04d](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/cccc04d1749271f705c272c6923fe875ddb20f07)) + +# [0.89.0-alpha.21](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.20...0.89.0-alpha.21) (2023-06-07) + + +### Bug Fixes + +* **aws:** fixes for beta release review ([d6dc132](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/d6dc132b1945f9532151f79b0c05efe7bc10b636)) + +# [0.89.0-alpha.20](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.19...0.89.0-alpha.20) (2023-06-06) + + +### Bug Fixes + +* refactor listenerCertificates method ([aab3b84](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/aab3b8474ba23ef6b7b16e55d0569432ed903ff1)) + +# [0.89.0-alpha.19](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.18...0.89.0-alpha.19) (2023-06-05) + + +### Features + +* **aws:** support missing ecs services ([87865d2](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/87865d2d9bf2c77466059594d98e9fdc88333b3e)) + +# [0.89.0-alpha.18](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.17...0.89.0-alpha.18) (2023-06-05) + + +### Features + +* add securityHub missing services ([734d0c1](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/734d0c138eec88d27d37aee2f8c1cc70f50516c4)) + +# [0.89.0-alpha.17](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.16...0.89.0-alpha.17) (2023-06-02) + + +### Features + +* Added new DocumentDBCluster service ([5ea6932](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/5ea6932f029a428790ef6a702d2a57573dbe9cba)) +* linked new service ([44e7659](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/44e765965e3ebddc3be2f5529f6327ce4c394118)) + +# [0.89.0-alpha.16](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.15...0.89.0-alpha.16) (2023-06-02) + + +### Features + +* **aws:** Add codepipeline services ([8043378](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/80433780dac8bc0e257c043726bbced4158811a4)) + +# [0.89.0-alpha.15](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.14...0.89.0-alpha.15) (2023-06-02) + + +### Features + +* **aws:** Add codeCommitRepository service ([10f8d86](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/10f8d86ec298e8031c421998e2bdb01b3967b349)) + +# [0.89.0-alpha.14](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.13...0.89.0-alpha.14) (2023-06-02) + + +### Features + +* add efs missing services ([ef37753](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/ef37753c09f67f6f40ae745fb3ecfa9101144793)) + +# [0.89.0-alpha.13](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.12...0.89.0-alpha.13) (2023-06-02) + + +### Features + +* add ecr missing services ([9b41282](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/9b4128203fd397aba9a8435482c3fe797c34ddcd)) + +# [0.89.0-alpha.12](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.11...0.89.0-alpha.12) (2023-06-02) + + +### Bug Fixes + +* Fixed error with VPC connections and elasticSearchDomain ([80af943](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/80af94379b3d1b6e46ccd15d4c887d5cfc53ed55)) + + +### Features + +* Added ses service configurations ([a1d550b](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/a1d550b19e93e15a33b328856f73f27843edd4a3)) +* Added sesReceiptRuleSet service configurations ([7e3ca02](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/7e3ca0222bdfee63e419930460770f477b7f2237)) +* Linked new services ([9eee1b3](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/9eee1b32ce18807dde113ff39d4f8f7ff35f358e)) +* Split up ses service depending on identity type ([214287f](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/214287fd993cf3424d61de42ae613cc98c7d2d94)) + +# [0.89.0-alpha.11](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.10...0.89.0-alpha.11) (2023-06-01) + + +### Features + +* **aws:** support missing glue services ([be11f33](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/be11f33b3611b123f0167560adf894671248cb30)) + +# [0.89.0-alpha.10](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.9...0.89.0-alpha.10) (2023-06-01) + + +### Features + +* add config missing services ([ad4f1a1](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/ad4f1a1e2f58caa21838cc1966621e863bc648e8)) + +# [0.89.0-alpha.9](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.8...0.89.0-alpha.9) (2023-06-01) + + +### Features + +* **aws:** support missing iam services ([d576b40](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/d576b40d8368a10c92119a95aeabf5c8bc0cafdc)) + +# [0.89.0-alpha.8](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.7...0.89.0-alpha.8) (2023-05-31) + + +### Features + +* add apigateway missing services ([afd255f](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/afd255ff59f3ea7238bfdbcba992dc3154b31236)) + +# [0.89.0-alpha.7](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.6...0.89.0-alpha.7) (2023-05-31) + + +### Features + +* Added rdsDBProxies ([7c3e5c0](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/7c3e5c05c176149ec12c802bbd929834cd02e433)) +* Added rdsEventSubscription ([76c4438](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/76c44380596efa087e1c5c0d57d4c047a85a993b)) +* Added rdsGlobalClusters ([fdc1342](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/fdc1342e455a50b2ea7357f5a67ce9c4ee5aae69)) +* Added snapshots for dbinstances ([1377e9a](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/1377e9aa4526ff35fb5f08cc281f7e5b01edd220)) +* Included groupOption and parameterGroup for dbInstance ([88d5c14](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/88d5c1413011d86aa547f5321da33eebecf17619)) +* Linked new rds services to awsAccount schema ([d18a849](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/d18a8497d07d9598c761d205f1a1ada828d4260e)) + +# [0.89.0-alpha.6](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.5...0.89.0-alpha.6) (2023-05-30) + + +### Features + +* **aws:** Add ssm parameter service and update redshift ([0d808e6](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/0d808e68aceafb1f75c4a3cbf4fb22478ba1dfb6)) +* **aws:** update readme file ([6c39235](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/6c392359828a2ac5445936ba6376e79a615f9f91)) + +# [0.89.0-alpha.5](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.4...0.89.0-alpha.5) (2023-05-30) + + +### Features + +* support some alb services ([5f36758](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/5f36758ee234fa1846384ed52b075d501899e1a5)) + +# [0.89.0-alpha.4](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.3...0.89.0-alpha.4) (2023-05-30) + + +### Features + +* add missing cloudwatch services ([c835307](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/c835307f304c1b76802c61f12ea545e0914b1bcc)) + +# [0.89.0-alpha.3](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.2...0.89.0-alpha.3) (2023-05-29) + + +### Features + +* Added aws_lambda_event_invoke_config for RT ([48ee1f0](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/48ee1f03a04287aa28fa901c895c01071e3319bc)) +* Included event source mappings for lambda service ([9afbfb0](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/9afbfb09c52dbeb1cb88b6ce1b2058b334c5c22e)) +* Included layers for aws_lambda_layers ([624f9c2](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/624f9c2523aec53deed8b40a716fbd1dbc488503)) +* Included name and statements id for aws_lambda_permissions ([8496b43](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/8496b432014bf11617b2074aff4cb3019a73e3de)) + +# [0.89.0-alpha.2](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.89.0-alpha.1...0.89.0-alpha.2) (2023-05-25) + + +### Features + +* **aws:** updated elastic beanstalk client to aws-sdk-v3 to fix empty crawl data issue ([3f3e6b0](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/3f3e6b0c23a522dd9e43b4f3a774e735e11a8029)) + +# [0.89.0-alpha.1](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.88.0...0.89.0-alpha.1) (2023-05-24) + + +### Features + +* **aws:** Update cloudfront and eksCluster ([d7377ba](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/d7377bac18e9757cf416918e6c6a9e0015078790)) +* Fetched extra grant information for kms service ([c99417b](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/c99417baf1c52b521695e8f460c835cb35635c28)) + +# [0.88.0](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.87.0...0.88.0) (2023-05-12) + + +### Bug Fixes + +* **aws:** minor change to normalize name ([07a9c02](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/07a9c027d5a0946365ebe46ac18bbae72ad7d7b9)) + + +### Features + +* add new regions ([d1bd407](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/d1bd40793f018fbb95202b9e319057348fadd153)) +* **aws:** Added some adjustment needed for TF ([fb8b1c5](https://github.com/cloudgraphdev/cloudgraph-provider-aws/commit/fb8b1c5af21999756c4c2720e9cb6fb5e60e858d)) + # [0.88.0-beta.1](https://github.com/cloudgraphdev/cloudgraph-provider-aws/compare/0.87.0...0.88.0-beta.1) (2023-05-12) diff --git a/README.md b/README.md index d74aa4b7..e8bd6612 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,6 @@ CloudGraph will generate this configuration file when you run `cg init aws`. You ], // Optional, defaults to the default profile "regions": "us-east-1,us-east-2,us-west-2", "resources": "alb,apiGatewayResource,apiGatewayRestApi,apiGatewayStage,appSync,asg,billing,cognitoIdentityPool,cognitoUserPool,cloudFormationStack,cloudFormationStackSet,cloudfront,cloudwatch,ebs,ec2Instance,eip,elb,igw,kinesisFirehose,kinesisStream,kms,lambda,nat,networkInterface,route53HostedZone,route53Record,routeTable,sg,vpc,sqs,s3" - } } ``` @@ -68,109 +67,131 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi # Supported Services -| Service | Relations | -| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| acm | | -| alb | ec2, elasticBeanstalkEnv, route53Record, securityGroup, subnet, vpc, wafV2WebAcl | -| apiGatewayDomainName | apiGatewayHttpApi, apiGatewayRestApi | -| apiGatewayHttpApi | apiGatewayDomainName | -| apiGatewayRestApi | apiGatewayDomainName, apiGatewayResource, apiGatewayStage, route53Record | -| apiGatewayStage | apiGatewayRestApi, wafV2WebAcl | -| apiGatewayResource | apiGatewayRestApi | -| appSync | cognitoUserPool, dynamodb, iamRole, lambda, rdsCluster, wafV2WebAcl | -| asg | ebs, ec2, elasticBeanstalkEnv, iamRole, securityGroup, subnet | -| athenaDataCatalog | | -| clientVpnEndpoint | securityGroup | -| cloud9 | | -| cloudformationStack | cloudformationStack, iamRole, sns | -| cloudformationStackSet | iamRole | -| cloudfront | cloudwatch, elb, s3 | -| cloudtrail | cloudwatch, cloudwatchLog, kms, s3, sns | -| cloudwatch | cloudfront, cloudtrail, cloudwatchLog, sns | -| cloudwatchLog | cloudtrail, cloudwatch, ecsCluster, elasticSearchDomain, kms, managedAirflow, rdsDbInstance | -| codebuild | iamRole, kms, vpc, securityGroup, subnet | -| cognitoIdentityPool | iamRole, iamOpenIdConnectProvider, iamSamlProvider, elasticSearchDomain | -| cognitoUserPool | appSync, elasticSearchDomain, lambda | -| configurationRecorder | iamRole | -| customerGateway | vpnConnection | -| dynamodb | appSync, iamRole, kms | -| dmsReplicationInstance | securityGroup, subnet, vpc, kms | -| ebs | asg, ec2, emrInstance, ebsSnapshot | -| ebsSnapshot | ebs, kms | -| ec2 | alb, asg, ebs, eip, emrInstance, eksCluster, elasticBeanstalkEnv, iamInstanceProfile, iamRole, networkInterface, securityGroup, subnet, systemsManagerInstance, vpc, ecsContainer | -| ecr | | -| ecsCluster | cloudwatchLog, ecsService, ecsTask, ecsTaskSet, kms, s3 | -| ecsContainer | ecsTask, ec2 | -| ecsService | ecsCluster, ecsTaskDefinition, ecsTaskSet, elb, iamRole, securityGroup, subnet, vpc | -| ecsTask | ecsContainer, ecsCluster, ecsTaskDefinition, iamRole | -| ecsTaskDefinition | ecsService, ecsTask, ecsTaskSet, iamRole | -| ecsTaskSet | ecsCluster, ecsService, ecsTaskDefinition | -| efs | kms | -| efsMountTarget | networkInterface, subnet, vpc | -| eip | ec2, networkInterface, vpc | -| eksCluster | ec2, iamRole, kms, securityGroup, subnet, vpc | -| elastiCacheCluster | securityGroup, subnet, vpc | -| elastiCacheReplicationGroup | kms | -| elasticBeanstalkApp | elasticBeanstalkEnv, iamRole | -| elasticBeanstalkEnv | alb, asg, ec2, elb, elasticBeanstalkApp, iamRole, sqs | -| elasticSearchDomain | cloudwatchLog, cognitoIdentityPool, cognitoUserPool, iamRole, kms, securityGroup, subnet, vpc | -| elb | cloudfront, ecsService, elasticBeanstalkEnv, securityGroup, subnet, vpc | -| emrCluster | iamRole, kms, subnet | -| emrInstance | ebs, ec2 | -| emrStep | | -| flowLog | vpc, iamRole, subnet, networkInterface | -| glueJob | iamRole | -| glueRegistry | | -| guardDutyDetector | iamRole | -| iamAccessAnalyzer | | -| iamInstanceProfile | ec2, iamRole | -| iamPasswordPolicy | | -| iamSamlProvider | cognitoIdentityPool | -| iamOpenIdConnectProvider | cognitoIdentityPool | -| iamServerCertificate | | -| iamUser | iamGroup | -| iamPolicy | iamRole, iamGroup | -| iamRole | appSync, asg, cloudformationStackSet, codebuild, cognitoIdentityPool, configurationRecorder, ec2, ecsTask, ecsTaskDefinition,iamInstanceProfile, iamPolicy, eksCluster, ecsService, emrCluster, flowLog, glueJob, managedAirflow, s3, sageMakerNotebookInstance, systemsManagerInstance, guardDutyDetector, lambda, kinesisFirehose, rdsCluster, rdsDbInstance, elasticBeanstalkApp, elasticBeanstalkEnv, elasticSearchDomain | -| iamGroup | iamUser, iamPolicy | -| igw | vpc | -| iot | | -| kinesisFirehose | kinesisStream, s3, iamRole | -| kinesisStream | kinesisFirehose | -| kms | cloudtrail, cloudwatchLog, codebuild, ecsCluster, efs, eksCluster, elastiCacheReplicationGroup, elasticSearchDomain, emrCluster, managedAirflow, lambda, rdsCluster, rdsClusterSnapshot, rdsDbInstance, sns, sageMakerNotebookInstance, secretsManager, dmsReplicationInstance, redshiftCluster, s3, ebsSnapshot | -| lambda | appSync, cognitoUserPool, kms, s3, secretsManager, securityGroup, subnet, vpc, iamRole | -| managedAirflow | cloudwatchLog, iamRole, kms, securityGroups, subnet, s3 | -| managedPrefixList | | -| mskCluster | securityGroup, subnet | -| nacl | vpc | -| natGateway | networkInterface, subnet, vpc | -| networkInterface | ec2, eip, efsMountTarget, natGateway, sageMakerNotebookInstance, subnet, vpc, vpcEndpoint, flowLog, securityGroup | -| organization | -| rdsCluster | appSync, rdsClusterSnapshot, rdsDbInstance, route53HostedZone, securityGroup, subnet, iamRole, kms | -| rdsClusterSnapshot | kms, rdsCluster, vpc | -| rdsDbInstance | kms, iamRole, rdsCluster, securityGroup, vpc, subnet, cloudwatchLog | -| redshiftCluster | kms, vpc | -| route53Record | alb, apiGatewayRestApi, elb, route53HostedZone | -| route53HostedZone | rdsCluster, route53Record, vpc | -| routeTable | subnet, vpc, vpcEndpoint | -| sageMakerExperiment | | -| sageMakerNotebookInstance | iamRole, kms, networkInterface, subnet, securityGroup | -| sageMakerProject | | -| s3 | cloudfront, cloudtrail, ecsCluster, iamRole, kinesisFirehose, kms, lambda, managedAirflow, sns, sqs | -| secretsManager | kms, lambda | -| securityGroup | alb, asg, clientVpnEndpoint, codebuild, dmsReplicationInstance, ecsService, lambda, ec2, elasticSearchDomain, elb, rdsCluster, rdsDbInstance, eksCluster, elastiCacheCluster, managedAirflow, sageMakerNotebookInstance, networkInterface, vpcEndpoint, mskCluster | -| securityHub | | -| ses | | -| sns | kms, cloudtrail, cloudwatch, s3 | -| sqs | elasticBeanstalkEnv, s3 | -| subnet | alb, asg, codebuild, dmsReplicationInstance, ec2, ecsService, efsMountTarget, elastiCacheCluster, elasticSearchDomain, elb, lambda, managedAirflow, natGateway, networkInterface, rdsCluster, sageMakerNotebookInstance, routeTable, vpc, vpcEndpoint, eksCluster, emrCluster, flowLog, mskCluster | -| systemsManagerInstance | ec2, iamRole | -| systemsManagerDocument | | -| transitGateway | transitGatewayAttachment, transitGatewayRouteTable, vpnConnection | -| transitGatewayAttachment | transitGateway, transitGatewayRouteTable, vpc, vpnConnection | -| transitGatewayRouteTable | transitGateway, transitGatewayAttachment | -| vpc | alb, codebuild, dmsReplicationInstance, ec2, eip, elb, ecsService, efsMountTarget, eksCluster igw, elastiCacheCluster, elasticSearchDomain, lambda, nacl, natGateway, networkInterface, rdsClusterSnapshot, rdsDbInstance, redshiftCluster, route53HostedZone, routeTable, subnet, flowLog, vpnGateway, transitGatewayAttachment, vpcEndpoint, vpcPeeringConnection | -| vpcEndpoint | networkInterface, routeTable, securityGroup, subnet, vpc | -| vpcPeeringConnection | vpc | -| vpnConnection | customerGateway, transitGateway, transitGatewayAttachment, vpnGateway | -| vpnGateway | vpc, vpnConnection | -| wafV2WebAcl | appSync, apiGatewayStage, alb | +| Service | Relations | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| acm | | +| alb | ec2, elasticBeanstalkEnv, route53Record, securityGroup, subnet, vpc, wafV2WebAcl | +| apiGatewayApiKey | | +| apiGatewayDomainName | apiGatewayHttpApi, apiGatewayRestApi | +| apiGatewayHttpApi | apiGatewayDomainName | +| apiGatewayRestApi | apiGatewayDomainName, apiGatewayResource, apiGatewayStage, route53Record | +| apiGatewayStage | apiGatewayRestApi, wafV2WebAcl | +| apiGatewayResource | apiGatewayRestApi | +| apiGatewayUsagePlan | | +| apiGatewayVpcLink | | +| appSync | cognitoUserPool, dynamodb, iamRole, lambda, rdsCluster, wafV2WebAcl | +| asg | ebs, ec2, elasticBeanstalkEnv, iamRole, securityGroup, subnet | +| athenaDataCatalog | | +| clientVpnEndpoint | securityGroup | +| cloud9 | | +| cloudformationStack | cloudformationStack, iamRole, sns | +| cloudformationStackSet | iamRole | +| cloudfront | cloudwatch, elb, s3 | +| cloudtrail | cloudwatch, cloudwatchLog, kms, s3, sns | +| cloudwatch | cloudfront, cloudtrail, cloudwatchLog, sns | +| cloudwatchLog | cloudtrail, cloudwatch, ecsCluster, elasticSearchDomain, kms, managedAirflow, rdsDbInstance | +| codeCommitRepository | | +| codebuild | iamRole, kms, vpc, securityGroup, subnet | +| codePipeline | | +| codePipelineWebhook | | +| cognitoIdentityPool | iamRole, iamOpenIdConnectProvider, iamSamlProvider, elasticSearchDomain | +| cognitoUserPool | appSync, elasticSearchDomain, lambda | +| configurationDeliveryChannel | | +| configurationRecorder | iamRole | +| configurationRule | | +| customerGateway | vpnConnection | +| dynamodb | appSync, iamRole, kms | +| docdbCluster | | +| dmsReplicationInstance | securityGroup, subnet, vpc, kms | +| ebs | asg, ec2, emrInstance, ebsSnapshot | +| ebsSnapshot | ebs, kms | +| ec2 | alb, asg, ebs, eip, emrInstance, eksCluster, elasticBeanstalkEnv, iamInstanceProfile, iamRole, networkInterface, securityGroup, subnet, systemsManagerInstance, vpc, ecsContainer | +| ecr | | +| ecsCluster | cloudwatchLog, ecsService, ecsTask, ecsTaskSet, kms, s3 | +| ecsContainer | ecsTask, ec2 | +| ecsService | ecsCluster, ecsTaskDefinition, ecsTaskSet, elb, iamRole, securityGroup, subnet, vpc | +| ecsTask | ecsContainer, ecsCluster, ecsTaskDefinition, iamRole | +| ecsTaskDefinition | ecsService, ecsTask, ecsTaskSet, iamRole | +| ecsTaskSet | ecsCluster, ecsService, ecsTaskDefinition | +| efs | kms | +| efsAccessPoint | | +| efsMountTarget | networkInterface, subnet, vpc | +| eip | ec2, networkInterface, vpc | +| eksCluster | ec2, iamRole, kms, securityGroup, subnet, vpc | +| elastiCacheCluster | securityGroup, subnet, vpc | +| elastiCacheReplicationGroup | kms | +| elasticBeanstalkApp | elasticBeanstalkEnv, iamRole | +| elasticBeanstalkEnv | alb, asg, ec2, elb, elasticBeanstalkApp, iamRole, sqs | +| elasticSearchDomain | cloudwatchLog, cognitoIdentityPool, cognitoUserPool, iamRole, kms, securityGroup, subnet, vpc | +| elb | cloudfront, ecsService, elasticBeanstalkEnv, securityGroup, subnet, vpc | +| emrCluster | iamRole, kms, subnet | +| emrInstance | ebs, ec2 | +| emrStep | | +| flowLog | vpc, iamRole, subnet, networkInterface | +| glueCrawler | | +| glueDatabase | | +| glueJob | iamRole | +| glueRegistry | | +| glueTrigger | | +| guardDutyDetector | iamRole | +| iamAccessAnalyzer | | +| iamInstanceProfile | ec2, iamRole | +| iamPasswordPolicy | | +| iamSamlProvider | cognitoIdentityPool | +| iamOpenIdConnectProvider | cognitoIdentityPool | +| iamServerCertificate | | +| iamUser | iamGroup | +| iamPolicy | iamRole, iamGroup | +| iamRole | appSync, asg, cloudformationStackSet, codebuild, cognitoIdentityPool, configurationRecorder, ec2, ecsTask, ecsTaskDefinition,iamInstanceProfile, iamPolicy, eksCluster, ecsService, emrCluster, flowLog, glueJob, managedAirflow, s3, sageMakerNotebookInstance, systemsManagerInstance, guardDutyDetector, lambda, kinesisFirehose, rdsCluster, rdsDbInstance, elasticBeanstalkApp, elasticBeanstalkEnv, elasticSearchDomain | +| iamGroup | iamUser, iamPolicy | +| igw | vpc | +| iot | | +| kinesisFirehose | kinesisStream, s3, iamRole | +| kinesisStream | kinesisFirehose | +| kms | cloudtrail, cloudwatchLog, codebuild, ecsCluster, efs, eksCluster, elastiCacheReplicationGroup, elasticSearchDomain, emrCluster, managedAirflow, lambda, rdsCluster, rdsClusterSnapshot, rdsDbInstance, sns, sageMakerNotebookInstance, secretsManager, dmsReplicationInstance, redshiftCluster, s3, ebsSnapshot | +| lambda | appSync, cognitoUserPool, kms, s3, secretsManager, securityGroup, subnet, vpc, iamRole | +| managedAirflow | cloudwatchLog, iamRole, kms, securityGroups, subnet, s3 | +| managedPrefixList | | +| mskCluster | securityGroup, subnet | +| nacl | vpc | +| natGateway | networkInterface, subnet, vpc | +| networkInterface | ec2, eip, efsMountTarget, natGateway, sageMakerNotebookInstance, subnet, vpc, vpcEndpoint, flowLog, securityGroup | +| organization | +| rdsCluster | appSync, rdsClusterSnapshot, rdsDbInstance, route53HostedZone, securityGroup, subnet, iamRole, kms | +| rdsClusterSnapshot | kms, rdsCluster, vpc | +| rdsDbProxies | | +| rdsEventSubscription | | +| rdsGlobalCluster | | +| rdsDbInstance | kms, iamRole, rdsCluster, securityGroup, vpc, subnet, cloudwatchLog | +| redshiftCluster | kms, vpc | +| route53Record | alb, apiGatewayRestApi, elb, route53HostedZone | +| route53HostedZone | rdsCluster, route53Record, vpc | +| routeTable | subnet, vpc, vpcEndpoint | +| sageMakerExperiment | | +| sageMakerNotebookInstance | iamRole, kms, networkInterface, subnet, securityGroup | +| sageMakerProject | | +| s3 | cloudfront, cloudtrail, ecsCluster, iamRole, kinesisFirehose, kms, lambda, managedAirflow, sns, sqs | +| secretsManager | kms, lambda | +| securityGroup | alb, asg, clientVpnEndpoint, codebuild, dmsReplicationInstance, ecsService, lambda, ec2, elasticSearchDomain, elb, rdsCluster, rdsDbInstance, eksCluster, elastiCacheCluster, managedAirflow, sageMakerNotebookInstance, networkInterface, vpcEndpoint, mskCluster | +| securityHub | | +| securityHubMember | | +| securityHubStandardSubscription | | +| ses | | +| sesReceiptRuleSet | | +| sesDomain | | +| sesEmail | cognitoUserPool | +| sns | kms, cloudtrail, cloudwatch, s3 | +| sqs | elasticBeanstalkEnv, s3 | +| subnet | alb, asg, codebuild, dmsReplicationInstance, ec2, ecsService, efsMountTarget, elastiCacheCluster, elasticSearchDomain, elb, lambda, managedAirflow, natGateway, networkInterface, rdsCluster, sageMakerNotebookInstance, routeTable, vpc, vpcEndpoint, eksCluster, emrCluster, flowLog, mskCluster | +| systemsManagerInstance | ec2, iamRole | +| systemsManagerDocument | | +| systemsManagerParameter | | +| transitGateway | transitGatewayAttachment, transitGatewayRouteTable, vpnConnection | +| transitGatewayAttachment | transitGateway, transitGatewayRouteTable, vpc, vpnConnection | +| transitGatewayRouteTable | transitGateway, transitGatewayAttachment | +| vpc | alb, codebuild, dmsReplicationInstance, ec2, eip, elb, ecsService, efsMountTarget, eksCluster igw, elastiCacheCluster, elasticSearchDomain, lambda, nacl, natGateway, networkInterface, rdsClusterSnapshot, rdsDbInstance, redshiftCluster, route53HostedZone, routeTable, subnet, flowLog, vpnGateway, transitGatewayAttachment, vpcEndpoint, vpcPeeringConnection | +| vpcEndpoint | networkInterface, routeTable, securityGroup, subnet, vpc | +| vpcPeeringConnection | vpc | +| vpnConnection | customerGateway, transitGateway, transitGatewayAttachment, vpnGateway | +| vpnGateway | vpc, vpnConnection | +| wafV2WebAcl | appSync, apiGatewayStage, alb | diff --git a/package.json b/package.json index 9854ff1c..6a5f107d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cloudgraph/cg-provider-aws", - "version": "0.88.0-beta.1", + "version": "0.89.0-alpha.22", "description": "cloud-graph provider plugin for AWS used to fetch AWS cloud data.", "publishConfig": { "registry": "https://registry.npmjs.org/", @@ -31,9 +31,14 @@ "terraform:cleanup": "rimraf ./tests/terraform/{.terraform,.terraform.lock.hcl,tfplan} ./tests/terraform/*.{tfstate,tfplan,backup}" }, "dependencies": { + "@aws-sdk/client-codecommit": "^3.344.0", + "@aws-sdk/client-codepipeline": "^3.344.0", + "@aws-sdk/client-elastic-beanstalk": "^3.338.0", + "@aws-sdk/client-glue": "^3.342.0", + "@aws-sdk/client-ssm": "^3.341.0", "@aws-sdk/credential-providers": "^3.256.0", "@aws-sdk/shared-ini-file-loader": "^3.254.0", - "@cloudgraph/sdk": "^0.22.1", + "@cloudgraph/sdk": "^0.23.0", "@fast-csv/parse": "^4.3.6", "@graphql-tools/load-files": "^6.5.3", "@graphql-tools/merge": "^8.2.1", diff --git a/src/enums/relations.ts b/src/enums/relations.ts index d476949f..4d3fa03f 100644 --- a/src/enums/relations.ts +++ b/src/enums/relations.ts @@ -7,6 +7,7 @@ export default { apiGatewayRestApi: ['apiGatewayResource', 'apiGatewayStage'], route53HostedZone: ['route53Record'], emrCluster: ['emrInstance', 'emrStep'], + ecsCluster: ['ecsService'], ecsService: ['ecsTaskSet', 'ecsTaskDefinition'], iamInstanceProfile: ['ec2Instance'], apiGatewayDomainName: ['apiGatewayRestApi'], diff --git a/src/enums/schemasMap.ts b/src/enums/schemasMap.ts index 6b34621f..f6dbc0af 100644 --- a/src/enums/schemasMap.ts +++ b/src/enums/schemasMap.ts @@ -25,12 +25,16 @@ export default { [services.cloudwatch]: 'awsCloudwatch', [services.cloudwatchLog]: 'awsCloudwatchLog', [services.codebuild]: 'awsCodebuild', + [services.codePipeline]: 'awsCodePipeline', + [services.codePipelineWebhook]: 'awsCodePipelineWebhook', + [services.codeCommitRepository]: 'awsCodeCommitRepository', [services.cognitoIdentityPool]: 'awsCognitoIdentityPool', [services.cognitoUserPool]: 'awsCognitoUserPool', [services.configurationRecorder]: 'awsConfigurationRecorder', [services.customerGateway]: 'awsCustomerGateway', [services.dmsReplicationInstance]: 'awsDmsReplicationInstance', [services.dynamodb]: 'awsDynamoDbTable', + [services.docdbCluster]: 'awsDocdbCluster', [services.ebs]: 'awsEbs', [services.ebsSnapshot]: 'awsEbsSnapshot', [services.ec2Instance]: 'awsEc2', @@ -52,8 +56,11 @@ export default { [services.elasticSearchDomain]: 'awsElasticSearchDomain', [services.elb]: 'awsElb', [services.flowLog]: 'awsFlowLog', + [services.glueCrawler]: 'awsGlueCrawler', + [services.glueDatabase]: 'awsGlueDatabase', [services.glueJob]: 'awsGlueJob', [services.glueRegistry]: 'awsGlueRegistry', + [services.glueTrigger]: 'awsGlueTrigger', [services.guardDutyDetector]: 'awsGuardDutyDetector', [services.emrCluster]: 'awsEmrCluster', [services.emrInstance]: 'awsEmrInstance', @@ -101,9 +108,12 @@ export default { [services.s3]: 'awsS3', [services.secretsManager]: 'awsSecretsManager', [services.ses]: 'awsSes', + [services.sesEmail]: 'awsSesEmail', + [services.sesDomain]: 'awsSesDomain', [services.sns]: 'awsSns', [services.systemsManagerInstance]: 'awsSystemsManagerInstance', [services.systemsManagerDocument]: 'awsSystemsManagerDocument', + [services.systemsManagerParameter]: 'awsSystemsManagerParameter', [services.transitGateway]: 'awsTransitGateway', [services.transitGatewayAttachment]: 'awsTransitGatewayAttachment', [services.transitGatewayRouteTable]: 'awsTransitGatewayRouteTable', diff --git a/src/enums/serviceAliases.ts b/src/enums/serviceAliases.ts index e7295c36..48b4467e 100644 --- a/src/enums/serviceAliases.ts +++ b/src/enums/serviceAliases.ts @@ -7,6 +7,9 @@ export default { [services.apiGatewayHttpApi]: 'apiGatewayHttpApis', [services.apiGatewayResource]: 'apiGatewayResources', [services.apiGatewayRestApi]: 'apiGatewayRestApis', + [services.apiGatewayApiKey]: 'apiGatewayApiKeys', + [services.apiGatewayVpcLink]: 'apiGatewayVpcLinks', + [services.apiGatewayUsagePlan]: 'apiGatewayUsagePlans', [services.apiGatewayStage]: 'apiGatewayStages', [services.asg]: 'asgs', [services.athenaDataCatalog]: 'athenaDataCatalogs', @@ -15,8 +18,15 @@ export default { [services.cloudFormationStackSet]: 'cloudFormationStackSets', [services.cloudfront]: 'cloudfrontDistributions', [services.cloudwatchLog]: 'cloudwatchLogs', + [services.cloudwatchDashboard]: 'cloudwatchDashboards', + [services.cloudwatchEventRule]: 'cloudwatchEventRules', [services.codebuild]: 'codebuilds', + [services.codePipeline]: 'codePipelines', + [services.codePipelineWebhook]: 'codePipelineWebhooks', + [services.codeCommitRepository]: 'codeCommitRepositories', + [services.configurationDeliveryChannel]: 'configurationDeliveryChannels', [services.configurationRecorder]: 'configurationRecorders', + [services.configurationRule]: 'configurationRules', [services.dmsReplicationInstance]: 'dmsReplicationInstances', [services.ebsSnapshot]: 'ebsSnapshots', [services.ec2Instance]: 'ec2Instances', @@ -26,6 +36,7 @@ export default { [services.ecsTask]: 'ecsTasks', [services.ecsTaskDefinition]: 'ecsTaskDefinitions', [services.ecsTaskSet]: 'ecsTaskSets', + [services.efsAccessPoint]: 'efsAccessPoints', [services.eksCluster]: 'eksClusters', [services.elastiCacheCluster]: 'elastiCacheClusters', [services.elastiCacheReplicationGroup]: 'elastiCacheReplicationGroups', @@ -37,8 +48,11 @@ export default { [services.emrInstance]: 'emrInstances', [services.emrStep]: 'emrSteps', [services.flowLog]: 'flowLogs', + [services.glueCrawler]: 'glueCrawlers', + [services.glueDatabase]: 'glueDatabases', [services.glueJob]: 'glueJobs', [services.glueRegistry]: 'glueRegistries', + [services.glueTrigger]: 'glueTriggers', [services.guardDutyDetector]: 'guardDutyDetectors', [services.iamAccessAnalyzer]: 'iamAccessAnalyzers', [services.iamGroup]: 'iamGroups', @@ -71,9 +85,13 @@ export default { [services.secretsManager]: 'secretsManager', [services.sg]: 'securityGroups', [services.securityHub]: 'securityHubs', + [services.securityHubMember]: 'securityHubMembers', + [services.securityHubStandardSubscription]: + 'securityHubStandardSubscriptions', [services.subnet]: 'subnets', [services.systemsManagerDocument]: 'systemsManagerDocuments', [services.systemsManagerInstance]: 'systemsManagerInstances', + [services.systemsManagerParameter]: 'systemsManagerParameters', [services.transitGateway]: 'transitGateways', [services.transitGatewayAttachment]: 'transitGatewayAttachments', [services.transitGatewayRouteTable]: 'transitGatewayRouteTables', diff --git a/src/enums/serviceMap.ts b/src/enums/serviceMap.ts index 9e7969c1..34442f98 100644 --- a/src/enums/serviceMap.ts +++ b/src/enums/serviceMap.ts @@ -1,31 +1,42 @@ import Account from '../services/account' import ACM from '../services/acm' import ALB from '../services/alb' +import APIGatewayApiKey from '../services/apiGatewayApiKey' +import APIGatewayDomainName from '../services/apiGatewayDomainName' +import APIGatewayHttpApi from '../services/apiGatewayHttpApi' import APIGatewayResource from '../services/apiGatewayResource' import APIGatewayRestApi from '../services/apiGatewayRestApi' import APIGatewayStage from '../services/apiGatewayStage' -import ASG from '../services/asg' +import APIGatewayUsagePlan from '../services/apiGatewayUsagePlan' +import APIGatewayVpcLink from '../services/apiGatewayVpcLink' import AppSync from '../services/appSync' -import AwsInternetGateway from '../services/igw' -import AwsKinesisFirehose from '../services/kinesisFirehose' -import AwsKinesisStream from '../services/kinesisStream' -import AwsKms from '../services/kms' -import AwsSecurityGroup from '../services/securityGroup' -import AwsSubnet from '../services/subnet' -import AwsTag from '../services/tag' +import ASG from '../services/asg' import AthenaDataCatalog from '../services/athenaDataCatalog' import Billing from '../services/billing' -import CloudFront from '../services/cloudfront' -import CloudTrail from '../services/cloudtrail' +import ClientVpnEndpoint from '../services/clientVpnEndpoint' +import Cloud9Environment from '../services/cloud9' import CloudFormationStack from '../services/cloudFormationStack' import CloudFormationStackSet from '../services/cloudFormationStackSet' +import CloudFront from '../services/cloudfront' +import CloudTrail from '../services/cloudtrail' import CloudWatch from '../services/cloudwatch' +import CloudWatchDashboard from '../services/cloudwatchDashboards' +import CloudWatchEventRule from '../services/cloudwatchEventRules' +import CloudWatchLog from '../services/cloudwatchLogs' +import CodeBuild from '../services/codeBuild' import CognitoIdentityPool from '../services/cognitoIdentityPool' import CognitoUserPool from '../services/cognitoUserPool' +import ConfigurationDeliveryChannel from '../services/configurationDeliveryChannel' +import ConfigurationRecorder from '../services/configurationRecorder' +import ConfigurationRule from '../services/configurationRule' +import CustomerGateway from '../services/customerGateway' +import DmsReplicationInstance from '../services/dmsReplicationInstance' import DynamoDB from '../services/dynamodb' +import DocDBCluster from '../services/docdbCluster' import EBS from '../services/ebs' import EBSSnapshot from '../services/ebsSnapshot' import EC2 from '../services/ec2' +import ECR from '../services/ecr' import EcsCluster from '../services/ecsCluster' import EcsContainer from '../services/ecsContainer' import EcsService from '../services/ecsService' @@ -33,79 +44,92 @@ import EcsTask from '../services/ecsTask' import EcsTaskDefinition from '../services/ecsTaskDefinition' import EcsTaskSet from '../services/ecsTaskSet' import EFS from '../services/efs' +import EfsAccessPoint from '../services/efsAccessPoint' import EfsMountTarget from '../services/efsMountTarget' import EIP from '../services/eip' -import ElasticBeanstalkApp from '../services/elasticBeanstalkApplication' -import ElasticBeanstalkEnv from '../services/elasticBeanstalkEnvironment' +import EKSCluster from '../services/eksCluster' import ElastiCacheCluster from '../services/elastiCacheCluster' import ElastiCacheReplicationGroup from '../services/elastiCacheReplicationGroup' +import ElasticBeanstalkApp from '../services/elasticBeanstalkApplication' +import ElasticBeanstalkEnv from '../services/elasticBeanstalkEnvironment' +import ElasticSearchDomain from '../services/elasticSearchDomain' import ELB from '../services/elb' -import FlowLog from '../services/flowLogs' import EmrCluster from '../services/emrCluster' import EmrInstance from '../services/emrInstance' import EmrStep from '../services/emrStep' +import FlowLog from '../services/flowLogs' +import GlueCrawler from '../services/glueCrawler' +import GlueDatabase from '../services/glueDatabase' +import GlueJob from '../services/glueJob' +import GlueRegistry from '../services/glueRegistry' +import GlueTrigger from '../services/glueTrigger' +import GuardDutyDetector from '../services/guardDutyDetector' +import IamAccessAnalyzer from '../services/iamAccessAnalyzer' +import IamGroup from '../services/iamGroup' +import IamInstanceProfile from '../services/iamInstanceProfile' +import IamOpenIdConnectProvider from '../services/iamOpenIdConnectProvider' +import IamPasswordPolicy from '../services/iamPasswordPolicy' +import IamPolicy from '../services/iamPolicy' +import IamRole from '../services/iamRole' +import IamSamlProvider from '../services/iamSamlProvider' +import IamServerCertificate from '../services/iamServerCertificate' +import IamUser from '../services/iamUser' +import AwsInternetGateway from '../services/igw' +import IotThingAttribute from '../services/iot' +import AwsKinesisFirehose from '../services/kinesisFirehose' +import AwsKinesisStream from '../services/kinesisStream' +import AwsKms from '../services/kms' import Lambda from '../services/lambda' -import NATGateway from '../services/natGateway' +import ManagedAirflow from '../services/managedAirflow' +import ManagedPrefixList from '../services/managedPrefixList' +import MskCluster from '../services/msk' import NetworkAcl from '../services/nacl' +import NATGateway from '../services/natGateway' import NetworkInterface from '../services/networkInterface' +import Organization from '../services/organization' import RDSCluster from '../services/rdsCluster' +import RdsClusterSnapshot from '../services/rdsClusterSnapshot' import RDSDbInstance from '../services/rdsDbInstance' +import RdsDbProxies from '../services/rdsDbProxies' +import RDSEventSubscription from '../services/rdsEventSubscription' +import RDSGlobalCluster from '../services/rdsGlobalCluster ' import RedshiftCluster from '../services/redshift' import Route53HostedZone from '../services/route53HostedZone' import Route53Record from '../services/route53Record' import RouteTable from '../services/routeTable' +import S3 from '../services/s3' +import SageMakerExperiment from '../services/sageMakerExperiment' +import SageMakerNotebookInstance from '../services/sageMakerNotebookInstance' +import SageMakerProject from '../services/sageMakerProject' import SecretsManager from '../services/secretsManager' +import AwsSecurityGroup from '../services/securityGroup' import SecurityHub from '../services/securityHub' -import S3 from '../services/s3' +import SecurityHubMember from '../services/securityHubMember' +import SecurityHubStandardSubscription from '../services/securityHubStandardSubscription' import SES from '../services/ses' -import SQS from '../services/sqs' -import VPC from '../services/vpc' -import ECR from '../services/ecr' -import IamAccessAnalyzer from '../services/iamAccessAnalyzer' -import IamGroup from '../services/iamGroup' -import IamUser from '../services/iamUser' -import IamRole from '../services/iamRole' -import IamPolicy from '../services/iamPolicy' -import IamPasswordPolicy from '../services/iamPasswordPolicy' -import IamSamlProvider from '../services/iamSamlProvider' -import IamOpenIdConnectProvider from '../services/iamOpenIdConnectProvider' -import IamServerCertificate from '../services/iamServerCertificate' -import IamInstanceProfile from '../services/iamInstanceProfile' +import SESReceiptRuleSet from '../services/sesReceiptRuleSet' +import SESEmail from '../services/sesEmail' +import SESDomain from '../services/sesDomain' import SNS from '../services/sns' -import EKSCluster from '../services/eksCluster' -import Cloud9Environment from '../services/cloud9' -import IotThingAttribute from '../services/iot' -import services from './services' +import SQS from '../services/sqs' +import AwsSubnet from '../services/subnet' +import SystemsManagerDocument from '../services/systemsManagerDocument' +import SystemsManagerInstance from '../services/systemsManagerInstance' +import SystemsManagerParameter from '../services/systemsManagerParameter' +import AwsTag from '../services/tag' import TransitGateway from '../services/transitGateway' import TransitGatewayAttachment from '../services/transitGatewayAttachment' -import CustomerGateway from '../services/customerGateway' -import VpnGateway from '../services/vpnGateway' -import ClientVpnEndpoint from '../services/clientVpnEndpoint' -import VpnConnection from '../services/vpnConnection' -import Organization from '../services/organization' -import CloudWatchLog from '../services/cloudwatchLogs' -import ConfigurationRecorder from '../services/configurationRecorder' -import CodeBuild from '../services/codeBuild' -import GlueJob from '../services/glueJob' -import GlueRegistry from '../services/glueRegistry' -import SageMakerProject from '../services/sageMakerProject' -import SageMakerExperiment from '../services/sageMakerExperiment' -import ManagedAirflow from '../services/managedAirflow' -import WafV2WebAcl from '../services/wafV2WebAcl' -import GuardDutyDetector from '../services/guardDutyDetector' -import ElasticSearchDomain from '../services/elasticSearchDomain' -import DmsReplicationInstance from '../services/dmsReplicationInstance' -import SageMakerNotebookInstance from '../services/sageMakerNotebookInstance' -import SystemsManagerInstance from '../services/systemsManagerInstance' -import SystemsManagerDocument from '../services/systemsManagerDocument' -import RdsClusterSnapshot from '../services/rdsClusterSnapshot' -import VpcEndpoint from '../services/vpcEndpoint' -import APIGatewayDomainName from '../services/apiGatewayDomainName' -import APIGatewayHttpApi from '../services/apiGatewayHttpApi' -import ManagedPrefixList from '../services/managedPrefixList' -import MskCluster from '../services/msk' import TransitGatewayRouteTable from '../services/transitGatewayRouteTable' +import VPC from '../services/vpc' +import VpcEndpoint from '../services/vpcEndpoint' import VpcPeeringConnection from '../services/vpcPeeringConnection' +import CodeCommitRepository from '../services/codeCommitRepository' +import VpnConnection from '../services/vpnConnection' +import VpnGateway from '../services/vpnGateway' +import WafV2WebAcl from '../services/wafV2WebAcl' +import services from './services' +import CodePipeline from '../services/codePipeline' +import CodePipelineWebhook from '../services/codePipelineWebhook' /** * serviceMap is an object that contains all currently supported services for AWS @@ -120,6 +144,9 @@ export default { [services.apiGatewayHttpApi]: APIGatewayHttpApi, [services.apiGatewayResource]: APIGatewayResource, [services.apiGatewayRestApi]: APIGatewayRestApi, + [services.apiGatewayApiKey]: APIGatewayApiKey, + [services.apiGatewayVpcLink]: APIGatewayVpcLink, + [services.apiGatewayUsagePlan]: APIGatewayUsagePlan, [services.apiGatewayStage]: APIGatewayStage, [services.athenaDataCatalog]: AthenaDataCatalog, [services.asg]: ASG, @@ -131,16 +158,24 @@ export default { [services.cloudFormationStack]: CloudFormationStack, [services.cloudFormationStackSet]: CloudFormationStackSet, [services.cloudwatch]: CloudWatch, + [services.cloudwatchDashboard]: CloudWatchDashboard, + [services.cloudwatchEventRule]: CloudWatchEventRule, [services.cloudwatchLog]: CloudWatchLog, [services.codebuild]: CodeBuild, + [services.codePipeline]: CodePipeline, + [services.codePipelineWebhook]: CodePipelineWebhook, + [services.codeCommitRepository]: CodeCommitRepository, [services.cognitoIdentityPool]: CognitoIdentityPool, [services.cognitoUserPool]: CognitoUserPool, + [services.configurationDeliveryChannel]: ConfigurationDeliveryChannel, [services.configurationRecorder]: ConfigurationRecorder, + [services.configurationRule]: ConfigurationRule, [services.ebs]: EBS, [services.ebsSnapshot]: EBSSnapshot, [services.ec2Instance]: EC2, [services.ecr]: ECR, [services.efs]: EFS, + [services.efsAccessPoint]: EfsAccessPoint, [services.efsMountTarget]: EfsMountTarget, [services.eip]: EIP, [services.eksCluster]: EKSCluster, @@ -151,14 +186,18 @@ export default { [services.elasticSearchDomain]: ElasticSearchDomain, [services.elb]: ELB, [services.flowLog]: FlowLog, + [services.glueCrawler]: GlueCrawler, + [services.glueDatabase]: GlueDatabase, [services.glueJob]: GlueJob, - [services.guardDutyDetector]: GuardDutyDetector, [services.glueRegistry]: GlueRegistry, + [services.glueTrigger]: GlueTrigger, + [services.guardDutyDetector]: GuardDutyDetector, [services.emrCluster]: EmrCluster, [services.emrInstance]: EmrInstance, [services.emrStep]: EmrStep, [services.dmsReplicationInstance]: DmsReplicationInstance, [services.dynamodb]: DynamoDB, + [services.docdbCluster]: DocDBCluster, [services.igw]: AwsInternetGateway, [services.iot]: IotThingAttribute, [services.kinesisFirehose]: AwsKinesisFirehose, @@ -178,8 +217,11 @@ export default { [services.vpcPeeringConnection]: VpcPeeringConnection, [services.sqs]: SQS, [services.rdsCluster]: RDSCluster, + [services.rdsGlobalCluster]: RDSGlobalCluster, [services.rdsClusterSnapshot]: RdsClusterSnapshot, [services.rdsDbInstance]: RDSDbInstance, + [services.rdsEventSubscription]: RDSEventSubscription, + [services.rdsDbProxies]: RdsDbProxies, [services.redshiftCluster]: RedshiftCluster, [services.route53HostedZone]: Route53HostedZone, [services.route53Record]: Route53Record, @@ -190,7 +232,12 @@ export default { [services.s3]: S3, [services.secretsManager]: SecretsManager, [services.securityHub]: SecurityHub, + [services.securityHubMember]: SecurityHubMember, + [services.securityHubStandardSubscription]: SecurityHubStandardSubscription, [services.ses]: SES, + [services.sesReceiptRuleSet]: SESReceiptRuleSet, + [services.sesEmail]: SESEmail, + [services.sesDomain]: SESDomain, [services.iamAccessAnalyzer]: IamAccessAnalyzer, [services.iamUser]: IamUser, [services.iamGroup]: IamGroup, @@ -218,5 +265,6 @@ export default { [services.wafV2WebAcl]: WafV2WebAcl, [services.systemsManagerInstance]: SystemsManagerInstance, [services.systemsManagerDocument]: SystemsManagerDocument, + [services.systemsManagerParameter]: SystemsManagerParameter, tag: AwsTag, } diff --git a/src/enums/services.ts b/src/enums/services.ts index 676aeabd..9fd16e8d 100644 --- a/src/enums/services.ts +++ b/src/enums/services.ts @@ -5,6 +5,9 @@ export default { apiGatewayHttpApi: 'apiGatewayHttpApi', apiGatewayResource: 'apiGatewayResource', apiGatewayRestApi: 'apiGatewayRestApi', + apiGatewayApiKey: 'apiGatewayApiKey', + apiGatewayVpcLink: 'apiGatewayVpcLink', + apiGatewayUsagePlan: 'apiGatewayUsagePlan', apiGatewayStage: 'apiGatewayStage', appSync: 'appSync', asg: 'asg', @@ -17,14 +20,22 @@ export default { cloudfront: 'cloudfront', cloudtrail: 'cloudtrail', cloudwatch: 'cloudwatch', + cloudwatchDashboard: 'cloudwatchDashboard', + cloudwatchEventRule: 'cloudwatchEventRule', cloudwatchLog: 'cloudwatchLog', codebuild: 'codebuild', + codePipeline: 'codePipeline', + codePipelineWebhook: 'codePipelineWebhook', + codeCommitRepository: 'codeCommitRepository', cognitoIdentityPool: 'cognitoIdentityPool', cognitoUserPool: 'cognitoUserPool', + configurationDeliveryChannel: 'configurationDeliveryChannel', configurationRecorder: 'configurationRecorder', + configurationRule: 'configurationRule', customerGateway: 'customerGateway', dmsReplicationInstance: 'dmsReplicationInstance', dynamodb: 'dynamodb', + docdbCluster: 'docdbCluster', ebs: 'ebs', ebsSnapshot: 'ebsSnapshot', ec2Instance: 'ec2Instance', @@ -36,6 +47,7 @@ export default { ecsTaskDefinition: 'ecsTaskDefinition', ecsTaskSet: 'ecsTaskSet', efs: 'efs', + efsAccessPoint: 'efsAccessPoint', efsMountTarget: 'efsMountTarget', eip: 'eip', eksCluster: 'eksCluster', @@ -46,8 +58,11 @@ export default { elasticSearchDomain: 'elasticSearchDomain', elb: 'elb', flowLog: 'flowLog', + glueCrawler: 'glueCrawler', + glueDatabase: 'glueDatabase', glueJob: 'glueJob', glueRegistry: 'glueRegistry', + glueTrigger: 'glueTrigger', guardDutyDetector: 'guardDutyDetector', emrCluster: 'emrCluster', emrInstance: 'emrInstance', @@ -76,8 +91,11 @@ export default { networkInterface: 'networkInterface', organization: 'organization', rdsCluster: 'rdsCluster', + rdsGlobalCluster: 'rdsGlobalCluster', rdsClusterSnapshot: 'rdsClusterSnapshot', rdsDbInstance: 'rdsDbInstance', + rdsEventSubscription: 'rdsEventSubscription', + rdsDbProxies: 'rdsDbProxies', redshiftCluster: 'redshiftCluster', route53HostedZone: 'route53HostedZone', route53Record: 'route53Record', @@ -88,13 +106,19 @@ export default { s3: 's3', secretsManager: 'secretsManager', securityHub: 'securityHub', + securityHubMember: 'securityHubMember', + securityHubStandardSubscription: 'securityHubStandardSubscription', ses: 'ses', + sesReceiptRuleSet: 'sesReceiptRuleSet', + sesEmail: 'sesEmail', + sesDomain: 'sesDomain', sg: 'sg', sns: 'sns', sqs: 'sqs', subnet: 'subnet', systemsManagerInstance: 'systemsManagerInstance', systemsManagerDocument: 'systemsManagerDocument', + systemsManagerParameter: 'systemsManagerParameter', transitGateway: 'transitGateway', transitGatewayAttachment: 'transitGatewayAttachment', transitGatewayRouteTable: 'transitGatewayRouteTable', diff --git a/src/properties/logger.ts b/src/properties/logger.ts index 7531bd44..429e0353 100644 --- a/src/properties/logger.ts +++ b/src/properties/logger.ts @@ -59,7 +59,7 @@ export default { */ fetchingCloudFrontData: 'Fetching CloudFront Distros for this AWS account via the AWS SDK...', - fetchedCloudFrontDistros: (num: number) => + fetchedCloudFrontDistros: (num: number): string => `Fetched ${num} CloudFront Distros`, fetchingCloudFrontDistrosConfigAndTags: 'Fetching CloudFront Distros Config Data and Tags...', @@ -94,6 +94,9 @@ export default { `Found ${num} CloudWatch metric alarms to add for ${namespace}`, gettingCloudwatchAlarms: 'Fetching CloudWatch alarms...', gettingCloudwatchAlarmTags: 'Fetching tags for each CloudWatch alarm...', + gettingCloudwatchDashboards: 'Fetching CloudWatch dashboards...', + gettingCloudwatchRules: 'Fetching CloudWatch events rules...', + gettingCloudwatchRuleTargets: 'Fetching CloudWatch events rule targets...', /** * Kinesis Data Streams */ @@ -114,7 +117,7 @@ export default { lookingForIotThing: 'Looking for IoT Things to add to Region...', addingIotThing: (num: number): string => `Created and added ${num} IoT Things to this region`, - foundMoreIoTThings: (num: number) => + foundMoreIoTThings: (num: number): string => `Found another ${num} IoT things in this region...`, gettingIoTThings: 'Fetching IoT things...', /** @@ -131,10 +134,24 @@ export default { `Fetched ${num} Api Gateway Stages`, fetchedApiGwDomainNames: (num: number): string => `Fetched ${num} API Gateway Domain Names`, + fetchedApiGatewayApiKeys: (num: number): string => + `Fetched ${num} Api Gateway Api Keys`, + fetchedApiGatewayVpcLinks: (num: number): string => + `Fetched ${num} Api Gateway Vpc Links`, + fetchedApiGatewayUsagePlans: (num: number): string => + `Fetched ${num} Api Gateway Usage Plans`, fetchingApiGatewayData: 'Fetching API Gateway data for this AWS account via the AWS SDK...', doneFetchingApiGatewayData: '✅ Done fetching API Gateway Data ✅', gettingApiGatewayTags: 'Fetching tags for each Api Gateway Rest Api...', + gettingApiGatewayAuthorizers: + 'Fetching authorizers for each Api Gateway Rest Api...', + gettingApiGatewayDocumentationParts: + 'Fetching authorizers for each Api Gateway Documentation Parts...', + gettingApiGatewayGatewayResponses: + 'Fetching authorizers for each Api Gateway Gateway Responses...', + gettingApiGatewayModels: + 'Fetching authorizers for each Api Gateway Models...', gettingApiGatewayStageTags: 'Fetching tags for each Api Gateway Stage...', /** * Vpc @@ -206,6 +223,8 @@ export default { `Fetched ${num} Attributes for ${albArn}`, fetchedAlbListeners: (num: number, albArn: string): string => `Fetched ${num} ALB Listeners for ${albArn}`, + fetchedAlbListenerCertificates: (num: number, listenerArn: string): string => + `Fetched ${num} ALB Listener Certificates for ${listenerArn}`, fetchedAlbTargetGroups: (num: number, albArn: string): string => `Fetched ${num} ALB Target Groups for ${albArn}`, fetchedAlbTargetIds: (num: number, albArn: string): string => @@ -257,10 +276,11 @@ export default { /** * EBS Snapshot */ - fetchingEbsSnapshotData: 'Fetching EBS Snapshot data for this AWS account via the AWS SDK...', - doneFetchingEbsSnapshotData: '✅ Done fetching EBS Snapshot Data ✅', - fetchedEbsSnapshots: (num: number): string => `Fetched ${num} EBS Snapshots`, - lookingForEbsSnapshot: 'Looking for EBS Snapshots...', + fetchingEbsSnapshotData: + 'Fetching EBS Snapshot data for this AWS account via the AWS SDK...', + doneFetchingEbsSnapshotData: '✅ Done fetching EBS Snapshot Data ✅', + fetchedEbsSnapshots: (num: number): string => `Fetched ${num} EBS Snapshots`, + lookingForEbsSnapshot: 'Looking for EBS Snapshots...', /** * EC2 */ @@ -274,8 +294,7 @@ export default { fetchedNetworkInterfaces: (num: number): string => `Fetched ${num} Network Interfaces`, lookingForNetworkInterfaces: 'Gathering Network Interfaces to add...', - foundKeyPair: (id: string): string => - `Found Key Pair ${id} for instance`, + foundKeyPair: (id: string): string => `Found Key Pair ${id} for instance`, doneFetchingEc2Data: '✅ Done fetching EC2 Instance Data ✅', /** * RDS @@ -286,8 +305,14 @@ export default { lookingforRdsClusters: 'Looking for RDS Clusters...', creatingRdsInstance: (num: number): string => `Creating RDS Instance #${num}`, fetchedRdsClusters: (num: number): string => `Fetched ${num} RDS Clusters`, + fetchedDocdbClusters: (num: number): string => `Fetched ${num} DocDB Clusters`, + fetchedRdsGlobalClusters: (num: number): string => + `Fetched ${num} RDS Global Clusters`, fetchedRdsInstances: (num: number): string => `Fetched ${num} RDS DB Instances`, + fetchedRdsEventSubscriptions: (num: number): string => + `Fetched ${num} RDS DB Event Subscriptions`, + fetchedRdsDbProxies: (num: number): string => `Fetched ${num} RDS DB Proxies`, noClusterFound: '❎ DB Instance is not part of a cluster ❎ ', foundCluster: 'Found the cluster the instance belongs to', addingRdsInstances: (num: number): string => @@ -308,13 +333,14 @@ export default { fetchedEmrClusters: (num: number): string => `Fetched ${num} EMR Clusters`, fetchedEmrClusterInstances: (num: number): string => `Fetched ${num} EMR Clusters Instances`, - foundAnotherFiftyClusters: (region: string) => + foundAnotherFiftyClusters: (region: string): string => `Found another 50 EMR clusters for the ${region} region...`, - foundAnotherTwoThousandInstances: (cluster: string) => + foundAnotherTwoThousandInstances: (cluster: string): string => `Found another 2000 EMR instances for the ${cluster} cluster...`, - foundAnotherFiftySteps: (cluster: string) => + foundAnotherFiftySteps: (cluster: string): string => `Found another 50 EMR steps for the ${cluster} cluster...`, - fetchedEmrClusterSteps: (num: number) => `Fetched ${num} EMR Cluster Steps`, + fetchedEmrClusterSteps: (num: number): string => + `Fetched ${num} EMR Cluster Steps`, addingEmrEc2Connection: ( clusterName: string, ec2InstanceName: string @@ -335,6 +361,8 @@ export default { `Found ${num} EFS Mount Targets, adding them to the subnet`, doneFetchingEfsData: '✅ Done fetching EFS Data ✅', fetchedEfs: (num: number): string => `Fetched ${num} EFS`, + fetchedEfsAccessPoints: (num: number): string => + `Fetched ${num} EFS Access Points`, fetchedEfsMountTargets: (num: number): string => `Fetched ${num} EFS Mount Targets`, fetchedEfsMountTargetSecurityGroups: (num: number): string => @@ -367,11 +395,11 @@ export default { lookingForDynamoDb: 'Looking for DynamoDb Tables to add...', fetchingDynamoDbData: 'Fetching DynamoDB data for this AWS account via the AWS SDK...', - doneFetchingDynamoDbData: (num: number) => + doneFetchingDynamoDbData: (num: number): string => `🕒 Done fetching DynamoDb Data in ${num} 🕘`, - fetchedDynamoDbTableNames: (num: number) => + fetchedDynamoDbTableNames: (num: number): string => `Fetched ${num} DynamoDB table names`, - addingDynamoDbTables: (num: number) => + addingDynamoDbTables: (num: number): string => `Found ${num} Dynamo DB tables, adding them to the Region`, gettingTableDetails: 'Fetching details for each table...', gettingTableTags: 'Fetching tags for each table...', @@ -381,10 +409,10 @@ export default { /** * SNS */ - fetchedSNSTopics: (num: number) => `Fetched ${num} SNS Topics`, - gettingSNSTopicAttributes: `Fetching attributes for each topic...`, - gettingSNSTopicTags: `Fetching tags for each topic...`, - gettingSNSTopicSubscriptions: `Fetching subscriptions for each topic...`, + fetchedSNSTopics: (num: number): string => `Fetched ${num} SNS Topics`, + gettingSNSTopicAttributes: 'Fetching attributes for each topic...', + gettingSNSTopicTags: 'Fetching tags for each topic...', + gettingSNSTopicSubscriptions: 'Fetching subscriptions for each topic...', lookingForSns: 'Looking for SNS topics and subscriptions to add...', addingSns: (num: number): string => `Found ${num} SNS topics, adding them to the Region`, @@ -449,7 +477,7 @@ export default { `Found ${num} EKS Clusters, adding them to the VPC`, canNotFindClusterForAsg: 'ERROR: Can not find ECS/EKS cluster for ASG - it should have been added already', - foundMoreEKSClusters: (num: number) => + foundMoreEKSClusters: (num: number): string => `Found another ${num} EKS clusters in this region...`, /** * Elastic Beanstalk @@ -466,16 +494,20 @@ export default { `Found ${num} ElastiCache Clusters, adding them to the VPC`, missingReplicationGroup: (is: string): string => `Missing replication group for ${is} ElastiCache Cluster! Not adding ElastiCache Data`, - fetchedElasticacheClusters: (num: number) => + fetchedElasticacheClusters: (num: number): string => `Fetched ${num} Elasticache clusters...`, /** * ECR */ fetchedECRRepos: (num: number): string => `Found ${num} ECR repos...`, - foundMoreECRRepos: (num: number) => + foundMoreECRRepos: (num: number): string => `Found another ${num} ECR repos in this region...`, gettingECRRepos: 'Fetching ECR repos...', gettingECRRepoTags: 'Fetching tags for each ECR repo...', + gettingECRRepoLifecyclePolicy: + 'Fetching lifecycle policy for each ECR repo...', + gettingECRRepoRepositoryPolicy: + 'Fetching repository policy for each ECR repo...', /** * Transit Gateway */ @@ -486,23 +518,25 @@ export default { `Adding Transit Gateway ${name} to the VPC`, addingTransitGatewayToRegion: ({ name }): string => `Transit Gateway not attached to a VPC, adding Transit Gateway ${name} to the region level`, - fetchedTransitGateways: (num: number): string => `Found ${num} Transit Gateways`, + fetchedTransitGateways: (num: number): string => + `Found ${num} Transit Gateways`, /** * Transit Gateway Attachment */ - fetchedTransitGatewayAttachments: (num: number): string => `Found ${num} Transit Gateway Attachments`, - /** + fetchedTransitGatewayAttachments: (num: number): string => + `Found ${num} Transit Gateway Attachments`, + /** * Transit Gateway Route Tables */ - fetchedTransitGatewayRouteTables: (num: number): string => `Found ${num} Transit Gateway Route Tables`, + fetchedTransitGatewayRouteTables: (num: number): string => + `Found ${num} Transit Gateway Route Tables`, /** * VPN Gateway */ lookingForVpnGateway: 'Looking for Vpn Gateways to add...', addingVpnGatewayToVpc: (num: number): string => `Adding ${num} Vpn Gateways to the VPC`, - fetchedVpnGateways: (num: number): string => - `Fetched ${num} Vpn Gateways`, + fetchedVpnGateways: (num: number): string => `Fetched ${num} Vpn Gateways`, /** * Customer Gateway */ @@ -613,7 +647,7 @@ export default { lookingForCloud9: 'Looking for Cloud9 to add to Region...', addingCloud9: (num: number): string => `Created and added ${num} Cloud9 to this region`, - foundMoreCloud9Environments: (num: number) => + foundMoreCloud9Environments: (num: number): string => `Found another ${num} Cloud9 environments in this region...`, gettingCloud9Environments: 'Fetching Cloud9 environments...', gettingCloud9EnvironmentTags: 'Fetching tags for each Cloud9 environment...', @@ -659,57 +693,81 @@ export default { * NACL */ fetchedNacls: (num: number): string => `Fetched ${num} NACLs`, - /** + /** * Customer Gateway */ - fetchedCustomerGateways: (num: number): string => `Fetched ${num} Customer Gateways`, + fetchedCustomerGateways: (num: number): string => + `Fetched ${num} Customer Gateways`, /** * CloudWatch Logs */ - lookingForCloudwatchLogGroups: 'Looking for CloudWatch Log groups to add to Region...', - fetchingCloudwatchLogGroupsData: - 'Fetching CloudWatch Log groups for this AWS account via the AWS SDK...', - doneFetchingCloudwatchLogGroupsData: (num: number): string => - `🕒 Done fetching CloudWatch Log groups in ${num} 🕘`, - foundMoreCloudwatchLogGroups: (num: number): string => - `Found another ${num} CloudWatch Log groups in this region...`, - gettingCloudwatchLogGroups: 'Fetching CloudWatch Log groups...', - foundMoreCloudwatchMetricFilters: (num: number): string => - `Found another ${num} CloudWatch Metric filters in this region...`, + lookingForCloudwatchLogGroups: + 'Looking for CloudWatch Log groups to add to Region...', + fetchingCloudwatchLogGroupsData: + 'Fetching CloudWatch Log groups for this AWS account via the AWS SDK...', + doneFetchingCloudwatchLogGroupsData: (num: number): string => + `🕒 Done fetching CloudWatch Log groups in ${num} 🕘`, + foundMoreCloudwatchLogGroups: (num: number): string => + `Found another ${num} CloudWatch Log groups in this region...`, + gettingCloudwatchLogGroups: 'Fetching CloudWatch Log groups...', + foundMoreCloudwatchMetricFilters: (num: number): string => + `Found another ${num} CloudWatch Metric filters in this region...`, + /** + * Configuration Delivery Channel + */ + fetchedCOnfigurationDeliveryChannels: (num: number): string => + `Fetched ${num} Configuration Delivery Channels`, /** * Configuration Recorders */ - fetchedConfigurationRecorders: (num: number): string => `Fetched ${num} Configuration Recorders`, + fetchedConfigurationRecorders: (num: number): string => + `Fetched ${num} Configuration Recorders`, /** * Configuration Recorder Status */ - fetchedConfigurationRecorderStatus: (num: number): string => `Fetched ${num} Configuration Recorder Status`, - /** + fetchedConfigurationRecorderStatus: (num: number): string => + `Fetched ${num} Configuration Recorder Status`, + /** + * Configuration Rules + */ + fetchedConfigurationRules: (num: number): string => + `Fetched ${num} Configuration Rules`, + /** * Vpc Endpoints */ - fetchedVpcEndpoints: (num: number): string => `Fetched ${num} Vpc Endpoints`, + fetchedVpcEndpoints: (num: number): string => `Fetched ${num} Vpc Endpoints`, /** * Access Analyzers */ - fetchedaccessAnalyzers: (num: number): string => `Found ${num} Access Analyzers`, + fetchedaccessAnalyzers: (num: number): string => + `Found ${num} Access Analyzers`, /** * Managed Prefix Lists */ - fetchedManagedPrefixLists: (num: number): string => `Found ${num} Managed Prefix Lists`, - fetchedManagedPrefixListEntries: (num: number): string => `Found ${num} Managed Prefix List Entries`, + fetchedManagedPrefixLists: (num: number): string => + `Found ${num} Managed Prefix Lists`, + fetchedManagedPrefixListEntries: (num: number): string => + `Found ${num} Managed Prefix List Entries`, /** * Vpc Peering Connections */ - fetchedVpcPeeringConnections: (num: number): string => `Found ${num} Vpc Peering Connections`, + fetchedVpcPeeringConnections: (num: number): string => + `Found ${num} Vpc Peering Connections`, /** * Security Hub */ - securityHubNotFound: (region: string): string => `Security Hub not found/disabled for region: ${region}`, - fetchedSecurityHub: (region: string): string => `Security Hub found/enabled for region: ${region}`, - fetchingSecurityHub: 'Fetching Security Hub data for this AWS account via the AWS SDK...', + securityHubNotFound: (region: string): string => + `Security Hub not found/disabled for region: ${region}`, + fetchedSecurityHub: (region: string): string => + `Security Hub found/enabled for region: ${region}`, + fetchingSecurityHub: + 'Fetching Security Hub data for this AWS account via the AWS SDK...', + fetchedSecurityHubMembers: (num: number): string => + `Found ${num} Security Hub Members`, + fetchedSecurityHubStandardSubscriptions: (num: number): string => + `Found ${num} Security Hub Standard Subscription`, /** * Msk */ - fetchedMskClusters: (num: number): string => - `Fetched ${num} Msk clusters`, + fetchedMskClusters: (num: number): string => `Fetched ${num} Msk clusters`, } diff --git a/src/services/account/schema.graphql b/src/services/account/schema.graphql index 06acc871..f44c9300 100644 --- a/src/services/account/schema.graphql +++ b/src/services/account/schema.graphql @@ -1,11 +1,14 @@ type awsAccount implements awsOptionalService @key(fields: "id") { regions: [String] @search(by: [hash]) albs: [awsAlb] + apiGatewayApiKeys: [awsApiGatewayApiKey] apiGatewayDomainNames: [awsApiGatewayDomainName] apiGatewayHttpApis: [awsApiGatewayHttpApi] apiGatewayResources: [awsApiGatewayResource] apiGatewayRestApis: [awsApiGatewayRestApi] apiGatewayStages: [awsApiGatewayStage] + apiGatewayUsagePlans: [awsApiGatewayUsagePlan] + apiGatewayVpcLinks: [awsApiGatewayVpcLink] appSync: [awsAppSync] asgs: [awsAsg] athenaDataCatalogs: [awsAthenaDataCatalog] @@ -19,12 +22,18 @@ type awsAccount implements awsOptionalService @key(fields: "id") { cloudwatch: [awsCloudwatch] cloudwatchLogs: [awsCloudwatchLog] codebuilds: [awsCodebuild] + codePipelines: [awsCodePipeline] + codePipelineWebhooks: [awsCodePipelineWebhook] + codeCommitRepository: [awsCodeCommitRepository] cognitoIdentityPool: [awsCognitoIdentityPool] cognitoUserPool: [awsCognitoUserPool] + configurationDeliveryChannels: [awsConfigurationDeliveryChannel] configurationRecorders: [awsConfigurationRecorder] + configurationRules: [awsConfigurationRule] customerGateway: [awsCustomerGateway] dmsReplicationInstances: [awsDmsReplicationInstance] dynamodb: [awsDynamoDbTable] + docdbCluster: [awsDocdbCluster] ebs: [awsEbs] ec2Instances: [awsEc2] ecr: [awsEcr] @@ -35,6 +44,7 @@ type awsAccount implements awsOptionalService @key(fields: "id") { ecsTaskDefinitions: [awsEcsTaskDefinition] ecsTaskSets: [awsEcsTaskSet] efs: [awsEfs] + efsAccessPoint: [awsEfsAccessPoint] efsMountTarget: [awsEfsMountTarget] eip: [awsEip] eksClusters: [awsEksCluster] @@ -48,8 +58,11 @@ type awsAccount implements awsOptionalService @key(fields: "id") { emrInstances: [awsEmrInstance] emrSteps: [awsEmrStep] flowLogs: [awsFlowLog] + glueCrawlers: [awsGlueCrawler] + glueDatabases: [awsGlueDatabase] glueJobs: [awsGlueJob] glueRegistries: [awsGlueRegistry] + glueTriggers: [awsGlueTrigger] guardDutyDetectors: [awsGuardDutyDetector] iamAccessAnalyzers: [awsIamAccessAnalyzer] iamGroups: [awsIamGroup] @@ -75,8 +88,11 @@ type awsAccount implements awsOptionalService @key(fields: "id") { networkInterfaces: [awsNetworkInterface] organizations: [awsOrganization] rdsClusters: [awsRdsCluster] + rdsGlobalCluster: [awsRdsGlobalCluster] rdsClusterSnapshots: [awsRdsClusterSnapshot] rdsDbInstances: [awsRdsDbInstance] + rdsEventSubscription: [awsRdsEventSubscription] + rdsDbProxies: [awsRdsDbProxies] redshiftClusters: [awsRedshiftCluster] route53HostedZones: [awsRoute53HostedZone] route53Records: [awsRoute53Record] @@ -88,9 +104,15 @@ type awsAccount implements awsOptionalService @key(fields: "id") { secretsManager: [awsSecretsManager] securityGroups: [awsSecurityGroup] securityHub: [awsSecurityHub] + securityHubMember: [awsSecurityHubMember] + securityHubStandardSubscription: [awsSecurityHubStandardSubscription] systemsManagerDocuments: [awsSystemsManagerDocument] systemsManagerInstances: [awsSystemsManagerInstance] + systemsManagerParameters: [awsSystemsManagerParameter] ses: [awsSes] + sesReceiptRuleSet: [awsSesReceiptRuleSet] + sesEmail: [awsSesEmail] + sesDomain: [awsSesDomain] sns: [awsSns] sqs: [awsSqs] subnets: [awsSubnet] diff --git a/src/services/alb/data.ts b/src/services/alb/data.ts index a7afaf4f..40226e5f 100644 --- a/src/services/alb/data.ts +++ b/src/services/alb/data.ts @@ -9,10 +9,13 @@ import ELBV2, { DescribeTargetGroupsInput, DescribeTargetGroupsOutput, DescribeTargetHealthOutput, + DescribeListenerCertificatesInput, Listeners, LoadBalancer, LoadBalancerAttributeValue, TargetGroups, + Certificate, + TargetHealthDescription, } from 'aws-sdk/clients/elbv2' import CloudGraph, { Opts } from '@cloudgraph/sdk' @@ -41,13 +44,75 @@ const customRetrySettings = setAwsRetryOptions({ baseDelay: ALB_CUSTOM_DELAY }) export type RawAwsAlb = LoadBalancer & { listeners: Listeners + listenerCertificates: Array targetIds: Array + targetHealth: Array attributes: { [property: string]: LoadBalancerAttributeValue } targetGroups: TargetGroups region: string Tags: TagMap } +const describeListenerCertificatesForAlb = async ({ + elbv2, + ListenerArn, +}: { + elbv2: ELBV2 + ListenerArn: string +}): Promise => + new Promise(resolve => { + const certificateList: Certificate[] = [] + const listAllCertificates = (token?: string): void => { + const args: DescribeListenerCertificatesInput = { ListenerArn } + if (token) { + args.Marker = token + } + + try { + elbv2.describeListenerCertificates(args, (err, data) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'elbv2:describeListenerCertificates', + err, + }) + resolve(certificateList) + return + } + + const { Certificates: certificates = [], NextMarker: marker } = + data || {} + + logger.debug( + lt.fetchedAlbListenerCertificates(certificates.length, ListenerArn) + ) + + if (isEmpty(certificates)) { + resolve(certificateList) + return + } + + certificateList.push(...certificates) + + /** + * Check to see if there are more + */ + if (marker) { + listAllCertificates(marker) + } else { + resolve(certificateList) + } + }) + } catch (err) { + errorLog.generateAwsErrorLog({ + functionName: 'elbv2:describeListenerCertificates', + err, + }) + resolve([]) + } + } + listAllCertificates() + }) + export default async ({ regions, config, @@ -64,6 +129,7 @@ export default async ({ const listenerPromises = [] const targetGroupPromises = [] const targetHealthPromises = [] + const listenerCertificatesPromises = [] /** * Step 1) for all regions, list all the albs @@ -131,7 +197,9 @@ export default async ({ region, Tags: {}, listeners: [], + listenerCertificates: [], targetIds: [], + targetHealth: [], attributes: {}, targetGroups: [], })) @@ -147,7 +215,7 @@ export default async ({ }) } - regions.split(',').map(region => + regions.split(',').forEach(region => regionPromises.push( new Promise(resolveRegion => describeAlbs({ @@ -217,7 +285,7 @@ export default async ({ const result = {} - tags.map(({ Key, Value }) => { + tags.forEach(({ Key, Value }) => { result[Key] = Value }) @@ -226,7 +294,7 @@ export default async ({ resolveTags() }) - albData.map(alb => { + albData.forEach(alb => { const { LoadBalancerArn: arn, region } = alb const elbv2 = new ELBV2({ ...config, @@ -302,7 +370,7 @@ export default async ({ const result = {} - attributes.map(({ Key, Value }) => { + attributes.forEach(({ Key, Value }) => { result[Key] = Value }) @@ -311,7 +379,7 @@ export default async ({ } ) - albData.map(alb => { + albData.forEach(alb => { const { LoadBalancerArn, region } = alb const elbv2 = new ELBV2({ ...config, @@ -416,7 +484,7 @@ export default async ({ }) } - albData.map(alb => { + albData.forEach(alb => { const { LoadBalancerArn, region } = alb const elbv2 = new ELBV2({ ...config, @@ -523,7 +591,7 @@ export default async ({ }) } - albData.map(alb => { + albData.forEach(alb => { const { LoadBalancerArn, region } = alb const elbv2 = new ELBV2({ ...config, @@ -592,15 +660,20 @@ export default async ({ /** * Add the ids to the alb's targetIds */ - alb.targetIds.push( ...targetHealth.map(({ Target: { Id = '' } = {} }) => Id) ) + alb.targetHealth.push( + ...targetHealth.map(({ Target }) => ({ + targetGroupArn: TargetGroupArn, + id: Target.Id, + })) + ) resolveTargetHealth() }) - albData.map(alb => { + albData.forEach(alb => { const { region, targetGroups = [] } = alb const elbv2 = new ELBV2({ ...config, @@ -608,7 +681,7 @@ export default async ({ endpoint, ...customRetrySettings, }) - targetGroups.map(({ TargetGroupArn }) => { + targetGroups.forEach(({ TargetGroupArn }) => { targetHealthPromises.push( new Promise(resolveTargetHealth => { describeTargetHealth({ @@ -623,6 +696,41 @@ export default async ({ }) await Promise.all(targetHealthPromises) + + /** + * Step 7, use the describeListenerCertificates method to get the certificates IDs + */ + albData.forEach(alb => { + const { listeners = [], region } = alb + const elbv2 = new ELBV2({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + listeners.forEach(({ ListenerArn }) => { + const certificatePromise = new Promise(async resolveListener => { + const certificates = await describeListenerCertificatesForAlb({ + elbv2, + ListenerArn, + }) + if (!isEmpty(certificates)) { + alb.listenerCertificates.push( + ...certificates.map(cerficate => ({ + ...cerficate, + listenerArn: ListenerArn, + })) + ) + } + resolveListener() + }) + listenerCertificatesPromises.push(certificatePromise) + }) + }) + + if (!isEmpty(listenerCertificatesPromises)) { + await Promise.all(listenerCertificatesPromises) + } errorLog.reset() resolve(groupBy(albData, 'region')) diff --git a/src/services/alb/format.ts b/src/services/alb/format.ts index b59f3073..ba7c510c 100644 --- a/src/services/alb/format.ts +++ b/src/services/alb/format.ts @@ -71,6 +71,9 @@ export default ({ }, CreatedTime: createdAt, listeners = [], + targetGroups, + listenerCertificates, + targetHealth, }: // attributes = {}, // SecurityGroups: securityGroups = [], // AvailabilityZones: azs = [], @@ -102,6 +105,9 @@ export default ({ createdAt: createdAt.toISOString(), status, listeners: listeners.map(awsAlbListernerGraphFormat), + targetGroups, + listenerCertificates, + targetGroupAttachment: targetHealth, } return albResult } diff --git a/src/services/apiGatewayApiKey/data.ts b/src/services/apiGatewayApiKey/data.ts new file mode 100644 index 00000000..e79f30ec --- /dev/null +++ b/src/services/apiGatewayApiKey/data.ts @@ -0,0 +1,106 @@ +import CloudGraph from '@cloudgraph/sdk' +import APIGW, { + ApiKey, + ListOfApiKey, + GetApiKeysRequest, + ApiKeys, +} from 'aws-sdk/clients/apigateway' +import { AWSError } from 'aws-sdk/lib/error' +import { Config } from 'aws-sdk/lib/config' +import isEmpty from 'lodash/isEmpty' +import groupBy from 'lodash/groupBy' +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint, setAwsRetryOptions } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import { API_GATEWAY_CUSTOM_DELAY } from '../../config/constants' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const MAX_API_KEYS = 500 +const serviceName = 'API Gateway Api Key' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) +const customRetrySettings = setAwsRetryOptions({ + baseDelay: API_GATEWAY_CUSTOM_DELAY, +}) + +export interface RawAwsApiGatewayApiKey extends ApiKey { + region: string +} + +export const getApiKeysForRegion = async ( + apiGw: APIGW +): Promise => + new Promise(resolve => { + const apiKeyList: ListOfApiKey = [] + const getApiKeyOpts: GetApiKeysRequest = {} + const listAllApiKeys = (token?: string): void => { + getApiKeyOpts.limit = MAX_API_KEYS + if (token) { + getApiKeyOpts.position = token + } + try { + apiGw.getApiKeys(getApiKeyOpts, (err: AWSError, data: ApiKeys) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getApiKeys', + err, + }) + } + + apiKeyList.push(...items) + + if (position) { + listAllApiKeys(position) + } else { + resolve(apiKeyList) + } + }) + } catch (error) { + resolve([]) + } + } + listAllApiKeys() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsApiGatewayApiKey[] }> => + new Promise(async resolve => { + const apiGatewayData = [] + const regionPromises = [] + + regions.split(',').forEach(region => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const regionPromise = new Promise(async resolveRegion => { + const apiKeyList = await getApiKeysForRegion(apiGw) + if (!isEmpty(apiKeyList)) { + apiGatewayData.push( + ...apiKeyList.map(apiKey => ({ + ...apiKey, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedApiGatewayApiKeys(apiGatewayData.length)) + + errorLog.reset() + + resolve(groupBy(apiGatewayData, 'region')) + }) diff --git a/src/services/apiGatewayApiKey/format.ts b/src/services/apiGatewayApiKey/format.ts new file mode 100644 index 00000000..14467c0c --- /dev/null +++ b/src/services/apiGatewayApiKey/format.ts @@ -0,0 +1,23 @@ +import { RawAwsApiGatewayApiKey } from './data' +import { AwsApiGatewayApiKey } from '../../types/generated' + +export default ({ + service, + account: accountId, + region, +}: { + service: RawAwsApiGatewayApiKey + account: string + region: string +}): AwsApiGatewayApiKey => { + const { id, value, name } = service + + return { + id, + arn: id, + accountId, + region, + value, + name, + } +} diff --git a/src/services/apiGatewayApiKey/index.ts b/src/services/apiGatewayApiKey/index.ts new file mode 100644 index 00000000..4c9f6f8a --- /dev/null +++ b/src/services/apiGatewayApiKey/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class APIGatewayApiKey extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/apiGatewayApiKey/mutation.ts b/src/services/apiGatewayApiKey/mutation.ts new file mode 100644 index 00000000..3da14e4d --- /dev/null +++ b/src/services/apiGatewayApiKey/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsApiGatewayApiKeyInput!]!) { + addawsApiGatewayApiKey(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/apiGatewayApiKey/schema.graphql b/src/services/apiGatewayApiKey/schema.graphql new file mode 100644 index 00000000..6ee80703 --- /dev/null +++ b/src/services/apiGatewayApiKey/schema.graphql @@ -0,0 +1,4 @@ +type awsApiGatewayApiKey implements awsBaseService @key(fields: "id") { + value: String + name: String +} diff --git a/src/services/apiGatewayRestApi/data.ts b/src/services/apiGatewayRestApi/data.ts index 874ca22b..90bc36da 100644 --- a/src/services/apiGatewayRestApi/data.ts +++ b/src/services/apiGatewayRestApi/data.ts @@ -5,6 +5,18 @@ import APIGW, { ListOfRestApi, GetRestApisRequest, Tags, + ListOfAuthorizer, + Authorizers, + GetAuthorizersRequest, + ListOfDocumentationPart, + GetDocumentationPartsRequest, + DocumentationParts, + ListOfGatewayResponse, + GetGatewayResponsesRequest, + GatewayResponses, + GetModelsRequest, + Models, + ListOfModel, } from 'aws-sdk/clients/apigateway' import APIGWv2, { DomainName } from 'aws-sdk/clients/apigatewayv2' import { AWSError } from 'aws-sdk/lib/error' @@ -37,6 +49,10 @@ export interface RawAwsApiGatewayRestApi extends Omit { accountId: string Tags: TagMap domainNames: string[] + authorizers: ListOfAuthorizer + documentationParts: ListOfDocumentationPart + gatewayResponses: ListOfGatewayResponse + models: ListOfModel region: string } @@ -76,6 +92,171 @@ export const getRestApisForRegion = async ( listAllRestApis() }) +const getAuthorizers = async ({ + apiGw, + restApiId, +}: { + apiGw: APIGW + restApiId: string +}): Promise => + new Promise(resolve => { + const authorizerList: ListOfAuthorizer = [] + const getAuthorizerOpts: GetAuthorizersRequest = { restApiId } + const listAllAuthorizer = (token?: string): void => { + if (token) { + getAuthorizerOpts.position = token + } + try { + apiGw.getAuthorizers( + getAuthorizerOpts, + (err: AWSError, data: Authorizers) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getAuthorizers', + err, + }) + } + + authorizerList.push(...items) + + if (position) { + listAllAuthorizer(position) + } else { + resolve(authorizerList) + } + } + ) + } catch (err) { + resolve([]) + } + } + listAllAuthorizer() + }) + +const getDocumentationParts = async ({ + apiGw, + restApiId, +}: { + apiGw: APIGW + restApiId: string +}): Promise => + new Promise(resolve => { + const documentationPartList: ListOfDocumentationPart = [] + const getDocumentationPartOpts: GetDocumentationPartsRequest = { restApiId } + const listAllDocumentationParts = (token?: string): void => { + if (token) { + getDocumentationPartOpts.position = token + } + try { + apiGw.getDocumentationParts( + getDocumentationPartOpts, + (err: AWSError, data: DocumentationParts) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getDocumentationParts', + err, + }) + } + + documentationPartList.push(...items) + + if (position) { + listAllDocumentationParts(position) + } else { + resolve(documentationPartList) + } + } + ) + } catch (err) { + resolve([]) + } + } + listAllDocumentationParts() + }) + +const getGatewayResponses = async ({ + apiGw, + restApiId, +}: { + apiGw: APIGW + restApiId: string +}): Promise => + new Promise(resolve => { + const gatewayReponseList: ListOfGatewayResponse = [] + const getGatewayReponseOpts: GetGatewayResponsesRequest = { restApiId } + const listAllGatewayReponses = (token?: string): void => { + if (token) { + getGatewayReponseOpts.position = token + } + try { + apiGw.getGatewayResponses( + getGatewayReponseOpts, + (err: AWSError, data: GatewayResponses) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getGatewayResponses', + err, + }) + } + + gatewayReponseList.push(...items) + + if (position) { + listAllGatewayReponses(position) + } else { + resolve(gatewayReponseList) + } + } + ) + } catch (err) { + resolve([]) + } + } + listAllGatewayReponses() + }) + +const getModels = async ({ + apiGw, + restApiId, +}: { + apiGw: APIGW + restApiId: string +}): Promise => + new Promise(resolve => { + const modelList: ListOfModel = [] + const getModelOpts: GetModelsRequest = { restApiId } + const listAllModels = (token?: string): void => { + if (token) { + getModelOpts.position = token + } + try { + apiGw.getModels(getModelOpts, (err: AWSError, data: Models) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getModels', + err, + }) + } + + modelList.push(...items) + + if (position) { + listAllModels(position) + } else { + resolve(modelList) + } + }) + } catch (err) { + resolve([]) + } + } + listAllModels() + }) + export const getTags = async ({ apiGw, arn, @@ -115,12 +296,16 @@ export default async ({ let domainNamesData: DomainName[] = [] const regionPromises = [] const tagsPromises = [] + const authorizerPromises = [] + const documentationPartPromises = [] + const gatewayReponsePromises = [] + const modelPromises = [] const existingData: { [property: string]: RawAwsApiGatewayDomainName[] } = rawData.find(({ name }) => name === services.apiGatewayDomainName) ?.data || {} - regions.split(',').map(region => { + regions.split(',').forEach(region => { const apiGw = new APIGW({ ...config, region, @@ -145,7 +330,8 @@ export default async ({ apiGatewayData.push( ...restApiList.map(restApi => ({ ...restApi, - domainNames: domainNamesData?.map(domain => domain.DomainName) || [], + domainNames: + domainNamesData?.map(domain => domain.DomainName) || [], region, })) ) @@ -159,7 +345,7 @@ export default async ({ logger.debug(lt.fetchedApiGatewayRestApis(apiGatewayData.length)) // get all tags for each rest api - apiGatewayData.map(({ id, region }, idx) => { + apiGatewayData.forEach(({ id, region }, idx) => { const apiGw = new APIGW({ ...config, region, @@ -179,6 +365,95 @@ export default async ({ logger.debug(lt.gettingApiGatewayTags) await Promise.all(tagsPromises) + + // get all authorizers for each rest api + apiGatewayData.forEach(({ id, region }, idx) => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const authorizerPromise = new Promise(async resolveAuthorizer => { + apiGatewayData[idx].authorizers = await getAuthorizers({ + apiGw, + restApiId: id, + }) + resolveAuthorizer() + }) + authorizerPromises.push(authorizerPromise) + }) + + logger.debug(lt.gettingApiGatewayAuthorizers) + await Promise.all(authorizerPromises) + + // get all documentation parts for each rest api + apiGatewayData.forEach(({ id, region }, idx) => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const documentationPartPromise = new Promise( + async resolveDocumentationPart => { + apiGatewayData[idx].documentationParts = await getDocumentationParts({ + apiGw, + restApiId: id, + }) + resolveDocumentationPart() + } + ) + documentationPartPromises.push(documentationPartPromise) + }) + + logger.debug(lt.gettingApiGatewayDocumentationParts) + await Promise.all(documentationPartPromises) + + // get all gateway responses for each rest api + apiGatewayData.forEach(({ id, region }, idx) => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const gatewayResponsePromise = new Promise( + async resolveGatewayResponse => { + apiGatewayData[idx].gatewayResponses = await getGatewayResponses({ + apiGw, + restApiId: id, + }) + resolveGatewayResponse() + } + ) + gatewayReponsePromises.push(gatewayResponsePromise) + }) + + logger.debug(lt.gettingApiGatewayGatewayResponses) + await Promise.all(gatewayReponsePromises) + + // get all models for each rest api + apiGatewayData.forEach(({ id, region }, idx) => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const modelPromise = new Promise(async resolveModel => { + apiGatewayData[idx].models = await getModels({ + apiGw, + restApiId: id, + }) + resolveModel() + }) + modelPromises.push(modelPromise) + }) + + logger.debug(lt.gettingApiGatewayModels) + await Promise.all(modelPromises) + errorLog.reset() resolve(groupBy(apiGatewayData, 'region')) diff --git a/src/services/apiGatewayRestApi/format.ts b/src/services/apiGatewayRestApi/format.ts index ba1ae671..8bd892e4 100644 --- a/src/services/apiGatewayRestApi/format.ts +++ b/src/services/apiGatewayRestApi/format.ts @@ -22,6 +22,10 @@ export default ({ minimumCompressionSize, binaryMediaTypes, tags = {}, + authorizers = [], + documentationParts = [], + gatewayResponses = [], + models = [], } = service const arn = apiGatewayRestApiArn({ restApiArn: apiGatewayArn({ region: service.region }), @@ -42,5 +46,9 @@ export default ({ minimumCompressionSize, binaryMediaTypes, tags: formatTagsFromMap(tags), + authorizers, + documentationParts, + gatewayResponses, + models, } } diff --git a/src/services/apiGatewayRestApi/schema.graphql b/src/services/apiGatewayRestApi/schema.graphql index 1b26a37e..47b8a7b2 100644 --- a/src/services/apiGatewayRestApi/schema.graphql +++ b/src/services/apiGatewayRestApi/schema.graphql @@ -18,4 +18,32 @@ type awsApiGatewayRestApi implements awsBaseService @key(fields: "arn") { resources: [awsApiGatewayResource] @hasInverse(field: restApi) route53Record: [awsRoute53Record] @hasInverse(field: restApi) #change to plural domainNames: [awsApiGatewayDomainName] @hasInverse(field: restApis) + authorizers: [awsApiGatewayRestApiAuthorizer] + documentationParts: [awsApiGatewayRestApiDocumentationPart] + gatewayResponses: [awsApiGatewayRestApiGatewayResponse] + models: [awsApiGatewayRestModel] +} + +type awsApiGatewayRestApiAuthorizer { + id: String + name: String + authorizerUri: String +} + +type awsApiGatewayRestApiDocumentationPart { + id: String + location: awsApiGatewayRestApiDocumentationPartLocation + properties: String +} + +type awsApiGatewayRestApiDocumentationPartLocation { + type: String +} + +type awsApiGatewayRestApiGatewayResponse { + responseType: String +} + +type awsApiGatewayRestModel { + name: String } diff --git a/src/services/apiGatewayUsagePlan/data.ts b/src/services/apiGatewayUsagePlan/data.ts new file mode 100644 index 00000000..63bf1c7b --- /dev/null +++ b/src/services/apiGatewayUsagePlan/data.ts @@ -0,0 +1,109 @@ +import CloudGraph from '@cloudgraph/sdk' +import APIGW, { + UsagePlan, + ListOfUsagePlan, + GetUsagePlansRequest, + UsagePlans, +} from 'aws-sdk/clients/apigateway' +import { AWSError } from 'aws-sdk/lib/error' +import { Config } from 'aws-sdk/lib/config' +import isEmpty from 'lodash/isEmpty' +import groupBy from 'lodash/groupBy' +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint, setAwsRetryOptions } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import { API_GATEWAY_CUSTOM_DELAY } from '../../config/constants' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const MAX_USAGE_PLANS = 500 +const serviceName = 'API Gateway Usage Plan' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) +const customRetrySettings = setAwsRetryOptions({ + baseDelay: API_GATEWAY_CUSTOM_DELAY, +}) + +export interface RawAwsApiGatewayUsagePlan extends UsagePlan { + region: string +} + +export const getUsagePlansForRegion = async ( + apiGw: APIGW +): Promise => + new Promise(resolve => { + const usagePlanList: ListOfUsagePlan = [] + const getUsagePlanOpts: GetUsagePlansRequest = {} + const listAllUsagePlans = (token?: string): void => { + getUsagePlanOpts.limit = MAX_USAGE_PLANS + if (token) { + getUsagePlanOpts.position = token + } + try { + apiGw.getUsagePlans( + getUsagePlanOpts, + (err: AWSError, data: UsagePlans) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getUsagePlans', + err, + }) + } + + usagePlanList.push(...items) + + if (position) { + listAllUsagePlans(position) + } else { + resolve(usagePlanList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllUsagePlans() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsApiGatewayUsagePlan[] }> => + new Promise(async resolve => { + const apiGatewayData = [] + const regionPromises = [] + + regions.split(',').forEach(region => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const regionPromise = new Promise(async resolveRegion => { + const usagePlanList = await getUsagePlansForRegion(apiGw) + if (!isEmpty(usagePlanList)) { + apiGatewayData.push( + ...usagePlanList.map(usagePlan => ({ + ...usagePlan, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedApiGatewayUsagePlans(apiGatewayData.length)) + + errorLog.reset() + + resolve(groupBy(apiGatewayData, 'region')) + }) diff --git a/src/services/apiGatewayUsagePlan/format.ts b/src/services/apiGatewayUsagePlan/format.ts new file mode 100644 index 00000000..56fd401e --- /dev/null +++ b/src/services/apiGatewayUsagePlan/format.ts @@ -0,0 +1,22 @@ +import { RawAwsApiGatewayUsagePlan } from './data' +import { AwsApiGatewayUsagePlan } from '../../types/generated' + +export default ({ + service, + account: accountId, + region, +}: { + service: RawAwsApiGatewayUsagePlan + account: string + region: string +}): AwsApiGatewayUsagePlan => { + const { id, name } = service + + return { + id, + arn: id, + accountId, + region, + name, + } +} diff --git a/src/services/apiGatewayUsagePlan/index.ts b/src/services/apiGatewayUsagePlan/index.ts new file mode 100644 index 00000000..79d44713 --- /dev/null +++ b/src/services/apiGatewayUsagePlan/index.ts @@ -0,0 +1,16 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class APIGatewayUsagePlan + extends BaseService + implements Service +{ + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/apiGatewayUsagePlan/mutation.ts b/src/services/apiGatewayUsagePlan/mutation.ts new file mode 100644 index 00000000..5bba42ea --- /dev/null +++ b/src/services/apiGatewayUsagePlan/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsApiGatewayUsagePlanInput!]!) { + addawsApiGatewayUsagePlan(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/apiGatewayUsagePlan/schema.graphql b/src/services/apiGatewayUsagePlan/schema.graphql new file mode 100644 index 00000000..d8a8fdbd --- /dev/null +++ b/src/services/apiGatewayUsagePlan/schema.graphql @@ -0,0 +1,3 @@ +type awsApiGatewayUsagePlan implements awsBaseService @key(fields: "id") { + name: String +} diff --git a/src/services/apiGatewayVpcLink/data.ts b/src/services/apiGatewayVpcLink/data.ts new file mode 100644 index 00000000..ec6c6d1d --- /dev/null +++ b/src/services/apiGatewayVpcLink/data.ts @@ -0,0 +1,106 @@ +import CloudGraph from '@cloudgraph/sdk' +import APIGW, { + VpcLink, + ListOfVpcLink, + GetVpcLinksRequest, + VpcLinks, +} from 'aws-sdk/clients/apigateway' +import { AWSError } from 'aws-sdk/lib/error' +import { Config } from 'aws-sdk/lib/config' +import isEmpty from 'lodash/isEmpty' +import groupBy from 'lodash/groupBy' +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint, setAwsRetryOptions } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import { API_GATEWAY_CUSTOM_DELAY } from '../../config/constants' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const MAX_VPC_LINKS = 500 +const serviceName = 'API Gateway Vpc Link' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) +const customRetrySettings = setAwsRetryOptions({ + baseDelay: API_GATEWAY_CUSTOM_DELAY, +}) + +export interface RawAwsApiGatewayVpcLink extends VpcLink { + region: string +} + +export const getVpcLinksForRegion = async ( + apiGw: APIGW +): Promise => + new Promise(resolve => { + const vpcLinkList: ListOfVpcLink = [] + const getVpcLinkOpts: GetVpcLinksRequest = {} + const listAllVpcLinks = (token?: string): void => { + getVpcLinkOpts.limit = MAX_VPC_LINKS + if (token) { + getVpcLinkOpts.position = token + } + try { + apiGw.getVpcLinks(getVpcLinkOpts, (err: AWSError, data: VpcLinks) => { + const { position, items = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'apiGw:getVpcLinks', + err, + }) + } + + vpcLinkList.push(...items) + + if (position) { + listAllVpcLinks(position) + } else { + resolve(vpcLinkList) + } + }) + } catch (error) { + resolve([]) + } + } + listAllVpcLinks() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsApiGatewayVpcLink[] }> => + new Promise(async resolve => { + const apiGatewayData = [] + const regionPromises = [] + + regions.split(',').forEach(region => { + const apiGw = new APIGW({ + ...config, + region, + endpoint, + ...customRetrySettings, + }) + const regionPromise = new Promise(async resolveRegion => { + const vpcLinkList = await getVpcLinksForRegion(apiGw) + if (!isEmpty(vpcLinkList)) { + apiGatewayData.push( + ...vpcLinkList.map(vpcLink => ({ + ...vpcLink, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedApiGatewayVpcLinks(apiGatewayData.length)) + + errorLog.reset() + + resolve(groupBy(apiGatewayData, 'region')) + }) diff --git a/src/services/apiGatewayVpcLink/format.ts b/src/services/apiGatewayVpcLink/format.ts new file mode 100644 index 00000000..a0fa34b9 --- /dev/null +++ b/src/services/apiGatewayVpcLink/format.ts @@ -0,0 +1,23 @@ +import { RawAwsApiGatewayVpcLink } from './data' +import { AwsApiGatewayVpcLink } from '../../types/generated' + +export default ({ + service, + account: accountId, + region, +}: { + service: RawAwsApiGatewayVpcLink + account: string + region: string +}): AwsApiGatewayVpcLink => { + const { id, targetArns, name } = service + + return { + id, + arn: id, + accountId, + region, + targetArns, + name, + } +} diff --git a/src/services/apiGatewayVpcLink/index.ts b/src/services/apiGatewayVpcLink/index.ts new file mode 100644 index 00000000..dcea0516 --- /dev/null +++ b/src/services/apiGatewayVpcLink/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class APIGatewayVpcLink extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/apiGatewayVpcLink/mutation.ts b/src/services/apiGatewayVpcLink/mutation.ts new file mode 100644 index 00000000..267368e8 --- /dev/null +++ b/src/services/apiGatewayVpcLink/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsApiGatewayVpcLinkInput!]!) { + addawsApiGatewayVpcLink(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/apiGatewayVpcLink/schema.graphql b/src/services/apiGatewayVpcLink/schema.graphql new file mode 100644 index 00000000..4deac042 --- /dev/null +++ b/src/services/apiGatewayVpcLink/schema.graphql @@ -0,0 +1,4 @@ +type awsApiGatewayVpcLink implements awsBaseService @key(fields: "id") { + name: String + targetArns: [String] +} diff --git a/src/services/cloudfront/format.ts b/src/services/cloudfront/format.ts index b366b220..c47f25af 100644 --- a/src/services/cloudfront/format.ts +++ b/src/services/cloudfront/format.ts @@ -134,6 +134,7 @@ export default ({ SmoothStreaming: smoothStreaming, TargetOriginId: targetOriginId, ViewerProtocolPolicy: viewerProtocolPolicy, + CachePolicyId: cachePolicyId, } = cache const forwardedValues = { @@ -156,6 +157,7 @@ export default ({ smoothStreaming: smoothStreaming ? t.yes : t.no, targetOriginId, viewerProtocolPolicy, + cachePolicyId } } diff --git a/src/services/cloudfront/schema.graphql b/src/services/cloudfront/schema.graphql index 6e7c1e4f..d22c78ae 100644 --- a/src/services/cloudfront/schema.graphql +++ b/src/services/cloudfront/schema.graphql @@ -79,6 +79,7 @@ type awsCloudfrontCacheBehavior { smoothStreaming: String @search(by: [hash]) targetOriginId: String @search(by: [hash]) viewerProtocolPolicy: String @search(by: [hash]) + cachePolicyId: String @search(by: [hash]) } type awsCloudfrontCustomErrorResponse { diff --git a/src/services/cloudwatchDashboards/data.ts b/src/services/cloudwatchDashboards/data.ts new file mode 100644 index 00000000..96a3c212 --- /dev/null +++ b/src/services/cloudwatchDashboards/data.ts @@ -0,0 +1,116 @@ +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' + +import CloudWatch, { + DashboardEntries, + ListDashboardsOutput, + ListDashboardsInput, + DashboardEntry, +} from 'aws-sdk/clients/cloudwatch' +import { Config } from 'aws-sdk/lib/config' +import { AWSError } from 'aws-sdk/lib/error' + +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +/** + * Cloudwatch Dashboard + */ +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'CloudwatchDashboard' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsCloudwatchDashboard extends DashboardEntry { + region: string +} + +const listDashboardsForRegion = async ({ + cloudwatch, + resolveRegion, +}: { + cloudwatch: CloudWatch + resolveRegion: () => void +}): Promise => + new Promise(resolve => { + const dashboardList: DashboardEntries = [] + const listDashboardOpts: ListDashboardsInput = {} + const listAllDashboard = (token?: string): void => { + if (token) { + listDashboardOpts.NextToken = token + } + try { + cloudwatch.listDashboards( + listDashboardOpts, + (err: AWSError, data: ListDashboardsOutput) => { + const { NextToken: nextToken, DashboardEntries: entries } = + data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'cloudwatch:listDashboards', + err, + }) + } + /** + * No dashboard for this region + */ + if (isEmpty(data)) { + return resolveRegion() + } + + dashboardList.push(...entries) + + if (nextToken) { + listAllDashboard(nextToken) + } else { + resolve(dashboardList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllDashboard() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsCloudwatchDashboard[] }> => + new Promise(async resolve => { + const cloudwatchData: RawAwsCloudwatchDashboard[] = [] + const regionPromises = [] + + // get all dashboard for all regions + regions.split(',').forEach(region => { + const cloudwatch = new CloudWatch({ + ...config, + region, + endpoint, + }) + const regionPromise = new Promise(async resolveRegion => { + const dashboards = await listDashboardsForRegion({ + cloudwatch, + resolveRegion, + }) + cloudwatchData.push( + ...dashboards.map(dashboard => ({ ...dashboard, region })) + ) + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + logger.debug(lt.gettingCloudwatchDashboards) + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(cloudwatchData, 'region')) + }) diff --git a/src/services/cloudwatchDashboards/format.ts b/src/services/cloudwatchDashboards/format.ts new file mode 100644 index 00000000..2e71b22f --- /dev/null +++ b/src/services/cloudwatchDashboards/format.ts @@ -0,0 +1,23 @@ +import { AwsCloudwatchDashboard } from '../../types/generated' +import { RawAwsCloudwatchDashboard } from './data' + +/** + * CloudWatch Dashboard + */ +export default ({ + service, + account, + region, +}: { + service: RawAwsCloudwatchDashboard + account: string + region: string +}): AwsCloudwatchDashboard => { + const { DashboardName: name, DashboardArn: arn } = service + return { + id: name, + accountId: account, + arn, + region, + } +} diff --git a/src/services/cloudwatchDashboards/index.ts b/src/services/cloudwatchDashboards/index.ts new file mode 100644 index 00000000..84de4fae --- /dev/null +++ b/src/services/cloudwatchDashboards/index.ts @@ -0,0 +1,16 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class CloudWatchDashboard + extends BaseService + implements Service +{ + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/cloudwatchDashboards/mutation.ts b/src/services/cloudwatchDashboards/mutation.ts new file mode 100644 index 00000000..bb2a5f97 --- /dev/null +++ b/src/services/cloudwatchDashboards/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsCloudwatchDashboardInput!]!) { + addawsCloudwatchDashboard(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/cloudwatchDashboards/schema.graphql b/src/services/cloudwatchDashboards/schema.graphql new file mode 100644 index 00000000..ed095ffc --- /dev/null +++ b/src/services/cloudwatchDashboards/schema.graphql @@ -0,0 +1 @@ +type awsCloudwatchDashboard implements awsBaseService @key(fields: "arn") diff --git a/src/services/cloudwatchEventRules/data.ts b/src/services/cloudwatchEventRules/data.ts new file mode 100644 index 00000000..9945f912 --- /dev/null +++ b/src/services/cloudwatchEventRules/data.ts @@ -0,0 +1,190 @@ +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' + +import CloudWatchEvents, { + ListRulesRequest, + ListRulesResponse, + ListTargetsByRuleRequest, + ListTargetsByRuleResponse, + Rule, + RuleResponseList, + TargetList, +} from 'aws-sdk/clients/cloudwatchevents' +import { Config } from 'aws-sdk/lib/config' +import { AWSError } from 'aws-sdk/lib/error' + +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +/** + * Cloudwatch Event Rules + */ +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'CloudwatchEventRule' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsCloudwatchEventRule extends Rule { + targets: TargetList + region: string +} + +const listRulesForRegion = async ({ + cloudwatch, + resolveRegion, +}: { + cloudwatch: CloudWatchEvents + resolveRegion: () => void +}): Promise => + new Promise(resolve => { + const ruleList: RuleResponseList = [] + const listRuleOpts: ListRulesRequest = {} + const listAllRule = (token?: string): void => { + if (token) { + listRuleOpts.NextToken = token + } + try { + cloudwatch.listRules( + listRuleOpts, + (err: AWSError, data: ListRulesResponse) => { + const { NextToken: nextToken, Rules: entries } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'cloudwatchevents:listRules', + err, + }) + } + /** + * No rule for this region + */ + if (isEmpty(data)) { + return resolveRegion() + } + + ruleList.push(...entries) + + if (nextToken) { + listAllRule(nextToken) + } else { + resolve(ruleList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllRule() + }) + +const listTargetsByRule = ({ + cloudwatch, + ruleName, + resolveRule, +}: { + cloudwatch: CloudWatchEvents + ruleName: string + resolveRule: () => void +}): Promise => + new Promise(resolve => { + const targetList: TargetList = [] + const listTargetOpts: ListTargetsByRuleRequest = { Rule: ruleName } + const listAllTarget = (token?: string): void => { + if (token) { + listTargetOpts.NextToken = token + } + try { + cloudwatch.listTargetsByRule( + listTargetOpts, + (err: AWSError, data: ListTargetsByRuleResponse) => { + const { NextToken: nextToken, Targets: entries } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'cloudwatchevents:listTargetsByRule', + err, + }) + } + + /** + * No targets for this rule + */ + if (isEmpty(data)) { + return resolveRule() + } + + targetList.push(...entries) + + if (nextToken) { + listAllTarget(nextToken) + } else { + resolve(targetList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllTarget() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsCloudwatchEventRule[] }> => + new Promise(async resolve => { + const rulesData: RawAwsCloudwatchEventRule[] = [] + const regionPromises = [] + const targetPromises = [] + + // get all rules for all regions + regions.split(',').forEach(region => { + const cloudwatch = new CloudWatchEvents({ + ...config, + region, + endpoint, + }) + const regionPromise = new Promise(async resolveRegion => { + const rules = await listRulesForRegion({ + cloudwatch, + resolveRegion, + }) + rulesData.push(...rules.map(rule => ({ ...rule, region, targets: [] }))) + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + logger.debug(lt.gettingCloudwatchRules) + await Promise.all(regionPromises) + + // load targets to every rule + rulesData.forEach((rule, index) => { + const cloudwatch = new CloudWatchEvents({ + ...config, + region: rule.region, + endpoint, + }) + const targetPromise = new Promise(async resolveRule => { + const targets = await listTargetsByRule({ + cloudwatch, + ruleName: rule.Name, + resolveRule, + }) + rulesData[index].targets.push(...targets) + resolveRule() + }) + targetPromises.push(targetPromise) + }) + logger.debug(lt.gettingCloudwatchRuleTargets) + await Promise.all(targetPromises) + errorLog.reset() + + resolve(groupBy(rulesData, 'region')) + }) diff --git a/src/services/cloudwatchEventRules/format.ts b/src/services/cloudwatchEventRules/format.ts new file mode 100644 index 00000000..9c38e1f8 --- /dev/null +++ b/src/services/cloudwatchEventRules/format.ts @@ -0,0 +1,32 @@ +import { TargetList } from 'aws-sdk/clients/cloudwatchevents' +import { AwsCloudwatchEventRule } from '../../types/generated' +import { RawAwsCloudwatchEventRule } from './data' + +const formatTargets = (targets: TargetList): { id: string; arn: string }[] => + targets.map(({ Id, Arn }) => ({ + id: Id, + arn: Arn, + })) + +/** + * CloudWatch Event Rule + */ +export default ({ + service, + account, + region, +}: { + service: RawAwsCloudwatchEventRule + account: string + region: string +}): AwsCloudwatchEventRule => { + const { EventBusName: eventBusName, Name: id, Arn: arn, targets } = service + return { + id, + accountId: account, + arn, + region, + eventBusName, + targets: formatTargets(targets), + } +} diff --git a/src/services/cloudwatchEventRules/index.ts b/src/services/cloudwatchEventRules/index.ts new file mode 100644 index 00000000..ec2c29f2 --- /dev/null +++ b/src/services/cloudwatchEventRules/index.ts @@ -0,0 +1,16 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class CloudWatchEventRules + extends BaseService + implements Service +{ + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/cloudwatchEventRules/mutation.ts b/src/services/cloudwatchEventRules/mutation.ts new file mode 100644 index 00000000..27436127 --- /dev/null +++ b/src/services/cloudwatchEventRules/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsCloudwatchEventRuleInput!]!) { + addawsCloudwatchEventRule(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/cloudwatchEventRules/schema.graphql b/src/services/cloudwatchEventRules/schema.graphql new file mode 100644 index 00000000..627444bd --- /dev/null +++ b/src/services/cloudwatchEventRules/schema.graphql @@ -0,0 +1,9 @@ +type awsCloudwatchEventRule implements awsBaseService @key(fields: "arn") { + eventBusName: String @search(by: [hash, regexp]) + targets: [Target] +} + +type Target { + id: String! @id + arn: String @search +} diff --git a/src/services/codeCommitRepository/data.ts b/src/services/codeCommitRepository/data.ts new file mode 100644 index 00000000..a34e3bef --- /dev/null +++ b/src/services/codeCommitRepository/data.ts @@ -0,0 +1,93 @@ +import { + CodeCommitClient, + ListRepositoriesCommand, + ListRepositoriesInput, + RepositoryNameIdPair, +} from '@aws-sdk/client-codecommit' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph + +const serviceName = 'Code Commit Repository' +const errorLog = new AwsErrorLog(serviceName) + +export interface RawAwsRepository extends RepositoryNameIdPair { + region: string +} + +const listRepositories = async ( + cc: CodeCommitClient +): Promise => + new Promise(async resolve => { + const ccRepositories: RepositoryNameIdPair[] = [] + + const input: ListRepositoriesInput = {} + + const listAllRepositories = (token?: string): void => { + if (token) { + input.nextToken = token + } + const command = new ListRepositoriesCommand(input) + cc.send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { repositories = [], nextToken } = data || {} + + ccRepositories.push(...repositories) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllRepositories(nextToken) + } else { + resolve(ccRepositories) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'codecommit:listRepositories', + err, + }) + resolve([]) + }) + } + listAllRepositories() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsRepository[] }> => + new Promise(async resolve => { + const { credentials } = config + const repositoriesData: RawAwsRepository[] = [] + + const regionPromises = regions.split(',').map(region => { + const cc = new CodeCommitClient({ + credentials, + region, + }) + return new Promise(async resolveRegion => { + const repos = (await listRepositories(cc)) || [] + if (!isEmpty(repos)) + repositoriesData.push(...repos.map(val => ({ ...val, region }))) + resolveRegion() + }) + }) + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(repositoriesData, 'region')) + }) diff --git a/src/services/codeCommitRepository/format.ts b/src/services/codeCommitRepository/format.ts new file mode 100644 index 00000000..3ccd2a31 --- /dev/null +++ b/src/services/codeCommitRepository/format.ts @@ -0,0 +1,28 @@ +import { AwsCodeCommitRepository } from '../../types/generated' +import { codeCommitRepositoryArn } from '../../utils/generateArns' +import { RawAwsRepository } from './data' + +/** + * Code Commit Repository + */ +export default ({ + account, + region, + service: parameter, +}: { + account: string + region: string + service: RawAwsRepository +}): AwsCodeCommitRepository => { + const { repositoryName, repositoryId } = parameter + + const arn = codeCommitRepositoryArn({ region, account, name: repositoryName }) + + return { + accountId: account, + arn, + id: repositoryId, + name: repositoryName, + region, + } +} diff --git a/src/services/codeCommitRepository/index.ts b/src/services/codeCommitRepository/index.ts new file mode 100644 index 00000000..2d78c7cd --- /dev/null +++ b/src/services/codeCommitRepository/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import getData from './data' +import format from './format' +import mutation from './mutation' + +export default class CodeCommitRepository extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/codeCommitRepository/mutation.ts b/src/services/codeCommitRepository/mutation.ts new file mode 100644 index 00000000..93eaccf5 --- /dev/null +++ b/src/services/codeCommitRepository/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsCodeCommitRepositoryInput!]!) { + addawsCodeCommitRepository(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/codeCommitRepository/schema.graphql b/src/services/codeCommitRepository/schema.graphql new file mode 100644 index 00000000..0bf41a97 --- /dev/null +++ b/src/services/codeCommitRepository/schema.graphql @@ -0,0 +1,3 @@ +type awsCodeCommitRepository implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/codePipeline/data.ts b/src/services/codePipeline/data.ts new file mode 100644 index 00000000..b8ffa5f6 --- /dev/null +++ b/src/services/codePipeline/data.ts @@ -0,0 +1,95 @@ +import { + CodePipelineClient, + ListPipelinesCommand, + ListPipelinesInput, + PipelineSummary, +} from '@aws-sdk/client-codepipeline' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Code Pipeline' +const errorLog = new AwsErrorLog(serviceName) +const MAX_ITEMS = 500 + +export interface RawAwsPipelineSummary extends PipelineSummary { + region: string +} + +const listPipelines = async ( + cp: CodePipelineClient +): Promise => + new Promise(async resolve => { + const codePipelines: PipelineSummary[] = [] + + const input: ListPipelinesInput = { + maxResults: MAX_ITEMS, + } + + const listAllPipelines = (token?: string): void => { + if (token) { + input.nextToken = token + } + const command = new ListPipelinesCommand(input) + cp.send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { pipelines = [], nextToken } = data || {} + + codePipelines.push(...pipelines) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllPipelines(nextToken) + } else { + resolve(codePipelines) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'codepipeline:listPipelines', + err, + }) + resolve([]) + }) + } + listAllPipelines() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsPipelineSummary[] }> => + new Promise(async resolve => { + const { credentials } = config + const pipelinesData: RawAwsPipelineSummary[] = [] + + const regionPromises = regions.split(',').map(region => { + const cpClient = new CodePipelineClient({ + credentials, + region, + }) + return new Promise(async resolveRegion => { + const pipelines = (await listPipelines(cpClient)) || [] + if (!isEmpty(pipelines)) + pipelinesData.push(...pipelines.map(val => ({ ...val, region }))) + resolveRegion() + }) + }) + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(pipelinesData, 'region')) + }) diff --git a/src/services/codePipeline/format.ts b/src/services/codePipeline/format.ts new file mode 100644 index 00000000..e1e20865 --- /dev/null +++ b/src/services/codePipeline/format.ts @@ -0,0 +1,29 @@ + +import { AwsCodePipeline } from '../../types/generated' +import { codePipelineArn } from '../../utils/generateArns' +import { RawAwsPipelineSummary } from './data' + +/** + * Code Pipeline + */ +export default ({ + account, + region, + service: pipeline, +}: { + account: string + region: string + service: RawAwsPipelineSummary +}): AwsCodePipeline => { + const { name } = pipeline + + const arn = codePipelineArn({ region, account, name }) + + return { + accountId: account, + arn, + id: arn, + name, + region, + } +} diff --git a/src/services/codePipeline/index.ts b/src/services/codePipeline/index.ts new file mode 100644 index 00000000..46154a1b --- /dev/null +++ b/src/services/codePipeline/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class CodePipeline extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/codePipeline/mutation.ts b/src/services/codePipeline/mutation.ts new file mode 100644 index 00000000..2b1a19dc --- /dev/null +++ b/src/services/codePipeline/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsCodePipelineInput!]!) { + addawsCodePipeline(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/codePipeline/schema.graphql b/src/services/codePipeline/schema.graphql new file mode 100644 index 00000000..87cfe1d2 --- /dev/null +++ b/src/services/codePipeline/schema.graphql @@ -0,0 +1,3 @@ +type awsCodePipeline implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/codePipelineWebhook/data.ts b/src/services/codePipelineWebhook/data.ts new file mode 100644 index 00000000..af678533 --- /dev/null +++ b/src/services/codePipelineWebhook/data.ts @@ -0,0 +1,95 @@ +import { + CodePipelineClient, + ListWebhookItem, + ListWebhooksCommand, + ListWebhooksInput, +} from '@aws-sdk/client-codepipeline' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Code Pipeline Webhook' +const errorLog = new AwsErrorLog(serviceName) +const MAX_ITEMS = 50 + +export interface RawAwsWebhook extends ListWebhookItem { + region: string +} + +const listWebhooks = async ( + cp: CodePipelineClient +): Promise => + new Promise(async resolve => { + const webhookDefinitions: ListWebhookItem[] = [] + + const input: ListWebhooksInput = { + MaxResults: MAX_ITEMS, + } + + const listAllWebhooks = (token?: string): void => { + if (token) { + input.NextToken = token + } + const command = new ListWebhooksCommand(input) + cp.send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { webhooks = [], NextToken } = data || {} + + webhookDefinitions.push(...webhooks) + + if (NextToken) { + logger.debug(lt.foundAnotherThousand) + listAllWebhooks(NextToken) + } else { + resolve(webhookDefinitions) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'codepipeline:listWebhooks', + err, + }) + resolve([]) + }) + } + listAllWebhooks() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsWebhook[] }> => + new Promise(async resolve => { + const { credentials } = config + const webhooksData: RawAwsWebhook[] = [] + + const regionPromises = regions.split(',').map(region => { + const cpClient = new CodePipelineClient({ + credentials, + region, + }) + return new Promise(async resolveRegion => { + const webhooks = (await listWebhooks(cpClient)) || [] + if (!isEmpty(webhooks)) + webhooksData.push(...webhooks.map(val => ({ ...val, region }))) + resolveRegion() + }) + }) + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(webhooksData, 'region')) + }) diff --git a/src/services/codePipelineWebhook/format.ts b/src/services/codePipelineWebhook/format.ts new file mode 100644 index 00000000..6061a872 --- /dev/null +++ b/src/services/codePipelineWebhook/format.ts @@ -0,0 +1,28 @@ +import { AwsCodePipelineWebhook } from '../../types/generated' +import { RawAwsWebhook } from './data' + +/** + * Code Pipeline Webhook + */ +export default ({ + account, + region, + service: webhook, +}: { + account: string + region: string + service: RawAwsWebhook +}): AwsCodePipelineWebhook => { + const { + arn, + definition, + } = webhook + + return { + accountId: account, + arn, + id: arn, + name: definition?.name || '', + region, + } +} diff --git a/src/services/codePipelineWebhook/index.ts b/src/services/codePipelineWebhook/index.ts new file mode 100644 index 00000000..75bb5fd3 --- /dev/null +++ b/src/services/codePipelineWebhook/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class CodePipelineWebhook extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/codePipelineWebhook/mutation.ts b/src/services/codePipelineWebhook/mutation.ts new file mode 100644 index 00000000..08fcc7d9 --- /dev/null +++ b/src/services/codePipelineWebhook/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsCodePipelineWebhookInput!]!) { + addawsCodePipelineWebhook(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/codePipelineWebhook/schema.graphql b/src/services/codePipelineWebhook/schema.graphql new file mode 100644 index 00000000..4bb03efa --- /dev/null +++ b/src/services/codePipelineWebhook/schema.graphql @@ -0,0 +1,3 @@ +type awsCodePipelineWebhook implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/cognitoUserPool/connections.ts b/src/services/cognitoUserPool/connections.ts index 29a26b2c..18c384b7 100644 --- a/src/services/cognitoUserPool/connections.ts +++ b/src/services/cognitoUserPool/connections.ts @@ -5,7 +5,7 @@ import { isEmpty } from 'lodash' import services from '../../enums/services' import { sesArn } from '../../utils/generateArns' import { RawAwsLambdaFunction } from '../lambda/data' -import { RawAwsSes } from '../ses/data' +import { RawAwsSesEmail } from '../sesEmail/data' import { RawAwsIamRole } from '../iamRole/data' import { AwsKms } from '../kms/data' @@ -121,20 +121,20 @@ export default ({ * related to this cognito user pool */ const emailConfigSourceArn = emailConfiguration?.SourceArn - const emails = data.find(({ name }) => name === services.ses) + const emails = data.find(({ name }) => name === services.sesEmail) if (emailConfigSourceArn && emails?.data?.[region]) { - const emailInRegion: RawAwsSes = emails.data[region].find( - ({ Identity }: RawAwsSes) => - emailConfigSourceArn === sesArn({ region, account, email: Identity }) + const emailInRegion: RawAwsSesEmail = emails.data[region].find( + ({ Identity }: RawAwsSesEmail) => + emailConfigSourceArn === sesArn({ region, account, identity: Identity }) ) if (emailInRegion) { connections.push({ - id: sesArn({ region, account, email: emailInRegion.Identity }), - resourceType: services.ses, + id: sesArn({ region, account, identity: emailInRegion.Identity }), + resourceType: services.sesEmail, relation: 'child', - field: 'ses', + field: 'sesEmail', }) } } diff --git a/src/services/cognitoUserPool/schema.graphql b/src/services/cognitoUserPool/schema.graphql index 8e8043a3..390a03fe 100644 --- a/src/services/cognitoUserPool/schema.graphql +++ b/src/services/cognitoUserPool/schema.graphql @@ -122,7 +122,7 @@ type awsCognitoUserPool implements awsBaseService @key(fields: "id") { lambdas: [awsLambda] @hasInverse(field: cognitoUserPools) appSync: [awsAppSync] @hasInverse(field: cognitoUserPool) kms: [awsKms] @hasInverse(field: cognitoUserPools) - ses: [awsSes] @hasInverse(field: cognitoUserPools) + sesEmail: [awsSesEmail] @hasInverse(field: cognitoUserPools) iamRole: [awsIamRole] @hasInverse(field: cognitoUserPools) elasticSearchDomains: [awsElasticSearchDomain] @hasInverse(field: cognitoUserPool) } diff --git a/src/services/configurationDeliveryChannel/data.ts b/src/services/configurationDeliveryChannel/data.ts new file mode 100644 index 00000000..1e3dde7a --- /dev/null +++ b/src/services/configurationDeliveryChannel/data.ts @@ -0,0 +1,106 @@ +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' + +import EC2, { + DeliveryChannel, + DeliveryChannelList, + DescribeDeliveryChannelsResponse, +} from 'aws-sdk/clients/configservice' + +import { Config } from 'aws-sdk/lib/config' +import { AWSError } from 'aws-sdk/lib/error' + +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import awsLoggerText from '../../properties/logger' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Configuration Delivery Channel' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsConfigurationDeliveryChannel extends DeliveryChannel { + region: string +} + +const listConfigurationDeliveryChannelData = async ({ + ec2, +}: { + ec2: EC2 +}): Promise => + new Promise(resolve => { + try { + ec2.describeDeliveryChannels( + {}, + (err: AWSError, data: DescribeDeliveryChannelsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ec2:describeDeliveryChannels', + err, + }) + } + + if (isEmpty(data)) { + return resolve([]) + } + + const { DeliveryChannels: channels = [] } = data || {} + + resolve(channels) + } + ) + } catch (error) { + resolve([]) + } + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ + [region: string]: RawAwsConfigurationDeliveryChannel[] +}> => + new Promise(async resolve => { + const configurationDeliveryChannelsResult: RawAwsConfigurationDeliveryChannel[] = + [] + + const regionPromises = regions.split(',').map(region => { + const ec2 = new EC2({ ...config, region, endpoint }) + + return new Promise( + async resolveConfigurationDeliveryChannelData => { + // Get Configuration Delivery Channel Data + const configurationDeliveryChannels = + await listConfigurationDeliveryChannelData({ + ec2, + }) + + if (!isEmpty(configurationDeliveryChannels)) { + for (const configurationDeliveryChannel of configurationDeliveryChannels) { + configurationDeliveryChannelsResult.push({ + ...configurationDeliveryChannel, + region, + }) + } + } + + resolveConfigurationDeliveryChannelData() + } + ) + }) + + await Promise.all(regionPromises) + logger.debug( + lt.fetchedCOnfigurationDeliveryChannels( + configurationDeliveryChannelsResult.length + ) + ) + errorLog.reset() + + resolve(groupBy(configurationDeliveryChannelsResult, 'region')) + }) diff --git a/src/services/configurationDeliveryChannel/format.ts b/src/services/configurationDeliveryChannel/format.ts new file mode 100644 index 00000000..0be5b049 --- /dev/null +++ b/src/services/configurationDeliveryChannel/format.ts @@ -0,0 +1,26 @@ +import { AwsConfigurationDeliveryChannel } from '../../types' +import { RawAwsConfigurationDeliveryChannel } from './data' + +/** + * Configuration Delivery Channel + */ + +export default ({ + service: rawData, + account, + region, +}: { + service: RawAwsConfigurationDeliveryChannel + account: string + region: string +}): AwsConfigurationDeliveryChannel => { + const { name } = rawData + + return { + id: name, + accountId: account, + arn: name, + region, + name, + } +} diff --git a/src/services/configurationDeliveryChannel/index.ts b/src/services/configurationDeliveryChannel/index.ts new file mode 100644 index 00000000..36fe683b --- /dev/null +++ b/src/services/configurationDeliveryChannel/index.ts @@ -0,0 +1,16 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class ConfigurationDeliveryChannel + extends BaseService + implements Service +{ + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/configurationDeliveryChannel/mutation.ts b/src/services/configurationDeliveryChannel/mutation.ts new file mode 100644 index 00000000..955df8cf --- /dev/null +++ b/src/services/configurationDeliveryChannel/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsConfigurationDeliveryChannelInput!]!) { + addawsConfigurationDeliveryChannel(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/configurationDeliveryChannel/schema.graphql b/src/services/configurationDeliveryChannel/schema.graphql new file mode 100644 index 00000000..7f0eb6f0 --- /dev/null +++ b/src/services/configurationDeliveryChannel/schema.graphql @@ -0,0 +1,4 @@ +type awsConfigurationDeliveryChannel implements awsBaseService + @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/configurationRule/data.ts b/src/services/configurationRule/data.ts new file mode 100644 index 00000000..6124f1f6 --- /dev/null +++ b/src/services/configurationRule/data.ts @@ -0,0 +1,118 @@ +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' + +import EC2, { + DescribeConfigRulesResponse, + ConfigRule, + ConfigRules, + DescribeConfigRulesRequest, +} from 'aws-sdk/clients/configservice' + +import { Config } from 'aws-sdk/lib/config' +import { AWSError } from 'aws-sdk/lib/error' + +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Configuration Rule' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsConfigurationRule extends ConfigRule { + region: string +} + +const listConfigurationRuleData = async ({ + ec2, +}: { + ec2: EC2 +}): Promise => + new Promise(resolve => { + const configurationRulesData: ConfigRules = [] + const getConfigurationRuleOpts: DescribeConfigRulesRequest = {} + const listAllConfigRules = (token?: string): void => { + if (token) { + getConfigurationRuleOpts.NextToken = token + } + try { + ec2.describeConfigRules( + getConfigurationRuleOpts, + (err: AWSError, data: DescribeConfigRulesResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ec2:describeConfigRules', + err, + }) + } + + if (isEmpty(data)) { + return resolve([]) + } + + const { NextToken: nextToken, ConfigRules: configRules = [] } = + data || {} + + if (isEmpty(configRules)) { + return resolve([]) + } + + configurationRulesData.push(...configRules) + + if (nextToken) { + listAllConfigRules(nextToken) + } else { + resolve(configurationRulesData) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllConfigRules() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ + [region: string]: RawAwsConfigurationRule[] +}> => + new Promise(async resolve => { + const configurationRulesResult: RawAwsConfigurationRule[] = [] + + const regionPromises = regions.split(',').map(region => { + const ec2 = new EC2({ ...config, region, endpoint }) + + return new Promise(async resolveConfigurationRuleData => { + // Get Configuration Rule Data + const configurationRules = await listConfigurationRuleData({ + ec2, + }) + + if (!isEmpty(configurationRules)) { + for (const configurationRule of configurationRules) { + configurationRulesResult.push({ + ...configurationRule, + region, + }) + } + } + + resolveConfigurationRuleData() + }) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedConfigurationRules(configurationRulesResult.length)) + errorLog.reset() + + resolve(groupBy(configurationRulesResult, 'region')) + }) diff --git a/src/services/configurationRule/format.ts b/src/services/configurationRule/format.ts new file mode 100644 index 00000000..a6f99842 --- /dev/null +++ b/src/services/configurationRule/format.ts @@ -0,0 +1,26 @@ +import { AwsConfigurationRule } from '../../types' +import { RawAwsConfigurationRule } from './data' + +/** + * Configuration Rule + */ + +export default ({ + service: rawData, + account, + region, +}: { + service: RawAwsConfigurationRule + account: string + region: string +}): AwsConfigurationRule => { + const { ConfigRuleId: id, ConfigRuleArn: arn, ConfigRuleName: name } = rawData + + return { + id, + accountId: account, + arn, + region, + name, + } +} diff --git a/src/services/configurationRule/index.ts b/src/services/configurationRule/index.ts new file mode 100644 index 00000000..02a30d55 --- /dev/null +++ b/src/services/configurationRule/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class ConfigurationRule extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/configurationRule/mutation.ts b/src/services/configurationRule/mutation.ts new file mode 100644 index 00000000..fc73c677 --- /dev/null +++ b/src/services/configurationRule/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsConfigurationRuleInput!]!) { + addawsConfigurationRule(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/configurationRule/schema.graphql b/src/services/configurationRule/schema.graphql new file mode 100644 index 00000000..9d75cadf --- /dev/null +++ b/src/services/configurationRule/schema.graphql @@ -0,0 +1,3 @@ +type awsConfigurationRule implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/docdbCluster/data.ts b/src/services/docdbCluster/data.ts new file mode 100644 index 00000000..67ec5a6c --- /dev/null +++ b/src/services/docdbCluster/data.ts @@ -0,0 +1,138 @@ +import CloudGraph from '@cloudgraph/sdk' +import DOCDB, { + DBCluster, + DBClusterMessage, + DBSubnetGroup, + DBSubnetGroupMessage, + DescribeDBClustersMessage, +} from 'aws-sdk/clients/docdb' +import { Config } from 'aws-sdk/lib/config' +import { AWSError } from 'aws-sdk/lib/error' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import { TagMap } from '../../types' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'DOC DB cluster' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +const listClustersForRegion = async (docdb: DOCDB): Promise => + new Promise(resolve => { + const clusterList: DBCluster[] = [] + const descClustersOpts: DescribeDBClustersMessage = {} + const listAllClusters = (token?: string): void => { + if (token) { + descClustersOpts.Marker = token + } + try { + docdb.describeDBClusters( + descClustersOpts, + (err: AWSError, data: DBClusterMessage) => { + const { Marker, DBClusters = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'docdb:describeDBClusters', + err, + }) + } + + clusterList.push(...DBClusters) + + if (Marker) { + listAllClusters(Marker) + } else { + resolve(clusterList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllClusters() + }) + +const describeDBSubnetGroups = async ( + docdb: DOCDB, + DBSubnetGroupName: string +): Promise => + new Promise(resolve => { + try { + docdb.describeDBSubnetGroups( + { DBSubnetGroupName }, + (err: AWSError, data: DBSubnetGroupMessage) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'docdb:describeDBSubnetGroups', + err, + }) + return resolve([]) + } + if (isEmpty(data)) { + return resolve([]) + } + const { DBSubnetGroups = [] } = data || {} + if (isEmpty(DBSubnetGroups)) { + return resolve([]) + } + resolve(DBSubnetGroups) + } + ) + } catch (error) { + resolve([]) + } + }) + +export interface RawAwsDocDBCluster extends DBCluster { + DbSubnetGroups: DBSubnetGroup[] + Tags?: TagMap + region: string +} + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsDocDBCluster[] }> => + new Promise(async resolve => { + const docDBData: RawAwsDocDBCluster[] = [] + const regionPromises = [] + + // Get all the clusters for the region + regions.split(',').map(region => { + const regionPromise = new Promise(async resolveRegion => { + const docdb = new DOCDB({ ...config, region, endpoint }) + const clusters = await listClustersForRegion(docdb) + + if (!isEmpty(clusters)) { + docDBData.push( + ...(await Promise.all( + clusters.map(async cluster => ({ + ...cluster, + DbSubnetGroups: await describeDBSubnetGroups( + docdb, + cluster.DBSubnetGroup + ), + region, + })) + )) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedDocdbClusters(docDBData.length)) + errorLog.reset() + + resolve(groupBy(docDBData, 'region')) + }) diff --git a/src/services/docdbCluster/format.ts b/src/services/docdbCluster/format.ts new file mode 100644 index 00000000..d0930e18 --- /dev/null +++ b/src/services/docdbCluster/format.ts @@ -0,0 +1,86 @@ +import { RawAwsDocDBCluster } from './data' +import { AwsDocdbCluster } from '../../types/generated' +import { formatTagsFromMap } from '../../utils/format' + +export default ({ + service, + account, + region, +}: { + service: RawAwsDocDBCluster + account: string + region: string +}): AwsDocdbCluster => { + const { + AvailabilityZones = [], + BackupRetentionPeriod: backupRetentionPeriod, + DBClusterIdentifier: dBClusterIdentifier, + DBClusterParameterGroup: dBClusterParameterGroup, + DBSubnetGroup: dBSubnetGroup, + Status: status, + PercentProgress: percentProgress, + EarliestRestorableTime: earliestRestorableTime, + Endpoint: endpoint, + ReaderEndpoint: readerEndpoint, + MultiAZ: multiAZ, + Engine: engine, + EngineVersion: engineVersion, + LatestRestorableTime: latestRestorableTime, + Port: port, + MasterUsername: masterUsername, + PreferredBackupWindow: preferredBackupWindow, + PreferredMaintenanceWindow: preferredMaintenanceWindow, + ReplicationSourceIdentifier: replicationSourceIdentifier, + ReadReplicaIdentifiers: readReplicaIdentifiers, + DBClusterMembers = [], + VpcSecurityGroups = [], + HostedZoneId: hostedZoneId, + StorageEncrypted: storageEncrypted, + KmsKeyId: kmsKeyId, + DbClusterResourceId: dbClusterResourceId, + DBClusterArn: arn, + CloneGroupId: cloneGroupId, + ClusterCreateTime: clusterCreateTime, + DeletionProtection: deletionProtection, + } = service + + const availabilityZones = AvailabilityZones.map(az => az) + const dBClusterMembers = DBClusterMembers.map(dbinstance => dbinstance.DBInstanceIdentifier) + const vpcSecurityGroups = VpcSecurityGroups.map(vpcsg => vpcsg.VpcSecurityGroupId) + + return { + id: arn, + accountId: account, + arn, + region, + availabilityZones, + backupRetentionPeriod, + dBClusterIdentifier, + dBClusterParameterGroup, + dBSubnetGroup, + status, + percentProgress, + earliestRestorableTime: earliestRestorableTime?.toISOString(), + endpoint, + readerEndpoint, + multiAZ, + engine, + engineVersion, + latestRestorableTime: latestRestorableTime?.toISOString(), + port, + masterUsername, + preferredBackupWindow, + preferredMaintenanceWindow, + replicationSourceIdentifier, + readReplicaIdentifiers, + dBClusterMembers, + vpcSecurityGroups, + hostedZoneId, + storageEncrypted, + kmsKeyId, + dbClusterResourceId, + cloneGroupId, + clusterCreateTime: clusterCreateTime?.toISOString(), + deletionProtection, + } +} diff --git a/src/services/docdbCluster/index.ts b/src/services/docdbCluster/index.ts new file mode 100644 index 00000000..88155b90 --- /dev/null +++ b/src/services/docdbCluster/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class DOCDBCluster extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/docdbCluster/mutation.ts b/src/services/docdbCluster/mutation.ts new file mode 100644 index 00000000..9ab45db0 --- /dev/null +++ b/src/services/docdbCluster/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsDocdbClusterInput!]!) { + addawsDocdbCluster(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/docdbCluster/schema.graphql b/src/services/docdbCluster/schema.graphql new file mode 100644 index 00000000..8f8717ac --- /dev/null +++ b/src/services/docdbCluster/schema.graphql @@ -0,0 +1,37 @@ +type awsDocdbCluster implements awsBaseService @key(fields: "arn") { + availabilityZones: [String] @search(by: [hash, regexp]) + backupRetentionPeriod: Int @search + dBClusterIdentifier: String @search(by: [hash, regexp]) + dBClusterParameterGroup: String @search(by: [hash, regexp]) + dBSubnetGroup: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + percentProgress: String @search(by: [hash, regexp]) + earliestRestorableTime: DateTime @search(by: [day]) + endpoint: String @search(by: [hash, regexp]) + readerEndpoint: String @search(by: [hash, regexp]) + multiAZ: Boolean @search + engine: String @search(by: [hash, regexp]) + engineVersion: String @search(by: [hash, regexp]) + latestRestorableTime: DateTime @search(by: [day]) + port: Int @search + masterUsername: String @search(by: [hash, regexp]) + preferredBackupWindow: String @search(by: [hash, regexp]) + preferredMaintenanceWindow: String @search(by: [hash, regexp]) + replicationSourceIdentifier: String @search(by: [hash, regexp]) + readReplicaIdentifiers: [String] @search(by: [hash, regexp]) + dBClusterMembers: [String] @search(by: [hash, regexp]) + vpcSecurityGroups: [String] @search(by: [hash, regexp]) + hostedZoneId: String @search(by: [hash, regexp]) + storageEncrypted: Boolean @search + kmsKeyId: String @search(by: [hash, regexp]) + dbClusterResourceId: String @search(by: [hash, regexp]) + dBClusterArn: String @search(by: [hash, regexp]) + cloneGroupId: String @search(by: [hash, regexp]) + clusterCreateTime: DateTime @search(by: [day]) + nabledCloudwatchLogsExports: [String] @search(by: [hash, regexp]) + deletionProtection: Boolean @search +} + + + + diff --git a/src/services/ecr/data.ts b/src/services/ecr/data.ts index 4ba6fbc9..1662c9f5 100644 --- a/src/services/ecr/data.ts +++ b/src/services/ecr/data.ts @@ -3,6 +3,8 @@ import { AWSError } from 'aws-sdk/lib/error' import ECR, { DescribeRepositoriesRequest, DescribeRepositoriesResponse, + GetLifecyclePolicyResponse, + GetRepositoryPolicyResponse, ListTagsForResourceResponse, Repository, RepositoryList, @@ -27,6 +29,8 @@ const MAX_ITEMS = 1000 export interface RawAwsEcr extends Repository { region: string Tags?: TagMap + lifecyclePolicy: GetLifecyclePolicyResponse + repositoryPolicy: GetRepositoryPolicyResponse } const listReposForRegion = async ({ @@ -99,6 +103,56 @@ const getResourceTags = async (ecr: ECR, arn: string): Promise => } }) +const getLifecyclePolicy = async ( + ecr: ECR, + registryId: string, + repositoryName: string +): Promise => + new Promise(resolve => { + try { + ecr.getLifecyclePolicy( + { registryId, repositoryName }, + (err: AWSError, data: GetLifecyclePolicyResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ecr:getLifecyclePolicy', + err, + }) + return resolve({}) + } + resolve(data) + } + ) + } catch (error) { + resolve({}) + } + }) + +const getRepositoryPolicy = async ( + ecr: ECR, + registryId: string, + repositoryName: string +): Promise => + new Promise(resolve => { + try { + ecr.getRepositoryPolicy( + { registryId, repositoryName }, + (err: AWSError, data: GetRepositoryPolicyResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ecr:getRepositoryPolicy', + err, + }) + return resolve({}) + } + resolve(data) + } + ) + } catch (error) { + resolve({}) + } + }) + export default async ({ regions, config, @@ -112,9 +166,11 @@ export default async ({ const ecrData: RawAwsEcr[] = [] const regionPromises = [] const tagsPromises = [] + const lifecyclePoliciesPromises = [] + const repositoryPoliciesPromises = [] // get all repositories for all regions - regions.split(',').map(region => { + regions.split(',').forEach(region => { const ecr = new ECR({ ...config, region, endpoint }) const regionPromise = new Promise(async resolveRegion => { const repositoryList = await listReposForRegion({ @@ -126,6 +182,8 @@ export default async ({ ...repositoryList.map(repo => ({ ...repo, region, + lifecyclePolicy: {}, + repositoryPolicy: {}, })) ) } @@ -138,7 +196,7 @@ export default async ({ await Promise.all(regionPromises) // get all tags for each repository - ecrData.map(({ repositoryArn, region }, idx) => { + ecrData.forEach(({ repositoryArn, region }, idx) => { const ecr = new ECR({ ...config, region, endpoint }) const tagsPromise = new Promise(async resolveTags => { const envTags: TagMap = await getResourceTags(ecr, repositoryArn) @@ -150,6 +208,47 @@ export default async ({ logger.debug(lt.gettingECRRepoTags) await Promise.all(tagsPromises) + + // get lifecycle policy for each repository + ecrData.forEach(({ registryId, repositoryName, region }, idx) => { + const ecr = new ECR({ ...config, region, endpoint }) + const lifecyclePolicyPromise = new Promise( + async resolveLifecyclePolicy => { + const lifecyclePolicy = await getLifecyclePolicy( + ecr, + registryId, + repositoryName + ) + ecrData[idx].lifecyclePolicy = lifecyclePolicy + resolveLifecyclePolicy() + } + ) + lifecyclePoliciesPromises.push(lifecyclePolicyPromise) + }) + + logger.debug(lt.gettingECRRepoLifecyclePolicy) + await Promise.all(lifecyclePoliciesPromises) + + // get repository policy for each repository + ecrData.forEach(({ registryId, repositoryName, region }, idx) => { + const ecr = new ECR({ ...config, region, endpoint }) + const repositoryPolicyPromise = new Promise( + async resolveRepositoryPolicy => { + const repositoryPolicy = await getRepositoryPolicy( + ecr, + registryId, + repositoryName + ) + ecrData[idx].repositoryPolicy = repositoryPolicy + resolveRepositoryPolicy() + } + ) + repositoryPoliciesPromises.push(repositoryPolicyPromise) + }) + + logger.debug(lt.gettingECRRepoRepositoryPolicy) + await Promise.all(repositoryPoliciesPromises) + errorLog.reset() resolve(groupBy(ecrData, 'region')) diff --git a/src/services/ecr/format.ts b/src/services/ecr/format.ts index b600b30d..b20170c7 100644 --- a/src/services/ecr/format.ts +++ b/src/services/ecr/format.ts @@ -5,7 +5,7 @@ import { RawAwsEcr } from './data' export default ({ service: rawData, account, - region + region, }: { service: RawAwsEcr account: string @@ -19,8 +19,13 @@ export default ({ createdAt, imageTagMutability, imageScanningConfiguration: { scanOnPush: imageScanOnPush = false } = {}, - encryptionConfiguration: { encryptionType: type = 'none', kmsKey = '' } = {}, + encryptionConfiguration: { + encryptionType: type = 'none', + kmsKey = '', + } = {}, Tags, + lifecyclePolicy, + repositoryPolicy, } = rawData return { @@ -36,5 +41,7 @@ export default ({ registryAccountId, repositoryUri, tags: formatTagsFromMap(Tags), + lifecyclePolicy, + repositoryPolicy, } } diff --git a/src/services/ecr/schema.graphql b/src/services/ecr/schema.graphql index cfe8f704..dbdbec65 100644 --- a/src/services/ecr/schema.graphql +++ b/src/services/ecr/schema.graphql @@ -8,6 +8,8 @@ type awsEcr implements awsBaseService @key(fields: "arn") { repositoryUri: String @search(by: [hash, regexp]) scanOnPush: Boolean @search tags: [awsRawTag] + lifecyclePolicy: awsEcrLifecyclePolicy + repositoryPolicy: awsEcrRepositoryPolicy } type awsEcrEncryptionConfiguration @@ -19,3 +21,15 @@ type awsEcrEncryptionConfiguration type: String @search(by: [hash, regexp]) kmsKey: String @search(by: [hash, regexp]) } + +type awsEcrLifecyclePolicy { + registryId: String + repositoryName: String + lifecyclePolicyText: String +} + +type awsEcrRepositoryPolicy { + registryId: String + repositoryName: String + policyText: String +} diff --git a/src/services/ecsCluster/data.ts b/src/services/ecsCluster/data.ts index 677a39d4..1b2e86ad 100644 --- a/src/services/ecsCluster/data.ts +++ b/src/services/ecsCluster/data.ts @@ -1,65 +1,41 @@ +import CloudGraph from '@cloudgraph/sdk' import { Config } from 'aws-sdk' -import { AWSError } from 'aws-sdk/lib/error' import ECS, { Cluster, ListClustersRequest, ListClustersResponse, } from 'aws-sdk/clients/ecs' -import CloudGraph from '@cloudgraph/sdk' +import { AWSError } from 'aws-sdk/lib/error' import groupBy from 'lodash/groupBy' import isEmpty from 'lodash/isEmpty' import awsLoggerText from '../../properties/logger' import { AwsTag, TagMap } from '../../types' -import { convertAwsTagsToTagMap } from '../../utils/format' -import AwsErrorLog from '../../utils/errorLog' import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import { convertAwsTagsToTagMap } from '../../utils/format' const lt = { ...awsLoggerText } const { logger } = CloudGraph const serviceName = 'ECS cluster' const errorLog = new AwsErrorLog(serviceName) const endpoint = initTestEndpoint(serviceName) - +const MAX_ITEMS = 100 export interface RawAwsEcsCluster extends Omit { region: string Tags?: TagMap } -export default async ({ - regions, - config, -}: { - regions: string - config: Config -}): Promise<{ [region: string]: RawAwsEcsCluster[] }> => - new Promise(async resolve => { - /** - * Get the arns of all the ECS Clusters - */ - const ecsClusterData: RawAwsEcsCluster[] = [] - const ecsClusterArns: Array<{ region: string; clusterArns: string[] }> = [] - const regionPromises = [] - - const listClusterArns = async ({ - ecs, - region, - token: nextToken = '', - resolveRegion, - }: { - ecs: ECS - region: string - token?: string - resolveRegion: Function - }) => { - let args: ListClustersRequest = {} - - if (nextToken) { - args = { ...args, nextToken } +export const listClusterArnsForRegion = async (ecs: ECS): Promise => + new Promise(resolve => { + const clusterArnList: string[] = [] + const args: ListClustersRequest = {} + const listAllClusterArns = (token?: string): void => { + args.maxResults = MAX_ITEMS + if (token) { + args.nextToken = token } - - return ecs.listClusters( - args, - (err: AWSError, data: ListClustersResponse) => { + try { + ecs.listClusters(args, (err: AWSError, data: ListClustersResponse) => { if (err) { errorLog.generateAwsErrorLog({ functionName: 'ecs:listClusters', @@ -67,55 +43,55 @@ export default async ({ }) } - /** - * No Cluster data for this region - */ if (isEmpty(data)) { - return resolveRegion() + return resolve([]) } - const { clusterArns, nextToken: token } = data - - logger.debug(lt.fetchedEcsClusters(clusterArns.length)) + const { clusterArns = [], nextToken } = data || {} - /** - * No Clusters Found - */ + clusterArnList.push(...clusterArns) - if (isEmpty(clusterArns)) { - return resolveRegion() + if (nextToken) { + listAllClusterArns(nextToken) + } else { + resolve(clusterArnList) } + }) + } catch (error) { + resolve([]) + } + } + listAllClusterArns() + }) - /** - * Check to see if there are more - */ - - if (token) { - listClusterArns({ region, token, ecs, resolveRegion }) - } - - /** - * Add the found Clusters to the ecsClusterArns - */ - - ecsClusterArns.push({ region, clusterArns }) - - /** - * If this is the last page of data then return - */ +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [region: string]: RawAwsEcsCluster[] }> => + new Promise(async resolve => { + /** + * Get all ECS Clusters Arns + */ + const ecsClusterData: RawAwsEcsCluster[] = [] + const ecsClusterArns: Array<{ region: string; clusterArns: string[] }> = [] + const regionPromises = [] - if (!token) { - resolveRegion() - } + regions.split(',').forEach(region => { + const ecs = new ECS({ ...config, region, endpoint }) + const regionPromise = new Promise(async resolveRegion => { + const clusterArnsList = await listClusterArnsForRegion(ecs) + if (!isEmpty(clusterArnsList)) { + ecsClusterArns.push({ + clusterArns: clusterArnsList, + region, + }) } - ) - } + resolveRegion() + }) - regions.split(',').map(region => { - const ecs = new ECS({ ...config, region, endpoint }) - const regionPromise = new Promise(resolveRegion => - listClusterArns({ ecs, region, resolveRegion }) - ) regionPromises.push(regionPromise) }) @@ -126,10 +102,10 @@ export default async ({ */ const clusterPromises = ecsClusterArns.map( - async ({ region, clusterArns: clusters }) => + async ({ region, clusterArns }) => new Promise(resolveEcsData => new ECS({ ...config, region, endpoint }).describeClusters( - { clusters }, + { clusters: clusterArns }, (err, data) => { if (err) { errorLog.generateAwsErrorLog({ diff --git a/src/services/ecsService/data.ts b/src/services/ecsService/data.ts index baec07ad..55109065 100644 --- a/src/services/ecsService/data.ts +++ b/src/services/ecsService/data.ts @@ -1,52 +1,132 @@ -import { Config } from 'aws-sdk' -import ECS, { Service } from 'aws-sdk/clients/ecs' import CloudGraph from '@cloudgraph/sdk' -import flatMap from 'lodash/flatMap' +import { Config } from 'aws-sdk' +import ECS, { ListServicesRequest, Service } from 'aws-sdk/clients/ecs' import groupBy from 'lodash/groupBy' import isEmpty from 'lodash/isEmpty' +import services from '../../enums/services' import awsLoggerText from '../../properties/logger' import { AwsTag, TagMap } from '../../types' -import { convertAwsTagsToTagMap } from '../../utils/format' -import AwsErrorLog from '../../utils/errorLog' import { initTestEndpoint } from '../../utils' -import EcsClusterClass from '../ecsCluster' -import { RawAwsEcsCluster } from '../ecsCluster/data' +import AwsErrorLog from '../../utils/errorLog' +import { convertAwsTagsToTagMap } from '../../utils/format' +import { listClusterArnsForRegion, RawAwsEcsCluster } from '../ecsCluster/data' const lt = { ...awsLoggerText } const { logger } = CloudGraph const serviceName = 'ECS service' const errorLog = new AwsErrorLog(serviceName) const endpoint = initTestEndpoint(serviceName) - +const MAX_ITEMS = 100 export interface RawAwsEcsService extends Service { region: string Tags?: TagMap + ClusterArn: string } +export const listServicesArnForRegion = async ( + ecs: ECS, + cluster: string +): Promise => + new Promise(resolve => { + const serviceArnList: string[] = [] + const getRestApisOpts: ListServicesRequest = { + cluster, + maxResults: MAX_ITEMS, + } + const listAllServiceArns = (token?: string): void => { + if (token) { + getRestApisOpts.nextToken = token + } + try { + ecs.listServices({ cluster }, (err, data) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ecs:listServices', + err, + }) + } + + if (isEmpty(data)) { + return resolve([]) + } + + const { serviceArns = [], nextToken } = data + + serviceArnList.push(...serviceArns) + + if (nextToken) { + listAllServiceArns(nextToken) + } else { + resolve(serviceArnList) + } + }) + } catch (error) { + resolve([]) + } + } + listAllServiceArns() + }) + export default async ({ regions, config, + rawData, }: { regions: string config: Config + rawData: any }): Promise<{ [region: string]: RawAwsEcsService[] }> => new Promise(async resolve => { const ecsServices: RawAwsEcsService[] = [] - const ecsClusterClass = new EcsClusterClass({ logger: CloudGraph.logger }) - const clusterResult = await ecsClusterClass.getData({ - ...config, - regions, - }) - const ecsClusters: RawAwsEcsCluster[] = flatMap(clusterResult) + const regionPromises = [] + const ecsClusterData: Array<{ region: string; clusterArn: string }> = [] + + const existingData: { [property: string]: RawAwsEcsCluster[] } = + rawData?.find(({ name }) => name === services.ecsCluster)?.data || {} + + if (isEmpty(existingData)) { + // Refresh data + regions.split(',').map(region => { + const ecsClient = new ECS({ ...config, region, endpoint }) + const regionPromise = new Promise(async resolveRegion => { + const clusterArnList = await listClusterArnsForRegion(ecsClient) + if (!isEmpty(clusterArnList)) { + ecsClusterData.push( + ...clusterArnList.map(arn => ({ + clusterArn: arn, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + return null + }) + await Promise.all(regionPromises) + } else { + // Uses existing data + regions.split(',').map(region => { + if (!isEmpty(existingData[region])) { + ecsClusterData.push( + ...existingData[region].map(ecsCluster => ({ + clusterArn: ecsCluster.clusterArn, + region, + })) + ) + } + return null + }) + } /** * Get the arns of all the services */ let ecsServiceArns: any = await Promise.all( - ecsClusters.map( - async ({ clusterName: cluster, region }) => + ecsClusterData.map( + async ({ clusterArn: cluster, region }) => new Promise(resolveEcsData => new ECS({ ...config, region, endpoint }).listServices( { cluster }, @@ -81,10 +161,10 @@ export default async ({ * Get all the details for each service */ const ecsServicePromises = ecsServiceArns.map( - async ({ region, serviceArns: services, cluster }) => + async ({ region, serviceArns, cluster }) => new Promise(resolveEcsData => new ECS({ ...config, region, endpoint }).describeServices( - { services, cluster }, + { services: serviceArns, cluster }, (err, data) => { if (err) { errorLog.generateAwsErrorLog({ @@ -97,14 +177,15 @@ export default async ({ return resolveEcsData() } - const { services = [] } = data + const { services: servicesList = [] } = data - logger.debug(lt.fetchedEcsServices(services.length)) + logger.debug(lt.fetchedEcsServices(servicesList.length)) ecsServices.push( - ...services.map(service => ({ + ...servicesList.map(service => ({ region, ...service, + ClusterArn: cluster, Tags: convertAwsTagsToTagMap(service.tags as AwsTag[]), })) ) diff --git a/src/services/ecsService/format.ts b/src/services/ecsService/format.ts index fa67f7c9..be1a1532 100644 --- a/src/services/ecsService/format.ts +++ b/src/services/ecsService/format.ts @@ -4,6 +4,8 @@ import { AwsEcsService } from '../../types/generated' import { formatTagsFromMap } from '../../utils/format' import { RawAwsEcsService } from './data' +const formatName = (arn: string): string => arn?.split('/').pop() || '' + export default ({ service, account, @@ -33,6 +35,7 @@ export default ({ propagateTags, enableExecuteCommand, Tags, + ClusterArn: clusterArn, } = service const loadBalancers = service.loadBalancers?.map(lb => ({ @@ -176,6 +179,8 @@ export default ({ enableECSManagedTags, propagateTags, enableExecuteCommand, + clusterArn, + clusterName: formatName(clusterArn), tags: formatTagsFromMap(Tags), } } diff --git a/src/services/ecsService/schema.graphql b/src/services/ecsService/schema.graphql index 2f59bfb4..7ef0f72d 100644 --- a/src/services/ecsService/schema.graphql +++ b/src/services/ecsService/schema.graphql @@ -24,6 +24,8 @@ type awsEcsService implements awsBaseService @key(fields: "arn") { enableECSManagedTags: Boolean @search propagateTags: String @search(by: [hash, regexp]) enableExecuteCommand: Boolean @search + clusterArn: String @search(by: [hash, regexp]) + clusterName: String @search(by: [hash, regexp]) tags: [awsRawTag] ecsCluster: [awsEcsCluster] @hasInverse(field: ecsService) ecsTaskDefinition: [awsEcsTaskDefinition] @hasInverse(field: ecsService) diff --git a/src/services/ecsTaskDefinition/data.ts b/src/services/ecsTaskDefinition/data.ts index a48ecaac..f5cb7b29 100644 --- a/src/services/ecsTaskDefinition/data.ts +++ b/src/services/ecsTaskDefinition/data.ts @@ -42,8 +42,9 @@ export default async ({ if (isEmpty(existingData)) { const ecsServiceClass = new EcsServiceClass({ logger: CloudGraph.logger }) const serviceResult = await ecsServiceClass.getData({ - ...config, regions, + config, + rawData, }) ecsServices = flatMap(serviceResult) } else { diff --git a/src/services/efs/data.ts b/src/services/efs/data.ts index fdbbdd3d..d9e4fd63 100644 --- a/src/services/efs/data.ts +++ b/src/services/efs/data.ts @@ -3,6 +3,9 @@ import EFS, { FileSystemDescription, DescribeFileSystemsRequest, DescribeFileSystemsResponse, + DescribeFileSystemPolicyRequest, + FileSystemPolicyDescription, + Policy, } from 'aws-sdk/clients/efs' import { AWSError } from 'aws-sdk/lib/error' import CloudGraph from '@cloudgraph/sdk' @@ -20,6 +23,42 @@ const serviceName = 'EFS' const errorLog = new AwsErrorLog(serviceName) const endpoint = initTestEndpoint(serviceName) +const getFileSystemPolicy = async ({ + efs, + FileSystemId, +}: { + efs: EFS + FileSystemId: string +}): Promise => + new Promise(resolve => { + const args: DescribeFileSystemPolicyRequest = { FileSystemId } + try { + efs.describeFileSystemPolicy( + args, + (err: AWSError, data: FileSystemPolicyDescription) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'efs:describeFileSystemPolicy', + err, + }) + } + + /** + * No policy for this file system + */ + if (isEmpty(data)) { + return resolve('') + } + + const { Policy: policy } = data + resolve(policy) + } + ) + } catch (error) { + resolve('') + } + }) + const listFileSystems = async ({ efs, region, @@ -29,7 +68,7 @@ const listFileSystems = async ({ efs: EFS region: string token?: string - resolveRegion: Function + resolveRegion: () => void }): Promise => new Promise(resolve => { const efsList: FileSystemDescription[] = [] @@ -57,10 +96,7 @@ const listFileSystems = async ({ return resolveRegion() } - const { - FileSystems: fileSystems = [], - NextMarker: token, - }: { FileSystems?: any; NextMarker?: any } = data + const { FileSystems: fileSystems = [], NextMarker: token } = data efsList.push(...fileSystems) @@ -100,6 +136,7 @@ const listFileSystems = async ({ export interface RawAwsEfs extends Omit { region: string + policy: Policy Tags?: TagMap } @@ -115,21 +152,23 @@ export default async ({ new Promise(async resolve => { const efsFileSystems: RawAwsEfs[] = [] const regionPromises = [] + const policyPromises = [] /** * Get all the EFS File Systems */ - regions.split(',').map(region => { + regions.split(',').forEach(region => { const efs = new EFS({ ...config, region, endpoint }) const regionPromise = new Promise(async resolveRegion => { const efsList = await listFileSystems({ efs, region, resolveRegion }) if (!isEmpty(efsList)) { efsFileSystems.push( - ...efsList.map(efs => ({ - ...efs, + ...efsList.map(efsItem => ({ + ...efsItem, region, - Tags: convertAwsTagsToTagMap(efs.Tags), + policy: '', + Tags: convertAwsTagsToTagMap(efsItem.Tags), })) ) } @@ -139,6 +178,21 @@ export default async ({ }) await Promise.all(regionPromises) + + // get policy for each rest api + efsFileSystems.forEach(({ FileSystemId: id, region }, idx) => { + const efs = new EFS({ ...config, region, endpoint }) + const modelPromise = new Promise(async resolvePolicy => { + efsFileSystems[idx].policy = await getFileSystemPolicy({ + efs, + FileSystemId: id, + }) + resolvePolicy() + }) + policyPromises.push(modelPromise) + }) + await Promise.all(policyPromises) + errorLog.reset() resolve(groupBy(efsFileSystems, 'region')) diff --git a/src/services/efs/format.ts b/src/services/efs/format.ts index e9f92659..92747ec2 100644 --- a/src/services/efs/format.ts +++ b/src/services/efs/format.ts @@ -27,6 +27,7 @@ export default ({ ProvisionedThroughputInMibps: provisionedThroughputInMibps, AvailabilityZoneName: availabilityZoneName, AvailabilityZoneId: availabilityZoneId, + policy, Tags, } = service @@ -46,7 +47,7 @@ export default ({ value: sizeInBytes?.Value, timestamp: sizeInBytes?.Timestamp?.toISOString(), valueInIA: sizeInBytes?.ValueInIA, - valueInStandard: sizeInBytes?.ValueInStandard + valueInStandard: sizeInBytes?.ValueInStandard, }, performanceMode, encrypted, @@ -54,6 +55,7 @@ export default ({ provisionedThroughputInMibps, availabilityZoneName, availabilityZoneId, + policy, tags: formatTagsFromMap(Tags), } } diff --git a/src/services/efs/schema.graphql b/src/services/efs/schema.graphql index a5888266..bb3647be 100644 --- a/src/services/efs/schema.graphql +++ b/src/services/efs/schema.graphql @@ -16,6 +16,7 @@ type awsEfs implements awsBaseService @key(fields: "arn") { tags: [awsRawTag] efsMountTarget: [awsEfsMountTarget] @hasInverse(field: efs) #change to plural kms: [awsKms] @hasInverse(field: efs) + policy: String } type awsEfsFileSystemSize diff --git a/src/services/efsAccessPoint/data.ts b/src/services/efsAccessPoint/data.ts new file mode 100644 index 00000000..5deb4b02 --- /dev/null +++ b/src/services/efsAccessPoint/data.ts @@ -0,0 +1,118 @@ +import { Config } from 'aws-sdk' +import EFS, { + DescribeAccessPointsResponse, + DescribeAccessPointsRequest, + AccessPointDescription, +} from 'aws-sdk/clients/efs' +import { AWSError } from 'aws-sdk/lib/error' +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' +import { initTestEndpoint } from '../../utils' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'EFS Access Point' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsEfsAccessPoint extends AccessPointDescription { + region: string +} + +const listAccessPoint = async ({ + efs, +}: { + efs: EFS +}): Promise => + new Promise(resolve => { + const accessPointList: AccessPointDescription[] = [] + const args: DescribeAccessPointsRequest = {} + const listAllAccessPoints = (token?: string): void => { + if (token) { + args.NextToken = token + } + + try { + efs.describeAccessPoints( + args, + (err: AWSError, data: DescribeAccessPointsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'efs:describeAccessPoints', + err, + }) + } + + /** + * No EFS access point data for this region + */ + if (isEmpty(data)) { + return resolve([]) + } + + const { AccessPoints: accessPoints = [], NextToken: nextToken } = + data + + accessPointList.push(...accessPoints) + + /** + * Check to see if there are more + */ + + if (nextToken) { + listAllAccessPoints(nextToken) + } else { + resolve(accessPointList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllAccessPoints() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ + [region: string]: RawAwsEfsAccessPoint[] +}> => + new Promise(async resolve => { + const efsAccessPoints: RawAwsEfsAccessPoint[] = [] + const regionPromises = [] + + /** + * Get all the EFS Access points + */ + + regions.split(',').forEach(region => { + const efs = new EFS({ ...config, region, endpoint }) + const regionPromise = new Promise(async resolveRegion => { + const accessPointList = await listAccessPoint({ efs }) + if (!isEmpty(accessPointList)) { + efsAccessPoints.push( + ...accessPointList.map(accessPoint => ({ + ...accessPoint, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedEfsAccessPoints(efsAccessPoints.length)) + errorLog.reset() + + resolve(groupBy(efsAccessPoints, 'region')) + }) diff --git a/src/services/efsAccessPoint/format.ts b/src/services/efsAccessPoint/format.ts new file mode 100644 index 00000000..3c0f5fa0 --- /dev/null +++ b/src/services/efsAccessPoint/format.ts @@ -0,0 +1,26 @@ +import { AwsEfsAccessPoint } from '../../types/generated' +import { RawAwsEfsAccessPoint } from './data' + +export default ({ + service, + account, + region, +}: { + service: RawAwsEfsAccessPoint + account: string + region: string +}): AwsEfsAccessPoint => { + const { + Name: name, + AccessPointArn: arn, + AccessPointId: accessPointId, + } = service + + return { + id: accessPointId, + arn, + accountId: account, + region, + name, + } +} diff --git a/src/services/efsAccessPoint/index.ts b/src/services/efsAccessPoint/index.ts new file mode 100644 index 00000000..471eda13 --- /dev/null +++ b/src/services/efsAccessPoint/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class EFSAccessPoint extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/efsAccessPoint/mutation.ts b/src/services/efsAccessPoint/mutation.ts new file mode 100644 index 00000000..31f5b5d6 --- /dev/null +++ b/src/services/efsAccessPoint/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsEfsAccessPointInput!]!) { + addawsEfsAccessPoint(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/efsAccessPoint/schema.graphql b/src/services/efsAccessPoint/schema.graphql new file mode 100644 index 00000000..378cd62f --- /dev/null +++ b/src/services/efsAccessPoint/schema.graphql @@ -0,0 +1,3 @@ +type awsEfsAccessPoint implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/eksCluster/data.ts b/src/services/eksCluster/data.ts index d60e01c3..caa12162 100644 --- a/src/services/eksCluster/data.ts +++ b/src/services/eksCluster/data.ts @@ -7,6 +7,8 @@ import EKS, { DescribeClusterRequest, DescribeClusterResponse, ListTagsForResourceResponse, + ListNodegroupsRequest, + ListNodegroupsResponse, } from 'aws-sdk/clients/eks' import CloudGraph from '@cloudgraph/sdk' import groupBy from 'lodash/groupBy' @@ -23,8 +25,8 @@ const errorLog = new AwsErrorLog(serviceName) const endpoint = initTestEndpoint(serviceName) const MAX_ITEMS = 100 -const listClustersForRegion = async ({ - eks, +const listClustersForRegion = async ({ + eks, resolveRegion, }: { eks: EKS @@ -64,7 +66,6 @@ const listClustersForRegion = async ({ } else { resolve(clusterList) } - } ) } catch (error) { @@ -123,9 +124,61 @@ const getResourceTags = async (eks: EKS, arn: string): Promise => } }) +const listNodegroups = async ({ + eks, + clusterName, +}: { + eks: EKS + clusterName: string +}): Promise => + new Promise(resolve => { + const nodeGroupsList: string[] = [] + let args: ListNodegroupsRequest = { clusterName } + const listAllNodeGroups = (token?: string): void => { + if (token) { + args = { ...args, nextToken: token } + } + + try { + eks.listNodegroups( + args, + (err: AWSError, data: ListNodegroupsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'eks:listNodegroups', + err, + }) + } + + /** + * No node groups for this region + */ + if (isEmpty(data)) { + return resolve(nodeGroupsList) + } + + const { nextToken, nodegroups } = data || {} + + nodeGroupsList.push(...nodegroups) + + if (nextToken) { + listAllNodeGroups(nextToken) + } else { + resolve(nodeGroupsList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllNodeGroups() + }) + export interface RawAwsEksCluster extends Omit { region: string Tags?: TagMap + NodeGroups?: string[] } export default async ({ @@ -140,6 +193,7 @@ export default async ({ const regionPromises = [] const clusterPromises = [] const tagsPromises = [] + const nodeGroupsPromises = [] // get all clusters for all regions regions.split(',').map(region => { @@ -192,6 +246,22 @@ export default async ({ }) await Promise.all(tagsPromises) + + // get all node groups for each cluster + eksData.map(({ name, region }, idx) => { + const eks = new EKS({ ...config, region, endpoint }) + const nodeGroupsPromise = new Promise(async resolveNodeGroups => { + const nodeGroups: string[] = await listNodegroups({ + eks, + clusterName: name, + }) + eksData[idx].NodeGroups = nodeGroups + resolveNodeGroups() + }) + nodeGroupsPromises.push(nodeGroupsPromise) + }) + + await Promise.all(nodeGroupsPromises) errorLog.reset() resolve(groupBy(eksData, 'region')) diff --git a/src/services/eksCluster/format.ts b/src/services/eksCluster/format.ts index 1c0d13c3..cc3b9596 100644 --- a/src/services/eksCluster/format.ts +++ b/src/services/eksCluster/format.ts @@ -29,6 +29,7 @@ export default ({ platformVersion, encryptionConfig, Tags = {}, + NodeGroups: nodeGroups = [] } = service const formattedKubernetesNetworkConfig = { @@ -70,5 +71,6 @@ export default ({ ...config, })), tags: formatTagsFromMap(Tags), + nodeGroups } } diff --git a/src/services/eksCluster/schema.graphql b/src/services/eksCluster/schema.graphql index 7e611a87..a3018850 100644 --- a/src/services/eksCluster/schema.graphql +++ b/src/services/eksCluster/schema.graphql @@ -13,6 +13,7 @@ type awsEksCluster implements awsBaseService @key(fields: "arn") { platformVersion: String @search(by: [hash, regexp]) encryptionConfig: [awsEksEncryptionConfig] tags: [awsRawTag] + nodeGroups: [String] @search(by: [hash]) iamRoles: [awsIamRole] @hasInverse(field: eksClusters) kms: [awsKms] @hasInverse(field: eksCluster) securityGroups: [awsSecurityGroup] @hasInverse(field: eksCluster) diff --git a/src/services/elasticBeanstalkApplication/data.ts b/src/services/elasticBeanstalkApplication/data.ts index 22f1b020..1af0a472 100644 --- a/src/services/elasticBeanstalkApplication/data.ts +++ b/src/services/elasticBeanstalkApplication/data.ts @@ -1,45 +1,36 @@ +import { + DescribeApplicationsCommand, + ElasticBeanstalkClient, + ListTagsForResourceCommand, +} from '@aws-sdk/client-elastic-beanstalk' import CloudGraph from '@cloudgraph/sdk' -import { AWSError } from 'aws-sdk' -import ElasticBeanstalk, { - ApplicationDescription, - ApplicationDescriptionsMessage, - ResourceTagsDescriptionMessage, -} from 'aws-sdk/clients/elasticbeanstalk' +import { Config } from 'aws-sdk' +import { ApplicationDescription } from 'aws-sdk/clients/elasticbeanstalk' +import { groupBy } from 'lodash' import isEmpty from 'lodash/isEmpty' - -import { AwsTag, Credentials, TagMap } from '../../types' -import { convertAwsTagsToTagMap } from '../../utils/format' -import { settleAllPromises } from '../../utils/index' import awsLoggerText from '../../properties/logger' -import { initTestEndpoint } from '../../utils' +import { AwsTag, TagMap } from '../../types' import AwsErrorLog from '../../utils/errorLog' +import { convertAwsTagsToTagMap } from '../../utils/format' +import { settleAllPromises } from '../../utils/index' const lt = { ...awsLoggerText } const { logger } = CloudGraph const serviceName = 'ElasticBeanstalkApp' const errorLog = new AwsErrorLog(serviceName) -const endpoint = initTestEndpoint(serviceName) export interface RawAwsElasticBeanstalkApp extends ApplicationDescription { + region: string Tags?: TagMap } const listApplications = async ( - eb: ElasticBeanstalk + eb: ElasticBeanstalkClient ): Promise => new Promise(async resolve => { - eb.describeApplications( - {}, - (err: AWSError, data: ApplicationDescriptionsMessage) => { - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'elasticBeanstalk:describeApplications', - err, - }) - } - /** - * No EB Applications for this region - */ + const command = new DescribeApplicationsCommand({}) + eb.send(command) + .then(data => { if (isEmpty(data)) { return resolve([]) } @@ -48,29 +39,24 @@ const listApplications = async ( return resolve([]) } resolve(Applications) - } - ) + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'elasticBeanstalk:describeApplications', + err, + }) + resolve([]) + }) }) export const getResourceTags = async ( - eb: ElasticBeanstalk, + eb: ElasticBeanstalkClient, resourceArn: string ): Promise => new Promise(resolveTags => { - eb.listTagsForResource( - { - ResourceArn: resourceArn, - }, - (err: AWSError, data: ResourceTagsDescriptionMessage) => { - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'elasticBeanstalk:listTagsForResource', - err, - }) - } - /** - * No EB Applications for this region - */ + const command = new ListTagsForResourceCommand({ ResourceArn: resourceArn }) + eb.send(command) + .then(data => { if (isEmpty(data)) { return resolveTags({}) } @@ -79,12 +65,18 @@ export const getResourceTags = async ( return resolveTags({}) } resolveTags(convertAwsTagsToTagMap(tags as AwsTag[])) - } - ) + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'elasticBeanstalk:listTagsForResource', + err, + }) + resolveTags({}) + }) }) const getApplications = async ( - eb: ElasticBeanstalk + eb: ElasticBeanstalkClient ): Promise => { const apps = await listApplications(eb) if (!isEmpty(apps)) { @@ -100,29 +92,33 @@ const getApplications = async ( export default async ({ regions, - credentials, + config, }: { regions: string - credentials: Credentials + config: Config }): Promise<{ [property: string]: RawAwsElasticBeanstalkApp[] }> => new Promise(async resolve => { + const { credentials } = config let numberOfApps = 0 - const output: { [property: string]: RawAwsElasticBeanstalkApp[] } = {} + const appsData: RawAwsElasticBeanstalkApp[] = [] - // First we get all applications for all regions - await Promise.all( - regions.split(',').map(region => { - const eb = new ElasticBeanstalk({ region, credentials, endpoint }) - output[region] = [] - return new Promise(async resolveRegion => { - const apps = (await getApplications(eb)) || [] - output[region] = apps + const regionPromises = regions.split(',').map(region => { + const eb = new ElasticBeanstalkClient({ + credentials, + region, + }) + return new Promise(async resolveRegion => { + const apps = (await getApplications(eb)) || [] + if (!isEmpty(apps)) { + appsData.push(...apps.map(val => ({ ...val, region }))) numberOfApps += apps.length - resolveRegion() - }) + } + resolveRegion() }) - ) + }) + + await Promise.all(regionPromises) errorLog.reset() logger.debug(lt.fetchedElasticBeanstalkApps(numberOfApps)) - resolve(output) + resolve(groupBy(appsData, 'region')) }) diff --git a/src/services/elasticBeanstalkEnvironment/data.ts b/src/services/elasticBeanstalkEnvironment/data.ts index 8cf77cd2..9ba0773a 100644 --- a/src/services/elasticBeanstalkEnvironment/data.ts +++ b/src/services/elasticBeanstalkEnvironment/data.ts @@ -1,126 +1,141 @@ +import { + DescribeConfigurationSettingsCommand, + DescribeConfigurationSettingsMessage, + DescribeEnvironmentResourcesCommand, + DescribeEnvironmentResourcesMessage, + DescribeEnvironmentsCommand, + ElasticBeanstalkClient, +} from '@aws-sdk/client-elastic-beanstalk' import CloudGraph from '@cloudgraph/sdk' -import { AWSError } from 'aws-sdk' -import ElasticBeanstalk, { +import { Config } from 'aws-sdk' +import { ConfigurationSettingsDescription, - ConfigurationSettingsDescriptions, DescribeEnvironmentsMessage, EnvironmentDescription, - EnvironmentDescriptionsMessage, EnvironmentResourceDescription, - EnvironmentResourceDescriptionsMessage, } from 'aws-sdk/clients/elasticbeanstalk' +import { groupBy } from 'lodash' import isEmpty from 'lodash/isEmpty' - -import { Credentials, TagMap } from '../../types' -import { settleAllPromises } from '../../utils/index' import awsLoggerText from '../../properties/logger' -import { initTestEndpoint } from '../../utils' +import { TagMap } from '../../types' import AwsErrorLog from '../../utils/errorLog' +import { settleAllPromises } from '../../utils/index' import { getResourceTags } from '../elasticBeanstalkApplication/data' const lt = { ...awsLoggerText } const { logger } = CloudGraph const serviceName = 'ElasticBeanstalkEnv' const errorLog = new AwsErrorLog(serviceName) -const endpoint = initTestEndpoint(serviceName) const MAX_ITEMS = 1000 export interface RawAwsElasticBeanstalkEnv extends EnvironmentDescription { resources?: EnvironmentResourceDescription settings?: ConfigurationSettingsDescription[] Tags?: TagMap + region: string } const listEnvironments = async ( - eb: ElasticBeanstalk + eb: ElasticBeanstalkClient ): Promise => new Promise(async resolve => { const environments: EnvironmentDescription[] = [] - const listAllEnvironmentsOpts: DescribeEnvironmentsMessage = { + const input: DescribeEnvironmentsMessage = { MaxRecords: MAX_ITEMS, } + const listAllEnvironments = (token?: string): void => { if (token) { - listAllEnvironmentsOpts.NextToken = token + input.NextToken = token } - try { - eb.describeEnvironments( - listAllEnvironmentsOpts, - (err: AWSError, data: EnvironmentDescriptionsMessage) => { - const { Environments = [], NextToken: nextToken } = data || {} - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'elasticBeanstalk:describeEnvironments', - err, - }) - } - - environments.push(...Environments) - - if (nextToken) { - logger.debug(lt.foundAnotherThousand) - listAllEnvironments(nextToken) - } else { - resolve(environments) - } + const command = new DescribeEnvironmentsCommand(input) + eb.send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) } - ) - } catch (error) { - resolve([]) - } + + const { Environments = [], NextToken: nextToken } = data || {} + + environments.push(...Environments) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllEnvironments(nextToken) + } else { + resolve(environments) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'elasticBeanstalk:describeEnvironments', + err, + }) + resolve([]) + }) } listAllEnvironments() }) const getConfigSettingsForEnv = async ( - eb: ElasticBeanstalk, + eb: ElasticBeanstalkClient, ApplicationName: string, EnvironmentName: string ): Promise => new Promise(resolve => { - eb.describeConfigurationSettings( - { - ApplicationName, - EnvironmentName, - }, - (err: AWSError, data: ConfigurationSettingsDescriptions) => { - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'elasticBeanstalk:describeConfigurationSettings', - err, - }) + const input: DescribeConfigurationSettingsMessage = { + ApplicationName, + EnvironmentName, + } + const command = new DescribeConfigurationSettingsCommand(input) + eb.send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) } + const { ConfigurationSettings: settings = [] } = data || {} resolve(settings) - } - ) + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'elasticBeanstalk:describeConfigurationSettings', + err, + }) + resolve([]) + }) }) const getResourcesForEnv = async ( - eb: ElasticBeanstalk, + eb: ElasticBeanstalkClient, EnvironmentName: string ): Promise => new Promise(resolve => { - eb.describeEnvironmentResources( - { - EnvironmentName, - }, - (err: AWSError, data: EnvironmentResourceDescriptionsMessage) => { - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'elasticBeanstalk:describeEnvironmentResources', - err, - }) + const input: DescribeEnvironmentResourcesMessage = { + EnvironmentName, + } + const command = new DescribeEnvironmentResourcesCommand(input) + eb.send(command) + .then(data => { + if (isEmpty(data)) { + return resolve({}) } + const { EnvironmentResources: resources = {} } = data || {} resolve(resources) - } - ) + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'elasticBeanstalk:describeEnvironmentResources', + err, + }) + resolve({}) + }) }) const getEnvironments = async ( - eb: ElasticBeanstalk + eb: ElasticBeanstalkClient ): Promise => { const envs = await listEnvironments(eb) if (!isEmpty(envs)) { @@ -152,33 +167,35 @@ const getEnvironments = async ( export default async ({ regions, - credentials, + config, }: { regions: string - credentials: Credentials + config: Config }): Promise<{ [property: string]: RawAwsElasticBeanstalkEnv[] }> => new Promise(async resolve => { + const { credentials } = config let numberOfEnvs = 0 - const output: { - [property: string]: RawAwsElasticBeanstalkEnv[] - } = {} - - // First we get all applications for all regions - await Promise.all( - regions.split(',').map(region => { - const eb = new ElasticBeanstalk({ region, credentials, endpoint }) - output[region] = [] - return new Promise(async resolveRegion => { - const envs = (await getEnvironments(eb)) || [] - output[region] = envs + const envsData: RawAwsElasticBeanstalkEnv[] = [] + + const regionPromises = regions.split(',').map(region => { + const eb = new ElasticBeanstalkClient({ + credentials, + region, + }) + return new Promise(async resolveRegion => { + const envs = (await getEnvironments(eb)) || [] + if (!isEmpty(envs)) { + envsData.push(...envs.map(val => ({ ...val, region }))) numberOfEnvs += envs.length - resolveRegion() - }) + } + resolveRegion() }) - ) + }) + + await Promise.all(regionPromises) errorLog.reset() logger.debug(lt.fetchedElasticBeanstalkEnvs(numberOfEnvs)) - resolve(output) + resolve(groupBy(envsData, 'region')) }) diff --git a/src/services/glueCrawler/data.ts b/src/services/glueCrawler/data.ts new file mode 100644 index 00000000..250bc213 --- /dev/null +++ b/src/services/glueCrawler/data.ts @@ -0,0 +1,95 @@ +import { + Crawler, + GetCrawlersCommand, + GetCrawlersRequest, + GlueClient +} from '@aws-sdk/client-glue' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Glue Crawler' +const errorLog = new AwsErrorLog(serviceName) +const MAX_ITEMS = 50 + +export interface RawAwsGlueCrawler extends Crawler { + region: string +} + +const listCrawlers = async (glue: GlueClient): Promise => + new Promise(async resolve => { + const crawlers: Crawler[] = [] + + const input: GetCrawlersRequest = { + MaxResults: MAX_ITEMS, + } + + const listAllCrawlers = (token?: string): void => { + if (token) { + input.NextToken = token + } + const command = new GetCrawlersCommand(input) + glue + .send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { Crawlers = [], NextToken: nextToken } = data || {} + + crawlers.push(...Crawlers) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllCrawlers(nextToken) + } else { + resolve(crawlers) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'glue:getCrawlers', + err, + }) + resolve([]) + }) + } + listAllCrawlers() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsGlueCrawler[] }> => + new Promise(async resolve => { + const { credentials } = config + const glueCrawlerData: RawAwsGlueCrawler[] = [] + + const regionPromises = regions.split(',').map(region => { + const glue = new GlueClient({ + credentials, + region, + }) + + return new Promise(async resolveRegion => { + const crawlers = (await listCrawlers(glue)) || [] + if (!isEmpty(crawlers)) + glueCrawlerData.push(...crawlers.map(val => ({ ...val, region }))) + resolveRegion() + }) + }) + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(glueCrawlerData, 'region')) + }) diff --git a/src/services/glueCrawler/format.ts b/src/services/glueCrawler/format.ts new file mode 100644 index 00000000..37ce04d6 --- /dev/null +++ b/src/services/glueCrawler/format.ts @@ -0,0 +1,28 @@ +import { AwsGlueCrawler } from '../../types/generated' +import { glueCrawlerArn } from '../../utils/generateArns' +import { RawAwsGlueCrawler } from './data' + +/** + * Glue Crawler + */ +export default ({ + account, + region, + service: crawler, +}: { + account: string + region: string + service: RawAwsGlueCrawler +}): AwsGlueCrawler => { + const { Name: name } = crawler + + const arn = glueCrawlerArn({ region, account, name }) + + return { + accountId: account, + arn, + id: arn, + region, + name + } +} diff --git a/src/services/glueCrawler/index.ts b/src/services/glueCrawler/index.ts new file mode 100644 index 00000000..8777e861 --- /dev/null +++ b/src/services/glueCrawler/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class GlueCrawler extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/glueCrawler/mutation.ts b/src/services/glueCrawler/mutation.ts new file mode 100644 index 00000000..95ee36c1 --- /dev/null +++ b/src/services/glueCrawler/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsGlueCrawlerInput!]!) { + addawsGlueCrawler(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/glueCrawler/schema.graphql b/src/services/glueCrawler/schema.graphql new file mode 100644 index 00000000..96898e7e --- /dev/null +++ b/src/services/glueCrawler/schema.graphql @@ -0,0 +1,3 @@ +type awsGlueCrawler implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/glueDatabase/data.ts b/src/services/glueDatabase/data.ts new file mode 100644 index 00000000..171d562a --- /dev/null +++ b/src/services/glueDatabase/data.ts @@ -0,0 +1,163 @@ +import { + Database, + GetDatabasesCommand, + GetDatabasesRequest, + GetTablesCommand, + GetTablesRequest, + GlueClient, + Table, +} from '@aws-sdk/client-glue' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Glue Database' +const errorLog = new AwsErrorLog(serviceName) +const MAX_ITEMS = 50 + +export interface RawAwsGlueDatabase extends Database { + region: string + tables?: Table[] +} + +const listDatabases = async (glue: GlueClient): Promise => + new Promise(async resolve => { + const databases: Database[] = [] + + const input: GetDatabasesRequest = { + MaxResults: MAX_ITEMS, + } + + const listAllDatabases = (token?: string): void => { + if (token) { + input.NextToken = token + } + const command = new GetDatabasesCommand(input) + glue + .send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { DatabaseList = [], NextToken: nextToken } = data || {} + + databases.push(...DatabaseList) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllDatabases(nextToken) + } else { + resolve(databases) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'glue:getDatabases', + err, + }) + resolve([]) + }) + } + listAllDatabases() + }) + +const getTables = async ({ + glue, + databaseName, +}: { + glue: GlueClient + databaseName: string +}): Promise => + new Promise(resolve => { + const tables: Table[] = [] + const input: GetTablesRequest = { DatabaseName: databaseName } + const listAllTables = (token?: string): void => { + if (token) { + input.NextToken = token + } + const command = new GetTablesCommand(input) + glue + .send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { TableList = [], NextToken: nextToken } = data || {} + + tables.push(...TableList) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllTables(nextToken) + } else { + resolve(tables) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'glue:getTables', + err, + }) + resolve([]) + }) + } + listAllTables() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsGlueDatabase[] }> => + new Promise(async resolve => { + const { credentials } = config + const glueDatabaseData: RawAwsGlueDatabase[] = [] + const tablesPromises = [] + + const regionPromises = regions.split(',').map(region => { + const glue = new GlueClient({ + credentials, + region, + }) + + return new Promise(async resolveRegion => { + const databases = (await listDatabases(glue)) || [] + if (!isEmpty(databases)) + glueDatabaseData.push(...databases.map(val => ({ ...val, region }))) + resolveRegion() + }) + }) + + await Promise.all(regionPromises) + + // get all tables for each database + glueDatabaseData.forEach(({ Name, region }, idx) => { + const glue = new GlueClient({ + credentials, + region, + }) + const tablePromise = new Promise(async resolveTable => { + glueDatabaseData[idx].tables = await getTables({ + glue, + databaseName: Name, + }) + resolveTable() + }) + tablesPromises.push(tablePromise) + }) + + await Promise.all(tablesPromises) + + errorLog.reset() + + resolve(groupBy(glueDatabaseData, 'region')) + }) diff --git a/src/services/glueDatabase/format.ts b/src/services/glueDatabase/format.ts new file mode 100644 index 00000000..712518c2 --- /dev/null +++ b/src/services/glueDatabase/format.ts @@ -0,0 +1,30 @@ +import { AwsGlueDatabase } from '../../types/generated' +import { glueDatabaseArn } from '../../utils/generateArns' +import { RawAwsGlueDatabase } from './data' + +/** + * Glue Database + */ +export default ({ + account, + region, + service: database, +}: { + account: string + region: string + service: RawAwsGlueDatabase +}): AwsGlueDatabase => { + const { Name: name, CatalogId: catalogId, tables = [] } = database + + const arn = glueDatabaseArn({ region, account, name }) + + return { + accountId: account, + arn, + id: arn, + name, + catalogId, + region, + tables: tables.map(({ Name }) => Name), + } +} diff --git a/src/services/glueDatabase/index.ts b/src/services/glueDatabase/index.ts new file mode 100644 index 00000000..4c44a643 --- /dev/null +++ b/src/services/glueDatabase/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class GlueDatabase extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/glueDatabase/mutation.ts b/src/services/glueDatabase/mutation.ts new file mode 100644 index 00000000..0ec56abb --- /dev/null +++ b/src/services/glueDatabase/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsGlueDatabaseInput!]!) { + addawsGlueDatabase(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/glueDatabase/schema.graphql b/src/services/glueDatabase/schema.graphql new file mode 100644 index 00000000..e114f3a8 --- /dev/null +++ b/src/services/glueDatabase/schema.graphql @@ -0,0 +1,5 @@ +type awsGlueDatabase implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) + catalogId: String @search(by: [hash, regexp]) + tables: [String] @search(by: [hash, regexp]) +} diff --git a/src/services/glueTrigger/data.ts b/src/services/glueTrigger/data.ts new file mode 100644 index 00000000..4a8da704 --- /dev/null +++ b/src/services/glueTrigger/data.ts @@ -0,0 +1,95 @@ +import { + GetTriggersCommand, + GetTriggersRequest, + GlueClient, + Trigger, +} from '@aws-sdk/client-glue' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'Glue Trigger' +const errorLog = new AwsErrorLog(serviceName) +const MAX_ITEMS = 50 + +export interface RawAwsGlueTrigger extends Trigger { + region: string +} + +const listTriggers = async (glue: GlueClient): Promise => + new Promise(async resolve => { + const triggers: Trigger[] = [] + + const input: GetTriggersRequest = { + MaxResults: MAX_ITEMS, + } + + const listAllTriggers = (token?: string): void => { + if (token) { + input.NextToken = token + } + const command = new GetTriggersCommand(input) + glue + .send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { Triggers = [], NextToken: nextToken } = data || {} + + triggers.push(...Triggers) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllTriggers(nextToken) + } else { + resolve(triggers) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'glue:getTriggers', + err, + }) + resolve([]) + }) + } + listAllTriggers() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsGlueTrigger[] }> => + new Promise(async resolve => { + const { credentials } = config + const glueTriggerData: RawAwsGlueTrigger[] = [] + + const regionPromises = regions.split(',').map(region => { + const glue = new GlueClient({ + credentials, + region, + }) + + return new Promise(async resolveRegion => { + const triggers = (await listTriggers(glue)) || [] + if (!isEmpty(triggers)) + glueTriggerData.push(...triggers.map(val => ({ ...val, region }))) + resolveRegion() + }) + }) + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(glueTriggerData, 'region')) + }) diff --git a/src/services/glueTrigger/format.ts b/src/services/glueTrigger/format.ts new file mode 100644 index 00000000..b2a96b80 --- /dev/null +++ b/src/services/glueTrigger/format.ts @@ -0,0 +1,28 @@ +import { AwsGlueTrigger } from '../../types/generated' +import { glueTriggerArn } from '../../utils/generateArns' +import { RawAwsGlueTrigger } from './data' + +/** + * Glue Trigger + */ +export default ({ + account, + region, + service: crawler, +}: { + account: string + region: string + service: RawAwsGlueTrigger +}): AwsGlueTrigger => { + const { Name: name } = crawler + + const arn = glueTriggerArn({ region, account, name }) + + return { + accountId: account, + arn, + id: arn, + region, + name + } +} diff --git a/src/services/glueTrigger/index.ts b/src/services/glueTrigger/index.ts new file mode 100644 index 00000000..b7a79047 --- /dev/null +++ b/src/services/glueTrigger/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class GlueTrigger extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/glueTrigger/mutation.ts b/src/services/glueTrigger/mutation.ts new file mode 100644 index 00000000..b0e467bc --- /dev/null +++ b/src/services/glueTrigger/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsGlueTriggerInput!]!) { + addawsGlueTrigger(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/glueTrigger/schema.graphql b/src/services/glueTrigger/schema.graphql new file mode 100644 index 00000000..a905cedf --- /dev/null +++ b/src/services/glueTrigger/schema.graphql @@ -0,0 +1,3 @@ +type awsGlueTrigger implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/iamGroup/format.ts b/src/services/iamGroup/format.ts index a17e2c96..d61d0e90 100644 --- a/src/services/iamGroup/format.ts +++ b/src/services/iamGroup/format.ts @@ -18,6 +18,7 @@ export default ({ Arn: arn = '', Path: path = '', Policies: inlinePolicies = [], + ManagedPolicies: managedPolicies = [], } = rawData const record = { @@ -27,6 +28,10 @@ export default ({ path, name, inlinePolicies, + managedPolicies: managedPolicies.map(({ PolicyArn, PolicyName }) => ({ + policyArn: PolicyArn, + policyName: PolicyName, + })), } return record } diff --git a/src/services/iamGroup/schema.graphql b/src/services/iamGroup/schema.graphql index 4f84e9e5..3ab8bcc5 100644 --- a/src/services/iamGroup/schema.graphql +++ b/src/services/iamGroup/schema.graphql @@ -1,7 +1,18 @@ +type awsIamGroupAttachedPolicy + @generate( + query: { get: false, query: false, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + policyArn: String! @id @search(by: [hash, regexp]) + policyName: String @search(by: [hash, regexp]) +} + type awsIamGroup implements awsBaseService @key(fields: "id") { path: String @search(by: [hash, regexp]) name: String @search(by: [hash, regexp]) inlinePolicies: [String] + managedPolicies: [awsIamGroupAttachedPolicy] iamAttachedPolicies: [awsIamPolicy] @hasInverse(field: iamGroups) iamUsers: [awsIamUser] @hasInverse(field: iamGroups) } diff --git a/src/services/iamPolicy/schema.graphql b/src/services/iamPolicy/schema.graphql index 63993dc4..95c14c1a 100644 --- a/src/services/iamPolicy/schema.graphql +++ b/src/services/iamPolicy/schema.graphql @@ -32,6 +32,7 @@ type awsIamJSONPolicyStatement action: [String] @search(by: [hash]) condition: [awsIamJSONPolicyCondition] effect: String @search(by: [hash, regexp]) + sid: String @search(by: [hash, regexp]) principal: [awsIamJSONPolicyPrincipal] resource: [String] @search(by: [hash]) notAction: [String] @search(by: [hash]) diff --git a/src/services/iamRole/format.ts b/src/services/iamRole/format.ts index bcedff90..26fb18d7 100644 --- a/src/services/iamRole/format.ts +++ b/src/services/iamRole/format.ts @@ -26,6 +26,7 @@ export default ({ AssumeRolePolicyDocument: assumeRolePolicy = '', MaxSessionDuration: maxSessionDuration = 0, InlinePolicies: inlinePolicies = [], + ManagedPolicies: managedPolicies = [], Tags: tags = {}, } = rawData @@ -55,6 +56,10 @@ export default ({ document: formatIamJsonPolicy(inlinePolicyDocument), }) ) ?? [], + managedPolicies: managedPolicies.map(({ PolicyArn, PolicyName }) => ({ + policyArn: PolicyArn, + policyName: PolicyName, + })), tags: roleTags, } return role diff --git a/src/services/iamRole/schema.graphql b/src/services/iamRole/schema.graphql index 4919a018..0bcceff9 100644 --- a/src/services/iamRole/schema.graphql +++ b/src/services/iamRole/schema.graphql @@ -1,3 +1,13 @@ +type awsIamRoleAttachedPolicy + @generate( + query: { get: false, query: false, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + policyArn: String! @id @search(by: [hash, regexp]) + policyName: String @search(by: [hash, regexp]) +} + type awsIamRoleInlinePolicy @generate( query: { get: false, query: true, aggregate: false } @@ -20,6 +30,7 @@ type awsIamRole implements awsBaseService @key(fields: "id") { maxSessionDuration: Int @search tags: [awsRawTag] inlinePolicies: [awsIamRoleInlinePolicy] + managedPolicies: [awsIamRoleAttachedPolicy] cloudFormationStack: [awsCloudFormationStack] @hasInverse(field: iamRole) codebuilds: [awsCodebuild] @hasInverse(field: iamRoles) configurationRecorder: [awsConfigurationRecorder] @hasInverse(field: iamRole) diff --git a/src/services/iamUser/data.ts b/src/services/iamUser/data.ts index 6623150d..dec5eeab 100644 --- a/src/services/iamUser/data.ts +++ b/src/services/iamUser/data.ts @@ -131,7 +131,7 @@ const groupsByUsername = async ( if (!isEmpty(data)) { const { Groups = [] } = data - const userGroups = Groups.map(({ GroupId }) => GroupId) + const userGroups = Groups.map(({ GroupName }) => GroupName) resolve({ UserName, Groups: userGroups }) } diff --git a/src/services/iamUser/format.ts b/src/services/iamUser/format.ts index 23380da6..b08faded 100644 --- a/src/services/iamUser/format.ts +++ b/src/services/iamUser/format.ts @@ -27,6 +27,7 @@ export default ({ VirtualMFADevices: virtualMfaDevices = [], Groups: groups = [], Policies: inlinePolicies = [], + ManagedPolicies: managedPolicies = [], ReportData: { AccessKey1LastRotated: accessKey1LastRotated, AccessKey2LastRotated: accessKey2LastRotated, @@ -130,6 +131,10 @@ export default ({ mfaActive: mfaActive === 'true', groups, inlinePolicies, + managedPolicies: managedPolicies.map(({ PolicyArn, PolicyName }) => ({ + policyArn: PolicyArn, + policyName: PolicyName, + })), tags: userTags, } return user diff --git a/src/services/iamUser/schema.graphql b/src/services/iamUser/schema.graphql index b01a7141..91a55914 100644 --- a/src/services/iamUser/schema.graphql +++ b/src/services/iamUser/schema.graphql @@ -14,6 +14,7 @@ type awsIamUser implements awsOptionalService @key(fields: "id") { groups: [String] tags: [awsRawTag] inlinePolicies: [String] + managedPolicies: [awsIamAttachedPolicy] iamAttachedPolicies: [awsIamPolicy] @hasInverse(field: iamUsers) iamGroups: [awsIamGroup] @hasInverse(field: iamUsers) } @@ -42,3 +43,13 @@ type awsIamMfaDevice serialNumber: String! @id @search(by: [hash, regexp]) enableDate: String @search(by: [hash, regexp]) } + +type awsIamAttachedPolicy + @generate( + query: { get: false, query: false, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + policyArn: String! @id @search(by: [hash, regexp]) + policyName: String @search(by: [hash, regexp]) +} \ No newline at end of file diff --git a/src/services/index.ts b/src/services/index.ts index 5a42defc..c3620655 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -26,6 +26,7 @@ import { obfuscateSensitiveString } from '../utils/format' import { checkAndMergeConnections } from '../utils' import { Account, rawDataInterface } from './base' import enhancers, { EnhancerConfig } from './base/enhancers' +import AwsErrorLog from '../utils/errorLog' const DEFAULT_REGION = 'us-east-1' const DEFAULT_RESOURCES = Object.values(services).join(',') @@ -314,15 +315,16 @@ export default class Provider extends CloudGraph.Client { // MFA token support mfaCodeProvider: async () => { this.logger.debug('MFA token needed, requesting...') - const { mfaToken = '' }: { mfaToken: string } = await this.interface.prompt([ - { - type: 'input', - message: `Please enter the MFA token for ${profile}`, - name: 'mfaToken' - }, - ]) + const { mfaToken = '' }: { mfaToken: string } = + await this.interface.prompt([ + { + type: 'input', + message: `Please enter the MFA token for ${profile}`, + name: 'mfaToken', + }, + ]) return mfaToken - } + }, }) if (creds) { sts = new AWS.STS({ credentials: await credsFunction() }) @@ -454,7 +456,7 @@ export default class Provider extends CloudGraph.Client { * getSchema is used to get the schema for provider * @returns A string of graphql sub schemas */ - getSchema(): DocumentNode { + getSchema(): DocumentNode { const typesArray = loadFilesSync(path.join(__dirname), { recursive: true, extensions: ['graphql'], @@ -495,7 +497,7 @@ export default class Provider extends CloudGraph.Client { } private async getProfilesFromSharedConfig(): Promise { - let profiles = [] + const profiles = [] try { const filesObject = await loadSharedConfigFiles() const files = Object.keys(filesObject) @@ -861,11 +863,12 @@ export default class Provider extends CloudGraph.Client { } } - return this.enhanceData({ + const enhancedData = this.enhanceData({ accounts: accounts.data[globalRegion], configuredRegions, rawData: mergedRawData, data: result, }) + return { ...enhancedData, errors: AwsErrorLog.errorsHistory } } } diff --git a/src/services/kms/data.ts b/src/services/kms/data.ts index 15033778..74708d85 100644 --- a/src/services/kms/data.ts +++ b/src/services/kms/data.ts @@ -11,6 +11,7 @@ import KMS, { KeyMetadata, ListKeysRequest, ListKeysResponse, + GrantListEntry } from 'aws-sdk/clients/kms' import { TagMap } from '../../types' @@ -35,6 +36,7 @@ export type AwsKms = KeyListEntry & Tags: TagMap keyRotationEnabled: boolean Aliases?: AliasListEntry[] + Grants?: GrantListEntry[] } export default async ({ @@ -53,6 +55,7 @@ export default async ({ const policyPromises = [] const tagPromises = [] const aliasesPromises = [] + const grantsPromises = [] /** * Step 1) for all regions, list the kms keys @@ -373,11 +376,43 @@ export default async ({ resolveAliases() }) ) - aliasesPromises.push(aliasesPromise) + + const grantsPromise = new Promise(resolveGrants => + kms.listGrants({ KeyId }, (err, data) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'kms:listGrants', + err, + }) + resolveGrants() + } + + /** + * No grants data + */ + + if (isEmpty(data)) { + return resolveGrants() + } + + /** + * Add the grants to the key + */ + + const { Grants: grants } = data || {} + + kmsData[idx].Grants = grants + + resolveGrants() + }) + ) + + grantsPromises.push(grantsPromise) }) await Promise.all(aliasesPromises) + await Promise.all(grantsPromises) errorLog.reset() resolve(groupBy(kmsData, 'region')) diff --git a/src/services/kms/format.ts b/src/services/kms/format.ts index 415e1d0e..c1df2f95 100644 --- a/src/services/kms/format.ts +++ b/src/services/kms/format.ts @@ -1,10 +1,11 @@ import { generateUniqueId } from '@cloudgraph/sdk' -import { AliasListEntry } from 'aws-sdk/clients/kms' +import { AliasListEntry, GrantListEntry } from 'aws-sdk/clients/kms' import { AwsKms } from './data' import { AwsKms as AwsKmsType, AwsKmsAliasListEntry, + AwsKmsGrantListEntry, } from '../../types/generated' import { formatTagsFromMap, formatIamJsonPolicy } from '../../utils/format' @@ -38,6 +39,7 @@ export default ({ DeletionDate: deletionDate, ValidTo: validTo, Aliases: aliases = [], + Grants: grants = [] } = key const formatAliases = ( @@ -58,6 +60,27 @@ export default ({ ) } + const formatGrants = ( + grants?: GrantListEntry[] + ): AwsKmsGrantListEntry[] => { + return ( + grants?.map(a => ({ + id: generateUniqueId({ + arn, + ...a, + }), + grantId: a.GrantId, + name: a.Name, + creationDate: a.CreationDate?.toISOString(), + granteePrincipal: a.GranteePrincipal, + retiringPrincipal: a.RetiringPrincipal, + issuingAccount: a.IssuingAccount, + keyId: a.KeyId, + operations: a.Operations + })) || [] + ) + } + return { accountId: account, arn, @@ -78,5 +101,6 @@ export default ({ deletionDate: deletionDate?.toISOString(), validTo: validTo?.toISOString(), aliases: formatAliases(aliases), + grants: formatGrants(grants), } } diff --git a/src/services/kms/schema.graphql b/src/services/kms/schema.graphql index b20bfa7d..a01c922b 100644 --- a/src/services/kms/schema.graphql +++ b/src/services/kms/schema.graphql @@ -1,3 +1,20 @@ +type awsKmsGrantListEntry + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + grantId: String @search(by: [hash, regexp]) + keyId: String @search(by: [hash, regexp]) + name: String @search(by: [hash, regexp]) + creationDate: DateTime @search(by: [day]) + granteePrincipal: String @search(by: [hash, regexp]) + retiringPrincipal: String @search(by: [hash, regexp]) + issuingAccount: String @search(by: [hash, regexp]) + operations: [String] @search(by: [hash, regexp]) +} + type awsKmsAliasListEntry @generate( query: { get: false, query: true, aggregate: false } @@ -28,6 +45,7 @@ type awsKms implements awsBaseService @key(fields: "id") { deletionDate: DateTime @search(by: [day]) validTo: DateTime @search(by: [day]) aliases: [awsKmsAliasListEntry] + grants: [awsKmsGrantListEntry] lambda: [awsLambda] @hasInverse(field: kms) #change to plural cloudtrail: [awsCloudtrail] @hasInverse(field: kms) #change to plural redshiftCluster: [awsRedshiftCluster] @hasInverse(field: kms) #change to plural diff --git a/src/services/lambda/data.ts b/src/services/lambda/data.ts index 11fd6387..3cae7a18 100644 --- a/src/services/lambda/data.ts +++ b/src/services/lambda/data.ts @@ -9,7 +9,12 @@ import Lambda, { GetFunctionConcurrencyRequest, GetFunctionConcurrencyResponse, ReservedConcurrentExecutions, - GetPolicyResponse + GetPolicyResponse, + ListEventSourceMappingsResponse, + EventSourceMappingConfiguration, + ListFunctionEventInvokeConfigsResponse, + FunctionEventInvokeConfig, + Layer } from 'aws-sdk/clients/lambda' import { AWSError } from 'aws-sdk/lib/error' import { Config } from 'aws-sdk/lib/config' @@ -35,6 +40,9 @@ export interface RawAwsLambdaFunction extends FunctionConfiguration { Policy?: string RevisionId?: string } + EventSourceMappings?: EventSourceMappingConfiguration[] + EventInvokeConfigs?: FunctionEventInvokeConfig[] + Layers?: Layer[] } const listFunctionsForRegion = async ({ @@ -137,7 +145,7 @@ const getResourceTags = async (lambda: Lambda, arn: string): Promise => } }) - const getLambdaPolicy = async (lambda: Lambda, arn: string): Promise<{ Policy?: string; RevisionId?: string }> => +const getLambdaPolicy = async (lambda: Lambda, arn: string): Promise<{ Policy?: string; RevisionId?: string }> => new Promise(resolve => { try { lambda.getPolicy( @@ -159,6 +167,52 @@ const getResourceTags = async (lambda: Lambda, arn: string): Promise => } }) +const getEventSourceMappings = async (lambda: Lambda, arn: string): Promise => + new Promise(resolve => { + try { + lambda.listEventSourceMappings( + { FunctionName: arn }, + (err: AWSError, data: ListEventSourceMappingsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'lambda:listEventSourceMappings', + err, + }) + resolve([]) + } + const { EventSourceMappings = [] } = data || {} + + resolve(EventSourceMappings) + } + ) + } catch (error) { + resolve([]) + } + }) + +const getEventInvokeConfigs = async (lambda: Lambda, name: string): Promise => + new Promise(resolve => { + try { + lambda.listFunctionEventInvokeConfigs( + { FunctionName: name }, + (err: AWSError, data: ListFunctionEventInvokeConfigsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'lambda:listFunctionEventInvokeConfigs', + err, + }) + resolve([]) + } + const { FunctionEventInvokeConfigs = [] } = data || {} + + resolve(FunctionEventInvokeConfigs) + } + ) + } catch (error) { + resolve([]) + } + }) + export default async ({ regions, config, @@ -199,16 +253,22 @@ export default async ({ logger.debug(lt.fetchedLambdas(lambdaData.length)) // get all tags and policy for each Lambda - lambdaData.map(({ FunctionArn: arn, region }, idx) => { + lambdaData.map(({ FunctionArn: arn, region, FunctionName: name, Layers }, idx) => { const lambda = new Lambda({ ...config, region, endpoint }) - const tagsAndPolicyPromise = new Promise(async resolveData => { + + const additionalMetadataPromise = new Promise(async resolveData => { const envTags: TagMap = await getResourceTags(lambda, arn) lambdaData[idx].Tags = envTags const policy = await getLambdaPolicy(lambda, arn) lambdaData[idx].PolicyData = policy + const eventSourceMappings = await getEventSourceMappings(lambda, arn) + lambdaData[idx].EventSourceMappings = eventSourceMappings + const eventInvokeConfigs = await getEventInvokeConfigs(lambda, name) + lambdaData[idx].EventInvokeConfigs = eventInvokeConfigs + lambdaData[idx].Layers = Layers resolveData() }) - tagsPromises.push(tagsAndPolicyPromise) + tagsPromises.push(additionalMetadataPromise) }) logger.debug(lt.gettingLambdaTags) diff --git a/src/services/lambda/format.ts b/src/services/lambda/format.ts index 57caeef0..6e528ec1 100644 --- a/src/services/lambda/format.ts +++ b/src/services/lambda/format.ts @@ -1,8 +1,10 @@ +import { generateUniqueId } from '@cloudgraph/sdk' import isEmpty from 'lodash/isEmpty' import t from '../../properties/translations' -import { AwsLambda } from '../../types/generated' +import { AwsLambda, AwsLambdaEventInvokeConfig, AwsLambdaEventSourceMappings, AwsLambdaLayerVersion } from '../../types/generated' import { formatTagsFromMap, formatIamJsonPolicy } from '../../utils/format' import { RawAwsLambdaFunction } from './data' +import { EventSourceMappingConfiguration, FunctionEventInvokeConfig, Layer } from 'aws-sdk/clients/lambda' /** * Lambda @@ -33,6 +35,9 @@ export default ({ reservedConcurrentExecutions: rawReservedConcurrentExecutions, VpcConfig: vpcConfig, PolicyData: { Policy: policy = '', RevisionId: policyRevisionId = '' }, + EventSourceMappings: eventSourceMappings = [], + EventInvokeConfigs: eventInvokeConfigs = [], + Layers: layers = [] } = rawData const environmentVariables = [] const secretNames = [t.pass, t.secret, t.private, t.cert] @@ -68,10 +73,120 @@ export default ({ securityGroupIds: vpcConfig?.SecurityGroupIds, } + const formatEventSourceMappings = ( + eventSourceMappings?: EventSourceMappingConfiguration[] + ): AwsLambdaEventSourceMappings[] => { + return ( + eventSourceMappings?.map(e => ({ + id: generateUniqueId({ + arn, + ...e, + }), + uuid: e.UUID, + startingPosition: e.StartingPosition, + batchSize: e.BatchSize, + maximumBatchingWindowInSeconds: e.MaximumBatchingWindowInSeconds, + parallelizationFactor: e.ParallelizationFactor, + eventSourceArn: e.EventSourceArn, + filterCriteria: e.FilterCriteria?.Filters?.map(f => f.Pattern) || [], + functionArn: e.FunctionArn, + lastModified: e.LastModified?.toISOString(), + lastProcessingResult: e.LastProcessingResult, + state: e.State, + stateTransitionReason: e.StateTransitionReason, + destinationConfig: { + id: generateUniqueId({ + arn, + ...e.DestinationConfig, + + }), + OnSuccess: e.DestinationConfig?.OnSuccess?.Destination, + OnFailure: e.DestinationConfig?.OnFailure?.Destination + + }, + topics: e.Topics, + queues: e.Queues, + maximumRecordAgeInSeconds: e.MaximumRecordAgeInSeconds, + bisectBatchOnFunctionError: e.BisectBatchOnFunctionError, + maximumRetryAttempts: e.MaximumRetryAttempts, + tumblingWindowInSeconds: e.TumblingWindowInSeconds, + functionResponseTypes: e.FunctionResponseTypes, + amazonManagedKafkaEventSourceConfig: { + id: generateUniqueId({ + arn, + ...e.AmazonManagedKafkaEventSourceConfig + }), + consumerGroupId: e.AmazonManagedKafkaEventSourceConfig?.ConsumerGroupId + }, + selfManagedKafkaEventSourceConfig: { + id: generateUniqueId({ + arn, + ...e.SelfManagedKafkaEventSourceConfig + }), + consumerGroupId: e.SelfManagedKafkaEventSourceConfig?.ConsumerGroupId + } + })) || [] + ) + } + + const formatEventInvokeConfigs = ( + eventInvokeConfigs?: FunctionEventInvokeConfig[] + ): AwsLambdaEventInvokeConfig[] => { + return ( + eventInvokeConfigs?.map(e => ({ + id: generateUniqueId({ + arn, + ...e, + }), + lastModified: e.LastModified?.toISOString(), + functionArn: e.FunctionArn, + maximumRetryAttempts: e.MaximumRetryAttempts, + maximumEventAgeInSeconds: e.MaximumEventAgeInSeconds, + destinationConfig: { + id: generateUniqueId({ + arn, + ...e.DestinationConfig, + + }), + OnSuccess: e.DestinationConfig?.OnSuccess?.Destination, + OnFailure: e.DestinationConfig?.OnFailure?.Destination + } + })) || [] + ) + } + + const formatLayers = ( + layers?: Layer[] + ): AwsLambdaLayerVersion[] => { + return ( + layers?.map(l => { + const arnParts = l.Arn?.split(':') + // get layer name from arn:aws:lambda:_REGION_:_ACCOUNT_ID_:layer:_LAYER_NAME_:_LAYER_VERSION_ + const layerName = arnParts[arnParts.length - 2] + return ({ + id: generateUniqueId({ + arn, + ...l, + }), + arn: l.Arn, + name: layerName, + codeSize: l.CodeSize, + signingProfileVersionArn: l.SigningProfileVersionArn, + signingJobArn: l.SigningJobArn, + }) + }) || [] + ) + } + + const functionName = arn.split(':').pop() + const functionPolicy = formatIamJsonPolicy(policy) + const policyStatementIds = functionPolicy?.statement?.map(s => s.sid) ?? [] + return { accountId: account, arn, region, + name: functionName, description, handler, id: arn, @@ -88,7 +203,11 @@ export default ({ vpcConfig: formattedVpcConfig, policyRevisionId, rawPolicy: policy, - policy: formatIamJsonPolicy(policy), + policy: functionPolicy, + policyStatementIds, tags: formatTagsFromMap(Tags), + eventSourceMappings: formatEventSourceMappings(eventSourceMappings), + eventInvokeConfigs: formatEventInvokeConfigs(eventInvokeConfigs), + layers: formatLayers(layers) } } diff --git a/src/services/lambda/schema.graphql b/src/services/lambda/schema.graphql index b188fa08..af7270a4 100644 --- a/src/services/lambda/schema.graphql +++ b/src/services/lambda/schema.graphql @@ -1,5 +1,97 @@ +type awsLambdaEventSourceConfig + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + consumerGroupId: String @search(by: [hash, regexp]) +} + +type awsLambdaSourceAccessConfiguration + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + type: String @search(by: [hash, regexp]) + uri: String @search(by: [hash, regexp]) +} + +type awsLambdaDestinationConfig + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + OnSuccess: String @search(by: [hash, regexp]) + OnFailure: String @search(by: [hash, regexp]) +} + +type awsLambdaEventInvokeConfig + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + lastModified: DateTime @search(by: [day]) + functionArn: String @search(by: [hash, regexp]) + maximumRetryAttempts: Int + maximumEventAgeInSeconds: Int + destinationConfig: awsLambdaDestinationConfig +} + +type awsLambdaEventSourceMappings + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + uuid: String @search(by: [hash, regexp]) + startingPosition: String @search(by: [hash, regexp]) + batchSize: Int + maximumBatchingWindowInSeconds: Int + parallelizationFactor: Int + eventSourceArn: String @search(by: [hash, regexp]) + filterCriteria: [String] @search(by: [hash, regexp]) + functionArn: String @search(by: [hash, regexp]) + lastModified: DateTime @search(by: [day]) + lastProcessingResult: String @search(by: [hash, regexp]) + state: String @search(by: [hash, regexp]) + stateTransitionReason: String @search(by: [hash, regexp]) + destinationConfig: awsLambdaDestinationConfig + topics: [String] @search(by: [hash, regexp]) + queues: [String] @search(by: [hash, regexp]) + maximumRecordAgeInSeconds: Int + bisectBatchOnFunctionError: Boolean + maximumRetryAttempts: Int + tumblingWindowInSeconds: Int + functionResponseTypes: [String] @search(by: [hash, regexp]) + amazonManagedKafkaEventSourceConfig: awsLambdaEventSourceConfig + selfManagedKafkaEventSourceConfig: awsLambdaEventSourceConfig +} + +type awsLambdaLayerVersion + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + arn: String @search(by: [hash, regexp]) + name: String @search(by: [hash, regexp]) + codeSize: Float + signingProfileVersionArn: String @search(by: [hash, regexp]) + signingJobArn: String @search(by: [hash, regexp]) +} + type awsLambda implements awsBaseService @key(fields: "arn") { description: String @search(by: [hash, regexp, fulltext]) + name: String @search(by: [hash, regexp]) handler: String @search(by: [hash, regexp]) kmsKeyArn: String @search(by: [hash, regexp]) lastModified: String @search(by: [hash, regexp]) @@ -15,6 +107,10 @@ type awsLambda implements awsBaseService @key(fields: "arn") { policyRevisionId: String @search(by: [hash, regexp]) rawPolicy: String @search(by: [hash, regexp]) policy: awsIamJSONPolicy + policyStatementIds: [String] @search(by: [hash, regexp]) + eventSourceMappings: [awsLambdaEventSourceMappings] + eventInvokeConfigs: [awsLambdaEventInvokeConfig] + layers: [awsLambdaLayerVersion] tags: [awsRawTag] kms: [awsKms] @hasInverse(field: lambda) securityGroups: [awsSecurityGroup] @hasInverse(field: lambda) diff --git a/src/services/rdsDbInstance/data.ts b/src/services/rdsDbInstance/data.ts index 837f1b2e..cdd823d5 100644 --- a/src/services/rdsDbInstance/data.ts +++ b/src/services/rdsDbInstance/data.ts @@ -4,6 +4,8 @@ import RDS, { DBInstance, DescribeDBInstancesMessage, DBInstanceMessage, + DBSnapshotMessage, + DBSnapshot, } from 'aws-sdk/clients/rds' import { AWSError } from 'aws-sdk/lib/error' import groupBy from 'lodash/groupBy' @@ -57,6 +59,28 @@ const listDBInstancesForRegion = async (rds: RDS): Promise => listAllDBInstances() }) +const getInstanceSnapshots = async (rds: RDS, arn: string): Promise => + new Promise(resolve => { + try { + rds.describeDBSnapshots( + { DBInstanceIdentifier: arn }, + (err: AWSError, data: DBSnapshotMessage) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'rds:describeDBSnapshots', + err, + }) + return resolve([]) + } + const { DBSnapshots: snapshots = [] } = data || {} + resolve(snapshots) + } + ) + } catch (error) { + resolve([]) + } + }) + const getResourceTags = async (rds: RDS, arn: string): Promise => new Promise(resolve => { try { @@ -81,6 +105,7 @@ const getResourceTags = async (rds: RDS, arn: string): Promise => export interface RawAwsRdsDbInstance extends DBInstance { Tags?: TagMap + Snapshots?: DBSnapshot[] region: string } @@ -123,6 +148,7 @@ export default async ({ const rds = new RDS({ ...config, region, endpoint }) const tagsPromise = new Promise(async resolveTags => { rdsData[idx].Tags = await getResourceTags(rds, DBInstanceArn) + rdsData[idx].Snapshots = await getInstanceSnapshots(rds, DBInstanceArn) resolveTags() }) tagsPromises.push(tagsPromise) diff --git a/src/services/rdsDbInstance/format.ts b/src/services/rdsDbInstance/format.ts index dc5320df..4507f7aa 100644 --- a/src/services/rdsDbInstance/format.ts +++ b/src/services/rdsDbInstance/format.ts @@ -1,20 +1,23 @@ +import { generateUniqueId } from '@cloudgraph/sdk' + import upperFirst from 'lodash/upperFirst' import { RawAwsRdsDbInstance } from './data' -import { - AwsRdsDbInstance, +import { + AwsRdsDbInstance, AwsRdsDbInstanceGroupOption, AwsRdsDbInstanceParameterGroup, AwsRdsDbInstanceSnapshot, } from '../../types/generated' -import { formatTagsFromMap } from '../../utils/format' +import { convertAwsTagsToTagMap, formatTagsFromMap } from '../../utils/format' +import { AwsTag } from '../../types' export default ({ service, account, region -}: -{ - service: RawAwsRdsDbInstance - account: string - region: string -}): AwsRdsDbInstance => { +}: + { + service: RawAwsRdsDbInstance + account: string + region: string + }): AwsRdsDbInstance => { const { DBInstanceArn: arn, DBInstanceIdentifier: dBInstanceIdentifier, @@ -42,19 +45,96 @@ export default ({ Endpoint: endpoint, LicenseModel: licenseModel, Tags = {}, + Snapshots = [] } = service const subnetGroup = service.DBSubnetGroup?.DBSubnetGroupName || '' - const parameterGroup = service.DBParameterGroups.map( - ({ DBParameterGroupName, ParameterApplyStatus }) => - `${DBParameterGroupName} (${ParameterApplyStatus})` - ).join(' | ') + const parameterGroups: AwsRdsDbInstanceParameterGroup[] = service.DBParameterGroups.map( + (parameter) => { + const { DBParameterGroupName, ParameterApplyStatus } = parameter + return ({ + id: generateUniqueId({ + arn, + ...parameter + }), + description: `${DBParameterGroupName} (${ParameterApplyStatus})`, + name: DBParameterGroupName, + status: ParameterApplyStatus + }) + } + ) + + const optionsGroups: AwsRdsDbInstanceGroupOption[] = service.OptionGroupMemberships.map( + (option) => { + const { OptionGroupName, Status } = option + return ({ + id: generateUniqueId({ + arn, + ...option + }), + description: `${OptionGroupName} (${upperFirst(Status)})`, + groupName: OptionGroupName, + status: Status + }) + } + + ) + + const snapshots: AwsRdsDbInstanceSnapshot[] = Snapshots.map( + (snapshot) => { + const tags = convertAwsTagsToTagMap(snapshot.TagList as AwsTag[]) + return ({ + id: generateUniqueId({ + arn, + ...snapshot + }), + dBSnapshotIdentifier: snapshot.DBSnapshotIdentifier, + dBInstanceIdentifier: snapshot.DBInstanceIdentifier, + snapshotCreateTime: snapshot.SnapshotCreateTime?.toISOString(), + engine: snapshot.Engine, + allocatedStorage: snapshot.AllocatedStorage, + status: snapshot.Status, + port: snapshot.Port, + availabilityZone: snapshot.AvailabilityZone, + vpcId: snapshot.VpcId, + instanceCreateTime: snapshot.InstanceCreateTime?.toISOString(), + masterUsername: snapshot.MasterUsername, + engineVersion: snapshot.EngineVersion, + licenseModel: snapshot.LicenseModel, + snapshotType: snapshot.SnapshotType, + iops: snapshot.Iops, + optionGroupName: snapshot.OptionGroupName, + percentProgress: snapshot.PercentProgress, + sourceRegion: snapshot.SourceRegion, + sourceDBSnapshotIdentifier: snapshot.SourceDBSnapshotIdentifier, + storageType: snapshot.StorageType, + tdeCredentialArn: snapshot.TdeCredentialArn, + encrypted: snapshot.Encrypted, + kmsKeyId: snapshot.KmsKeyId, + dBSnapshotArn: snapshot.DBSnapshotArn, + timezone: snapshot.Timezone, + iAMDatabaseAuthenticationEnabled: snapshot.IAMDatabaseAuthenticationEnabled, + processorFeatures: snapshot.ProcessorFeatures?.map(p => ({ + id: generateUniqueId({ + arn, + ...p + }), + name: p.Name, + value: p.Value + })), + dbiResourceId: snapshot.DbiResourceId, + tagList: snapshot.TagList, + originalSnapshotCreateTime: snapshot.OriginalSnapshotCreateTime?.toISOString(), + snapshotDatabaseTime: snapshot.SnapshotDatabaseTime?.toISOString(), + snapshotTarget: snapshot.SnapshotTarget, + storageThroughput: snapshot.StorageThroughput, + tags: formatTagsFromMap(tags) + }) + } + ) + - const optionsGroups = service.OptionGroupMemberships.map( - ({ OptionGroupName, Status }) => - `${OptionGroupName} (${upperFirst(Status)})` - ).join(' | ') return { id: arn, @@ -77,7 +157,7 @@ export default ({ autoMinorVersionUpgrade, iamDbAuthenticationEnabled, optionsGroups, - parameterGroup, + parameterGroups, storageType, instanceClass, allocatedStorage, @@ -91,6 +171,7 @@ export default ({ kmsKey, encrypted, licenseModel, + snapshots, tags: formatTagsFromMap(Tags), } } diff --git a/src/services/rdsDbInstance/schema.graphql b/src/services/rdsDbInstance/schema.graphql index a08e72e8..4ae79b86 100644 --- a/src/services/rdsDbInstance/schema.graphql +++ b/src/services/rdsDbInstance/schema.graphql @@ -1,3 +1,69 @@ +type awsRdsDbInstanceParameterGroup { + id: String! @id + name: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + description: String @search(by: [hash, regexp]) +} + +type awsRdsDbInstanceGroupOption { + id: String! @id + groupName: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + description: String @search(by: [hash, regexp]) +} + +type awsRdsDbInstanceSnapshot { + id: String! @id + groupName: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + description: String @search(by: [hash, regexp]) +} + + +type awsRdsDbInstanceProcessorFeature { + id: String! @id + name: String @search(by: [hash, regexp]) + value: String @search(by: [hash, regexp]) +} + +type awsRdsDbInstanceSnapshot { + id: String! @id + dBSnapshotIdentifier: String @search(by: [hash, regexp]) + dBInstanceIdentifier: String @search(by: [hash, regexp]) + snapshotCreateTime: DateTime @search(by: [day]) + engine: String @search(by: [hash, regexp]) + allocatedStorage: Int @search + status: String @search(by: [hash, regexp]) + port: Int @search + availabilityZone: String @search(by: [hash, regexp]) + vpcId: String @search(by: [hash, regexp]) + instanceCreateTime: DateTime @search(by: [day]) + masterUsername: String @search(by: [hash, regexp]) + engineVersion: String @search(by: [hash, regexp]) + licenseModel: String @search(by: [hash, regexp]) + snapshotType: String @search(by: [hash, regexp]) + iops: Int @search + optionGroupName: String @search(by: [hash, regexp]) + percentProgress: Int @search + sourceRegion: String @search(by: [hash, regexp]) + sourceDBSnapshotIdentifier: String @search(by: [hash, regexp]) + storageType: String @search(by: [hash, regexp]) + tdeCredentialArn: String @search(by: [hash, regexp]) + encrypted: Boolean @search + kmsKeyId: String @search(by: [hash, regexp]) + dBSnapshotArn: String @search(by: [hash, regexp]) + timezone: String @search(by: [hash, regexp]) + iAMDatabaseAuthenticationEnabled: Boolean @search + processorFeatures: [awsRdsDbInstanceProcessorFeature] + dbiResourceId: String @search(by: [hash, regexp]) + tags: [awsRawTag] + originalSnapshotCreateTime: DateTime @search(by: [day]) + snapshotDatabaseTime: DateTime @search(by: [day]) + snapshotTarget: String @search(by: [hash, regexp]) + storageThroughput: Int @search +} + + type awsRdsDbInstance implements awsBaseService @key(fields: "arn") { name: String @search(by: [hash, regexp]) port: Int @search @@ -14,8 +80,8 @@ type awsRdsDbInstance implements awsBaseService @key(fields: "arn") { performanceInsightsEnabled: Boolean @search autoMinorVersionUpgrade: Boolean @search iamDbAuthenticationEnabled: Boolean @search - optionsGroups: String - parameterGroup: String + optionsGroups: [awsRdsDbInstanceGroupOption] + parameterGroups: [awsRdsDbInstanceParameterGroup] storageType: String @search(by: [hash, regexp]) instanceClass: String @search(by: [hash, regexp]) allocatedStorage: Int @search @@ -30,6 +96,7 @@ type awsRdsDbInstance implements awsBaseService @key(fields: "arn") { encrypted: Boolean @search licenseModel: String @search(by: [hash, regexp]) tags: [awsRawTag] + snapshots: [awsRdsDbInstanceSnapshot] cluster: [awsRdsCluster] @hasInverse(field: instances) kms: [awsKms] @hasInverse(field: rdsDbInstance) securityGroups: [awsSecurityGroup] @hasInverse(field: rdsDbInstance) diff --git a/src/services/rdsDbProxies/data.ts b/src/services/rdsDbProxies/data.ts new file mode 100644 index 00000000..1499607d --- /dev/null +++ b/src/services/rdsDbProxies/data.ts @@ -0,0 +1,97 @@ +import CloudGraph from '@cloudgraph/sdk' +import RDS, { + DescribeDBProxiesResponse, + DBProxy, + DescribeDBProxiesRequest +} from 'aws-sdk/clients/rds' +import { AWSError } from 'aws-sdk/lib/error' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import { Config } from 'aws-sdk/lib/config' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import awsLoggerText from '../../properties/logger' + + +const { logger } = CloudGraph +const lt = { ...awsLoggerText } +const serviceName = 'RDS DB Proxies' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +const listDBProxiesForRegion = async (rds: RDS): Promise => + new Promise(resolve => { + const proxies: DBProxy[] = [] + const descDBProxiesOpts: DescribeDBProxiesRequest = {} + const listProxies = (token?: string): void => { + if (token) { + descDBProxiesOpts.Marker = token + } + try { + rds.describeDBProxies( + descDBProxiesOpts, + (err: AWSError, data: DescribeDBProxiesResponse) => { + const { Marker, DBProxies = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'rds:describeDBProxies', + err, + }) + } + + proxies.push(...DBProxies) + + if (Marker) { + listProxies(Marker) + } else { + resolve(proxies) + } + } + ) + } catch (error) { + resolve([]) + } + } + listProxies() + }) + +export interface RawAwsRdsDbProxies extends DBProxy { + region: string +} + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsRdsDbProxies[] }> => + new Promise(async resolve => { + const rdsData: RawAwsRdsDbProxies[] = [] + const regionPromises = [] + + // Get all the proxies for the region + regions.split(',').map(region => { + const regionPromise = new Promise(async resolveRegion => { + const rds = new RDS({ ...config, region, endpoint }) + const subscriptions = await listDBProxiesForRegion(rds) + + if (!isEmpty(subscriptions)) { + rdsData.push( + ...subscriptions.map(subscription => ({ + ...subscription, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedRdsDbProxies(rdsData.length)) + + errorLog.reset() + resolve(groupBy(rdsData, 'region')) + }) diff --git a/src/services/rdsDbProxies/format.ts b/src/services/rdsDbProxies/format.ts new file mode 100644 index 00000000..79acadc8 --- /dev/null +++ b/src/services/rdsDbProxies/format.ts @@ -0,0 +1,81 @@ +import { UserAuthConfigInfo } from 'aws-sdk/clients/rds' +import { AwsRdsDbProxies, AwsRdsDbProxiesUserAuthConfigInfo } from '../../types/generated' +import { RawAwsRdsDbProxies } from './data' +import { generateUniqueId } from '@cloudgraph/sdk' + +/** + * RdsDbProxies + */ + +export default ({ + account, + service: rawData, + region, +}: { + account, + service: RawAwsRdsDbProxies + region, +}): AwsRdsDbProxies => { + const { + DBProxyName: dBProxyName, + DBProxyArn: arn, + Status: status, + EngineFamily: engineFamily, + VpcId: vpcId, + VpcSecurityGroupIds: vpcSecurityGroupIds = [], + VpcSubnetIds: vpcSubnetIds = [], + Auth: auth, + RoleArn: roleArn, + Endpoint: endpoint, + RequireTLS: requireTLS, + IdleClientTimeout: idleClientTimeout, + DebugLogging: debugLogging, + CreatedDate: createdDate, + UpdatedDate: updatedDate, + } = rawData + + + + const formatUserAuthConfigInfo = ( + configList?: UserAuthConfigInfo[] + ): AwsRdsDbProxiesUserAuthConfigInfo[] => { + return ( + configList?.map(c => ({ + id: generateUniqueId({ + arn, + ...c, + }), + description: c.Description, + userName: c.UserName, + authScheme: c.AuthScheme, + secretArn: c.SecretArn, + iAMAuth: c.IAMAuth, + clientPasswordAuthType: c.ClientPasswordAuthType + })) || [] + ) + } + + + + + return { + id: arn, + accountId: account, + region, + dBProxyName, + arn, + status, + engineFamily, + vpcId, + vpcSecurityGroupIds, + vpcSubnetIds, + auth: formatUserAuthConfigInfo(auth), + roleArn, + endpoint, + requireTLS, + idleClientTimeout, + debugLogging, + createdDate: createdDate.toISOString(), + updatedDate: updatedDate.toISOString(), + } +} diff --git a/src/services/rdsDbProxies/index.ts b/src/services/rdsDbProxies/index.ts new file mode 100644 index 00000000..aaf74ade --- /dev/null +++ b/src/services/rdsDbProxies/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class RdsDbProxies extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/rdsDbProxies/mutation.ts b/src/services/rdsDbProxies/mutation.ts new file mode 100644 index 00000000..19507181 --- /dev/null +++ b/src/services/rdsDbProxies/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsRdsDbProxiesInput!]!) { + addawsRdsDbProxies(input: $input, upsert: true) { + numUids + } +}`; \ No newline at end of file diff --git a/src/services/rdsDbProxies/schema.graphql b/src/services/rdsDbProxies/schema.graphql new file mode 100644 index 00000000..af5cbc77 --- /dev/null +++ b/src/services/rdsDbProxies/schema.graphql @@ -0,0 +1,32 @@ + +type awsRdsDbProxiesUserAuthConfigInfo + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + Description: String @search(by: [hash, regexp]) + UserName: String @search(by: [hash, regexp]) + AuthScheme: String @search(by: [hash, regexp]) + SecretArn: String @search(by: [hash, regexp]) + IAMAuth: String @search(by: [hash, regexp]) + ClientPasswordAuthType: String @search(by: [hash, regexp]) +} + +type awsRdsDbProxies implements awsBaseService @key(fields: "arn") { + dBProxyName: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + engineFamily: String @search(by: [hash, regexp]) + vpcId: String @search(by: [hash, regexp]) + vpcSecurityGroupIds: [String] @search(by: [hash]) + vpcSubnetIds: [String] @search(by: [hash]) + auth: [awsRdsDbProxiesUserAuthConfigInfo] + roleArn: String @search(by: [hash, regexp]) + endpoint: String @search(by: [hash, regexp]) + requireTLS: Boolean @search + idleClientTimeout: Int @search + debugLogging: Boolean @search + createdDate: DateTime @search(by: [day]) + updatedDate: DateTime @search(by: [day]) +} \ No newline at end of file diff --git a/src/services/rdsEventSubscription/data.ts b/src/services/rdsEventSubscription/data.ts new file mode 100644 index 00000000..79ebd96c --- /dev/null +++ b/src/services/rdsEventSubscription/data.ts @@ -0,0 +1,97 @@ +import CloudGraph from '@cloudgraph/sdk' +import RDS, { + EventSubscription, + EventSubscriptionsMessage, + DescribeEventSubscriptionsMessage +} from 'aws-sdk/clients/rds' +import { AWSError } from 'aws-sdk/lib/error' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import { Config } from 'aws-sdk/lib/config' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import awsLoggerText from '../../properties/logger' + + +const { logger } = CloudGraph +const lt = { ...awsLoggerText } +const serviceName = 'RDS Event Subscriptions' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +const listDBEventSubscriptionsForRegion = async (rds: RDS): Promise => + new Promise(resolve => { + const eventSubscriptions: EventSubscription[] = [] + const descDBInstancesOpts: DescribeEventSubscriptionsMessage = {} + const listEventSubscriptions = (token?: string): void => { + if (token) { + descDBInstancesOpts.Marker = token + } + try { + rds.describeEventSubscriptions( + descDBInstancesOpts, + (err: AWSError, data: EventSubscriptionsMessage) => { + const { Marker, EventSubscriptionsList = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'rds:describeEventSubscriptions', + err, + }) + } + + eventSubscriptions.push(...EventSubscriptionsList) + + if (Marker) { + listEventSubscriptions(Marker) + } else { + resolve(eventSubscriptions) + } + } + ) + } catch (error) { + resolve([]) + } + } + listEventSubscriptions() + }) + +export interface RawAwsRdsEventSubscription extends EventSubscription { + region: string +} + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsRdsEventSubscription[] }> => + new Promise(async resolve => { + const rdsData: RawAwsRdsEventSubscription[] = [] + const regionPromises = [] + + // Get all the events subscriptions for the region + regions.split(',').map(region => { + const regionPromise = new Promise(async resolveRegion => { + const rds = new RDS({ ...config, region, endpoint }) + const subscriptions = await listDBEventSubscriptionsForRegion(rds) + + if (!isEmpty(subscriptions)) { + rdsData.push( + ...subscriptions.map(subscription => ({ + ...subscription, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedRdsEventSubscriptions(rdsData.length)) + + errorLog.reset() + resolve(groupBy(rdsData, 'region')) + }) diff --git a/src/services/rdsEventSubscription/format.ts b/src/services/rdsEventSubscription/format.ts new file mode 100644 index 00000000..7476079e --- /dev/null +++ b/src/services/rdsEventSubscription/format.ts @@ -0,0 +1,45 @@ +import { AwsRdsEventSubscription } from '../../types/generated' +import { RawAwsRdsEventSubscription } from './data' + +/** + * RdsEventSubscription + */ + +export default ({ + account, + service: rawData, + region, +}: { + account, + service: RawAwsRdsEventSubscription + region, +}): AwsRdsEventSubscription => { + const { + EventSubscriptionArn: arn, + CustomerAwsId: customerAwsId, + CustSubscriptionId: custSubscriptionId, + SnsTopicArn: snsTopicArn, + Status: status, + SubscriptionCreationTime: subscriptionCreationTime, + SourceType: sourceType, + SourceIdsList: sourceIdsList = [], + EventCategoriesList: eventCategoriesList = [], + Enabled: enabled + } = rawData + + return { + id: arn, + accountId: account, + arn, + region, + customerAwsId, + custSubscriptionId, + snsTopicArn, + status, + subscriptionCreationTime, + sourceType, + sourceIdsList, + eventCategoriesList, + enabled + } +} diff --git a/src/services/rdsEventSubscription/index.ts b/src/services/rdsEventSubscription/index.ts new file mode 100644 index 00000000..d758c675 --- /dev/null +++ b/src/services/rdsEventSubscription/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class RdsEventSubscription extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/rdsEventSubscription/mutation.ts b/src/services/rdsEventSubscription/mutation.ts new file mode 100644 index 00000000..ff905695 --- /dev/null +++ b/src/services/rdsEventSubscription/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsRdsEventSubscriptionInput!]!) { + addawsRdsEventSubscription(input: $input, upsert: true) { + numUids + } +}`; \ No newline at end of file diff --git a/src/services/rdsEventSubscription/schema.graphql b/src/services/rdsEventSubscription/schema.graphql new file mode 100644 index 00000000..a3bcb7a8 --- /dev/null +++ b/src/services/rdsEventSubscription/schema.graphql @@ -0,0 +1,12 @@ +type awsRdsEventSubscription implements awsBaseService @key(fields: "arn") { + customerAwsId: String @search(by: [hash, regexp]) + custSubscriptionId: String @search(by: [hash, regexp]) + snsTopicArn: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + subscriptionCreationTime: String @search(by: [hash, regexp]) + sourceType: String @search(by: [hash, regexp]) + sourceIdsList: [String] @search(by: [hash]) + eventCategoriesList: [String] @search(by: [hash]) + enabled: Boolean @search +} + diff --git a/src/services/rdsGlobalCluster /data.ts b/src/services/rdsGlobalCluster /data.ts new file mode 100644 index 00000000..0eaf52bb --- /dev/null +++ b/src/services/rdsGlobalCluster /data.ts @@ -0,0 +1,99 @@ +import CloudGraph from '@cloudgraph/sdk' +import RDS, { + GlobalClustersMessage, + DescribeGlobalClustersMessage, + GlobalCluster, +} from 'aws-sdk/clients/rds' +import { AWSError } from 'aws-sdk/lib/error' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import { Config } from 'aws-sdk/lib/config' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' +import { initTestEndpoint } from '../../utils' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'RDS DB cluster' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +const listGlobalClustersForRegion = async (rds: RDS): Promise => + new Promise(resolve => { + const clusterList: GlobalCluster[] = [] + const descClustersOpts: DescribeGlobalClustersMessage = {} + const listAllClusters = (token?: string): void => { + if (token) { + descClustersOpts.Marker = token + } + try { + rds.describeGlobalClusters( + descClustersOpts, + (err: AWSError, data: GlobalClustersMessage) => { + const { Marker, GlobalClusters = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'rds:describeGlobalClusters', + err, + }) + } + + clusterList.push(...GlobalClusters) + + if (Marker) { + listAllClusters(Marker) + } else { + resolve(clusterList) + } + } + ) + } catch (error) { + resolve([]) + } + } + listAllClusters() + }) + + +export interface RawAwsRdsGlobalCluster extends GlobalCluster { + region: string +} + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsRdsGlobalCluster[] }> => + new Promise(async resolve => { + const rdsData: RawAwsRdsGlobalCluster[] = [] + const regionPromises = [] + const tagsPromises = [] + + // Get all the global clusters for the region + regions.split(',').map(region => { + const regionPromise = new Promise(async resolveRegion => { + const rds = new RDS({ ...config, region, endpoint }) + const clusters = await listGlobalClustersForRegion(rds) + + if (!isEmpty(clusters)) { + rdsData.push( + ...(await Promise.all( + clusters.map(async cluster => ({ + ...cluster, + region, + })) + )) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedRdsGlobalClusters(rdsData.length)) + errorLog.reset() + resolve(groupBy(rdsData, 'region')) + }) diff --git a/src/services/rdsGlobalCluster /format.ts b/src/services/rdsGlobalCluster /format.ts new file mode 100644 index 00000000..bc91a7d8 --- /dev/null +++ b/src/services/rdsGlobalCluster /format.ts @@ -0,0 +1,64 @@ +import { RawAwsRdsGlobalCluster } from './data' +import { AwsRdsGlobalCluster } from '../../types/generated' +import { generateUniqueId } from '@cloudgraph/sdk' + +export default ({ + service, + account, + region, +}: { + service: RawAwsRdsGlobalCluster + account: string + region: string +}): AwsRdsGlobalCluster => { + const { + GlobalClusterIdentifier: globalClusterIdentifier, + GlobalClusterResourceId: globalClusterResourceId, + GlobalClusterArn: arn, + Status: status, + Engine: engine, + EngineVersion: engineVersion, + DatabaseName: databaseName, + StorageEncrypted: storageEncrypted, + DeletionProtection: deletionProtection, + GlobalClusterMembers = [], + FailoverState = {}, + } = service + + + const failoverState = { + status: FailoverState.Status, + fromDbClusterArn: FailoverState.FromDbClusterArn, + toDbClusterArn: FailoverState.ToDbClusterArn, + } + + const globalClusterMembers = GlobalClusterMembers.map(gc => ({ + id: generateUniqueId({ + arn, + ...gc, + }), + dBClusterArn: gc.DBClusterArn, + isWriter: gc.IsWriter, + globalWriteForwardingStatus: gc.GlobalWriteForwardingStatus, + readers: gc.Readers ?? [], + })) + + + return { + id: arn, + accountId: account, + arn, + region, + globalClusterIdentifier, + globalClusterResourceId, + status, + engine, + engineVersion, + databaseName, + storageEncrypted, + deletionProtection, + globalClusterMembers, + failoverState, + + } +} diff --git a/src/services/rdsGlobalCluster /index.ts b/src/services/rdsGlobalCluster /index.ts new file mode 100644 index 00000000..5c388c3e --- /dev/null +++ b/src/services/rdsGlobalCluster /index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class RDSGlobalCluster extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/rdsGlobalCluster /mutation.ts b/src/services/rdsGlobalCluster /mutation.ts new file mode 100644 index 00000000..113ff049 --- /dev/null +++ b/src/services/rdsGlobalCluster /mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsRdsGlobalClusterInput!]!) { + addawsRdsGlobalCluster(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/rdsGlobalCluster /schema.graphql b/src/services/rdsGlobalCluster /schema.graphql new file mode 100644 index 00000000..441b41b4 --- /dev/null +++ b/src/services/rdsGlobalCluster /schema.graphql @@ -0,0 +1,33 @@ +type awsRdsGlobalClusterFailoverState { + status: String @search(by: [hash, regexp]) + fromDbClusterArn: String @search(by: [hash, regexp]) + toDbClusterArn: String @search(by: [hash, regexp]) +} + +type awsRdsGlobalClusterMembers + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + dBClusterArn: String @search(by: [hash, regexp]) + readers: [String] @search(by: [hash]) + isWriter: Boolean @search + globalWriteForwardingStatus: String @search(by: [hash, regexp]) +} + + +type awsRdsGlobalCluster implements awsBaseService @key(fields: "arn") { + globalClusterIdentifier: String @search(by: [hash, regexp]) + globalClusterResourceId: String @search(by: [hash, regexp]) + globalClusterArn: String @search(by: [hash, regexp]) + status: String @search(by: [hash, regexp]) + engine: String @search(by: [hash, regexp]) + engineVersion: String @search(by: [hash, regexp]) + databaseName: String @search(by: [hash, regexp]) + storageEncrypted: Boolean @search + deletionProtection: Boolean @search + globalClusterMembers: [awsRdsGlobalClusterMembers] + failoverState: awsRdsGlobalClusterFailoverState +} diff --git a/src/services/redshift/format.ts b/src/services/redshift/format.ts index 36e130a7..ffafc415 100644 --- a/src/services/redshift/format.ts +++ b/src/services/redshift/format.ts @@ -45,6 +45,7 @@ export default ({ id: arn, accountId: account, arn, + name: id, region, allowVersionUpgrade, automatedSnapshotRetentionPeriod, diff --git a/src/services/redshift/schema.graphql b/src/services/redshift/schema.graphql index 7d94fa1b..e1360f13 100644 --- a/src/services/redshift/schema.graphql +++ b/src/services/redshift/schema.graphql @@ -1,4 +1,5 @@ type awsRedshiftCluster implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) allowVersionUpgrade: Boolean @search automatedSnapshotRetentionPeriod: Int @search availabilityZone: String @search(by: [hash, regexp]) diff --git a/src/services/securityHubMember/data.ts b/src/services/securityHubMember/data.ts new file mode 100644 index 00000000..beb7822c --- /dev/null +++ b/src/services/securityHubMember/data.ts @@ -0,0 +1,100 @@ +import CloudGraph from '@cloudgraph/sdk' +import SecurityHub, { + ListMembersRequest, + ListMembersResponse, + Member, + MemberList, +} from 'aws-sdk/clients/securityhub' +import { AWSError } from 'aws-sdk/lib/error' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import { Config } from 'aws-sdk/lib/config' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import awsLoggerText from '../../properties/logger' + +const { logger } = CloudGraph +const lt = { ...awsLoggerText } +const serviceName = 'SecurityHub Member' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsSecurityHubMember extends Member { + region: string +} + +const getMembersForRegion = async ({ + securityHub, +}: { + securityHub: SecurityHub +}): Promise => + new Promise(resolve => { + const memberList: MemberList = [] + const listMemberOpts: ListMembersRequest = {} + const listAllMembers = (token?: string): void => { + if (token) { + listMemberOpts.NextToken = token + } + try { + securityHub.listMembers( + listMemberOpts, + (err: AWSError, data: ListMembersResponse) => { + const { NextToken: nextToken, Members = [] } = data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'securityHub:listMembers', + err, + }) + } + + memberList.push(...Members) + + if (nextToken) { + listAllMembers(nextToken) + } else { + resolve(memberList) + } + } + ) + } catch (err) { + resolve([]) + } + } + listAllMembers() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsSecurityHubMember[] }> => + new Promise(async resolve => { + const memberData: RawAwsSecurityHubMember[] = [] + const regionPromises = [] + + regions.split(',').forEach(region => { + const securityHub = new SecurityHub({ ...config, region, endpoint }) + + const regionPromise = new Promise(async resolveRegion => { + const members = await getMembersForRegion({ securityHub }) + if (!isEmpty(members)) { + memberData.push( + ...members.map(member => ({ + ...member, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug(lt.fetchedSecurityHubMembers(memberData.length)) + errorLog.reset() + + resolve(groupBy(memberData, 'region')) + }) diff --git a/src/services/securityHubMember/format.ts b/src/services/securityHubMember/format.ts new file mode 100644 index 00000000..8267dadd --- /dev/null +++ b/src/services/securityHubMember/format.ts @@ -0,0 +1,25 @@ +import { RawAwsSecurityHubMember } from './data' +import { AwsSecurityHubMember } from '../../types/generated' + +/** + * Security Hub Member + */ + +export default ({ + service, + account, + region, +}: { + service: RawAwsSecurityHubMember + account: string + region: string +}): AwsSecurityHubMember => { + const { AccountId: accountId } = service + + return { + id: accountId, + accountId: account, + arn: accountId, + region, + } +} diff --git a/src/services/securityHubMember/index.ts b/src/services/securityHubMember/index.ts new file mode 100644 index 00000000..9319b3ad --- /dev/null +++ b/src/services/securityHubMember/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class SecurityHubMember extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/securityHubMember/mutation.ts b/src/services/securityHubMember/mutation.ts new file mode 100644 index 00000000..b2f4c510 --- /dev/null +++ b/src/services/securityHubMember/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsSecurityHubMemberInput!]!) { + addawsSecurityHubMember(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/securityHubMember/schema.graphql b/src/services/securityHubMember/schema.graphql new file mode 100644 index 00000000..83218a4a --- /dev/null +++ b/src/services/securityHubMember/schema.graphql @@ -0,0 +1 @@ +type awsSecurityHubMember implements awsBaseService @key(fields: "arn") diff --git a/src/services/securityHubStandardSubscription/data.ts b/src/services/securityHubStandardSubscription/data.ts new file mode 100644 index 00000000..8b9245c6 --- /dev/null +++ b/src/services/securityHubStandardSubscription/data.ts @@ -0,0 +1,105 @@ +import CloudGraph from '@cloudgraph/sdk' +import SecurityHub, { + DescribeStandardsRequest, + DescribeStandardsResponse, + Standard, + Standards, +} from 'aws-sdk/clients/securityhub' +import { AWSError } from 'aws-sdk/lib/error' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' +import { Config } from 'aws-sdk/lib/config' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' +import awsLoggerText from '../../properties/logger' + +const { logger } = CloudGraph +const lt = { ...awsLoggerText } +const serviceName = 'SecurityHub Standard Subscription' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +export interface RawAwsSecurityHubStandardSubscription extends Standard { + region: string +} + +const getStandardSubscriptionForRegion = async ({ + securityHub, +}: { + securityHub: SecurityHub +}): Promise => + new Promise(resolve => { + const standardList: Standards = [] + const listStandardOpts: DescribeStandardsRequest = {} + const listAllStandards = (token?: string): void => { + if (token) { + listStandardOpts.NextToken = token + } + try { + securityHub.describeStandards( + listStandardOpts, + (err: AWSError, data: DescribeStandardsResponse) => { + const { NextToken: nextToken, Standards: standards = [] } = + data || {} + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'securityHub:describeStandards', + err, + }) + } + + standardList.push(...standards) + + if (nextToken) { + listAllStandards(nextToken) + } else { + resolve(standardList) + } + } + ) + } catch (err) { + resolve([]) + } + } + listAllStandards() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsSecurityHubStandardSubscription[] }> => + new Promise(async resolve => { + const standardData: RawAwsSecurityHubStandardSubscription[] = [] + const regionPromises = [] + + regions.split(',').forEach(region => { + const securityHub = new SecurityHub({ ...config, region, endpoint }) + + const regionPromise = new Promise(async resolveRegion => { + const standards = await getStandardSubscriptionForRegion({ + securityHub, + }) + if (!isEmpty(standards)) { + standardData.push( + ...standards.map(standard => ({ + ...standard, + region, + })) + ) + } + resolveRegion() + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + logger.debug( + lt.fetchedSecurityHubStandardSubscriptions(standardData.length) + ) + errorLog.reset() + + resolve(groupBy(standardData, 'region')) + }) diff --git a/src/services/securityHubStandardSubscription/format.ts b/src/services/securityHubStandardSubscription/format.ts new file mode 100644 index 00000000..2d2c469c --- /dev/null +++ b/src/services/securityHubStandardSubscription/format.ts @@ -0,0 +1,25 @@ +import { RawAwsSecurityHubStandardSubscription } from './data' +import { AwsSecurityHubStandardSubscription } from '../../types/generated' + +/** + * Security Hub Standard Subscription + */ + +export default ({ + service, + account, + region, +}: { + service: RawAwsSecurityHubStandardSubscription + account: string + region: string +}): AwsSecurityHubStandardSubscription => { + const { StandardsArn: arn } = service + + return { + id: arn, + accountId: account, + arn, + region, + } +} diff --git a/src/services/securityHubStandardSubscription/index.ts b/src/services/securityHubStandardSubscription/index.ts new file mode 100644 index 00000000..74fb4e7e --- /dev/null +++ b/src/services/securityHubStandardSubscription/index.ts @@ -0,0 +1,16 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class SecurityHubStandardSubscription + extends BaseService + implements Service +{ + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/securityHubStandardSubscription/mutation.ts b/src/services/securityHubStandardSubscription/mutation.ts new file mode 100644 index 00000000..4495652d --- /dev/null +++ b/src/services/securityHubStandardSubscription/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsSecurityHubStandardSubscriptionInput!]!) { + addawsSecurityHubStandardSubscription(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/securityHubStandardSubscription/schema.graphql b/src/services/securityHubStandardSubscription/schema.graphql new file mode 100644 index 00000000..65706a78 --- /dev/null +++ b/src/services/securityHubStandardSubscription/schema.graphql @@ -0,0 +1,2 @@ +type awsSecurityHubStandardSubscription implements awsBaseService + @key(fields: "arn") diff --git a/src/services/ses/data.ts b/src/services/ses/data.ts index c7a5c066..4258ddc2 100644 --- a/src/services/ses/data.ts +++ b/src/services/ses/data.ts @@ -1,14 +1,14 @@ import SES, { - ListIdentitiesResponse, - IdentityVerificationAttributes, - GetIdentityVerificationAttributesResponse, + ListConfigurationSetsResponse, + ConfigurationSet, + ListTemplatesResponse, + TemplateMetadata, } from 'aws-sdk/clients/ses' import { AWSError } from 'aws-sdk/lib/error' import { Config } from 'aws-sdk/lib/config' import CloudGraph from '@cloudgraph/sdk' import groupBy from 'lodash/groupBy' -import isEmpty from 'lodash/isEmpty' import awsLoggerText from '../../properties/logger' import { initTestEndpoint } from '../../utils' @@ -16,18 +16,62 @@ import AwsErrorLog from '../../utils/errorLog' const lt = { ...awsLoggerText } const { logger } = CloudGraph -const serviceName = 'SES' +const serviceName = 'SES ' const errorLog = new AwsErrorLog(serviceName) const endpoint = initTestEndpoint(serviceName) /** - * SES + * SES */ -export interface RawAwsSes extends IdentityVerificationAttributes { - Identity: string +export interface RawAwsSes { + ConfigurationSets: ConfigurationSet[] + EmailTemplates: TemplateMetadata[] region: string } + +const getEmailTemplates = async (ses: SES): Promise => + new Promise(resolve => { + try { + ses.listTemplates( + (err: AWSError, data: ListTemplatesResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ses:listTemplates', + err, + }) + return resolve([]) + } + const { TemplatesMetadata = [] } = data || {} + resolve(TemplatesMetadata) + } + ) + } catch (error) { + resolve([]) + } + }) + +const getConfigurationSets = async (ses: SES): Promise => + new Promise(resolve => { + try { + ses.listConfigurationSets( + (err: AWSError, data: ListConfigurationSetsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'ses:listConfigurationSets', + err, + }) + return resolve([]) + } + const { ConfigurationSets = [] } = data || {} + resolve(ConfigurationSets) + } + ) + } catch (error) { + resolve([]) + } + }) + export default async ({ regions, config, @@ -38,84 +82,28 @@ export default async ({ new Promise(async resolve => { const sesData: RawAwsSes[] = [] const regionPromises = [] - const identityVerificationPromises = [] regions.split(',').map(region => { - const regionPromise = new Promise(resolveRegion => { + const regionPromise = new Promise(async resolveRegion => { const ses = new SES({ ...config, region, endpoint }) - ses.listIdentities( - {}, - (err: AWSError, data: ListIdentitiesResponse) => { - /** - * No Data for the region - */ - if (isEmpty(data)) { - return resolveRegion() - } - - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'ses:listIdentities', - err, - }) - } - - const { Identities }: { Identities: string[] } = data - - /** - * No Identities Found - */ - - if (isEmpty(Identities)) { - return resolveRegion() - } - - logger.debug(lt.fetchedSesIdentities(Identities.length)) - - const identityVerificationPromise = new Promise( - resolveIdVer => { - ses.getIdentityVerificationAttributes( - { Identities }, - ( - err: AWSError, - { - VerificationAttributes: identities, - }: GetIdentityVerificationAttributesResponse - ) => { - if (err) { - errorLog.generateAwsErrorLog({ - functionName: 'ses:getIdentityVerificationAttributes', - err, - }) - } - - if (!isEmpty(identities)) { - sesData.push( - ...Identities.map(Identity => ({ - Identity, - ...identities[Identity], - region, - })) - ) - } - - resolveIdVer() - resolveRegion() - } - ) - } - ) - identityVerificationPromises.push(identityVerificationPromise) - } - ) + const configurationSets = await getConfigurationSets(ses) + const emailTemplates = await getEmailTemplates(ses) + + sesData.push({ + ConfigurationSets: configurationSets, + EmailTemplates: emailTemplates, + region + }) + resolveRegion() + + }) regionPromises.push(regionPromise) }) - await Promise.all(regionPromises) - await Promise.all(identityVerificationPromises) + await Promise.all(regionPromises) errorLog.reset() resolve(groupBy(sesData, 'region')) diff --git a/src/services/ses/format.ts b/src/services/ses/format.ts index 57efd188..a5104d04 100644 --- a/src/services/ses/format.ts +++ b/src/services/ses/format.ts @@ -1,32 +1,37 @@ import { RawAwsSes } from './data' import { AwsSes } from '../../types/generated' -import { sesArn } from '../../utils/generateArns' +import { generateUniqueId } from '@cloudgraph/sdk' /** - * SES + * SES */ -export default ({ +export default ({ service, account, region, -}:{ +}: { service: RawAwsSes account: string region: string }): AwsSes => { const { - Identity: email, - VerificationStatus: verificationStatus, + ConfigurationSets = [], + EmailTemplates = [], } = service - const arn = sesArn({region, account, email}) + + const configurationSets = ConfigurationSets.map(cs => cs.Name) + const emailTemplates = EmailTemplates.map(e => e.Name) return { - id: arn, + id: generateUniqueId({ + ...service, + account, + region + }), accountId: account, - arn, region, - email, - verificationStatus, + configurationSets, + emailTemplates, } } diff --git a/src/services/ses/schema.graphql b/src/services/ses/schema.graphql index 5ae942f1..179fa924 100644 --- a/src/services/ses/schema.graphql +++ b/src/services/ses/schema.graphql @@ -1,5 +1,4 @@ -type awsSes implements awsBaseService @key(fields: "arn") { - email: String @search(by: [hash, regexp]) - verificationStatus: String @search(by: [hash, regexp]) - cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: ses) +type awsSes implements awsOptionalService @key(fields: "id") { + configurationSets: [String] @search(by: [hash]) + emailTemplates: [String] @search(by: [hash]) } diff --git a/src/services/sesDomain/data.ts b/src/services/sesDomain/data.ts new file mode 100644 index 00000000..dff46a5a --- /dev/null +++ b/src/services/sesDomain/data.ts @@ -0,0 +1,125 @@ +import SES, { + ListIdentitiesResponse, + IdentityVerificationAttributes, + GetIdentityVerificationAttributesResponse, +} from 'aws-sdk/clients/ses' +import { AWSError } from 'aws-sdk/lib/error' +import { Config } from 'aws-sdk/lib/config' + +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' + +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'SES Domain' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +/** + * SES Domains + */ +export interface RawAwsSesDomain extends IdentityVerificationAttributes { + Identity: string + region: string +} + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsSesDomain[] }> => + new Promise(async resolve => { + const sesData: RawAwsSesDomain[] = [] + const regionPromises = [] + const identityVerificationPromises = [] + + regions.split(',').map(region => { + const regionPromise = new Promise(resolveRegion => { + const ses = new SES({ ...config, region, endpoint }) + + ses.listIdentities( + { IdentityType: 'Domain' }, + (err: AWSError, data: ListIdentitiesResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'sesDomain:listIdentities', + err, + }) + } + + /** + * No Data for the region + */ + if (isEmpty(data)) { + return resolveRegion() + } + + const { Identities }: { Identities: string[] } = data + + /** + * No Identities Found + */ + + if (isEmpty(Identities)) { + return resolveRegion() + } + + logger.debug(lt.fetchedSesIdentities(Identities.length)) + + const identityVerificationPromise = new Promise( + resolveIdVer => { + ses.getTemplate() + ses.getIdentityVerificationAttributes( + { Identities }, + ( + err: AWSError, + { + VerificationAttributes: identities, + }: GetIdentityVerificationAttributesResponse + ) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: + 'sesDomain:getIdentityVerificationAttributes', + err, + }) + } + + if (!isEmpty(identities)) { + sesData.push( + ...Identities.map(Identity => ({ + Identity, + ...identities[Identity], + region, + })) + ) + } + + resolveIdVer() + resolveRegion() + } + ) + ses.listConfigurationSets() + } + ) + identityVerificationPromises.push(identityVerificationPromise) + } + ) + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + + await Promise.all(identityVerificationPromises) + errorLog.reset() + + resolve(groupBy(sesData, 'region')) + }) diff --git a/src/services/sesDomain/format.ts b/src/services/sesDomain/format.ts new file mode 100644 index 00000000..1a55847c --- /dev/null +++ b/src/services/sesDomain/format.ts @@ -0,0 +1,32 @@ +import { RawAwsSesDomain } from './data' +import { AwsSesDomain } from '../../types/generated' +import { sesArn } from '../../utils/generateArns' + +/** + * SES Domain + */ + +export default ({ + service, + account, + region, +}: { + service: RawAwsSesDomain + account: string + region: string +}): AwsSesDomain => { + const { + Identity: domain, + VerificationStatus: verificationStatus, + } = service + const arn = sesArn({ region, account, identity: domain }) + + return { + id: arn, + accountId: account, + arn, + region, + domain, + verificationStatus, + } +} diff --git a/src/services/sesDomain/index.ts b/src/services/sesDomain/index.ts new file mode 100644 index 00000000..a9fb1eac --- /dev/null +++ b/src/services/sesDomain/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class SESDomain extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/sesDomain/mutation.ts b/src/services/sesDomain/mutation.ts new file mode 100644 index 00000000..2dd90db2 --- /dev/null +++ b/src/services/sesDomain/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsSesDomainInput!]!) { + addawsSesDomain(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/sesDomain/schema.graphql b/src/services/sesDomain/schema.graphql new file mode 100644 index 00000000..2312c72d --- /dev/null +++ b/src/services/sesDomain/schema.graphql @@ -0,0 +1,4 @@ +type awsSesDomain implements awsBaseService @key(fields: "arn") { + domain: String @search(by: [hash, regexp]) + verificationStatus: String @search(by: [hash, regexp]) +} diff --git a/src/services/sesEmail/data.ts b/src/services/sesEmail/data.ts new file mode 100644 index 00000000..7b07a33d --- /dev/null +++ b/src/services/sesEmail/data.ts @@ -0,0 +1,125 @@ +import SES, { + ListIdentitiesResponse, + IdentityVerificationAttributes, + GetIdentityVerificationAttributesResponse, +} from 'aws-sdk/clients/ses' +import { AWSError } from 'aws-sdk/lib/error' +import { Config } from 'aws-sdk/lib/config' + +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' +import isEmpty from 'lodash/isEmpty' + +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'SES Email' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +/** + * SES Email + */ +export interface RawAwsSesEmail extends IdentityVerificationAttributes { + Identity: string + region: string +} + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsSesEmail[] }> => + new Promise(async resolve => { + const sesData: RawAwsSesEmail[] = [] + const regionPromises = [] + const identityVerificationPromises = [] + + regions.split(',').map(region => { + const regionPromise = new Promise(resolveRegion => { + const ses = new SES({ ...config, region, endpoint }) + + ses.listIdentities( + { IdentityType: 'EmailAddress' }, + (err: AWSError, data: ListIdentitiesResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'sesEmail:listIdentities', + err, + }) + } + + /** + * No Data for the region + */ + if (isEmpty(data)) { + return resolveRegion() + } + + const { Identities }: { Identities: string[] } = data + + /** + * No Identities Found + */ + + if (isEmpty(Identities)) { + return resolveRegion() + } + + logger.debug(lt.fetchedSesIdentities(Identities.length)) + + const identityVerificationPromise = new Promise( + resolveIdVer => { + ses.getTemplate() + ses.getIdentityVerificationAttributes( + { Identities }, + ( + err: AWSError, + { + VerificationAttributes: identities, + }: GetIdentityVerificationAttributesResponse + ) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: + 'sesEmail:getIdentityVerificationAttributes', + err, + }) + } + + if (!isEmpty(identities)) { + sesData.push( + ...Identities.map(Identity => ({ + Identity, + ...identities[Identity], + region, + })) + ) + } + + resolveIdVer() + resolveRegion() + } + ) + ses.listConfigurationSets() + } + ) + identityVerificationPromises.push(identityVerificationPromise) + } + ) + }) + regionPromises.push(regionPromise) + }) + + await Promise.all(regionPromises) + + await Promise.all(identityVerificationPromises) + errorLog.reset() + + resolve(groupBy(sesData, 'region')) + }) diff --git a/src/services/sesEmail/format.ts b/src/services/sesEmail/format.ts new file mode 100644 index 00000000..69a1a0fd --- /dev/null +++ b/src/services/sesEmail/format.ts @@ -0,0 +1,32 @@ +import { RawAwsSesEmail } from './data' +import { AwsSesEmail } from '../../types/generated' +import { sesArn } from '../../utils/generateArns' + +/** + * SES Email + */ + +export default ({ + service, + account, + region, +}: { + service: RawAwsSesEmail + account: string + region: string +}): AwsSesEmail => { + const { + Identity: email, + VerificationStatus: verificationStatus, + } = service + const arn = sesArn({ region, account, identity: email }) + + return { + id: arn, + accountId: account, + arn, + region, + email, + verificationStatus, + } +} diff --git a/src/services/sesEmail/index.ts b/src/services/sesEmail/index.ts new file mode 100644 index 00000000..6024539b --- /dev/null +++ b/src/services/sesEmail/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class SESEmail extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/sesEmail/mutation.ts b/src/services/sesEmail/mutation.ts new file mode 100644 index 00000000..36e9372f --- /dev/null +++ b/src/services/sesEmail/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsSesEmailInput!]!) { + addawsSesEmail(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/sesEmail/schema.graphql b/src/services/sesEmail/schema.graphql new file mode 100644 index 00000000..dba07e62 --- /dev/null +++ b/src/services/sesEmail/schema.graphql @@ -0,0 +1,5 @@ +type awsSesEmail implements awsBaseService @key(fields: "arn") { + email: String @search(by: [hash, regexp]) + verificationStatus: String @search(by: [hash, regexp]) + cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: sesEmail) +} diff --git a/src/services/sesReceiptRuleSet/data.ts b/src/services/sesReceiptRuleSet/data.ts new file mode 100644 index 00000000..a5f3665d --- /dev/null +++ b/src/services/sesReceiptRuleSet/data.ts @@ -0,0 +1,116 @@ +import SES, { + ListReceiptRuleSetsResponse, + ReceiptRuleSetMetadata, + ReceiptRule, +} from 'aws-sdk/clients/ses' +import { AWSError } from 'aws-sdk/lib/error' +import { Config } from 'aws-sdk/lib/config' + +import CloudGraph from '@cloudgraph/sdk' +import groupBy from 'lodash/groupBy' + +import awsLoggerText from '../../properties/logger' +import { initTestEndpoint } from '../../utils' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'SES Receipt Rule Set' +const errorLog = new AwsErrorLog(serviceName) +const endpoint = initTestEndpoint(serviceName) + +/** + * SES Receipt Rule Set + */ + +export interface RawAwsSesReceiptRuleSet { + ReceiptRuleSet: ReceiptRuleSetMetadata + Rules: ReceiptRule[] + region: string +} + + +const getReceiptRuleSets = async (ses: SES): Promise => + new Promise(resolve => { + try { + ses.listReceiptRuleSets( + (err: AWSError, data: ListReceiptRuleSetsResponse) => { + if (err) { + errorLog.generateAwsErrorLog({ + functionName: 'sesReceiptRuleSet:listReceiptRuleSets', + err, + }) + return resolve([]) + } + const { RuleSets = [] } = data || {} + resolve(RuleSets) + } + ) + } catch (error) { + resolve([]) + } + }) + +const getReceiptRules = async (ses: SES, ruleSets: ReceiptRuleSetMetadata[]): Promise<{ ruleSet: ReceiptRuleSetMetadata, rules: ReceiptRule[] }[]> => { + const receiptRules: { ruleSet: ReceiptRuleSetMetadata, rules: ReceiptRule[] }[] = [] + for (const ruleSet of ruleSets) { + try { + const response = await ses.describeReceiptRuleSet({ + RuleSetName: ruleSet.Name, + }).promise() + const { Metadata, Rules = [] } = response + + receiptRules.push({ + ruleSet: Metadata, + rules: Rules + }) + } catch (error) { + errorLog.generateAwsErrorLog({ + functionName: 'sesReceiptRuleSet:describeReceiptRuleSet', + err: error, + }) + } + } + return receiptRules +} + + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsSesReceiptRuleSet[] }> => + new Promise(async resolve => { + const sesData: RawAwsSesReceiptRuleSet[] = [] + const regionPromises = [] + + regions.split(',').map(region => { + const regionPromise = new Promise(async resolveRegion => { + const ses = new SES({ ...config, region, endpoint }) + + const ruleSets = await getReceiptRuleSets(ses) + const receiptRuleSets = await getReceiptRules(ses, ruleSets) + + for (const { ruleSet, rules } of receiptRuleSets) { + sesData.push({ + ReceiptRuleSet: ruleSet, + Rules: rules, + region + }) + } + + resolveRegion() + + + }) + regionPromises.push(regionPromise) + }) + + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(sesData, 'region')) + }) diff --git a/src/services/sesReceiptRuleSet/format.ts b/src/services/sesReceiptRuleSet/format.ts new file mode 100644 index 00000000..e0aac2c2 --- /dev/null +++ b/src/services/sesReceiptRuleSet/format.ts @@ -0,0 +1,46 @@ +import { RawAwsSesReceiptRuleSet } from './data' +import { AwsSesReceiptRuleSet } from '../../types/generated' +import { generateUniqueId } from '@cloudgraph/sdk' + +/** + * SES Receipt Rule Set + */ + +export default ({ + service, + account, + region, +}: { + service: RawAwsSesReceiptRuleSet + account: string + region: string +}): AwsSesReceiptRuleSet => { + const { + ReceiptRuleSet, + Rules = [] + } = service + + const rules = Rules.map(r => ({ + id: generateUniqueId({ + ...r, + account, + region + }), + name: r.Name, + enabled: r.Enabled, + tlsPolicy: r.TlsPolicy, + scanEnabled: r.ScanEnabled + })) + + return { + id: generateUniqueId({ + ...service, + account, + region + }), + accountId: account, + region, + name: ReceiptRuleSet?.Name, + rules + } +} diff --git a/src/services/sesReceiptRuleSet/index.ts b/src/services/sesReceiptRuleSet/index.ts new file mode 100644 index 00000000..d6baa64b --- /dev/null +++ b/src/services/sesReceiptRuleSet/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class SESReceiptRuleSet extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/sesReceiptRuleSet/mutation.ts b/src/services/sesReceiptRuleSet/mutation.ts new file mode 100644 index 00000000..b6e188b5 --- /dev/null +++ b/src/services/sesReceiptRuleSet/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsSesReceiptRuleSetInput!]!) { + addawsSesReceiptRuleSet(input: $input, upsert: true) { + numUids + } +}` diff --git a/src/services/sesReceiptRuleSet/schema.graphql b/src/services/sesReceiptRuleSet/schema.graphql new file mode 100644 index 00000000..8ac918db --- /dev/null +++ b/src/services/sesReceiptRuleSet/schema.graphql @@ -0,0 +1,19 @@ +type awsSesReceiptRuleSetRule + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) { + id: String! @id + name: String @search(by: [hash, regexp]) + enabled: Boolean @search + tlsPolicy: String @search(by: [hash, regexp]) + scanEnabled: Boolean @search +} + + +type awsSesReceiptRuleSet implements awsOptionalService @key(fields: "id") { + accountId: String @search(by: [hash, regexp]) + name: String @search(by: [hash, regexp]) + rules: [awsSesReceiptRuleSetRule] +} diff --git a/src/services/systemsManagerParameter/data.ts b/src/services/systemsManagerParameter/data.ts new file mode 100644 index 00000000..2e462714 --- /dev/null +++ b/src/services/systemsManagerParameter/data.ts @@ -0,0 +1,92 @@ +import { + DescribeParametersCommand, + DescribeParametersCommandInput, + ParameterMetadata, + SSMClient, +} from '@aws-sdk/client-ssm' +import CloudGraph from '@cloudgraph/sdk' +import { Config } from 'aws-sdk' +import { groupBy } from 'lodash' +import isEmpty from 'lodash/isEmpty' +import awsLoggerText from '../../properties/logger' +import AwsErrorLog from '../../utils/errorLog' + +const lt = { ...awsLoggerText } +const { logger } = CloudGraph +const serviceName = 'SystemsManagerParameter' +const errorLog = new AwsErrorLog(serviceName) +const MAX_ITEMS = 50 + +export interface RawAwsParameterMetadata extends ParameterMetadata { + region: string +} + +const listParameters = async (ssm: SSMClient): Promise => + new Promise(async resolve => { + const parameters: ParameterMetadata[] = [] + + const input: DescribeParametersCommandInput = { + MaxResults: MAX_ITEMS, + } + + const listAllParameters = (token?: string): void => { + if (token) { + input.NextToken = token + } + const command = new DescribeParametersCommand(input) + ssm + .send(command) + .then(data => { + if (isEmpty(data)) { + return resolve([]) + } + + const { Parameters = [], NextToken: nextToken } = data || {} + + parameters.push(...Parameters) + + if (nextToken) { + logger.debug(lt.foundAnotherThousand) + listAllParameters(nextToken) + } else { + resolve(parameters) + } + }) + .catch(err => { + errorLog.generateAwsErrorLog({ + functionName: 'ssm:describeParameters', + err, + }) + resolve([]) + }) + } + listAllParameters() + }) + +export default async ({ + regions, + config, +}: { + regions: string + config: Config +}): Promise<{ [property: string]: RawAwsParameterMetadata[] }> => + new Promise(async resolve => { + const { credentials } = config + const paramsData: RawAwsParameterMetadata[] = [] + + const regionPromises = regions.split(',').map(async region => { + const ssm = new SSMClient({ + credentials, + region, + }) + const params = (await listParameters(ssm)) || [] + if (!isEmpty(params)) { + paramsData.push(...params.map(val => ({ ...val, region }))) + } + }) + + await Promise.all(regionPromises) + errorLog.reset() + + resolve(groupBy(paramsData, 'region')) + }) diff --git a/src/services/systemsManagerParameter/format.ts b/src/services/systemsManagerParameter/format.ts new file mode 100644 index 00000000..5376fdf4 --- /dev/null +++ b/src/services/systemsManagerParameter/format.ts @@ -0,0 +1,28 @@ +import { AwsSystemsManagerParameter } from '../../types/generated' +import { ssmParameterArn } from '../../utils/generateArns' +import { RawAwsParameterMetadata } from './data' + +/** + * Systems Manager Parameter + */ +export default ({ + account, + region, + service: parameter, +}: { + account: string + region: string + service: RawAwsParameterMetadata +}): AwsSystemsManagerParameter => { + const { Name: name } = parameter + + const arn = ssmParameterArn({ region, account, name }) + + return { + accountId: account, + arn, + id: arn, + name, + region, + } +} diff --git a/src/services/systemsManagerParameter/index.ts b/src/services/systemsManagerParameter/index.ts new file mode 100644 index 00000000..2ac721d8 --- /dev/null +++ b/src/services/systemsManagerParameter/index.ts @@ -0,0 +1,13 @@ +import { Service } from '@cloudgraph/sdk' +import BaseService from '../base' +import format from './format' +import getData from './data' +import mutation from './mutation' + +export default class SystemsManagerParameter extends BaseService implements Service { + format = format.bind(this) + + getData = getData.bind(this) + + mutation = mutation +} diff --git a/src/services/systemsManagerParameter/mutation.ts b/src/services/systemsManagerParameter/mutation.ts new file mode 100644 index 00000000..36be273f --- /dev/null +++ b/src/services/systemsManagerParameter/mutation.ts @@ -0,0 +1,5 @@ +export default `mutation($input: [AddawsSystemsManagerParameterInput!]!) { + addawsSystemsManagerParameter(input: $input, upsert: true) { + numUids + } +}`; diff --git a/src/services/systemsManagerParameter/schema.graphql b/src/services/systemsManagerParameter/schema.graphql new file mode 100644 index 00000000..7a04b95d --- /dev/null +++ b/src/services/systemsManagerParameter/schema.graphql @@ -0,0 +1,3 @@ +type awsSystemsManagerParameter implements awsBaseService @key(fields: "arn") { + name: String @search(by: [hash, regexp]) +} diff --git a/src/services/vpc/connections.ts b/src/services/vpc/connections.ts index 5f4547ee..2c1b99a6 100644 --- a/src/services/vpc/connections.ts +++ b/src/services/vpc/connections.ts @@ -149,7 +149,7 @@ export default ({ if (domains?.data?.[region]) { const dataAtRegion: RawAwsElasticSearchDomain[] = domains.data[ region - ].filter(({ VPCOptions }) => VPCOptions.VPCId === id) + ].filter(({ VPCOptions }) => VPCOptions?.VPCId === id) for (const domain of dataAtRegion) { connections.push({ diff --git a/src/types/generated.ts b/src/types/generated.ts index 0dbe8eb7..a956c55f 100644 --- a/src/types/generated.ts +++ b/src/types/generated.ts @@ -126,6 +126,11 @@ export type AwsStringMap = { value?: Maybe; }; +export type Target = { + arn?: Maybe; + id: Scalars['String']; +}; + export type AwsAccessLogSettings = { destinationArn?: Maybe; format?: Maybe; @@ -134,11 +139,14 @@ export type AwsAccessLogSettings = { export type AwsAccount = AwsOptionalService & { albs?: Maybe>>; + apiGatewayApiKeys?: Maybe>>; apiGatewayDomainNames?: Maybe>>; apiGatewayHttpApis?: Maybe>>; apiGatewayResources?: Maybe>>; apiGatewayRestApis?: Maybe>>; apiGatewayStages?: Maybe>>; + apiGatewayUsagePlans?: Maybe>>; + apiGatewayVpcLinks?: Maybe>>; appSync?: Maybe>>; asgs?: Maybe>>; athenaDataCatalogs?: Maybe>>; @@ -151,12 +159,18 @@ export type AwsAccount = AwsOptionalService & { cloudtrail?: Maybe>>; cloudwatch?: Maybe>>; cloudwatchLogs?: Maybe>>; + codeCommitRepository?: Maybe>>; + codePipelineWebhooks?: Maybe>>; + codePipelines?: Maybe>>; codebuilds?: Maybe>>; cognitoIdentityPool?: Maybe>>; cognitoUserPool?: Maybe>>; + configurationDeliveryChannels?: Maybe>>; configurationRecorders?: Maybe>>; + configurationRules?: Maybe>>; customerGateway?: Maybe>>; dmsReplicationInstances?: Maybe>>; + docdbCluster?: Maybe>>; dynamodb?: Maybe>>; ebs?: Maybe>>; ec2Instances?: Maybe>>; @@ -168,6 +182,7 @@ export type AwsAccount = AwsOptionalService & { ecsTaskSets?: Maybe>>; ecsTasks?: Maybe>>; efs?: Maybe>>; + efsAccessPoint?: Maybe>>; efsMountTarget?: Maybe>>; eip?: Maybe>>; eksClusters?: Maybe>>; @@ -181,8 +196,11 @@ export type AwsAccount = AwsOptionalService & { emrInstances?: Maybe>>; emrSteps?: Maybe>>; flowLogs?: Maybe>>; + glueCrawlers?: Maybe>>; + glueDatabases?: Maybe>>; glueJobs?: Maybe>>; glueRegistries?: Maybe>>; + glueTriggers?: Maybe>>; guardDutyDetectors?: Maybe>>; iamAccessAnalyzers?: Maybe>>; iamGroups?: Maybe>>; @@ -210,6 +228,9 @@ export type AwsAccount = AwsOptionalService & { rdsClusterSnapshots?: Maybe>>; rdsClusters?: Maybe>>; rdsDbInstances?: Maybe>>; + rdsDbProxies?: Maybe>>; + rdsEventSubscription?: Maybe>>; + rdsGlobalCluster?: Maybe>>; redshiftClusters?: Maybe>>; regions?: Maybe>>; route53HostedZones?: Maybe>>; @@ -222,12 +243,18 @@ export type AwsAccount = AwsOptionalService & { secretsManager?: Maybe>>; securityGroups?: Maybe>>; securityHub?: Maybe>>; + securityHubMember?: Maybe>>; + securityHubStandardSubscription?: Maybe>>; ses?: Maybe>>; + sesDomain?: Maybe>>; + sesEmail?: Maybe>>; + sesReceiptRuleSet?: Maybe>>; sns?: Maybe>>; sqs?: Maybe>>; subnets?: Maybe>>; systemsManagerDocuments?: Maybe>>; systemsManagerInstances?: Maybe>>; + systemsManagerParameters?: Maybe>>; transitGatewayAttachments?: Maybe>>; transitGatewayRouteTables?: Maybe>>; transitGateways?: Maybe>>; @@ -323,6 +350,11 @@ export type AwsAlbListenerSettings = { sslPolicy?: Maybe; }; +export type AwsApiGatewayApiKey = AwsBaseService & { + name?: Maybe; + value?: Maybe; +}; + export type AwsApiGatewayCors = { allowCredentials?: Maybe; allowHeaders?: Maybe>>; @@ -396,12 +428,16 @@ export type AwsApiGatewayResource = AwsBaseService & { export type AwsApiGatewayRestApi = AwsBaseService & { apiKeySource?: Maybe; + authorizers?: Maybe>>; binaryMediaTypes?: Maybe>>; createdDate?: Maybe; description?: Maybe; + documentationParts?: Maybe>>; domainNames?: Maybe>>; endpointConfiguration?: Maybe; + gatewayResponses?: Maybe>>; minimumCompressionSize?: Maybe; + models?: Maybe>>; policy?: Maybe; rawPolicy?: Maybe; resources?: Maybe>>; @@ -410,6 +446,30 @@ export type AwsApiGatewayRestApi = AwsBaseService & { tags?: Maybe>>; }; +export type AwsApiGatewayRestApiAuthorizer = { + authorizerUri?: Maybe; + id?: Maybe; + name?: Maybe; +}; + +export type AwsApiGatewayRestApiDocumentationPart = { + id?: Maybe; + location?: Maybe; + properties?: Maybe; +}; + +export type AwsApiGatewayRestApiDocumentationPartLocation = { + type?: Maybe; +}; + +export type AwsApiGatewayRestApiGatewayResponse = { + responseType?: Maybe; +}; + +export type AwsApiGatewayRestModel = { + name?: Maybe; +}; + export type AwsApiGatewayStage = AwsBaseService & { accessLogSettings?: Maybe; cacheCluster?: Maybe; @@ -432,6 +492,15 @@ export type AwsApiGatewayStageVariable = { value?: Maybe; }; +export type AwsApiGatewayUsagePlan = AwsBaseService & { + name?: Maybe; +}; + +export type AwsApiGatewayVpcLink = AwsBaseService & { + name?: Maybe; + targetArns?: Maybe>>; +}; + export type AwsAppSync = AwsBaseService & { additionalAuthenticationProviders?: Maybe>>; apiKeys?: Maybe>>; @@ -849,6 +918,7 @@ export type AwsCloudfront = AwsBaseService & { export type AwsCloudfrontCacheBehavior = { allowedMethods?: Maybe>>; + cachePolicyId?: Maybe; cachedMethods?: Maybe>>; compress?: Maybe; defaultTtl?: Maybe; @@ -995,12 +1065,19 @@ export type AwsCloudwatch = AwsBaseService & { threshold?: Maybe; }; +export type AwsCloudwatchDashboard = AwsBaseService; + export type AwsCloudwatchDimensions = { id: Scalars['String']; name?: Maybe; value?: Maybe; }; +export type AwsCloudwatchEventRule = AwsBaseService & { + eventBusName?: Maybe; + targets?: Maybe>>; +}; + export type AwsCloudwatchLog = { accountId: Scalars['String']; arn: Scalars['String']; @@ -1029,6 +1106,18 @@ export type AwsCodeBuildFilterGroup = { type?: Maybe; }; +export type AwsCodeCommitRepository = AwsBaseService & { + name?: Maybe; +}; + +export type AwsCodePipeline = AwsBaseService & { + name?: Maybe; +}; + +export type AwsCodePipelineWebhook = AwsBaseService & { + name?: Maybe; +}; + export type AwsCodebuild = AwsBaseService & { artifacts?: Maybe; badge?: Maybe; @@ -1267,7 +1356,7 @@ export type AwsCognitoUserPool = AwsBaseService & { name?: Maybe; policies?: Maybe; schemaAttributes?: Maybe>>; - ses?: Maybe>>; + sesEmail?: Maybe>>; smsAuthenticationMessage?: Maybe; smsConfigurationExternalId?: Maybe; smsConfigurationFailure?: Maybe; @@ -1328,6 +1417,10 @@ export type AwsCognitoUserPoolSchemaAttribute = { stringAttributeConstraintsMinValue?: Maybe; }; +export type AwsConfigurationDeliveryChannel = AwsBaseService & { + name?: Maybe; +}; + export type AwsConfigurationRecorder = AwsBaseService & { iamRole?: Maybe>>; name?: Maybe; @@ -1336,6 +1429,10 @@ export type AwsConfigurationRecorder = AwsBaseService & { status?: Maybe; }; +export type AwsConfigurationRule = AwsBaseService & { + name?: Maybe; +}; + export type AwsConnectionLogResponseOptions = { cloudwatchLogGroup?: Maybe; cloudwatchLogStream?: Maybe; @@ -1384,6 +1481,40 @@ export type AwsDmsReplicationInstance = AwsBaseService & { vpcSecurityGroups?: Maybe>>; }; +export type AwsDocdbCluster = AwsBaseService & { + availabilityZones?: Maybe>>; + backupRetentionPeriod?: Maybe; + cloneGroupId?: Maybe; + clusterCreateTime?: Maybe; + dBClusterArn?: Maybe; + dBClusterIdentifier?: Maybe; + dBClusterMembers?: Maybe>>; + dBClusterParameterGroup?: Maybe; + dBSubnetGroup?: Maybe; + dbClusterResourceId?: Maybe; + deletionProtection?: Maybe; + earliestRestorableTime?: Maybe; + endpoint?: Maybe; + engine?: Maybe; + engineVersion?: Maybe; + hostedZoneId?: Maybe; + kmsKeyId?: Maybe; + latestRestorableTime?: Maybe; + masterUsername?: Maybe; + multiAZ?: Maybe; + nabledCloudwatchLogsExports?: Maybe>>; + percentProgress?: Maybe; + port?: Maybe; + preferredBackupWindow?: Maybe; + preferredMaintenanceWindow?: Maybe; + readReplicaIdentifiers?: Maybe>>; + readerEndpoint?: Maybe; + replicationSourceIdentifier?: Maybe; + status?: Maybe; + storageEncrypted?: Maybe; + vpcSecurityGroups?: Maybe>>; +}; + export type AwsDynamoDbTable = AwsBaseService & { appSync?: Maybe>>; attributes?: Maybe>>; @@ -1671,8 +1802,10 @@ export type AwsEcr = AwsBaseService & { encryptionConfig?: Maybe; imageScanOnPush?: Maybe; imageTagMutability?: Maybe; + lifecyclePolicy?: Maybe; name?: Maybe; registryAccountId?: Maybe; + repositoryPolicy?: Maybe; repositoryUri?: Maybe; scanOnPush?: Maybe; tags?: Maybe>>; @@ -1683,6 +1816,18 @@ export type AwsEcrEncryptionConfiguration = { type?: Maybe; }; +export type AwsEcrLifecyclePolicy = { + lifecyclePolicyText?: Maybe; + registryId?: Maybe; + repositoryName?: Maybe; +}; + +export type AwsEcrRepositoryPolicy = { + policyText?: Maybe; + registryId?: Maybe; + repositoryName?: Maybe; +}; + export type AwsEcsAttachment = { details?: Maybe>>; id: Scalars['String']; @@ -2083,6 +2228,8 @@ export type AwsEcsSecret = { export type AwsEcsService = AwsBaseService & { capacityProviderStrategy?: Maybe>>; + clusterArn?: Maybe; + clusterName?: Maybe; createdAt?: Maybe; createdBy?: Maybe; deploymentConfiguration?: Maybe; @@ -2309,12 +2456,17 @@ export type AwsEfs = AwsBaseService & { numberOfMountTargets?: Maybe; ownerId?: Maybe; performanceMode?: Maybe; + policy?: Maybe; provisionedThroughputInMibps?: Maybe; sizeInBytes?: Maybe; tags?: Maybe>>; throughputMode?: Maybe; }; +export type AwsEfsAccessPoint = AwsBaseService & { + name?: Maybe; +}; + export type AwsEfsEfsAuthorizationConfig = { accessPointId?: Maybe; iam?: Maybe; @@ -2376,6 +2528,7 @@ export type AwsEksCluster = AwsBaseService & { kubernetesNetworkConfig?: Maybe; logging?: Maybe; name?: Maybe; + nodeGroups?: Maybe>>; platformVersion?: Maybe; resourcesVpcConfig?: Maybe; securityGroups?: Maybe>>; @@ -2996,6 +3149,16 @@ export type AwsFlowLog = AwsBaseService & { vpc?: Maybe>>; }; +export type AwsGlueCrawler = AwsBaseService & { + name?: Maybe; +}; + +export type AwsGlueDatabase = AwsBaseService & { + catalogId?: Maybe; + name?: Maybe; + tables?: Maybe>>; +}; + export type AwsGlueJob = AwsBaseService & { allocatedCapacity?: Maybe; command?: Maybe; @@ -3058,6 +3221,10 @@ export type AwsGlueRegistrySchema = { schemaStatus?: Maybe; }; +export type AwsGlueTrigger = AwsBaseService & { + name?: Maybe; +}; + export type AwsGuardDutyDataSource = { status?: Maybe; }; @@ -3113,14 +3280,25 @@ export type AwsIamAccessKey = { status?: Maybe; }; +export type AwsIamAttachedPolicy = { + policyArn: Scalars['String']; + policyName?: Maybe; +}; + export type AwsIamGroup = AwsBaseService & { iamAttachedPolicies?: Maybe>>; iamUsers?: Maybe>>; inlinePolicies?: Maybe>>; + managedPolicies?: Maybe>>; name?: Maybe; path?: Maybe; }; +export type AwsIamGroupAttachedPolicy = { + policyArn: Scalars['String']; + policyName?: Maybe; +}; + export type AwsIamInstanceProfile = AwsBaseService & { createDate?: Maybe; ec2Instances?: Maybe>>; @@ -3159,6 +3337,7 @@ export type AwsIamJsonPolicyStatement = { notResource?: Maybe>>; principal?: Maybe>>; resource?: Maybe>>; + sid?: Maybe; }; export type AwsIamMfaDevice = { @@ -3236,6 +3415,7 @@ export type AwsIamRole = AwsBaseService & { lambda?: Maybe>>; lastUsedDate?: Maybe; managedAirflows?: Maybe>>; + managedPolicies?: Maybe>>; maxSessionDuration?: Maybe; name?: Maybe; path?: Maybe; @@ -3248,6 +3428,11 @@ export type AwsIamRole = AwsBaseService & { tags?: Maybe>>; }; +export type AwsIamRoleAttachedPolicy = { + policyArn: Scalars['String']; + policyName?: Maybe; +}; + export type AwsIamRoleInlinePolicy = { document?: Maybe; id: Scalars['String']; @@ -3276,6 +3461,7 @@ export type AwsIamUser = AwsOptionalService & { iamAttachedPolicies?: Maybe>>; iamGroups?: Maybe>>; inlinePolicies?: Maybe>>; + managedPolicies?: Maybe>>; mfaActive?: Maybe; mfaDevices?: Maybe>>; name?: Maybe; @@ -3375,6 +3561,7 @@ export type AwsKms = AwsBaseService & { elasticSearchDomains?: Maybe>>; emrCluster?: Maybe>>; enabled?: Maybe; + grants?: Maybe>>; keyManager?: Maybe; keyRotationEnabled?: Maybe; keyState?: Maybe; @@ -3405,19 +3592,36 @@ export type AwsKmsAliasListEntry = { targetKeyId?: Maybe; }; +export type AwsKmsGrantListEntry = { + creationDate?: Maybe; + grantId?: Maybe; + granteePrincipal?: Maybe; + id: Scalars['String']; + issuingAccount?: Maybe; + keyId?: Maybe; + name?: Maybe; + operations?: Maybe>>; + retiringPrincipal?: Maybe; +}; + export type AwsLambda = AwsBaseService & { appSync?: Maybe>>; cognitoUserPools?: Maybe>>; description?: Maybe; environmentVariables?: Maybe>>; + eventInvokeConfigs?: Maybe>>; + eventSourceMappings?: Maybe>>; handler?: Maybe; iamRole?: Maybe>>; kms?: Maybe>>; kmsKeyArn?: Maybe; lastModified?: Maybe; + layers?: Maybe>>; memorySize?: Maybe; + name?: Maybe; policy?: Maybe; policyRevisionId?: Maybe; + policyStatementIds?: Maybe>>; rawPolicy?: Maybe; reservedConcurrentExecutions?: Maybe; runtime?: Maybe; @@ -3434,12 +3638,73 @@ export type AwsLambda = AwsBaseService & { vpcConfig?: Maybe; }; +export type AwsLambdaDestinationConfig = { + OnFailure?: Maybe; + OnSuccess?: Maybe; + id: Scalars['String']; +}; + export type AwsLambdaEnvironmentVariable = { id: Scalars['String']; key: Scalars['String']; value?: Maybe; }; +export type AwsLambdaEventInvokeConfig = { + destinationConfig?: Maybe; + functionArn?: Maybe; + id: Scalars['String']; + lastModified?: Maybe; + maximumEventAgeInSeconds?: Maybe; + maximumRetryAttempts?: Maybe; +}; + +export type AwsLambdaEventSourceConfig = { + consumerGroupId?: Maybe; + id: Scalars['String']; +}; + +export type AwsLambdaEventSourceMappings = { + amazonManagedKafkaEventSourceConfig?: Maybe; + batchSize?: Maybe; + bisectBatchOnFunctionError?: Maybe; + destinationConfig?: Maybe; + eventSourceArn?: Maybe; + filterCriteria?: Maybe>>; + functionArn?: Maybe; + functionResponseTypes?: Maybe>>; + id: Scalars['String']; + lastModified?: Maybe; + lastProcessingResult?: Maybe; + maximumBatchingWindowInSeconds?: Maybe; + maximumRecordAgeInSeconds?: Maybe; + maximumRetryAttempts?: Maybe; + parallelizationFactor?: Maybe; + queues?: Maybe>>; + selfManagedKafkaEventSourceConfig?: Maybe; + startingPosition?: Maybe; + state?: Maybe; + stateTransitionReason?: Maybe; + topics?: Maybe>>; + tumblingWindowInSeconds?: Maybe; + uuid?: Maybe; +}; + +export type AwsLambdaLayerVersion = { + arn?: Maybe; + codeSize?: Maybe; + id: Scalars['String']; + name?: Maybe; + signingJobArn?: Maybe; + signingProfileVersionArn?: Maybe; +}; + +export type AwsLambdaSourceAccessConfiguration = { + id: Scalars['String']; + type?: Maybe; + uri?: Maybe; +}; + export type AwsLambdaVpcConfig = { securityGroupIds?: Maybe>>; subnetIds?: Maybe>>; @@ -3942,14 +4207,15 @@ export type AwsRdsDbInstance = AwsBaseService & { licenseModel?: Maybe; multiAZ?: Maybe; name?: Maybe; - optionsGroups?: Maybe; - parameterGroup?: Maybe; + optionsGroups?: Maybe>>; + parameterGroups?: Maybe>>; performanceInsightsEnabled?: Maybe; port?: Maybe; publiclyAccessible?: Maybe; resourceId?: Maybe; route53HostedZone?: Maybe>>; securityGroups?: Maybe>>; + snapshots?: Maybe>>; status?: Maybe; storageType?: Maybe; subnet?: Maybe>>; @@ -3959,6 +4225,132 @@ export type AwsRdsDbInstance = AwsBaseService & { vpc?: Maybe>>; }; +export type AwsRdsDbInstanceGroupOption = { + description?: Maybe; + groupName?: Maybe; + id: Scalars['String']; + status?: Maybe; +}; + +export type AwsRdsDbInstanceParameterGroup = { + description?: Maybe; + id: Scalars['String']; + name?: Maybe; + status?: Maybe; +}; + +export type AwsRdsDbInstanceProcessorFeature = { + id: Scalars['String']; + name?: Maybe; + value?: Maybe; +}; + +export type AwsRdsDbInstanceSnapshot = { + allocatedStorage?: Maybe; + availabilityZone?: Maybe; + dBInstanceIdentifier?: Maybe; + dBSnapshotArn?: Maybe; + dBSnapshotIdentifier?: Maybe; + dbiResourceId?: Maybe; + description?: Maybe; + encrypted?: Maybe; + engine?: Maybe; + engineVersion?: Maybe; + groupName?: Maybe; + iAMDatabaseAuthenticationEnabled?: Maybe; + id: Scalars['String']; + instanceCreateTime?: Maybe; + iops?: Maybe; + kmsKeyId?: Maybe; + licenseModel?: Maybe; + masterUsername?: Maybe; + optionGroupName?: Maybe; + originalSnapshotCreateTime?: Maybe; + percentProgress?: Maybe; + port?: Maybe; + processorFeatures?: Maybe>>; + snapshotCreateTime?: Maybe; + snapshotDatabaseTime?: Maybe; + snapshotTarget?: Maybe; + snapshotType?: Maybe; + sourceDBSnapshotIdentifier?: Maybe; + sourceRegion?: Maybe; + status?: Maybe; + storageThroughput?: Maybe; + storageType?: Maybe; + tags?: Maybe>>; + tdeCredentialArn?: Maybe; + timezone?: Maybe; + vpcId?: Maybe; +}; + +export type AwsRdsDbProxies = AwsBaseService & { + auth?: Maybe>>; + createdDate?: Maybe; + dBProxyName?: Maybe; + debugLogging?: Maybe; + endpoint?: Maybe; + engineFamily?: Maybe; + idleClientTimeout?: Maybe; + requireTLS?: Maybe; + roleArn?: Maybe; + status?: Maybe; + updatedDate?: Maybe; + vpcId?: Maybe; + vpcSecurityGroupIds?: Maybe>>; + vpcSubnetIds?: Maybe>>; +}; + +export type AwsRdsDbProxiesUserAuthConfigInfo = { + AuthScheme?: Maybe; + ClientPasswordAuthType?: Maybe; + Description?: Maybe; + IAMAuth?: Maybe; + SecretArn?: Maybe; + UserName?: Maybe; + id: Scalars['String']; +}; + +export type AwsRdsEventSubscription = AwsBaseService & { + custSubscriptionId?: Maybe; + customerAwsId?: Maybe; + enabled?: Maybe; + eventCategoriesList?: Maybe>>; + snsTopicArn?: Maybe; + sourceIdsList?: Maybe>>; + sourceType?: Maybe; + status?: Maybe; + subscriptionCreationTime?: Maybe; +}; + +export type AwsRdsGlobalCluster = AwsBaseService & { + databaseName?: Maybe; + deletionProtection?: Maybe; + engine?: Maybe; + engineVersion?: Maybe; + failoverState?: Maybe; + globalClusterArn?: Maybe; + globalClusterIdentifier?: Maybe; + globalClusterMembers?: Maybe>>; + globalClusterResourceId?: Maybe; + status?: Maybe; + storageEncrypted?: Maybe; +}; + +export type AwsRdsGlobalClusterFailoverState = { + fromDbClusterArn?: Maybe; + status?: Maybe; + toDbClusterArn?: Maybe; +}; + +export type AwsRdsGlobalClusterMembers = { + dBClusterArn?: Maybe; + globalWriteForwardingStatus?: Maybe; + id: Scalars['String']; + isWriter?: Maybe; + readers?: Maybe>>; +}; + export type AwsRecorderStatus = { lastStartTime?: Maybe; lastStatus?: Maybe; @@ -3991,6 +4383,7 @@ export type AwsRedshiftCluster = AwsBaseService & { manualSnapshotRetentionPeriod?: Maybe; masterUsername?: Maybe; modifyStatus?: Maybe; + name?: Maybe; nodeType?: Maybe; numberOfNodes?: Maybe; preferredMaintenanceWindow?: Maybe; @@ -4258,6 +4651,10 @@ export type AwsSecurityHub = AwsBaseService & { subscribedAt?: Maybe; }; +export type AwsSecurityHubMember = AwsBaseService; + +export type AwsSecurityHubStandardSubscription = AwsBaseService; + export type AwsServiceBillingInfo = { cost?: Maybe; currency?: Maybe; @@ -4265,12 +4662,36 @@ export type AwsServiceBillingInfo = { name: Scalars['String']; }; -export type AwsSes = AwsBaseService & { +export type AwsSes = AwsOptionalService & { + configurationSets?: Maybe>>; + emailTemplates?: Maybe>>; +}; + +export type AwsSesDomain = AwsBaseService & { + domain?: Maybe; + verificationStatus?: Maybe; +}; + +export type AwsSesEmail = AwsBaseService & { cognitoUserPools?: Maybe>>; email?: Maybe; verificationStatus?: Maybe; }; +export type AwsSesReceiptRuleSet = AwsOptionalService & { + accountId?: Maybe; + name?: Maybe; + rules?: Maybe>>; +}; + +export type AwsSesReceiptRuleSetRule = { + enabled?: Maybe; + id: Scalars['String']; + name?: Maybe; + scanEnabled?: Maybe; + tlsPolicy?: Maybe; +}; + export type AwsSgInboundRule = { description?: Maybe; fromPort?: Maybe; @@ -4456,6 +4877,10 @@ export type AwsSystemsManagerInstance = AwsBaseService & { sourceType?: Maybe; }; +export type AwsSystemsManagerParameter = AwsBaseService & { + name?: Maybe; +}; + export type AwsTag = { alb?: Maybe>>; apiGatewayDomainName?: Maybe>>; diff --git a/src/utils/errorLog.ts b/src/utils/errorLog.ts index 1ef22dbf..d39fdb0e 100644 --- a/src/utils/errorLog.ts +++ b/src/utils/errorLog.ts @@ -1,4 +1,5 @@ import CloudGraph from '@cloudgraph/sdk' +import { ProviderError } from '@cloudgraph/sdk/dist/src/types' import { AWSError } from 'aws-sdk' const notAuthorized = 'not authorized' // part of the error string aws passes back for permissions errors @@ -7,6 +8,9 @@ const throttling = 'Throttling' const { logger } = CloudGraph export default class AwsErrorLog { + // store errors for futher analysis + static errorsHistory: ProviderError[] = [] + constructor(serviceName: string) { this.serviceName = serviceName } @@ -35,6 +39,13 @@ export default class AwsErrorLog { logger.warn( `There was a problem getting data for service ${this.serviceName}, CG encountered an error calling ${functionName}` ) + + AwsErrorLog.errorsHistory.push({ + service: this.serviceName, + function: functionName, + message: err?.message, + }) + if ( err?.message?.includes(notAuthorized) || err?.code === accessDenied diff --git a/src/utils/format.ts b/src/utils/format.ts index 32dcb411..c198ed1c 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -124,6 +124,7 @@ export const formatIamJsonPolicy = (json: string): AwsIamJsonPolicy => { notAction: isArray(el.NotAction) ? el.NotAction : [toString(el.NotAction)], + sid: el.Sid, condition: formatCondition(el.Condition), effect: el.Effect, principal: formatPrincipal(el.Principal), diff --git a/src/utils/generateArns.ts b/src/utils/generateArns.ts index fc7e921a..aa2dded3 100644 --- a/src/utils/generateArns.ts +++ b/src/utils/generateArns.ts @@ -45,12 +45,12 @@ export const networkAclArn = ({ export const sesArn = ({ region, account, - email, + identity, }: { region: string account: string - email: string -}): string => `arn:aws:ses:${region}:${account}:identity/${email}` + identity: string +}): string => `arn:aws:ses:${region}:${account}:identity/${identity}` export const redshiftArn = ({ region, @@ -254,6 +254,36 @@ export const glueJobArn = ({ name: string }): string => `arn:aws:glue:${region}:${account}:job/${name}` +export const glueDatabaseArn = ({ + region, + account, + name, +}: { + region: string + account: string + name: string +}): string => `arn:aws:glue:${region}:${account}:database/${name}` + +export const glueCrawlerArn = ({ + region, + account, + name, +}: { + region: string + account: string + name: string +}): string => `arn:aws:glue:${region}:${account}:crawler/${name}` + +export const glueTriggerArn = ({ + region, + account, + name, +}: { + region: string + account: string + name: string +}): string => `arn:aws:glue:${region}:${account}:trigger/${name}` + export const ssmManagedInstanceArn = ({ region, account, @@ -274,6 +304,16 @@ export const ssmDocumentArn = ({ name: string }): string => `arn:aws:ssm:${region}:${account}:document/${name}` +export const ssmParameterArn = ({ + region, + account, + name, +}: { + region: string + account: string + name: string +}): string => `arn:aws:ssm:${region}:${account}:parameter/${name.replace('/', '')}` + export const cognitoIdentityPoolArn = ({ region, account, @@ -344,4 +384,24 @@ export const transitGatewayRouteTableArn = ({ region: string account: string id: string -}): string => `arn:aws:ec2:${region}:${account}:transit-gateway-routetable/${id}` \ No newline at end of file +}): string => `arn:aws:ec2:${region}:${account}:transit-gateway-routetable/${id}` + +export const codeCommitRepositoryArn = ({ + region, + account, + name, +}: { + region: string + account: string + name: string +}): string => `arn:aws:codecommit:${region}:${account}:repository/${name.replace('/', '')}` + +export const codePipelineArn = ({ + region, + account, + name, +}: { + region: string + account: string + name: string +}): string => `arn:aws:codepipeline:${region}:${account}:pipeline/${name}` \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e1c4f630..41a1dbe5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -53,6 +53,15 @@ eslint-plugin-import "^2.22.1" eslint-plugin-prettier "^3.4.0" +"@aws-crypto/crc32@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" + integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + "@aws-crypto/ie11-detection@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" @@ -107,6 +116,116 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/abort-controller@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.338.0.tgz#955203aab957906479aaca978e23a3131db068cf" + integrity sha512-/yLI32+HwFNBRJ39jMXw+/cn3AnlCuJpQd7Ax4887g32Dgte5eyrfY8sJUOL6902BUmAq4oSRI5QeBXNplO0Xw== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/abort-controller@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.341.0.tgz#736c1c82a4e52931ce13d9c0c538799ebfb32d0d" + integrity sha512-D27hLlUPJTM4rNtMBPduD1vdPSmbUs0Eat8DZWCv3bg+v60loairha87oYL5x6Kj4IhbK93shI1OfzbxDqG1Yw== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/abort-controller@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.342.0.tgz#a84a5fc884d87ae4adfe852aa6a43effc63e7af1" + integrity sha512-W1lAYldbzDjfn8vwnwNe+6qNWfSu1+JrdiVIRSwsiwKvF2ahjKuaLoc8rJM09C6ieNWRi5634urFgfwAJuv6vg== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/client-codecommit@^3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-codecommit/-/client-codecommit-3.344.0.tgz#64015191674491a46938b7cdcffab471379cbe01" + integrity sha512-DYW0aOfnGHUow6p+ZqGjKrV1JrK8Py7uon3UXl9RFZicR1i1k04VhQ/H7LeJNaaYtMBZr+7aiKeAFGobKQq40w== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.344.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/credential-provider-node" "3.344.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.344.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.344.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-signing" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.344.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + uuid "^8.3.2" + +"@aws-sdk/client-codepipeline@^3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-codepipeline/-/client-codepipeline-3.344.0.tgz#ba14eaa3fc9defea58df42507321b7f8e0acfbbc" + integrity sha512-zL7YmdcJ+uqpKs8p3j4Y6JocKgT3w8P8oJ5tyINnZBK2oCXda+ulsq2H8ACDOThiNqhIj1P4/J9k23bIUdpGNQ== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.344.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/credential-provider-node" "3.344.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.344.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.344.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-signing" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.344.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + uuid "^8.3.2" + "@aws-sdk/client-cognito-identity@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.256.0.tgz#8607eb1cda6672d590bc6570477cca09bc0ab52e" @@ -149,6 +268,136 @@ "@aws-sdk/util-utf8-node" "3.208.0" tslib "^2.3.1" +"@aws-sdk/client-elastic-beanstalk@^3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-elastic-beanstalk/-/client-elastic-beanstalk-3.338.0.tgz#2ae19551e4c72e2267e7c9223476b51b4216633c" + integrity sha512-4aQMRqxebNnmV5cPFJUKrtrOxqBvxJxbDwowErQFXCktDbk5f8Z1bo3ecctSawZup3de/Yj5jTpZmkW5VHBRWA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.338.0" + "@aws-sdk/config-resolver" "3.338.0" + "@aws-sdk/credential-provider-node" "3.338.0" + "@aws-sdk/fetch-http-handler" "3.338.0" + "@aws-sdk/hash-node" "3.338.0" + "@aws-sdk/invalid-dependency" "3.338.0" + "@aws-sdk/middleware-content-length" "3.338.0" + "@aws-sdk/middleware-endpoint" "3.338.0" + "@aws-sdk/middleware-host-header" "3.338.0" + "@aws-sdk/middleware-logger" "3.338.0" + "@aws-sdk/middleware-recursion-detection" "3.338.0" + "@aws-sdk/middleware-retry" "3.338.0" + "@aws-sdk/middleware-serde" "3.338.0" + "@aws-sdk/middleware-signing" "3.338.0" + "@aws-sdk/middleware-stack" "3.338.0" + "@aws-sdk/middleware-user-agent" "3.338.0" + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/node-http-handler" "3.338.0" + "@aws-sdk/smithy-client" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/url-parser" "3.338.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.338.0" + "@aws-sdk/util-defaults-mode-node" "3.338.0" + "@aws-sdk/util-endpoints" "3.338.0" + "@aws-sdk/util-retry" "3.338.0" + "@aws-sdk/util-user-agent-browser" "3.338.0" + "@aws-sdk/util-user-agent-node" "3.338.0" + "@aws-sdk/util-utf8" "3.310.0" + "@aws-sdk/util-waiter" "3.338.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + fast-xml-parser "4.1.2" + tslib "^2.5.0" + +"@aws-sdk/client-glue@^3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-glue/-/client-glue-3.342.0.tgz#6fd1fc4000a383d8ee01d946a723a6db7dafe157" + integrity sha512-chGUoLJnS9En/CHUMphyNLAqYmI7hRGokIIPEyYzchUESqjwGZUUQNn3q5Xqevm78VBYfvzl3iYhHSymr91bew== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.342.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/credential-provider-node" "3.342.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.342.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.342.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-signing" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.342.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-ssm@^3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.341.0.tgz#ba0233d0fe292cbc48cb7300eb52e4c6571cdd1a" + integrity sha512-TbTsQJ7N/IVnnzneo7rl0M/al1eWKeONyNFF8iiPA1OFiqgoE/gx5JKJ9Dlx9V+USBPLvARRDFw+0v6fALckxg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.341.0" + "@aws-sdk/config-resolver" "3.341.0" + "@aws-sdk/credential-provider-node" "3.341.0" + "@aws-sdk/fetch-http-handler" "3.341.0" + "@aws-sdk/hash-node" "3.341.0" + "@aws-sdk/invalid-dependency" "3.341.0" + "@aws-sdk/middleware-content-length" "3.341.0" + "@aws-sdk/middleware-endpoint" "3.341.0" + "@aws-sdk/middleware-host-header" "3.341.0" + "@aws-sdk/middleware-logger" "3.341.0" + "@aws-sdk/middleware-recursion-detection" "3.341.0" + "@aws-sdk/middleware-retry" "3.341.0" + "@aws-sdk/middleware-serde" "3.341.0" + "@aws-sdk/middleware-signing" "3.341.0" + "@aws-sdk/middleware-stack" "3.341.0" + "@aws-sdk/middleware-user-agent" "3.341.0" + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/node-http-handler" "3.341.0" + "@aws-sdk/smithy-client" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/url-parser" "3.341.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.341.0" + "@aws-sdk/util-defaults-mode-node" "3.341.0" + "@aws-sdk/util-endpoints" "3.341.0" + "@aws-sdk/util-retry" "3.341.0" + "@aws-sdk/util-user-agent-browser" "3.341.0" + "@aws-sdk/util-user-agent-node" "3.341.0" + "@aws-sdk/util-utf8" "3.310.0" + "@aws-sdk/util-waiter" "3.341.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + uuid "^8.3.2" + "@aws-sdk/client-sso-oidc@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.256.0.tgz#c71f29df3fb1cd152208575bd7f3ee102211bebf" @@ -188,6 +437,162 @@ "@aws-sdk/util-utf8-node" "3.208.0" tslib "^2.3.1" +"@aws-sdk/client-sso-oidc@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.338.0.tgz#ba3115962fc8c5ccec8c2c984063641a1b1ed283" + integrity sha512-mny5Q3LWKTcMMFS8WxeOCTinl193z7vS3b+eQz09K4jb1Lq04Bpjw25cySgBnhMGZ7QHQiYBscNLyu/TfOKiHA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.338.0" + "@aws-sdk/fetch-http-handler" "3.338.0" + "@aws-sdk/hash-node" "3.338.0" + "@aws-sdk/invalid-dependency" "3.338.0" + "@aws-sdk/middleware-content-length" "3.338.0" + "@aws-sdk/middleware-endpoint" "3.338.0" + "@aws-sdk/middleware-host-header" "3.338.0" + "@aws-sdk/middleware-logger" "3.338.0" + "@aws-sdk/middleware-recursion-detection" "3.338.0" + "@aws-sdk/middleware-retry" "3.338.0" + "@aws-sdk/middleware-serde" "3.338.0" + "@aws-sdk/middleware-stack" "3.338.0" + "@aws-sdk/middleware-user-agent" "3.338.0" + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/node-http-handler" "3.338.0" + "@aws-sdk/smithy-client" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/url-parser" "3.338.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.338.0" + "@aws-sdk/util-defaults-mode-node" "3.338.0" + "@aws-sdk/util-endpoints" "3.338.0" + "@aws-sdk/util-retry" "3.338.0" + "@aws-sdk/util-user-agent-browser" "3.338.0" + "@aws-sdk/util-user-agent-node" "3.338.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sso-oidc@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.341.0.tgz#0a87db818c04e6e2e9a3dbb7b33ce7e68f0c19d3" + integrity sha512-BjG4E7E1StsHCM0Mex7EZA6oPMQ+PLZY5axr554ErYxlzYlzE8b/Aq3N/mCCqeUSIdz4zAGr8di7XYCUB3CRdg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.341.0" + "@aws-sdk/fetch-http-handler" "3.341.0" + "@aws-sdk/hash-node" "3.341.0" + "@aws-sdk/invalid-dependency" "3.341.0" + "@aws-sdk/middleware-content-length" "3.341.0" + "@aws-sdk/middleware-endpoint" "3.341.0" + "@aws-sdk/middleware-host-header" "3.341.0" + "@aws-sdk/middleware-logger" "3.341.0" + "@aws-sdk/middleware-recursion-detection" "3.341.0" + "@aws-sdk/middleware-retry" "3.341.0" + "@aws-sdk/middleware-serde" "3.341.0" + "@aws-sdk/middleware-stack" "3.341.0" + "@aws-sdk/middleware-user-agent" "3.341.0" + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/node-http-handler" "3.341.0" + "@aws-sdk/smithy-client" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/url-parser" "3.341.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.341.0" + "@aws-sdk/util-defaults-mode-node" "3.341.0" + "@aws-sdk/util-endpoints" "3.341.0" + "@aws-sdk/util-retry" "3.341.0" + "@aws-sdk/util-user-agent-browser" "3.341.0" + "@aws-sdk/util-user-agent-node" "3.341.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sso-oidc@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.342.0.tgz#0d6c54d4a5e000ac515439747d775cd454665aea" + integrity sha512-C1jeKD39pWXlpGRxhWWBw2No1lyZnyIN72M2Qg3BWK6QlsSDtd9kdhpGS9rQU0i1F4w5x178a+qiGWHHMhCwLg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.342.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.342.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.342.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sso-oidc@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.344.0.tgz#6e13b659399b9cd6acf8b7b5bdf775935ed3f4eb" + integrity sha512-J+XsIpuinsra+QkwfQAWj2MnMzbiwEVp8KbLrZQxRNViCAbcgOQ+e0TiiViOnEM0MgII4qAF0zJejSWZ8EVDEg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.344.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.344.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.344.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + "@aws-sdk/client-sso@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.256.0.tgz#8dfd3e69e0eae9937f1b7cee0d95dca7995ad867" @@ -227,6 +632,162 @@ "@aws-sdk/util-utf8-node" "3.208.0" tslib "^2.3.1" +"@aws-sdk/client-sso@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.338.0.tgz#a65301eafb61f308589f17b9769e2e62d7f022dd" + integrity sha512-EglKsGlVph65PuFPKq1nGlxsY99XM2xHJaB1uX0bQEC94qrmS/M4a5kno5tiUnTWO1K+K4JBQiOxdGJs0GUS+w== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.338.0" + "@aws-sdk/fetch-http-handler" "3.338.0" + "@aws-sdk/hash-node" "3.338.0" + "@aws-sdk/invalid-dependency" "3.338.0" + "@aws-sdk/middleware-content-length" "3.338.0" + "@aws-sdk/middleware-endpoint" "3.338.0" + "@aws-sdk/middleware-host-header" "3.338.0" + "@aws-sdk/middleware-logger" "3.338.0" + "@aws-sdk/middleware-recursion-detection" "3.338.0" + "@aws-sdk/middleware-retry" "3.338.0" + "@aws-sdk/middleware-serde" "3.338.0" + "@aws-sdk/middleware-stack" "3.338.0" + "@aws-sdk/middleware-user-agent" "3.338.0" + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/node-http-handler" "3.338.0" + "@aws-sdk/smithy-client" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/url-parser" "3.338.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.338.0" + "@aws-sdk/util-defaults-mode-node" "3.338.0" + "@aws-sdk/util-endpoints" "3.338.0" + "@aws-sdk/util-retry" "3.338.0" + "@aws-sdk/util-user-agent-browser" "3.338.0" + "@aws-sdk/util-user-agent-node" "3.338.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.341.0.tgz#0a9ba2ae442fb915ecdacf92020d78daf1b400f7" + integrity sha512-RWFKz3DBgEy92mce3TTgcq/UOKr/LKNyC189M8UXhWRyyoaQpE9gIyHUQwuh7a2bbnI7XKgpa2rO54Ns0rFJzw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.341.0" + "@aws-sdk/fetch-http-handler" "3.341.0" + "@aws-sdk/hash-node" "3.341.0" + "@aws-sdk/invalid-dependency" "3.341.0" + "@aws-sdk/middleware-content-length" "3.341.0" + "@aws-sdk/middleware-endpoint" "3.341.0" + "@aws-sdk/middleware-host-header" "3.341.0" + "@aws-sdk/middleware-logger" "3.341.0" + "@aws-sdk/middleware-recursion-detection" "3.341.0" + "@aws-sdk/middleware-retry" "3.341.0" + "@aws-sdk/middleware-serde" "3.341.0" + "@aws-sdk/middleware-stack" "3.341.0" + "@aws-sdk/middleware-user-agent" "3.341.0" + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/node-http-handler" "3.341.0" + "@aws-sdk/smithy-client" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/url-parser" "3.341.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.341.0" + "@aws-sdk/util-defaults-mode-node" "3.341.0" + "@aws-sdk/util-endpoints" "3.341.0" + "@aws-sdk/util-retry" "3.341.0" + "@aws-sdk/util-user-agent-browser" "3.341.0" + "@aws-sdk/util-user-agent-node" "3.341.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.342.0.tgz#8f532e299a0c0e697b737d4bf6603f31a2be7035" + integrity sha512-DbEL+sWBua/04zTlJ6QmUsOpbeIlnPp8eYXQllCwsFzsIT04MjMI4hCZNia/weymwcq3vWTJOk2++SZf0sCGcw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.342.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.342.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.342.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.344.0.tgz#9ccf466ef45972376ebe6fe820df225943b1377e" + integrity sha512-pM+LkEGzuG2lLE3qnJy8WxvNW/MdY0LAi9G8dBferC2uF3MrKIYP+5IOFmeYQ9lVQF63gknEb4t8CqrHwmB3dQ== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.344.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.344.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.344.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + "@aws-sdk/client-sts@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.256.0.tgz#c71610393736b63c58c4cdc1caec302508fe8fc8" @@ -270,6 +831,178 @@ fast-xml-parser "4.0.11" tslib "^2.3.1" +"@aws-sdk/client-sts@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.338.0.tgz#8e2d27b5cdf6af59c8144f8c0dc4602bd607f210" + integrity sha512-FBHy/G7BAPX0CdEeeGYpoAnKXVCSIIkESLU2wF6x880z+U2IqiL48Fzoa5qoLaLPQaK/30P7ytznkqm4vd1OFw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.338.0" + "@aws-sdk/credential-provider-node" "3.338.0" + "@aws-sdk/fetch-http-handler" "3.338.0" + "@aws-sdk/hash-node" "3.338.0" + "@aws-sdk/invalid-dependency" "3.338.0" + "@aws-sdk/middleware-content-length" "3.338.0" + "@aws-sdk/middleware-endpoint" "3.338.0" + "@aws-sdk/middleware-host-header" "3.338.0" + "@aws-sdk/middleware-logger" "3.338.0" + "@aws-sdk/middleware-recursion-detection" "3.338.0" + "@aws-sdk/middleware-retry" "3.338.0" + "@aws-sdk/middleware-sdk-sts" "3.338.0" + "@aws-sdk/middleware-serde" "3.338.0" + "@aws-sdk/middleware-signing" "3.338.0" + "@aws-sdk/middleware-stack" "3.338.0" + "@aws-sdk/middleware-user-agent" "3.338.0" + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/node-http-handler" "3.338.0" + "@aws-sdk/smithy-client" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/url-parser" "3.338.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.338.0" + "@aws-sdk/util-defaults-mode-node" "3.338.0" + "@aws-sdk/util-endpoints" "3.338.0" + "@aws-sdk/util-retry" "3.338.0" + "@aws-sdk/util-user-agent-browser" "3.338.0" + "@aws-sdk/util-user-agent-node" "3.338.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + fast-xml-parser "4.1.2" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.341.0.tgz#5ffa75db58882fd14a8dd90a7492dd73478d558b" + integrity sha512-Ec8lzyPkd7N6VE4O73RuY04hgxMSXCD+uyWmYCoCCuamAx+xEP4ifVL0spApr8tttm51QLBgc01pVKNL62Oprw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.341.0" + "@aws-sdk/credential-provider-node" "3.341.0" + "@aws-sdk/fetch-http-handler" "3.341.0" + "@aws-sdk/hash-node" "3.341.0" + "@aws-sdk/invalid-dependency" "3.341.0" + "@aws-sdk/middleware-content-length" "3.341.0" + "@aws-sdk/middleware-endpoint" "3.341.0" + "@aws-sdk/middleware-host-header" "3.341.0" + "@aws-sdk/middleware-logger" "3.341.0" + "@aws-sdk/middleware-recursion-detection" "3.341.0" + "@aws-sdk/middleware-retry" "3.341.0" + "@aws-sdk/middleware-sdk-sts" "3.341.0" + "@aws-sdk/middleware-serde" "3.341.0" + "@aws-sdk/middleware-signing" "3.341.0" + "@aws-sdk/middleware-stack" "3.341.0" + "@aws-sdk/middleware-user-agent" "3.341.0" + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/node-http-handler" "3.341.0" + "@aws-sdk/smithy-client" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/url-parser" "3.341.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.341.0" + "@aws-sdk/util-defaults-mode-node" "3.341.0" + "@aws-sdk/util-endpoints" "3.341.0" + "@aws-sdk/util-retry" "3.341.0" + "@aws-sdk/util-user-agent-browser" "3.341.0" + "@aws-sdk/util-user-agent-node" "3.341.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + fast-xml-parser "4.1.2" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.342.0.tgz#21a65e365113418a7816dd4fef16d24b8227d496" + integrity sha512-MUgYm/2ra1Pwoqw9ng75rVsvTLQvLHZLsTjJuKJ4hnHx1GdmQt4/ZlG1q/J2ZK2o6RZXqgavscz/nyrZH0QumA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/credential-provider-node" "3.342.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.342.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.342.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-sdk-sts" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-signing" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.342.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + fast-xml-parser "4.1.2" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.344.0.tgz#5d2a554766ca70ee6af929aa9617850b54d4b9a3" + integrity sha512-GmSTttvx5rR+OBqC+Dd/87A6BQC3vgnXWm/sVhoHabW18lwywfstNahzzmSqNPXj8IxCCgOXlWnD8DftmP4MEA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/credential-provider-node" "3.344.0" + "@aws-sdk/fetch-http-handler" "3.342.0" + "@aws-sdk/hash-node" "3.344.0" + "@aws-sdk/invalid-dependency" "3.342.0" + "@aws-sdk/middleware-content-length" "3.342.0" + "@aws-sdk/middleware-endpoint" "3.344.0" + "@aws-sdk/middleware-host-header" "3.342.0" + "@aws-sdk/middleware-logger" "3.342.0" + "@aws-sdk/middleware-recursion-detection" "3.342.0" + "@aws-sdk/middleware-retry" "3.342.0" + "@aws-sdk/middleware-sdk-sts" "3.342.0" + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/middleware-signing" "3.342.0" + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/middleware-user-agent" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/node-http-handler" "3.344.0" + "@aws-sdk/smithy-client" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + "@aws-sdk/util-body-length-browser" "3.310.0" + "@aws-sdk/util-body-length-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.342.0" + "@aws-sdk/util-defaults-mode-node" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + "@aws-sdk/util-user-agent-browser" "3.342.0" + "@aws-sdk/util-user-agent-node" "3.342.0" + "@aws-sdk/util-utf8" "3.310.0" + "@smithy/protocol-http" "^1.0.1" + "@smithy/types" "^1.0.0" + fast-xml-parser "4.1.2" + tslib "^2.5.0" + "@aws-sdk/config-resolver@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.254.0.tgz#82504a1886f90fc1374b77d65187058a04430204" @@ -281,6 +1014,36 @@ "@aws-sdk/util-middleware" "3.254.0" tslib "^2.3.1" +"@aws-sdk/config-resolver@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.338.0.tgz#fa698ff05bdabc3af42f571ac3a7e895b2a91f6a" + integrity sha512-rB9WUaMfTB74Hd2mOiyPFR7Q1viT+w6SaDSR9SA1P8EeIg5H13FNdIKb736Z8/6QJhDj7whdyk1CTGV+DmXOOg== + dependencies: + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-config-provider" "3.310.0" + "@aws-sdk/util-middleware" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/config-resolver@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.341.0.tgz#4bc4f901b2cb9a5aed2031266b48046b52526b43" + integrity sha512-BpU6JTvT2SJLrsKxe4hjDDVbFnLc5iRcD+dwF/uV4rltFlXPOhqrx1S4NtRLpRaT3oYwA3DnBGC5CkV6QHWW5Q== + dependencies: + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-config-provider" "3.310.0" + "@aws-sdk/util-middleware" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/config-resolver@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.342.0.tgz#186684780ffe74ceb7a384ee8a58f32c45d1c233" + integrity sha512-jUg6DTTrCvG8AOPv5NRJ6PSQSC5fEI2gVv4luzvrGkRJULYbIqpdfUYdW7jB3rWAWC79pQQr5lSqC5DWH91stw== + dependencies: + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-config-provider" "3.310.0" + "@aws-sdk/util-middleware" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-cognito-identity@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.256.0.tgz#471d3fcab17f4922c716008a8d80c3212dd1e1ab" @@ -300,6 +1063,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-env@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.338.0.tgz#97d83054e36ce4adb5293b85a66d532d2e412182" + integrity sha512-j14vApy80tpk87C3x3uBf1caQsuR8RdQ8iOW830H/AOhsa88XaZIB/NQSX7exaIKZa2RU0Vv2wIlGAA8ko7J6g== + dependencies: + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-env@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.341.0.tgz#f0f1a9f5bf5fdb1c3dec9183f4e7536f0b011cb7" + integrity sha512-oqFMmGvtKjqcY6Io4CweHz0blgyyZtlfxWJbttPK7dSLk9EtRUuvVilcRtzXWXuAB2hk9zUN9wavd8nyaTcidA== + dependencies: + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-env@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.342.0.tgz#1fef895b6460787fdf3b8fef6e67c9d1196fbd4f" + integrity sha512-mufOcoqdXZXkvA7u6hUcJz6wKpVaho8SRWCvJrGO4YkyudUAoI9KSP5R4U+gtneDJ2Y/IEKPuw8ugNfANa1J+A== + dependencies: + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-imds@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.254.0.tgz#876282edc865747b574a537d59c4cf47cf4b37d3" @@ -311,6 +1101,39 @@ "@aws-sdk/url-parser" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-imds@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.338.0.tgz#4202049ee596c86f57e0464905c61482be2439c0" + integrity sha512-qsqeywYfJevg5pgUUUBmm7pK1bckVrl091PZB2IliFdQVnDvI5GFLf4B0oZqjaLAzPG1gVtxRvqIve+tnP/+xA== + dependencies: + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/url-parser" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-imds@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.341.0.tgz#b2ffcb34f85db6050fefa3c587f1b55eb781ae19" + integrity sha512-dkvc7WcKxFR0KgAScbRQ16wg0qH8tKxaVS3hfgHDYJR4UIKqV/sM6r5H2OvAdegY9/T180O2srtq2N4pyywPSQ== + dependencies: + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/url-parser" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-imds@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.342.0.tgz#f18345d69e2ebeb2396d16756ed92370cc250120" + integrity sha512-ReaHwFLfcsEYjDFvi95OFd+IU8frPwuAygwL56aiMT7Voc0oy3EqB3MFs3gzFxdLsJ0vw9TZMRbaouepAEVCkA== + dependencies: + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-ini@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.256.0.tgz#6fc7905cedbdb33df40bdbfc7bbfe0a0a5200e4a" @@ -326,6 +1149,66 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-ini@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.338.0.tgz#f21ba58225c1088dc57d7241b3cbc35f3b38cdd8" + integrity sha512-UhgYgymT9sJiRm0peqP5EvtR4dXiS2Q2AuFgDUjBvDz8JaZlqafsIS4cfyGwTHV/xY6cdiMu5rCTe8hTyXsukQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.338.0" + "@aws-sdk/credential-provider-imds" "3.338.0" + "@aws-sdk/credential-provider-process" "3.338.0" + "@aws-sdk/credential-provider-sso" "3.338.0" + "@aws-sdk/credential-provider-web-identity" "3.338.0" + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/shared-ini-file-loader" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.341.0.tgz#775226304af783a7ae39de92821c3023fcf0c530" + integrity sha512-o+44n3VFErRNOHZi4Psbu0JQWB7RT15QJzRtYquAPohgKNDT9jQ/VN0JesEVyktpIklsPJBNAbDb68fExsjKUg== + dependencies: + "@aws-sdk/credential-provider-env" "3.341.0" + "@aws-sdk/credential-provider-imds" "3.341.0" + "@aws-sdk/credential-provider-process" "3.341.0" + "@aws-sdk/credential-provider-sso" "3.341.0" + "@aws-sdk/credential-provider-web-identity" "3.341.0" + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/shared-ini-file-loader" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.342.0.tgz#54b7e6d2d968ba86ea40faf21687cf3bada7be3b" + integrity sha512-VJ7+IlI3rx5XfO8AarbKeqNVwfExsWW0S6fqBXIim0s10FJAy7R+wxYyhZhawfRm0ydCggT+Ji6dftS+WXF8fg== + dependencies: + "@aws-sdk/credential-provider-env" "3.342.0" + "@aws-sdk/credential-provider-imds" "3.342.0" + "@aws-sdk/credential-provider-process" "3.342.0" + "@aws-sdk/credential-provider-sso" "3.342.0" + "@aws-sdk/credential-provider-web-identity" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.344.0.tgz#59560ca30ef7380adc103eec209a66a8b15bb735" + integrity sha512-21awwuyIG0qXirgeDdq9EbyXzk/5pZswfBem8W2EAtwNPI8HO84S0EHyHybj/5l5QdPrKd/W3ohRkKY0uXSEcQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.342.0" + "@aws-sdk/credential-provider-imds" "3.342.0" + "@aws-sdk/credential-provider-process" "3.342.0" + "@aws-sdk/credential-provider-sso" "3.344.0" + "@aws-sdk/credential-provider-web-identity" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-node@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.256.0.tgz#ab9954548416130152d8496a3b6494d78dc555e6" @@ -342,6 +1225,70 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-node@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.338.0.tgz#3a5414f77a744112a01f285896d5720ef86d62b8" + integrity sha512-nZjaMRxJqX0EXMV9LA5IbRQI1pDGGZiPYX2KDfZ1Y9Gc1Y/vIZhHKOHGb1uKMAonlR076CsXlev4/tjC8SGGuw== + dependencies: + "@aws-sdk/credential-provider-env" "3.338.0" + "@aws-sdk/credential-provider-imds" "3.338.0" + "@aws-sdk/credential-provider-ini" "3.338.0" + "@aws-sdk/credential-provider-process" "3.338.0" + "@aws-sdk/credential-provider-sso" "3.338.0" + "@aws-sdk/credential-provider-web-identity" "3.338.0" + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/shared-ini-file-loader" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.341.0.tgz#5fe6add80ad24ab86304f0c63d334bc7d21ef950" + integrity sha512-O4gxP5PLu86361sGgnyxcwP5L2Ek7N65KM3MYJNgDpXRig+FP/pxBmdOtYkTYJYymPspGxnsNM6p2tbARJ1WMw== + dependencies: + "@aws-sdk/credential-provider-env" "3.341.0" + "@aws-sdk/credential-provider-imds" "3.341.0" + "@aws-sdk/credential-provider-ini" "3.341.0" + "@aws-sdk/credential-provider-process" "3.341.0" + "@aws-sdk/credential-provider-sso" "3.341.0" + "@aws-sdk/credential-provider-web-identity" "3.341.0" + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/shared-ini-file-loader" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.342.0.tgz#712d00d7ee34483edaae714e722dbd55e2b738d0" + integrity sha512-u3oUo0UxGEaHLtIx7a38aFLgcTe1OevCNe5exL3ugf5C4ifvUjM8rLWySQ9zrKRgPT2yDRYG/oq4ezjoR9fhHg== + dependencies: + "@aws-sdk/credential-provider-env" "3.342.0" + "@aws-sdk/credential-provider-imds" "3.342.0" + "@aws-sdk/credential-provider-ini" "3.342.0" + "@aws-sdk/credential-provider-process" "3.342.0" + "@aws-sdk/credential-provider-sso" "3.342.0" + "@aws-sdk/credential-provider-web-identity" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.344.0.tgz#9d802aea6866267a7da6844eef676fa570943a9a" + integrity sha512-kkdMFeKlvRni5RwY0nAeMMAeLkHd3AFh3PoV9TSSQQsZD3e0shSZ0ohWJmV6ghZJHXUx+gPfEGtJTadtoTnHMQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.342.0" + "@aws-sdk/credential-provider-imds" "3.342.0" + "@aws-sdk/credential-provider-ini" "3.344.0" + "@aws-sdk/credential-provider-process" "3.342.0" + "@aws-sdk/credential-provider-sso" "3.344.0" + "@aws-sdk/credential-provider-web-identity" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-process@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.254.0.tgz#31e6c0c709d47b9a87397698ab942a820dfa5f38" @@ -352,6 +1299,36 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-process@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.338.0.tgz#32eb4a9655f481f24986f9fb9d87a549d5515163" + integrity sha512-5I1EgJxFFEg8xel2kInMpkdBKajUut0hR2fBajqCmK7Pflu8s0I2NKDots9a3YJagNrFJq38+EzoDcUvRrd2dg== + dependencies: + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/shared-ini-file-loader" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-process@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.341.0.tgz#3aeb488457be4f71278559884321469ef2d2f324" + integrity sha512-t+12surwkdZO7dAdtA7xz+O6Hk0H3yOVqXH+Y8UINXbFc9/uUgstPZq5qhpQIeDPRes/lqYUiZ4tho5mhpGItw== + dependencies: + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/shared-ini-file-loader" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-process@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.342.0.tgz#faccc5937f055e2888217140e47499da844c01a6" + integrity sha512-q03yJQPa4jnZtwKFW3yEYNMcpYH7wQzbEOEXjnXG4v8935oOttZjXBvRK7ax+f0D1ZHZFeFSashjw0A/bi1efQ== + dependencies: + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-sso@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.256.0.tgz#5aa418c87ec6018ed768fe02bab42a1b5d6a3420" @@ -364,6 +1341,54 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-sso@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.338.0.tgz#55b827f2678dd2ac53b2fb134416a482e810a5a2" + integrity sha512-fpzYHK17iF/uFkrm4cLg/utDVKSBTWNjAiNlE3GF6CaixBCwc0QBLKHk2nG4d1ZZeMVCbIUMS7eoqfR0LYc/yw== + dependencies: + "@aws-sdk/client-sso" "3.338.0" + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/shared-ini-file-loader" "3.338.0" + "@aws-sdk/token-providers" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.341.0.tgz#06ade30c8f4290b78e7d15d6dbcdac0c89bed77f" + integrity sha512-ooOntFPVwawHO8WwwTSDFysno+nZFt1+GPlAr9N9QxIWQSRZYLaNFeplnxT/58jJoMcyHH5JjY4Zu4g46htmkw== + dependencies: + "@aws-sdk/client-sso" "3.341.0" + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/shared-ini-file-loader" "3.341.0" + "@aws-sdk/token-providers" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.342.0.tgz#0682696f07c2093548a241c633a5f7db069e4d56" + integrity sha512-ank2703Riz5gwTxC11FDnZtMcq1Z1JjN3Nd53ahyZ+KOJPgWXEw+uolEuzMl4oAovmbTJ6WANo2qMVmLzZEaQg== + dependencies: + "@aws-sdk/client-sso" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/token-providers" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.344.0.tgz#03c4d92850a35891999ecfe6a3d4a7975431174a" + integrity sha512-uS8iKMyjSQch/oKSDno6k3TZ0lr/kL6ZzvBRXcOsmprgW+ffP6ZcRVOPHIwUbjLyuZtDHRq4QcSBGXCnazar+Q== + dependencies: + "@aws-sdk/client-sso" "3.344.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/token-providers" "3.344.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-provider-web-identity@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.254.0.tgz#17ef2052180c929f1f3807704522bd1931b7c2ab" @@ -373,6 +1398,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/credential-provider-web-identity@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.338.0.tgz#b71bb648f59440760b5c364d3f7269f2c8f1d42a" + integrity sha512-kjT/P18jM1icwjYwr8wfY//T8lv2s81ms7OC7vgiSqckmQOxpVkdsep9d44ymSUXwopmotFP7M9gGnEHS6HwAA== + dependencies: + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-web-identity@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.341.0.tgz#5793375eee35c7be67fadb7bbeb7536445bcf070" + integrity sha512-NxoyxnxiycO1IG3FG7/soE3CYLLwuc4pv5PWoMHwy6VjH5yiUIeC8CQHHCF5ndCvB/p5XW1TT5z3YmWKknGqaw== + dependencies: + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-web-identity@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.342.0.tgz#d05f0478c897a69a7010643c5aac1bae0f1861ec" + integrity sha512-+an5oGnzoXMmGJql0Qs9MtyQTmz5GFqrWleQ0k9UVhN3uIfCS9AITS7vb+q1+G7A7YXy9+KshgBhcHco0G/JWQ== + dependencies: + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/credential-providers@^3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-providers/-/credential-providers-3.256.0.tgz#9625d1d70e74029113404ae67206dca1e0caa61c" @@ -394,6 +1446,16 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/eventstream-codec@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-codec/-/eventstream-codec-3.342.0.tgz#aef9ab3c5fdaa02c6da9836194eada9d35515fa1" + integrity sha512-IwtvSuplioMyiu/pQgpazKkGWDM5M5BOx85zmsB0uNxt6rmje8+WqPmGmuPdmJv4bLC5dJPLovcCp/fuH8XWhA== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-hex-encoding" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/fetch-http-handler@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.254.0.tgz#cdc646f48bbfe35ea87ebcc2b5b050e17bbda7a8" @@ -405,6 +1467,39 @@ "@aws-sdk/util-base64" "3.208.0" tslib "^2.3.1" +"@aws-sdk/fetch-http-handler@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.338.0.tgz#7d27c3ffbb791f6d7f7508fbbc5826e4df279b93" + integrity sha512-NOIQmeSa51J2nFAzl99IjxwQkq27cdNJzF59jQWzpUCGbxXfMD4WWy2NHubabSFuJ4FJU2eyoQHUNUFc6/uxXA== + dependencies: + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/querystring-builder" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-base64" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/fetch-http-handler@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.341.0.tgz#69ef5c8a54d52c4b58caff0ef98fdfa7e49cd4d6" + integrity sha512-GclHYOFKmhft9Bp+wX4CgVv4q48P/md/xiKN7kJpGUvazCRhBN7DqfcvMoMCPhobh+llYSefyiqJBxEccEq/TA== + dependencies: + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/querystring-builder" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-base64" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/fetch-http-handler@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.342.0.tgz#7db371a02a5d7e5db80715d3f14803727fb9e984" + integrity sha512-zsC23VUQMHEu4OKloLCVyWLG0ns6n+HKZ9euGLnNO3l0VSRne9qj/94yR+4jr/h04M7MhGf9mlczGfnZUFxs5w== + dependencies: + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/querystring-builder" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-base64" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/hash-node@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.254.0.tgz#b69c9dba780ce86cf24effb3c8416eb16586a502" @@ -415,6 +1510,46 @@ "@aws-sdk/util-utf8" "3.254.0" tslib "^2.3.1" +"@aws-sdk/hash-node@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.338.0.tgz#f7ab49ac7c09e0f80b2abeca2180d6010140fef1" + integrity sha512-udveX3ZRO1oUbyBTQH0LJ8Ika7uk0pHuXrqapdi66GGRJB50IhmOg372zUEwZjDB7DZYXfGTCuAj2OoEalgpBA== + dependencies: + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-buffer-from" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/hash-node@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.341.0.tgz#209ba119620f1d819c299aabe49ffc16fcef227c" + integrity sha512-legGgjmhQnA8veIuVjJEVNE18YIhWj6JaLNm47xgiBbEoZ1BApoBY1GsX1AunV6FrA18fRpCeTynW3u4MVIIow== + dependencies: + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-buffer-from" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/hash-node@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.342.0.tgz#5f1d7019e7246997beaa323b6108772da0534262" + integrity sha512-cFgXy9CDNQdYCdJBsG91FF0P0tNkCfi7+vTy7fzAEchxLxhcfLtC0cS6+gv2e3Dy8mv+uqp45Tu24+8Trx9hJQ== + dependencies: + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-buffer-from" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/hash-node@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.344.0.tgz#4ce5d69a39b5f722d02cd4ae6d0518571c0028fd" + integrity sha512-K0/mSvYR4hEfTRnnyoTj8ccqbXe2PpwvP4u8GXwk3Nr7s8qhDPYe8tFMv+6hoDJ50WJHrMTYGZ1HDAmjvP9uhA== + dependencies: + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-buffer-from" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/invalid-dependency@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.254.0.tgz#a2df8be8257a2edda41301600a73520f7539540d" @@ -423,6 +1558,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/invalid-dependency@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.338.0.tgz#0f0a2a14474c936066e0e2404fd76a9d2d14a92b" + integrity sha512-m6r1fTTGSl0V6l8Z+Ii4Ei8VFpDmu0AT6A59ZhJaMZgxf925ywuCPydyDW9ZqTLE0e7CgxhEHEsH1+HzpVuHTw== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/invalid-dependency@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.341.0.tgz#ee61fe12cf7398c2f587932793f93fc0d94ba31e" + integrity sha512-1GNk+J/Q76bzuj27OqPOqTmFGEYXtyB02afn0cIeadDf0qbjo3G7qkRd3jrJrBIdHNg+DYbBYEHfFB5EuK1s8g== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/invalid-dependency@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.342.0.tgz#90fbfab6f8789962ba7291d1a06d70ca1054b83e" + integrity sha512-3qza2Br1jGKJi8toPYG9u5aGJ3sbGmJLgKDvlga7q3F8JaeB92He6muRJ07eyDvxZ9jiKhLZ2mtYoVcEjI7Mgw== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/is-array-buffer@3.201.0": version "3.201.0" resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz#06e557adc284fac2f26071c2944ae01f61b95854" @@ -430,6 +1589,13 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/is-array-buffer@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz#f87a79f1b858c88744f07e8d8d0a791df204017e" + integrity sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ== + dependencies: + tslib "^2.5.0" + "@aws-sdk/middleware-content-length@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.254.0.tgz#ecf39dac8b056fb6c32860d65080b9b71d02a72c" @@ -439,6 +1605,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-content-length@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.338.0.tgz#027e2f4a5cb7d5afa3cd992191a84634c78e3df7" + integrity sha512-m2C+yJaNmbA3ocBp/7ImUUuimymV5JsFdV7yAibpbYMX22g3q83nieOF9x0I66J0+h+/bcriz/T1ZJAPANLz/g== + dependencies: + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-content-length@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.341.0.tgz#fda1808c9f4fc3652f25f8e0cbbfd3fc84ad935a" + integrity sha512-m663QyL1qvMnXOsXUtLvQz5B5l1kulQMTOwVxxhefPxO0nZbIlXdMQurEOwI1FHfaMnR8UQ1FfPLY6GIkJkX/g== + dependencies: + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-content-length@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.342.0.tgz#6b42d8e6d07631b080a3e30065ec3c1efb6ae0bc" + integrity sha512-7LUMZqhihSAptGRFFQvuwt9nCLNzNPkGd1oU1RpVXw6YPQfKP9Ec5tgg4oUlv1t58IYQvdVj5ITKp4X2aUJVPg== + dependencies: + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-endpoint@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.254.0.tgz#9af598ce63a87eed13f84d1a9bfff4da9dd25790" @@ -453,6 +1646,50 @@ "@aws-sdk/util-middleware" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-endpoint@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.338.0.tgz#5cde32cc018aaef97f634edef7cc5c0d64c3c1b6" + integrity sha512-bzL9Q8lFidg2NTjGVGDKI6yPG/XiPS+VIAMHJeihQmcv1alIy+N3IL4bEN15Fg+cwaGm+P3BevcLIHmcCOVb4w== + dependencies: + "@aws-sdk/middleware-serde" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/url-parser" "3.338.0" + "@aws-sdk/util-middleware" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-endpoint@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.341.0.tgz#27284b0b38918de236f862b833fc6e4790e4083f" + integrity sha512-IucQO8JjAjxnA+7RI1tkxOjUtpuUpkS3v56u5vk6Oypq1iovVBvD8yiFBR2wPh9X/O+3Ts7eWsZ4jhuf4JQQUQ== + dependencies: + "@aws-sdk/middleware-serde" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/url-parser" "3.341.0" + "@aws-sdk/util-middleware" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-endpoint@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.342.0.tgz#fdc6c318bc5a27962538a164e274fe0d126b8a3c" + integrity sha512-/rE+3a2EbNQoylc7vyN+O6GFfcLitboZ8f/Kdkld3Ijcp9whPHdfjiqujlwyiUTgBVP3BqgyB3r7AZDloc7B0g== + dependencies: + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-middleware" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-endpoint@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.344.0.tgz#3acd2815fcbd07b005fb8ffea09a0a109b5acb93" + integrity sha512-rg4ysfusGw5tm8XTqNpdWo0wP0K79hZs3z1xkkskeSsMrbYiDn78Bkkt4s3JELUJY64VanQktPaKo08dNFYNZw== + dependencies: + "@aws-sdk/middleware-serde" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/url-parser" "3.342.0" + "@aws-sdk/util-middleware" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-host-header@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.254.0.tgz#6cdf432132e546f248f626dc6d955285abee6595" @@ -462,6 +1699,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-host-header@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.338.0.tgz#0c872f85b3995e6e124536600fa0b9b7d9187a20" + integrity sha512-k3C7oppkrqeKrAJt9XIl45SdELtnph9BF0QypjyRfT5MNEDnMMsQkc6xy3ZMqG5dWQq6B2l8C+JL7pOvkSQP3w== + dependencies: + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-host-header@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.341.0.tgz#6b8387e8cfcf77417be634f89793a6cf8759a505" + integrity sha512-1AidcDDtGd7LUGtDV+F+FuLb6NmBlpupY2FpuqasUDH5f7ExcEbPaGYjOp4ozktQ6Qb0c0oJ4qxhv5sDos5Qww== + dependencies: + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-host-header@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.342.0.tgz#7e82300466d458a2726c52de264e013f50bd5898" + integrity sha512-EOoix2D2Mk3NQtv7UVhJttfttGYechQxKuGvCI8+8iEKxqlyXaKqAkLR07BQb6epMYeKP4z1PfJm203Sf0WPUQ== + dependencies: + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-logger@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.254.0.tgz#d5ece30ef193da78c71c9abe38ae30b6511000c0" @@ -470,6 +1734,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-logger@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.338.0.tgz#d8bcb19c9b362ed8b6612635f6404875c022b595" + integrity sha512-btj9U0Xovq/UAu3Ur4lAfF7Q3DvvwJ/0UUWsI6GgSzzqSOFgKCz7hCP2GZIT8aXEA5hJOpBOEMkNMjWPNa91Hg== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-logger@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.341.0.tgz#bd0a2cae2e7b8f75f2cc3d5595231c2ff3454b90" + integrity sha512-JQgnPQMlNs542SL/ANbQSWbPMeWeY4+GW/fEfSRgM9uVBZaKPO5dZW7F761odxoK7f3qPSujEZb0ECmTYaEqgg== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-logger@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.342.0.tgz#0f89a98a5e771c18ffa9bc9c70176df5f4866323" + integrity sha512-wbkp85T7p9sHLNPMY6HAXHvLOp+vOubFT/XLIGtgRhYu5aRJSlVo9qlwtdZjyhEgIRQ6H/QUnqAN7Zgk5bCLSw== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-recursion-detection@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.254.0.tgz#605ab3ff47c8ac1fca2d092d570151d7afbe8ae8" @@ -479,6 +1767,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-recursion-detection@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.338.0.tgz#2b9746c626a8a58a891af5964b418743d55ffb2d" + integrity sha512-fu5KwiHHSqC8KTQH6xdJ9+dua4gQcXSFLE5fVsergqd0uVdsmhiI+IDfW6QNwF/lmCqnoKDkpeasuB98eG2tow== + dependencies: + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-recursion-detection@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.341.0.tgz#a49c08cfbdd7b473654825b7ffe9e8253852b0dc" + integrity sha512-DAfZgW7Bb4MB4ZHsjAhiaCXKqTeUFWazrgmNHAa8FkSE8MmgJv/4k8tvnWDtxkAO2GBOwqg7wG9LspeBG/RGMw== + dependencies: + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-recursion-detection@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.342.0.tgz#16568a3bf89e20f978b2145168f62acd8d881847" + integrity sha512-KUDseSAz95kXCqnXEQxNObpviZ6F7eJ5lEgpi+ZehlzGDk/GyOVgjVuAyI7nNxWI5v0ZJ5nIDy+BH273dWbnmQ== + dependencies: + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-retry@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.254.0.tgz#0af8f8c06e42879cbc1f23e6d2166d61953c0f2d" @@ -492,6 +1807,45 @@ tslib "^2.3.1" uuid "^8.3.2" +"@aws-sdk/middleware-retry@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.338.0.tgz#11aab11993cb1cf3654b0c73df854cd5a9204e12" + integrity sha512-nw1oPFkB7TdDG4Vlz2Td47ft/2Gmx1bA18QfE9K1mMWZ4nnoAL8xnHbowlTfHo62+BbFCAPu53PzDUCncBL0iw== + dependencies: + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/service-error-classification" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-middleware" "3.338.0" + "@aws-sdk/util-retry" "3.338.0" + tslib "^2.5.0" + uuid "^8.3.2" + +"@aws-sdk/middleware-retry@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.341.0.tgz#9213c7581a7e83e87ea376fb92e19e64a32f410c" + integrity sha512-EyL2N4ohUQc4CdlccydPuybd4ngVx12MTSIGQVc0PcMZ39ayPbgYOZyCkAGb1rRCEIMayMrF9hF4GfNo4BvV5g== + dependencies: + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/service-error-classification" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-middleware" "3.341.0" + "@aws-sdk/util-retry" "3.341.0" + tslib "^2.5.0" + uuid "^8.3.2" + +"@aws-sdk/middleware-retry@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.342.0.tgz#63f8e132845f2528f1c653e90a06489a0230716a" + integrity sha512-Bfllrjqs0bXNG7A3ydLjTAE5zPEdigG+/lDuEsCfB35gywZnnxqi6BjTeQ9Ss6gbEWX+WyXP7/oVdNaUDQUr9Q== + dependencies: + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/service-error-classification" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-middleware" "3.342.0" + "@aws-sdk/util-retry" "3.342.0" + tslib "^2.5.0" + uuid "^8.3.2" + "@aws-sdk/middleware-sdk-sts@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.254.0.tgz#5382f65872fe9917ac817273ae6e1ffa6cbcdffa" @@ -504,6 +1858,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-sdk-sts@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.338.0.tgz#671e1bba42806a42a8cb88f20d29655ac0bdd29d" + integrity sha512-aZ8eFVaot8oYQri1wOesrA3gLizeAHtlA/ELlqxoGDJtO011J4/hTHTn0iJGbktaCvc1L3TF6mgOsgXpudYqMg== + dependencies: + "@aws-sdk/middleware-signing" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-sts@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.341.0.tgz#3c90e2eac205fa9efbf18df5104fbfe99c304a48" + integrity sha512-A7sXKhL9wzVqeq7sy3eWx7D5FPWdzrJTVpRRBYez/qBY4UjfLcxF9zpB0mw/xhQ7PUta7iJ5tSlPmZZQ4MBnmg== + dependencies: + "@aws-sdk/middleware-signing" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-sts@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.342.0.tgz#99bd8ac1f39ea8baa30e5e36d5a874e89595c74f" + integrity sha512-eGcGDC+6UWKC87mex3voBVRcZN3hzFN6GVzWkTS574hDqp/uJG3yPk3Dltw0qf8skikTGi3/ZE+yAxerq/f5rg== + dependencies: + "@aws-sdk/middleware-signing" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-serde@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.254.0.tgz#57b6579d6d5b6dcd260c088bec8f4cacb6adf5f0" @@ -512,6 +1893,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-serde@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.338.0.tgz#d4fb684a39465615e52d99ca346b8f82e7e96101" + integrity sha512-AabRLrE6sk9tqQlQ7z3kn4gTHNN7Anjk/AM0ZEu96WcWjedcpgM1vVpKTBE7vjnxcTRNq0CEM3GLtQqaZ7/HjQ== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-serde@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.341.0.tgz#9e26fdd4a5678f7ec9ff5e3394b596eaf3d74d87" + integrity sha512-FaPpbEGo/OETxnexg+TYet71fP6dM+y3NPXRUrd5dAulVhmr+CkdzOxqkqtMC1HinKAqHdUpjlsuf7gYg14deQ== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-serde@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.342.0.tgz#ed051e4e7dfc33e431aa27f260e065b9fbb5ee0f" + integrity sha512-WRD+Cyu6+h1ymfPnAw4fI2q3zXjihJ55HFe1uRF8VPN4uBbJNfN3IqL38y/SMEdZ0gH9zNlRNxZLhR0q6SNZEQ== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-signing@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.254.0.tgz#d08cf8c163a90d76a5139c23eecfffb475b6494f" @@ -524,6 +1929,42 @@ "@aws-sdk/util-middleware" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-signing@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.338.0.tgz#c1877ada8e9f7c0afa459b5b36cebf85a1a97ffa" + integrity sha512-AprhhShMF75mOx80SABujLwrU/w2uHQIvWd6aF3BsE5JRI3uQZRqspfjFCaK52HNLQPj3sCQUw1GeiZJ8GyWCw== + dependencies: + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/signature-v4" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-middleware" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-signing@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.341.0.tgz#1feb95cf06b85d9222c66fb734af87bab023eec4" + integrity sha512-KbyBIblgrGRizFJF3sLvx+ON84qOBHrDztNc++Xg2/UmdjLuEtm1sVvpQ2SxrKcfumx+ztVOuDpbD5pd0lBkOA== + dependencies: + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/signature-v4" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-middleware" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-signing@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.342.0.tgz#f0964e6c1e6dc7eaf4a90a8a15f1de5f5fb03b7e" + integrity sha512-CFRQyPv4OjRGmFoB3OfKcQ0aHgS9VWC0YwoHnSWIcLt3Xltorug/Amk0obr/MFoIrktdlVtmvLEJ4Z+8cdsz8g== + dependencies: + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/signature-v4" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-middleware" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/middleware-stack@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.254.0.tgz#1ec3b7ce4a9e62c630119cb3d4ec47df8cf2c185" @@ -531,6 +1972,27 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/middleware-stack@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.338.0.tgz#ab923fc8ebeb5dc23874b357101a575daa1ada21" + integrity sha512-9zXyiklX9AK9ZIXuIPzWzz2vevBEcnBs9UNIxiHl4NBZ8d8oyTvaES1PtFuwL6f7ANSZ9EGVQ2rdTTnMNxMI1A== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/middleware-stack@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.341.0.tgz#85cc11941278cb5168ca850cfe58c55c0074ce57" + integrity sha512-pBAN9T4tBSHp7gJKu0Ma0MepZqP3GvecEh7eZWwTrJrRMgY1k8M1zpUOXBFG6EVRzVdyy7A4DWSuD4kcXE+BIw== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/middleware-stack@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.342.0.tgz#e755815cb22a66f15a964db12e998211f736eda0" + integrity sha512-nDYtLAv9IZq8YFxtbyAiK/U1mtvtJS0DG6HiIPT5jpHcRpuWRHQ170EAW51zYts+21Ffj1VA6ZPkbup83+T6/w== + dependencies: + tslib "^2.5.0" + "@aws-sdk/middleware-user-agent@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.254.0.tgz#b0b54aae78044db72605bfb3cda7099c840f600f" @@ -540,6 +2002,36 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/middleware-user-agent@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.338.0.tgz#25de08397fde96bbea0fa7dc7209ca95869aff64" + integrity sha512-DMqODOsDMFMPcDw2Ya6a0i34AhaBDRpp3vJ+FK3zPxUIsv6iHA+XqEcXLOxROLLoydoyxus7k2U+EWibLZrFbQ== + dependencies: + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-endpoints" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-user-agent@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.341.0.tgz#ae57aac72bcd3f695d7a71ff723001a61a6785ab" + integrity sha512-9gpVXPMkgwv0yV1Lbuc9bvb3MHLEjj5whgbM1WNrtRiogeFwWB0cxOQQgb2cY+xgQLMLnH7VvfRGN79TNVnI7w== + dependencies: + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-endpoints" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-user-agent@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.342.0.tgz#b4983412786b4b42e4c8ada295476bc1f0bdbe63" + integrity sha512-6iiFno+rq7W82mqM4KQKndIkZdGG1XZDlZIb77fcmQGYYlB1J2S/d0pIPdMk5ZQteuKJ5iorANUC0dKWw1mWTg== + dependencies: + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-endpoints" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/node-config-provider@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.254.0.tgz#0919e198e28144a85f97928ceccaf509db796a5b" @@ -550,6 +2042,36 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/node-config-provider@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.338.0.tgz#930546e2d5494e51d8c645c6d364e8c4a2ae033c" + integrity sha512-YO7yWg3ipnUI5u6D+Zn2NUpjj5krwc8zNWeY79ULVIp9g7faqGX3xMSjeRSrpZ83s5jg1dOm/+bB0gw7mCrRCw== + dependencies: + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/shared-ini-file-loader" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/node-config-provider@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.341.0.tgz#5320d51d00cddd4ca212eb96e96d80de244277a0" + integrity sha512-Le/WSf9t0ItrHuGhOlEPiA+J/nYpYJaC1WgLefRG9j17xKF/fp7X+XSylF1xQ+cOMbHFMi7SNcXRhyfwFreU0w== + dependencies: + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/shared-ini-file-loader" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/node-config-provider@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.342.0.tgz#ef4bb4642e885c7f634af358c9312809373c67ca" + integrity sha512-Mwkj4+zt64w7a8QDrI9q4SrEt7XRO30Vk0a0xENqcOGrKIPfF5aeqlw85NYLoGys+KV1oatqQ+k0GzKx8qTIdQ== + dependencies: + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/node-http-handler@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.254.0.tgz#5007434b0ed387f110639cf74f7cbb6abebd6e68" @@ -561,6 +2083,50 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/node-http-handler@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.338.0.tgz#3a7332ca68a08f72311ec99d64e7c5a0fcff1e64" + integrity sha512-V1BLzCruiv45tJ0vXjiamY8LncIsUFsXYJGDupomFYhWRN8L1MUB9f2vdKn5X3wXn/yKrluwTmNaryrIqd9akA== + dependencies: + "@aws-sdk/abort-controller" "3.338.0" + "@aws-sdk/protocol-http" "3.338.0" + "@aws-sdk/querystring-builder" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/node-http-handler@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.341.0.tgz#91eb7126dd84e713b0e42160490cc7a757c1c084" + integrity sha512-pXkX1amhWhkgffs76bf+pR814JnBUa199Nb6Wm2l20LLPgSsQrRX0IwucM/KtAdEhFeJTR8bLhRJBzrm3ONMwQ== + dependencies: + "@aws-sdk/abort-controller" "3.341.0" + "@aws-sdk/protocol-http" "3.341.0" + "@aws-sdk/querystring-builder" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/node-http-handler@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.342.0.tgz#6bd98ea8c81a477a87ff65c38bb9560ea6565d0d" + integrity sha512-ieNdrfJJMh46qY6rkV1azJBo3UfS9hc7d8CuHtkgHhCfH3BhxbtFqEiGilOdBmY5Sk69b//lFr4zHpUPYsXKaA== + dependencies: + "@aws-sdk/abort-controller" "3.342.0" + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/querystring-builder" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/node-http-handler@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.344.0.tgz#df6a167a583a1fcf968dfec8480e618874930113" + integrity sha512-04o5rrFBd8VzzN0Pcs7EEsyC6dz1maILbA6vdXrDvVLYqaO40Tpx2E/3KA/jZtOpHcGXxgDw2rv1kjJesoiEMw== + dependencies: + "@aws-sdk/abort-controller" "3.342.0" + "@aws-sdk/protocol-http" "3.342.0" + "@aws-sdk/querystring-builder" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/property-provider@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.254.0.tgz#4c815471e0aade6644b2923bb3c1a26c1e2cb1e8" @@ -569,6 +2135,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/property-provider@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.338.0.tgz#88b6f6be61d09f26277c1982bfd10f499870393d" + integrity sha512-mC+ZJ738ipif6ZkH59gcipozYj1FOfpXr9pGVCA2hJGLDdaBwI2Jfpb2qCqbsTNtoCjBuIy+sQHGmUHyclgYHg== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/property-provider@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.341.0.tgz#e9de4670a592f24eebc35d1ea50cccb4ec7d2993" + integrity sha512-5Ynks9iUS/VJcZa/J3c5G+XAaUw4SkWltQp4Y7dzWpJXS3AaUm9gby7DsWYopbH5dLeeSmvKENHTsKpsM5pQoQ== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/property-provider@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.342.0.tgz#04acca6ddb0dec6fdc190ef28ef5c19af192629f" + integrity sha512-p4TR9yRakIpwupEH3BUijWMYThGG0q43n1ICcsBOcvWZpE636lIUw6nzFlOuBUwqyPfUyLbXzchvosYxfCl0jw== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/protocol-http@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.254.0.tgz#b1ea17a599e50f30a3fc252de7aa4ced1f99acdd" @@ -577,6 +2167,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/protocol-http@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.338.0.tgz#0d3e20881dfb5a00daa246e79a2c0da0a088489b" + integrity sha512-JX03Q2gshdzOWtA/07kdpk0hqeOrOfwuF8TB97g66VCcIopYQkCeNH1zzkWu+RsGxfSlzQ7up+ZM6sclYXyB1A== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/protocol-http@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.341.0.tgz#f8b23d7c895139c117dbd33426d78082dd5b7114" + integrity sha512-Av+qcOA+gYXWgYYtzbTn2goHGlNdt+nbrzhUI6dWczYPzBe8aNnMR5d/ACNt0mD7O41muULmSTQBHOKBmOmNJA== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/protocol-http@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.342.0.tgz#2f4852a1ff14491f8785ca094684e7fcd80db4e5" + integrity sha512-zuF2urcTJBZ1tltPdTBQzRasuGB7+4Yfs9i5l0F7lE0luK5Azy6G+2r3WWENUNxFTYuP94GrrqaOhVyj8XXLPQ== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/querystring-builder@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.254.0.tgz#e542ca41e9b24828a92087d24e1f37aec1c3c4b3" @@ -586,6 +2200,33 @@ "@aws-sdk/util-uri-escape" "3.201.0" tslib "^2.3.1" +"@aws-sdk/querystring-builder@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.338.0.tgz#2f8668d3bfb1cf9c49876116a07902b17025da8f" + integrity sha512-IB3YhO93Htwt2SxJx4VWsN57Rt1KEsvZ6PbneO4bcS96E04BlfBujYMZ+QxEM3EJxorhpkwbI2QnI12IjD8FhA== + dependencies: + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-uri-escape" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/querystring-builder@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.341.0.tgz#14fdd5500aab1d9b4c9a0c498242ba828bd86795" + integrity sha512-71RNU1VB8tSfqeu9t61YWDmMS/5C9NH8ua6LXb5HGzlnq68BSLq3lGa4zx/h2K0OpZ6ERUORFdw6pmqA17pDmg== + dependencies: + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-uri-escape" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/querystring-builder@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.342.0.tgz#1163c1b9ec901b1264911be504a42638113f1002" + integrity sha512-tb3FbtC36a7XBYeupdKm60LeM0etp73I6/7pDAkzAlw7zJdvY0aQIvj1c0U6nZlwZF8sSSxC7vlamR+wCspdMw== + dependencies: + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-uri-escape" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/querystring-parser@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.254.0.tgz#ebca5a4e78bb5ad4e2e6a44447083d09212cf450" @@ -594,11 +2235,50 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/querystring-parser@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.338.0.tgz#6b376b0b05b773d8ce8271a1d80593d1af94234c" + integrity sha512-vtI8Gqx4yj0BZlWonRMgLz68sHt5H48HN+ClnY+fDDB/8KLnCuwZ3TGKmYIbYbshL9wjJz0A9aLzuC6nPQ5JKw== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/querystring-parser@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.341.0.tgz#d97660c7cf5fbeaec3005e4a7c4029557fd0ccee" + integrity sha512-7O61bRUdo2x73TTeyyriibLpx9tUPO13gBdI9oHpJTZEkOiUYxoxjMdo5s7ofis12MdmzelqIUjPmAvJNtB5wA== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/querystring-parser@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.342.0.tgz#20b3e13cb727171045625c1fbb87e351f300bb20" + integrity sha512-6svvr/LZW1EPJaARnOpjf92FIiK25wuO7fRq05gLTcTRAfUMDvub+oDg3Ro9EjJERumrYQrYCem5Qi4X9w8K2g== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/service-error-classification@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.254.0.tgz#1cf2a2e79fd73d48e751207e25527988dd6716d1" integrity sha512-8GHqMJBBF9yoMBG/Nf9PusUSMFjG8ygps/cSJPlgcG2vbFn8BCdBZVc4ptXqICZUnBB/6lrxy8nCmNUaru48jg== +"@aws-sdk/service-error-classification@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.338.0.tgz#67d009b177fb03133fdfacbcd98b054dd34efbf0" + integrity sha512-BJFr2mx/N3NbycGTlMMGRBc0tGcHXHEbMPy1H2RbejzL23zh27MchaL1WAK9SvwVMKS29hSDbhkuVR2ABRjerA== + +"@aws-sdk/service-error-classification@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.341.0.tgz#ebdf95fcf9817b68c61f22d184f703ba62471b79" + integrity sha512-mqf9rV/j8Ry2RWDQsaJDPyDm/VDQ4ZDdmi8rzm/AeSgEDaNWublt31zlWtgUWfjISfTtbBgzI48n6ZBJqyYmUA== + +"@aws-sdk/service-error-classification@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.342.0.tgz#6ddb08a7976bc93cfafab4584719883baa787f6f" + integrity sha512-MwHO5McbdAVKxfQj1yhleboAXqrzcGoi9ODS+bwCwRfe2lakGzBBhu8zaGDlKYOdv5rS+yAPP/5fZZUiuZY8Bw== + "@aws-sdk/shared-ini-file-loader@3.254.0", "@aws-sdk/shared-ini-file-loader@^3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.254.0.tgz#1d26b8d98541755dc6a4b8027110fea2b86b6257" @@ -607,6 +2287,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/shared-ini-file-loader@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.338.0.tgz#c443df5fea13fe42785c2dc93bec312aa32d803d" + integrity sha512-MA1Sp97LFlOXcUaXgo47j86IsPRWYq1V/JqR+uu0zofZw4Xlt7Y6F+mmnDHvuuMy6R2ltzjXSwgrrW3k0bxFPA== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/shared-ini-file-loader@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.341.0.tgz#efdfff8bd12cf60f7f5906f647839bbe067715e2" + integrity sha512-/ikCc2XRL8zG//EB2g6SXFvMMa7KD2T8RpM4dYEisdvHDoF9khVX3/SLLUs2Y32rr1x9tnh7X9DdV8lX9MP/ZA== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/shared-ini-file-loader@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.342.0.tgz#395c3cad50c831979751842e81eefbf1cee55d35" + integrity sha512-kQG7TMQMhNp5+Y8vhGuO/+wU3K/dTx0xC0AKoDFiBf6EpDRmDfr2pPRnfJ9GwgS9haHxJ/3Uwc03swHMlsj20A== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/signature-v4@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.254.0.tgz#a68a1f420c98cbfe1d5f15227172d26bb7980338" @@ -620,6 +2324,46 @@ "@aws-sdk/util-utf8" "3.254.0" tslib "^2.3.1" +"@aws-sdk/signature-v4@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.338.0.tgz#3d5402ee10027958c5271b390c0966683d681a53" + integrity sha512-EwKTe/8Iwab/v0eo27w7DRYlqp9wEZEhuRfOMwTikUVH6iuTnW6AXjcIUfcRYBRbx2zqnRSiMAZkjN6ZFYm0bQ== + dependencies: + "@aws-sdk/is-array-buffer" "3.310.0" + "@aws-sdk/types" "3.338.0" + "@aws-sdk/util-hex-encoding" "3.310.0" + "@aws-sdk/util-middleware" "3.338.0" + "@aws-sdk/util-uri-escape" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/signature-v4@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.341.0.tgz#3ebf018adfcbd1a5e097e545aa9ef4819a54b7c4" + integrity sha512-4nWgDiw68lEFBwrQY1JsKBvcMmcRhClpWzi3iKHwU1PJogId6g4XRU89Zo0QzBQihmFZIKklRSF/150pbNGdcg== + dependencies: + "@aws-sdk/is-array-buffer" "3.310.0" + "@aws-sdk/types" "3.341.0" + "@aws-sdk/util-hex-encoding" "3.310.0" + "@aws-sdk/util-middleware" "3.341.0" + "@aws-sdk/util-uri-escape" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/signature-v4@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.342.0.tgz#c2249594c53c76891986e3a54a077062a0b55b63" + integrity sha512-OWrGO2UOa1ENpy0kYd2shK4sklQygWUqvWLx9FotDbjIeUIEfAnqoPq/QqcXVrNyT/UvPi4iIrjHJEO8JCNRmA== + dependencies: + "@aws-sdk/eventstream-codec" "3.342.0" + "@aws-sdk/is-array-buffer" "3.310.0" + "@aws-sdk/types" "3.342.0" + "@aws-sdk/util-hex-encoding" "3.310.0" + "@aws-sdk/util-middleware" "3.342.0" + "@aws-sdk/util-uri-escape" "3.310.0" + "@aws-sdk/util-utf8" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/smithy-client@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.254.0.tgz#053bb490fe6db91ce90471e285e37c8adb77440c" @@ -629,6 +2373,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/smithy-client@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.338.0.tgz#fc391b1fd57e1c002cae2bc93db6e931312a6a59" + integrity sha512-IpFLdLG8GwaiFdqVXf+WyU47Hfa2BMIupAU6iSkE2ZO0lBdg+efn/BBwis5WbBNTDCaaU0xH9y68SmnqqtD7pA== + dependencies: + "@aws-sdk/middleware-stack" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/smithy-client@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.341.0.tgz#ef120806d76ff2dfc942d9694c7b976b02f5a7f7" + integrity sha512-4ReKR+UciZ012W8OimFZfGy1LRZeWcl/i7h6lTIiXasni4Q+5k1rqneCRtJpBgfB5YbJg4EawmWxsxChrX9pwQ== + dependencies: + "@aws-sdk/middleware-stack" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/smithy-client@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.342.0.tgz#976ec7ca4e029145707c33d6300d60efcee53214" + integrity sha512-HQ4JejjHU2X7OAZPwixFG+EyPSjmoZqll7EvWjPSKyclWrM320haWWz1trVzjG/AgPfeDLfRkH/JoMr13lECew== + dependencies: + "@aws-sdk/middleware-stack" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/token-providers@3.256.0": version "3.256.0" resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.256.0.tgz#a07ddab7649ff70ccb5dc419d0d457553531dc56" @@ -640,6 +2411,50 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/token-providers@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.338.0.tgz#7df35becb85bb689e0de51a0cad27f7978f3fb8a" + integrity sha512-wuiEGcWiMeq5N68M489i2iGYcCad9p1btNEOFgus+JO3DRSA6HZXizLI1wqfbUm5Ei8512AvUKB6N8PMzahQsg== + dependencies: + "@aws-sdk/client-sso-oidc" "3.338.0" + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/shared-ini-file-loader" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.341.0.tgz#1d16210b8cabbc8a1a5e9f3d96a10d9c3c09dc77" + integrity sha512-PNskQMWVV6hUTPZmwcfAU0nknY0+Ge60ZVdNx6B4bpor6oEXl/jUCDOmymyHJl85LiIN7AZDrwq1gpdsDDVhZw== + dependencies: + "@aws-sdk/client-sso-oidc" "3.341.0" + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/shared-ini-file-loader" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.342.0.tgz#3e8af8ab0ee27b2bd17d17f48c91f88bd4c06590" + integrity sha512-gYShxImNQVx3FYOUKB7nzzowYiiP1joyx43KrduHwBDV7hiqg7QhtJHr6Ek+QLPqcFKP9rRvo7NhGxu+T7dEQg== + dependencies: + "@aws-sdk/client-sso-oidc" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.344.0": + version "3.344.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.344.0.tgz#94cda399c22d7c0e3082d6698d844878bdd4d90f" + integrity sha512-xal48wStqjmsjrtA2cgJbwtT9dIIrwqOfhuoAPurg8wF0CRXgyBZUeeeWxjR7rMFE2LEknb6QmFKRpWU6VrNJw== + dependencies: + "@aws-sdk/client-sso-oidc" "3.344.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/shared-ini-file-loader" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/types@3.254.0", "@aws-sdk/types@^3.222.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.254.0.tgz#760b4a876efa2edcec191dd8b18b989fa717a42e" @@ -647,6 +2462,27 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/types@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.338.0.tgz#2b14c063f3be09d2465fe23fd2554ce2287fbeca" + integrity sha512-hrNK15o+EObLrl9oWOyxJN2dwjgbdBMGolLEVP/wR/+M9ojHgk/x1kMsCVcV82a8Vgdtqx1TyOC3UugUPT0+NA== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/types@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.341.0.tgz#b4282a2d3a9f7ae85650a4b61a80326588ca9400" + integrity sha512-2KJf64BhJly/Ty35oWKlCElIqUP4kQ0LA+meSrgAmwl7oE0AYuO7V0ar1nsTGlsubYkLRvOuEhMcuNuumaUdoQ== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/types@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.342.0.tgz#0bcba3b5966f28e0725122697a19ece8647afbec" + integrity sha512-5uyXVda/AgUpdZNJ9JPHxwyxr08miPiZ/CKSMcRdQVjcNnrdzY9m/iM9LvnQT44sQO+IEEkF2IoZIWvZcq199A== + dependencies: + tslib "^2.5.0" + "@aws-sdk/url-parser@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.254.0.tgz#4b1fd769a4c546bd6571181feac2be1e8feaacab" @@ -656,6 +2492,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/url-parser@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.338.0.tgz#ef7bee904d55dc2a55a819028dec63d7e4c1128f" + integrity sha512-x8a5swfZ6iWJZEA8rm99OKQ1A6xhWPP1taQUzoPavGCzPAOqyc8cd0FcXYMxvtXb3FeBhGaI8tiGKvelJro0+A== + dependencies: + "@aws-sdk/querystring-parser" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/url-parser@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.341.0.tgz#468acdc289485edbd200967855b170d39fd32a32" + integrity sha512-pAT+4Yp3NkHKnLhYjbFj9DGKTRavBIVoe0fbQLm1G/MD11FAlUOlswf5EYFjgz0wfdgnbyFE3ai837/eO0fGjw== + dependencies: + "@aws-sdk/querystring-parser" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/url-parser@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.342.0.tgz#c0be80c1d88b0ff8a8224de0ff7de64ccd5ef186" + integrity sha512-r4s/FDK6iywl8l4TqEwIwtNvxWO0kZes03c/yCiRYqxlkjVmbXEOodn5IAAweAeS9yqC3sl/wKbsaoBiGFn45g== + dependencies: + "@aws-sdk/querystring-parser" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/util-base64@3.208.0": version "3.208.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz#36b430e5396251f761590f7c2f0c5c12193f353c" @@ -664,6 +2527,14 @@ "@aws-sdk/util-buffer-from" "3.208.0" tslib "^2.3.1" +"@aws-sdk/util-base64@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64/-/util-base64-3.310.0.tgz#d0fd49aff358c5a6e771d0001c63b1f97acbe34c" + integrity sha512-v3+HBKQvqgdzcbL+pFswlx5HQsd9L6ZTlyPVL2LS9nNXnCcR3XgGz9jRskikRUuUvUXtkSG1J88GAOnJ/apTPg== + dependencies: + "@aws-sdk/util-buffer-from" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/util-body-length-browser@3.188.0": version "3.188.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz#e1d949318c10a621b38575a9ef01e39f9857ddb0" @@ -671,6 +2542,13 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/util-body-length-browser@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.310.0.tgz#3fca9d2f73c058edf1907e4a1d99a392fdd23eca" + integrity sha512-sxsC3lPBGfpHtNTUoGXMQXLwjmR0zVpx0rSvzTPAuoVILVsp5AU/w5FphNPxD5OVIjNbZv9KsKTuvNTiZjDp9g== + dependencies: + tslib "^2.5.0" + "@aws-sdk/util-body-length-node@3.208.0": version "3.208.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz#baabd1fa1206ff2bd4ce3785122d86eb3258dd20" @@ -678,6 +2556,13 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/util-body-length-node@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.310.0.tgz#4846ae72834ab0636f29f89fc1878520f6543fed" + integrity sha512-2tqGXdyKhyA6w4zz7UPoS8Ip+7sayOg9BwHNidiGm2ikbDxm1YrCfYXvCBdwaJxa4hJfRVz+aL9e+d3GqPI9pQ== + dependencies: + tslib "^2.5.0" + "@aws-sdk/util-buffer-from@3.208.0": version "3.208.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz#285e86f6dc9030148a4147d65239e75cb254a1b0" @@ -686,6 +2571,14 @@ "@aws-sdk/is-array-buffer" "3.201.0" tslib "^2.3.1" +"@aws-sdk/util-buffer-from@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz#7a72cb965984d3c6a7e256ae6cf1621f52e54a57" + integrity sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw== + dependencies: + "@aws-sdk/is-array-buffer" "3.310.0" + tslib "^2.5.0" + "@aws-sdk/util-config-provider@3.208.0": version "3.208.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz#c485fd83fbac051337e5f6be60ea3f9fa61c0139" @@ -693,6 +2586,13 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/util-config-provider@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.310.0.tgz#ff21f73d4774cfd7bd16ae56f905828600dda95f" + integrity sha512-xIBaYo8dwiojCw8vnUcIL4Z5tyfb1v3yjqyJKJWV/dqKUFOOS0U591plmXbM+M/QkXyML3ypon1f8+BoaDExrg== + dependencies: + tslib "^2.5.0" + "@aws-sdk/util-defaults-mode-browser@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.254.0.tgz#6baa31a48521f2758f919130e0bd5180b179c7ad" @@ -703,6 +2603,36 @@ bowser "^2.11.0" tslib "^2.3.1" +"@aws-sdk/util-defaults-mode-browser@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.338.0.tgz#6cdeec6c5f702a61cc4ce79471789162d0b39c4b" + integrity sha512-Zfr5c7JKMJTfb7z+hgd0ioU5iw+wId6Cppc5V1HpZuS2YY4Mn3aJIixzyzhIoCzbmk/yIkf96981epM9eo3/TA== + dependencies: + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/types" "3.338.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-defaults-mode-browser@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.341.0.tgz#eee0afa53564458be93e2085b8f6311f6f95ad79" + integrity sha512-FjZg0T/7lcEgeMTdC8iMaNcHlHwqVzS0FlyUdJrMZqXEo70h3KlByijv8N9VlV8XQUfiCPuTNlhpLpDEDMdtbw== + dependencies: + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/types" "3.341.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-defaults-mode-browser@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.342.0.tgz#309b8191801f31647b259c8f8cf30de9b47895df" + integrity sha512-N1ZRvCLbrt4Re9MKU3pLYR0iO+H7GU7RsXG4yAq6DtSWT9WCw6xhIUpeV2T5uxWKL92o3WHNiGjwcebq+N73Bg== + dependencies: + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/types" "3.342.0" + bowser "^2.11.0" + tslib "^2.5.0" + "@aws-sdk/util-defaults-mode-node@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.254.0.tgz#e92b3196ddc93fe5851b584aa5ac7fb22215d0ba" @@ -715,6 +2645,42 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/util-defaults-mode-node@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.338.0.tgz#cb87b039f90d124e70a53769ae1ebbce6d253f3c" + integrity sha512-DFM3BSpSetshZTgTjueCkAYZWS0tn5zl7SjkSpFhWQZ8Tt/Df3/DEjcPvxzmC/5vgYSUXNsqcI7lLAJk9aGZAA== + dependencies: + "@aws-sdk/config-resolver" "3.338.0" + "@aws-sdk/credential-provider-imds" "3.338.0" + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/property-provider" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/util-defaults-mode-node@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.341.0.tgz#1dfb67b3a6d679be1340368b0ffa9a268053f996" + integrity sha512-I943vmtUHqOdHvWCCnO3Vv/XXKCZ4O3XPNl9jvIC8m0n6CXqf7qjs9R72t3PQCTBAbsbIRGfkKMKfH2ab5ci/g== + dependencies: + "@aws-sdk/config-resolver" "3.341.0" + "@aws-sdk/credential-provider-imds" "3.341.0" + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/property-provider" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/util-defaults-mode-node@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.342.0.tgz#ddd7180ff1cf0429be6077a2b67856fa6088eb4c" + integrity sha512-yNa/eX8sELnwM5NONOFR/PCJMHTNrUVklSo/QHy57CT/L3KOqosRNAMnDVMzH1QolGaVN/8jgtDI2xVsvlP+AA== + dependencies: + "@aws-sdk/config-resolver" "3.342.0" + "@aws-sdk/credential-provider-imds" "3.342.0" + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/property-provider" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/util-endpoints@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.254.0.tgz#b21eed05e60210ac533ed96784d039015295895d" @@ -723,6 +2689,30 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/util-endpoints@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.338.0.tgz#f54c09b06daa8dd1bd96e479ebda3b21492631ea" + integrity sha512-0gBQcohbNcBsBR7oyaD0Dg2m6qOmfp0G1iN/NM23gwAr2H3ni8tUXfs1HsZzxikOwUr6dSLASokc30vQXBF44A== + dependencies: + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/util-endpoints@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.341.0.tgz#7a6117f0fc83376c5d1a112d52f9ce188523c046" + integrity sha512-J15adxRV+YwWasOcCHDZoxXXQS7l8yBgWbId2ozGond/GwHifKhElF0RX9QKB4R/Vq1Cj7WVTyQsugYJAlLWrw== + dependencies: + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/util-endpoints@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.342.0.tgz#19aa3176c6f3d7e35d5a6f02d5808c6129ea24f2" + integrity sha512-ZsYF413hkVwSOjvZG6U0SshRtzSg6MtwzO+j90AjpaqgoHAxE5LjO5eVYFfPXTC2U8NhU7xkzASY6++e5bRRnw== + dependencies: + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/util-hex-encoding@3.201.0": version "3.201.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz#21d7ec319240ee68c33d938e71cb79830bea315d" @@ -730,6 +2720,13 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/util-hex-encoding@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz#19294c78986c90ae33f04491487863dc1d33bd87" + integrity sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA== + dependencies: + tslib "^2.5.0" + "@aws-sdk/util-locate-window@^3.0.0": version "3.208.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz#0f598fc238a1256e4bcb64d01459f03a922dd4c3" @@ -744,6 +2741,27 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/util-middleware@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.338.0.tgz#3b405eba916285a7764885376e0d16f973efdf98" + integrity sha512-oQuAmhi16HWEqVa+Nq4VD4Ymet9vS+uiW92reaagQrW2QFjAgJW9A6pU0PcIHF9sWY1iDKeNdV5b9odQ45PDJA== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-middleware@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.341.0.tgz#1012412783e66b6e6056f8373604f0a4f0e79b9e" + integrity sha512-JsuZGZw9pMYMHzaJW31Y3Zl1Dh/R2PNVxnlQPsPy37RhHoSLPZ6wR9G828Y1ZY2thBpR+DU3D/VfNJOxBmWGkw== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-middleware@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.342.0.tgz#db8f50136bcba3d480d5c8e5340aecaa1e1c3a6c" + integrity sha512-P2LYyMP4JUFZBy9DcMvCDxWU34mlShCyrqBZ1ouuGW7UMgRb1PTEvpLAVndIWn9H+1KGDFjMqOWp1FZHr4YZOA== + dependencies: + tslib "^2.5.0" + "@aws-sdk/util-retry@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.254.0.tgz#c4cdf051439b4c12d1865dd2944b9eeb1d489bcc" @@ -752,6 +2770,30 @@ "@aws-sdk/service-error-classification" "3.254.0" tslib "^2.3.1" +"@aws-sdk/util-retry@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.338.0.tgz#c71c8a52033a619896296c532246f67703ef9ef9" + integrity sha512-diR6M3gJgSgBg/87L2e8iF8urG+LOW9ZGWxhntYpYX4uhiIjwNgUPUa993553C8GIOZDHez5X9ExU4asYGQ71Q== + dependencies: + "@aws-sdk/service-error-classification" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/util-retry@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.341.0.tgz#d4a753ccb37982f5b27c0115de61ec9f2d219f94" + integrity sha512-UxAZiajjj65Zi9Q8PJ53vGydsa6dv9ZJC+bfO70czGGTWjB+L7kb2UoRdtGo9NBzRTFYXV6OjP6yBw5yFb39kw== + dependencies: + "@aws-sdk/service-error-classification" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/util-retry@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.342.0.tgz#9451a6809a51b9915661fcbea0335c89f24eab4e" + integrity sha512-U1LXXtOMAQjU4H9gjYZng8auRponAH0t3vShHMKT8UQggT6Hwz1obdXUZgcLCtcjp/1aEK4MkDwk2JSjuUTaZw== + dependencies: + "@aws-sdk/service-error-classification" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/util-uri-escape@3.201.0": version "3.201.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz#5e708d4cde001a4558ee616f889ceacfadd2ab03" @@ -759,6 +2801,13 @@ dependencies: tslib "^2.3.1" +"@aws-sdk/util-uri-escape@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz#9f942f09a715d8278875013a416295746b6085ba" + integrity sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q== + dependencies: + tslib "^2.5.0" + "@aws-sdk/util-user-agent-browser@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.254.0.tgz#a1e7783d4210eb6f4cfda3e6c9403e4a565f8244" @@ -768,6 +2817,33 @@ bowser "^2.11.0" tslib "^2.3.1" +"@aws-sdk/util-user-agent-browser@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.338.0.tgz#51d78d6fa7a071211260814aaa86bc24c7f7765c" + integrity sha512-3e8D+SOtOQEtRtksOEF7EC26xPkuY6YK6biLgdtvR9JspK96rHk5eX1HEJeBJJqbxhyPaxpIw+OhWhnsrUS3hA== + dependencies: + "@aws-sdk/types" "3.338.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-browser@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.341.0.tgz#f61c64a34a4bca51e7d20b1630abf0919d91bf05" + integrity sha512-VCgWM03lbcfjBQFhJJcF7Gs+XKxdtSYuK5txFiXy/glin5eCY+9VB3vqMrYwvEgIlwZynUYXvh9+OkU2AeRaBg== + dependencies: + "@aws-sdk/types" "3.341.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-browser@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.342.0.tgz#7127e523973b382d98c916ae069285eb48a01d8b" + integrity sha512-FWHiBi1xaebzmq3LJsizgd2LCix/bKHUTOjTeO6hEYny5DyrOl0liwIA0mqgvfgwIoMOF/l6FGg7kTfKtNgkEA== + dependencies: + "@aws-sdk/types" "3.342.0" + bowser "^2.11.0" + tslib "^2.5.0" + "@aws-sdk/util-user-agent-node@3.254.0": version "3.254.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.254.0.tgz#044de697c3e7d151ecb80ccef529fec345e4c440" @@ -777,6 +2853,33 @@ "@aws-sdk/types" "3.254.0" tslib "^2.3.1" +"@aws-sdk/util-user-agent-node@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.338.0.tgz#e321e70da741356b348f4f0921a8bc94ad18320d" + integrity sha512-rc+bC5KM9h25urRc+MXuViJkJ+qYG2NlCRw6xm2lSIvHFJTUjH1ZMO3mqNDYkGnQRbj0mmrVe+N77TJZGf3Q2Q== + dependencies: + "@aws-sdk/node-config-provider" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-node@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.341.0.tgz#2703938b1d094ceaada99e07927b96788fcdb038" + integrity sha512-ac1VcSQOn4fhif51hoSZtrfkFGZHNqXXv2mWzNo1xgsyDwCJh2/H6fPBBGtjT3TNc/o5yOuyBFRP4BIjJ5GkPA== + dependencies: + "@aws-sdk/node-config-provider" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-node@3.342.0": + version "3.342.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.342.0.tgz#5b8e849b83e9fbaae5664e2e0c284892093af783" + integrity sha512-YMAhUar4CAB6hfUR72FH0sRqMBhPajDIhiKrZEOy7+qaWFdfb/t9DYi6p3PYIUZWK2vkESiDoX9Ays2xsp9rOQ== + dependencies: + "@aws-sdk/node-config-provider" "3.342.0" + "@aws-sdk/types" "3.342.0" + tslib "^2.5.0" + "@aws-sdk/util-utf8-browser@3.188.0", "@aws-sdk/util-utf8-browser@^3.0.0": version "3.188.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz#484762bd600401350e148277731d6744a4a92225" @@ -800,6 +2903,32 @@ "@aws-sdk/util-buffer-from" "3.208.0" tslib "^2.3.1" +"@aws-sdk/util-utf8@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz#4a7b9dcebb88e830d3811aeb21e9a6df4273afb4" + integrity sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA== + dependencies: + "@aws-sdk/util-buffer-from" "3.310.0" + tslib "^2.5.0" + +"@aws-sdk/util-waiter@3.338.0": + version "3.338.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.338.0.tgz#a7f2906fbd624a114e329f1517c8f3e2e9b76bc6" + integrity sha512-15yWYJo/M4VDpZjlXgQDM4Du8UjX33eIVPJDrOmn/u+UrD6QUXoBuLXKns0uAMUTPFacBGZ0NwMywxieq0g11Q== + dependencies: + "@aws-sdk/abort-controller" "3.338.0" + "@aws-sdk/types" "3.338.0" + tslib "^2.5.0" + +"@aws-sdk/util-waiter@3.341.0": + version "3.341.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.341.0.tgz#7478b2270908e5315d32ae290ca64d799b4db4b4" + integrity sha512-YNKFk3xwq3lgyZ+udgvwACE0thV6bWtSBeEoSuVIOVz6yR0Td9NsA+5gOBgAMKLWSoWP/4II57+ZnEEuhuyzzg== + dependencies: + "@aws-sdk/abort-controller" "3.341.0" + "@aws-sdk/types" "3.341.0" + tslib "^2.5.0" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -1345,10 +3474,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cloudgraph/sdk@^0.22.1": - version "0.22.1" - resolved "https://registry.yarnpkg.com/@cloudgraph/sdk/-/sdk-0.22.1.tgz#bf5c2f263df17b085147a3ca234ac5b0a8806545" - integrity sha512-aMrnoTRRIODAVvgtmqGZPB7Z8x1kMgKjFtLjpiHa121o0GCEZCjbxDmU8T3DwmRwI1u4QD5iKbXf9dB0573mJA== +"@cloudgraph/sdk@^0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@cloudgraph/sdk/-/sdk-0.23.0.tgz#3f6012c0e3573f527da27ebcccb8841bbeffd21b" + integrity sha512-c+Ozu8yLK3RlAcKy4d0fdTQc9JkdUJ2ESmrcW7oC5XdIARrDWQ5+Kr8AGPABOK1/UYtFyVR2JmUHnoSJdGAv6Q== dependencies: "@graphql-tools/load-files" "^6.5.3" "@graphql-tools/merge" "^8.2.1" @@ -2520,6 +4649,21 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@smithy/protocol-http@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-1.0.1.tgz#62fd73d73db285fd8e9a2287ed2904ac66e0d43f" + integrity sha512-9OrEn0WfOVtBNYJUjUAn9AOiJ4lzERCJJ/JeZs8E6yajTGxBaFRxUnNBHiNqoDJVg076hY36UmEnPx7xXrvUSg== + dependencies: + "@smithy/types" "^1.0.0" + tslib "^2.5.0" + +"@smithy/types@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.0.0.tgz#87ab6131fe5e19cbd4d383ffb94d2b806d027d38" + integrity sha512-kc1m5wPBHQCTixwuaOh9vnak/iJm21DrSf9UK6yDE5S3mQQ4u11pqAUiKWnlrZnYkeLfAI9UEHj9OaMT1v5Umg== + dependencies: + tslib "^2.5.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -3170,9 +5314,9 @@ available-typed-arrays@^1.0.5: integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== aws-sdk@^2.1084.0: - version "2.1261.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1261.0.tgz#838657b29348feee067b887e352e488331590c1b" - integrity sha512-Lumifi52Vj6ss1tlZ9Z+BvJ+Yk2MTwPQyrDCZh79xggFgXYoDU/g4rZUr47/1AXBZje3mVkLeRM15hvUwKlTaA== + version "2.1384.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1384.0.tgz#b8a642a849af25dbfed42818c162c30ab04dfbac" + integrity sha512-5b1ShZ8508yamZKjpRJJlMcztH2EBxnuH8KZObEH4FY/+pHqGIfUtrSVO0IaPNj7RmOnQJ93zCzBc7dhTnEK4A== dependencies: buffer "4.9.2" events "1.1.1" @@ -3183,7 +5327,7 @@ aws-sdk@^2.1084.0: url "0.10.3" util "^0.12.4" uuid "8.0.0" - xml2js "0.4.19" + xml2js "0.5.0" babel-jest@^27.5.1: version "27.5.1" @@ -4886,6 +7030,13 @@ fast-xml-parser@4.0.11: dependencies: strnum "^1.0.5" +fast-xml-parser@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz#5a98c18238d28a57bbdfa9fe4cda01211fff8f4a" + integrity sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -9721,6 +11872,11 @@ tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== +tslib@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" + integrity sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -10228,18 +12384,18 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== +xml2js@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== dependencies: sax ">=0.6.0" - xmlbuilder "~9.0.1" + xmlbuilder "~11.0.0" -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== xmlchars@^2.2.0: version "2.2.0"