runbooks 0.2.5__py3-none-any.whl → 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. conftest.py +26 -0
  2. jupyter-agent/.env.template +2 -0
  3. jupyter-agent/.gitattributes +35 -0
  4. jupyter-agent/README.md +16 -0
  5. jupyter-agent/app.py +256 -0
  6. jupyter-agent/cloudops-agent.png +0 -0
  7. jupyter-agent/ds-system-prompt.txt +154 -0
  8. jupyter-agent/jupyter-agent.png +0 -0
  9. jupyter-agent/llama3_template.jinja +123 -0
  10. jupyter-agent/requirements.txt +9 -0
  11. jupyter-agent/utils.py +409 -0
  12. runbooks/__init__.py +71 -3
  13. runbooks/__main__.py +13 -0
  14. runbooks/aws/ec2_describe_instances.py +1 -1
  15. runbooks/aws/ec2_run_instances.py +8 -2
  16. runbooks/aws/ec2_start_stop_instances.py +17 -4
  17. runbooks/aws/ec2_unused_volumes.py +5 -1
  18. runbooks/aws/s3_create_bucket.py +4 -2
  19. runbooks/aws/s3_list_objects.py +6 -1
  20. runbooks/aws/tagging_lambda_handler.py +13 -2
  21. runbooks/aws/tags.json +12 -0
  22. runbooks/base.py +353 -0
  23. runbooks/cfat/README.md +49 -0
  24. runbooks/cfat/__init__.py +74 -0
  25. runbooks/cfat/app.ts +644 -0
  26. runbooks/cfat/assessment/__init__.py +40 -0
  27. runbooks/cfat/assessment/asana-import.csv +39 -0
  28. runbooks/cfat/assessment/cfat-checks.csv +31 -0
  29. runbooks/cfat/assessment/cfat.txt +520 -0
  30. runbooks/cfat/assessment/collectors.py +200 -0
  31. runbooks/cfat/assessment/jira-import.csv +39 -0
  32. runbooks/cfat/assessment/runner.py +387 -0
  33. runbooks/cfat/assessment/validators.py +290 -0
  34. runbooks/cfat/cli.py +103 -0
  35. runbooks/cfat/docs/asana-import.csv +24 -0
  36. runbooks/cfat/docs/cfat-checks.csv +31 -0
  37. runbooks/cfat/docs/cfat.txt +335 -0
  38. runbooks/cfat/docs/checks-output.png +0 -0
  39. runbooks/cfat/docs/cloudshell-console-run.png +0 -0
  40. runbooks/cfat/docs/cloudshell-download.png +0 -0
  41. runbooks/cfat/docs/cloudshell-output.png +0 -0
  42. runbooks/cfat/docs/downloadfile.png +0 -0
  43. runbooks/cfat/docs/jira-import.csv +24 -0
  44. runbooks/cfat/docs/open-cloudshell.png +0 -0
  45. runbooks/cfat/docs/report-header.png +0 -0
  46. runbooks/cfat/models.py +1026 -0
  47. runbooks/cfat/package-lock.json +5116 -0
  48. runbooks/cfat/package.json +38 -0
  49. runbooks/cfat/report.py +496 -0
  50. runbooks/cfat/reporting/__init__.py +46 -0
  51. runbooks/cfat/reporting/exporters.py +337 -0
  52. runbooks/cfat/reporting/formatters.py +496 -0
  53. runbooks/cfat/reporting/templates.py +135 -0
  54. runbooks/cfat/run-assessment.sh +23 -0
  55. runbooks/cfat/runner.py +69 -0
  56. runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
  57. runbooks/cfat/src/actions/check-config-existence.ts +37 -0
  58. runbooks/cfat/src/actions/check-control-tower.ts +37 -0
  59. runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
  60. runbooks/cfat/src/actions/check-iam-users.ts +50 -0
  61. runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
  62. runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
  63. runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
  64. runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
  65. runbooks/cfat/src/actions/create-backlog.ts +372 -0
  66. runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
  67. runbooks/cfat/src/actions/create-report.ts +616 -0
  68. runbooks/cfat/src/actions/define-account-type.ts +51 -0
  69. runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
  70. runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
  71. runbooks/cfat/src/actions/get-idc-info.ts +34 -0
  72. runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
  73. runbooks/cfat/src/actions/get-org-details.ts +35 -0
  74. runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
  75. runbooks/cfat/src/actions/get-org-ous.ts +35 -0
  76. runbooks/cfat/src/actions/get-regions.ts +22 -0
  77. runbooks/cfat/src/actions/zip-assessment.ts +27 -0
  78. runbooks/cfat/src/types/index.d.ts +147 -0
  79. runbooks/cfat/tests/__init__.py +141 -0
  80. runbooks/cfat/tests/test_cli.py +340 -0
  81. runbooks/cfat/tests/test_integration.py +290 -0
  82. runbooks/cfat/tests/test_models.py +505 -0
  83. runbooks/cfat/tests/test_reporting.py +354 -0
  84. runbooks/cfat/tsconfig.json +16 -0
  85. runbooks/cfat/webpack.config.cjs +27 -0
  86. runbooks/config.py +260 -0
  87. runbooks/finops/__init__.py +88 -0
  88. runbooks/finops/aws_client.py +245 -0
  89. runbooks/finops/cli.py +151 -0
  90. runbooks/finops/cost_processor.py +410 -0
  91. runbooks/finops/dashboard_runner.py +448 -0
  92. runbooks/finops/helpers.py +355 -0
  93. runbooks/finops/main.py +14 -0
  94. runbooks/finops/profile_processor.py +174 -0
  95. runbooks/finops/types.py +66 -0
  96. runbooks/finops/visualisations.py +80 -0
  97. runbooks/inventory/.gitignore +354 -0
  98. runbooks/inventory/ArgumentsClass.py +261 -0
  99. runbooks/inventory/Inventory_Modules.py +6130 -0
  100. runbooks/inventory/LandingZone/delete_lz.py +1075 -0
  101. runbooks/inventory/README.md +1320 -0
  102. runbooks/inventory/__init__.py +62 -0
  103. runbooks/inventory/account_class.py +532 -0
  104. runbooks/inventory/all_my_instances_wrapper.py +123 -0
  105. runbooks/inventory/aws_decorators.py +201 -0
  106. runbooks/inventory/cfn_move_stack_instances.py +1526 -0
  107. runbooks/inventory/check_cloudtrail_compliance.py +614 -0
  108. runbooks/inventory/check_controltower_readiness.py +1107 -0
  109. runbooks/inventory/check_landingzone_readiness.py +711 -0
  110. runbooks/inventory/cloudtrail.md +727 -0
  111. runbooks/inventory/collectors/__init__.py +20 -0
  112. runbooks/inventory/collectors/aws_compute.py +518 -0
  113. runbooks/inventory/collectors/aws_networking.py +275 -0
  114. runbooks/inventory/collectors/base.py +222 -0
  115. runbooks/inventory/core/__init__.py +19 -0
  116. runbooks/inventory/core/collector.py +303 -0
  117. runbooks/inventory/core/formatter.py +296 -0
  118. runbooks/inventory/delete_s3_buckets_objects.py +169 -0
  119. runbooks/inventory/discovery.md +81 -0
  120. runbooks/inventory/draw_org_structure.py +748 -0
  121. runbooks/inventory/ec2_vpc_utils.py +341 -0
  122. runbooks/inventory/find_cfn_drift_detection.py +272 -0
  123. runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
  124. runbooks/inventory/find_cfn_stackset_drift.py +733 -0
  125. runbooks/inventory/find_ec2_security_groups.py +669 -0
  126. runbooks/inventory/find_landingzone_versions.py +201 -0
  127. runbooks/inventory/find_vpc_flow_logs.py +1221 -0
  128. runbooks/inventory/inventory.sh +659 -0
  129. runbooks/inventory/list_cfn_stacks.py +558 -0
  130. runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
  131. runbooks/inventory/list_cfn_stackset_operations.py +734 -0
  132. runbooks/inventory/list_cfn_stacksets.py +453 -0
  133. runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
  134. runbooks/inventory/list_ds_directories.py +354 -0
  135. runbooks/inventory/list_ec2_availability_zones.py +286 -0
  136. runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
  137. runbooks/inventory/list_ec2_instances.py +425 -0
  138. runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
  139. runbooks/inventory/list_elbs_load_balancers.py +411 -0
  140. runbooks/inventory/list_enis_network_interfaces.py +526 -0
  141. runbooks/inventory/list_guardduty_detectors.py +568 -0
  142. runbooks/inventory/list_iam_policies.py +404 -0
  143. runbooks/inventory/list_iam_roles.py +518 -0
  144. runbooks/inventory/list_iam_saml_providers.py +359 -0
  145. runbooks/inventory/list_lambda_functions.py +882 -0
  146. runbooks/inventory/list_org_accounts.py +446 -0
  147. runbooks/inventory/list_org_accounts_users.py +354 -0
  148. runbooks/inventory/list_rds_db_instances.py +406 -0
  149. runbooks/inventory/list_route53_hosted_zones.py +318 -0
  150. runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
  151. runbooks/inventory/list_sns_topics.py +360 -0
  152. runbooks/inventory/list_ssm_parameters.py +402 -0
  153. runbooks/inventory/list_vpc_subnets.py +433 -0
  154. runbooks/inventory/list_vpcs.py +422 -0
  155. runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
  156. runbooks/inventory/models/__init__.py +24 -0
  157. runbooks/inventory/models/account.py +192 -0
  158. runbooks/inventory/models/inventory.py +309 -0
  159. runbooks/inventory/models/resource.py +247 -0
  160. runbooks/inventory/recover_cfn_stack_ids.py +205 -0
  161. runbooks/inventory/requirements.txt +12 -0
  162. runbooks/inventory/run_on_multi_accounts.py +211 -0
  163. runbooks/inventory/tests/common_test_data.py +3661 -0
  164. runbooks/inventory/tests/common_test_functions.py +204 -0
  165. runbooks/inventory/tests/script_test_data.py +0 -0
  166. runbooks/inventory/tests/setup.py +24 -0
  167. runbooks/inventory/tests/src.py +18 -0
  168. runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
  169. runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
  170. runbooks/inventory/tests/test_inventory_modules.py +55 -0
  171. runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
  172. runbooks/inventory/tests/test_moto_integration_example.py +273 -0
  173. runbooks/inventory/tests/test_org_list_accounts.py +49 -0
  174. runbooks/inventory/update_aws_actions.py +173 -0
  175. runbooks/inventory/update_cfn_stacksets.py +1215 -0
  176. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
  177. runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
  178. runbooks/inventory/update_s3_public_access_block.py +539 -0
  179. runbooks/inventory/utils/__init__.py +23 -0
  180. runbooks/inventory/utils/aws_helpers.py +510 -0
  181. runbooks/inventory/utils/threading_utils.py +493 -0
  182. runbooks/inventory/utils/validation.py +682 -0
  183. runbooks/inventory/verify_ec2_security_groups.py +1430 -0
  184. runbooks/main.py +785 -0
  185. runbooks/organizations/__init__.py +12 -0
  186. runbooks/organizations/manager.py +374 -0
  187. runbooks/security_baseline/README.md +324 -0
  188. runbooks/security_baseline/checklist/alternate_contacts.py +8 -1
  189. runbooks/security_baseline/checklist/bucket_public_access.py +4 -1
  190. runbooks/security_baseline/checklist/cloudwatch_alarm_configuration.py +9 -2
  191. runbooks/security_baseline/checklist/guardduty_enabled.py +9 -2
  192. runbooks/security_baseline/checklist/multi_region_instance_usage.py +5 -1
  193. runbooks/security_baseline/checklist/root_access_key.py +6 -1
  194. runbooks/security_baseline/config-origin.json +1 -1
  195. runbooks/security_baseline/config.json +1 -1
  196. runbooks/security_baseline/permission.json +1 -1
  197. runbooks/security_baseline/report_generator.py +10 -2
  198. runbooks/security_baseline/report_template_en.html +7 -7
  199. runbooks/security_baseline/report_template_jp.html +7 -7
  200. runbooks/security_baseline/report_template_kr.html +12 -12
  201. runbooks/security_baseline/report_template_vn.html +7 -7
  202. runbooks/security_baseline/requirements.txt +7 -0
  203. runbooks/security_baseline/run_script.py +8 -2
  204. runbooks/security_baseline/security_baseline_tester.py +10 -2
  205. runbooks/security_baseline/utils/common.py +5 -1
  206. runbooks/utils/__init__.py +204 -0
  207. runbooks-0.6.1.dist-info/METADATA +373 -0
  208. runbooks-0.6.1.dist-info/RECORD +237 -0
  209. {runbooks-0.2.5.dist-info → runbooks-0.6.1.dist-info}/WHEEL +1 -1
  210. runbooks-0.6.1.dist-info/entry_points.txt +7 -0
  211. runbooks-0.6.1.dist-info/licenses/LICENSE +201 -0
  212. runbooks-0.6.1.dist-info/top_level.txt +3 -0
  213. runbooks/python101/calculator.py +0 -34
  214. runbooks/python101/config.py +0 -1
  215. runbooks/python101/exceptions.py +0 -16
  216. runbooks/python101/file_manager.py +0 -218
  217. runbooks/python101/toolkit.py +0 -153
  218. runbooks-0.2.5.dist-info/METADATA +0 -439
  219. runbooks-0.2.5.dist-info/RECORD +0 -61
  220. runbooks-0.2.5.dist-info/entry_points.txt +0 -3
  221. runbooks-0.2.5.dist-info/top_level.txt +0 -1
@@ -0,0 +1,69 @@
1
+ """
2
+ Cloud Foundations Assessment Tool - Backward Compatibility Module.
3
+
4
+ This module maintains backward compatibility for existing code
5
+ while providing access to the enhanced assessment engine.
6
+
7
+ For new implementations, consider using the enhanced assessment
8
+ module directly:
9
+
10
+ from runbooks.cfat.assessment import CloudFoundationsAssessment
11
+
12
+ This module will be deprecated in a future version.
13
+ """
14
+
15
+ from typing import Optional
16
+
17
+ from loguru import logger
18
+
19
+ from runbooks.cfat.assessment.runner import CloudFoundationsAssessment
20
+ from runbooks.config import RunbooksConfig
21
+
22
+
23
+ class AssessmentRunner(CloudFoundationsAssessment):
24
+ """
25
+ Backward Compatibility Wrapper for Cloud Foundations Assessment.
26
+
27
+ This class provides backward compatibility for existing code that
28
+ uses the original AssessmentRunner class. All functionality is
29
+ delegated to the enhanced CloudFoundationsAssessment engine.
30
+
31
+ **Deprecation Notice**: This class is deprecated and will be removed
32
+ in a future version. Please migrate to using CloudFoundationsAssessment
33
+ directly:
34
+
35
+ ```python
36
+ # Old way (deprecated)
37
+ from runbooks.cfat.runner import AssessmentRunner
38
+ runner = AssessmentRunner()
39
+
40
+ # New way (recommended)
41
+ from runbooks.cfat.assessment import CloudFoundationsAssessment
42
+ assessment = CloudFoundationsAssessment()
43
+ ```
44
+
45
+ Args:
46
+ profile: AWS CLI profile for authentication
47
+ region: AWS region for assessment
48
+ config: RunbooksConfig instance for configuration
49
+ """
50
+
51
+ def __init__(
52
+ self, profile: Optional[str] = None, region: Optional[str] = None, config: Optional[RunbooksConfig] = None
53
+ ):
54
+ """
55
+ Initialize backward compatibility wrapper.
56
+
57
+ Args:
58
+ profile: AWS CLI profile to use
59
+ region: AWS region for assessment
60
+ config: Configuration object
61
+ """
62
+ # Log deprecation warning
63
+ logger.warning(
64
+ "AssessmentRunner is deprecated. Please use CloudFoundationsAssessment "
65
+ "from runbooks.cfat.assessment instead."
66
+ )
67
+
68
+ # Initialize the enhanced assessment engine
69
+ super().__init__(profile=profile, region=region, config=config)
@@ -0,0 +1,43 @@
1
+ import { CloudTrailClient, DescribeTrailsCommand } from '@aws-sdk/client-cloudtrail';
2
+ import { CloudTrailInfo } from '../types';
3
+
4
+ async function checkCloudTrailExists(regions: string[]): Promise<CloudTrailInfo[]> {
5
+ let cloudTrailValidation: CloudTrailInfo[] = []
6
+ for (const region of regions){
7
+ const cloudTrailClient = new CloudTrailClient({ region });
8
+ const cloudTrailDescribeCommand = new DescribeTrailsCommand({});
9
+
10
+ try {
11
+ const cloudTrailResponse = await cloudTrailClient.send(cloudTrailDescribeCommand);
12
+ if(cloudTrailResponse.trailList){
13
+ for (const trail of cloudTrailResponse.trailList) {
14
+ let trailInfo: CloudTrailInfo = {}
15
+ if(trail.HomeRegion == region){
16
+ //console.log(`trail found in ${region}`)
17
+ trailInfo = {
18
+ region: region,
19
+ trailFound: true,
20
+ isOrgTrail: trail.IsMultiRegionTrail,
21
+ isMultiRegion: trail.IsMultiRegionTrail
22
+ }
23
+ }
24
+ else{
25
+ trailInfo = {
26
+ region: region,
27
+ trailFound: false
28
+ }
29
+ }
30
+ cloudTrailValidation.push(trailInfo)
31
+ }
32
+ }
33
+ } catch (error) {
34
+ console.log(`Error checking instance: ${error}`);
35
+ }
36
+ finally {
37
+ cloudTrailClient.destroy();
38
+ }
39
+ }// end for regions
40
+ return cloudTrailValidation;
41
+ };
42
+
43
+ export default checkCloudTrailExists;
@@ -0,0 +1,37 @@
1
+ import { ConfigServiceClient, DescribeConfigurationRecorderStatusCommand, DescribeDeliveryChannelsCommand } from '@aws-sdk/client-config-service';
2
+ import { ConfigInfo } from '../types';
3
+
4
+ async function checkConfigExists(regions: string[]): Promise<ConfigInfo[]> {
5
+ let configDetails:ConfigInfo[] = [];
6
+ for (const region of regions) {
7
+ const configServiceClient = new ConfigServiceClient({ region });
8
+ let configDetail: ConfigInfo = {
9
+ region: region,
10
+ configRecorderFound: false,
11
+ configDeliveryChannelFound: false
12
+ }
13
+ try {
14
+ // Check if Config recorder exists
15
+ const recorderResponse = await configServiceClient.send(new DescribeConfigurationRecorderStatusCommand({}));
16
+ const recorderExists = recorderResponse.ConfigurationRecordersStatus?.length !== 0;
17
+ if(recorderExists){
18
+ configDetail.configRecorderFound = true
19
+ }
20
+ // Check if Config delivery channel exists
21
+ const channelResponse = await configServiceClient.send(new DescribeDeliveryChannelsCommand({}));
22
+ const channelExists = channelResponse.DeliveryChannels?.length !== 0;
23
+ if(channelExists){
24
+ configDetail.configDeliveryChannelFound = true
25
+ }
26
+ configDetails.push(configDetail)
27
+ } catch (error) {
28
+ console.error(`Error checking AWS Config in ${region}:`, error);
29
+ }
30
+ finally {
31
+ configServiceClient.destroy();
32
+ }
33
+ }
34
+ return configDetails;
35
+ }
36
+
37
+ export default checkConfigExists
@@ -0,0 +1,37 @@
1
+ import { ControlTowerClient, ListLandingZonesCommand, GetLandingZoneCommand } from "@aws-sdk/client-controltower";
2
+ import { ControlTowerInfo } from '../types';
3
+
4
+ async function getControlTower(region: string): Promise<ControlTowerInfo> {
5
+ let controlTowerInfo:ControlTowerInfo = {}
6
+ const controlTowerClient = new ControlTowerClient({ region });
7
+ try {
8
+ const command = new ListLandingZonesCommand({});
9
+ const response = await controlTowerClient.send(command);
10
+ if(response.landingZones && response.landingZones.length > 0){
11
+ const input = {
12
+ landingZoneIdentifier: response.landingZones[0].arn,
13
+ };
14
+ const lzRegion:string = response.landingZones[0].arn?.toString().split(':')[3] ?? ""
15
+ if(lzRegion){
16
+ controlTowerInfo.controlTowerRegion = lzRegion
17
+ const controlTowerClientRegion = new ControlTowerClient({ region: lzRegion });
18
+ const command = new GetLandingZoneCommand(input);
19
+ const lzResponse = await controlTowerClientRegion.send(command);
20
+ if(lzResponse.landingZone){
21
+ controlTowerInfo.status= lzResponse.landingZone.status
22
+ controlTowerInfo.latestAvailableVersion = lzResponse.landingZone.latestAvailableVersion
23
+ controlTowerInfo.deployedVersion = lzResponse.landingZone.version
24
+ controlTowerInfo.driftStatus = lzResponse.landingZone.driftStatus?.status
25
+ }
26
+ }
27
+ }
28
+ } catch (error) {
29
+ console.error(`Error checking Control Tower in ${region}:`, error);
30
+ }
31
+ finally {
32
+ controlTowerClient.destroy();
33
+ }
34
+ return controlTowerInfo
35
+ }
36
+
37
+ export default getControlTower
@@ -0,0 +1,46 @@
1
+ import { EC2Client, DescribeInstancesCommand, DescribeInstancesCommandOutput } from "@aws-sdk/client-ec2";
2
+ import { Ec2Check } from '../types';
3
+
4
+ async function checkEc2Exists(regions: string[]): Promise<Ec2Check[]> {
5
+ let ec2Validation: Ec2Check[] = []
6
+ for (const region of regions){
7
+ const ec2Client = new EC2Client({ region });
8
+
9
+ const command = new DescribeInstancesCommand({});
10
+
11
+ try {
12
+ const response = await ec2Client.send(command);
13
+ if(response.Reservations){
14
+ if (response.Reservations.length > 0) {
15
+ //console.log(`WARNING: Instance(s) exists in region: ${region}`);
16
+ const ec2Found: Ec2Check = {
17
+ region: region,
18
+ ec2Found: true
19
+ }
20
+ ec2Validation.push(ec2Found)
21
+ }
22
+ else{
23
+ const ec2Found: Ec2Check = {
24
+ region: region,
25
+ ec2Found: false
26
+ }
27
+ ec2Validation.push(ec2Found)
28
+ }
29
+ } else {
30
+ const ec2Found: Ec2Check = {
31
+ region: region,
32
+ ec2Found: false
33
+ }
34
+ ec2Validation.push(ec2Found)
35
+ }
36
+ } catch (error) {
37
+ console.log(`Error checking instance: ${error}`);
38
+ }
39
+ finally {
40
+ ec2Client.destroy();
41
+ }
42
+ }// end for
43
+ return ec2Validation;
44
+ };
45
+
46
+ export default checkEc2Exists;
@@ -0,0 +1,50 @@
1
+ import { IamUserInfo } from '../types';
2
+ import { IAMClient, ListUsersCommand, ListAccessKeysCommand, GetAccessKeyLastUsedCommand } from "@aws-sdk/client-iam";
3
+
4
+ // function list all IAM users and if they have keys in the management account
5
+ const checkIamUsers = async (): Promise<IamUserInfo[]> => {
6
+ // Set to us-east-1 as IAM is global and region isn't a concern
7
+ const iamClient = new IAMClient({ region: 'us-east-1' });
8
+ const iamUserInfo: IamUserInfo[] = [];
9
+ try {
10
+ const listUsersCommand = new ListUsersCommand({});
11
+ const listUsersResponse = await iamClient.send(listUsersCommand);
12
+ for (const user of listUsersResponse.Users || []) {
13
+ const userName = user.UserName || "";
14
+ const listAccessKeysCommand = new ListAccessKeysCommand({
15
+ UserName: userName,
16
+ });
17
+ const listAccessKeysResponse = await iamClient.send(listAccessKeysCommand);
18
+ const accessKeys = listAccessKeysResponse.AccessKeyMetadata || [];
19
+ if (accessKeys.length > 0) {
20
+ for (const accessKey of accessKeys) {
21
+ const accessKeyId = accessKey.AccessKeyId || "";
22
+ const getLastUsedCommand = new GetAccessKeyLastUsedCommand({
23
+ AccessKeyId: accessKeyId,
24
+ });
25
+ const lastUsedResponse = await iamClient.send(getLastUsedCommand);
26
+ const foundUserInfo: IamUserInfo = {
27
+ userName,
28
+ accessKeyId,
29
+ lastUsed: lastUsedResponse && lastUsedResponse.AccessKeyLastUsed
30
+ ? `${lastUsedResponse.AccessKeyLastUsed.LastUsedDate}` || "Not available"
31
+ : "Not available",
32
+ };
33
+ iamUserInfo.push(foundUserInfo);
34
+ }
35
+ } else {
36
+ const foundUserInfo: IamUserInfo = {
37
+ userName
38
+ };
39
+ iamUserInfo.push(foundUserInfo);
40
+ }
41
+ }
42
+ } catch (error) {
43
+ console.error("Error:", error);
44
+ } finally {
45
+ iamClient.destroy();
46
+ }
47
+ return iamUserInfo;
48
+ };
49
+
50
+ export default checkIamUsers;
@@ -0,0 +1,30 @@
1
+ import { CostAndUsageReportServiceClient, DescribeReportDefinitionsCommand } from "@aws-sdk/client-cost-and-usage-report-service";
2
+ import { LegacyCurInfo } from '../types';
3
+
4
+ const checkLegacyCur = async (region: string): Promise<LegacyCurInfo> => {
5
+ // Set up AWS SDK client for Cost Explorer
6
+ const curClient = new CostAndUsageReportServiceClient({ region });
7
+ let isLegacyCurSetup = false;
8
+
9
+ try {
10
+ // Check if Cost Explorer is set up
11
+ const input = {};
12
+ const command = new DescribeReportDefinitionsCommand(input);
13
+ const response = await curClient.send(command);
14
+ if (response.ReportDefinitions && response.ReportDefinitions.length > 0) {
15
+ isLegacyCurSetup = true;
16
+ }
17
+
18
+ return { isLegacyCurSetup };
19
+ } catch (error) {
20
+ // Check if the error is related to Cost Explorer setup
21
+ console.error(`Error: ${error}`);
22
+ isLegacyCurSetup = false;
23
+ return { isLegacyCurSetup };
24
+ } finally {
25
+ // Close the AWS SDK client
26
+ curClient.destroy();
27
+ }
28
+ };
29
+
30
+ export default checkLegacyCur;
@@ -0,0 +1,30 @@
1
+ import { CloudFormationClient,
2
+ DescribeOrganizationsAccessCommand,
3
+ DescribeOrganizationsAccessInput,
4
+ } from "@aws-sdk/client-cloudformation";
5
+
6
+ import {OrgCloudFormationStatus} from '../types'
7
+
8
+ async function getOrgCloudFormation(region: string): Promise<OrgCloudFormationStatus> {
9
+ let orgCfnStatus: OrgCloudFormationStatus = {
10
+ status: "disabled"
11
+ }
12
+ const cloudFormationClient = new CloudFormationClient({region});
13
+ try {
14
+ const describeOrgAccessInput: DescribeOrganizationsAccessInput = {};
15
+ const command = new DescribeOrganizationsAccessCommand(describeOrgAccessInput);
16
+ const cloudFormationOrgAccess = await cloudFormationClient.send(command);
17
+ //console.log("CloudFormation activation status: ", cloudFormationOrgAccess.Status)
18
+ orgCfnStatus.status = cloudFormationOrgAccess.Status ?? "disabled"
19
+ }
20
+ catch (error) {
21
+ console.log(`Error: ${error}`);
22
+ //throw new Error(`Error: ${error}`);
23
+ }
24
+ finally {
25
+ cloudFormationClient.destroy()
26
+ return orgCfnStatus
27
+ }
28
+ };
29
+
30
+ export default getOrgCloudFormation;
@@ -0,0 +1,43 @@
1
+ import { EC2Client, DescribeVpcsCommand} from "@aws-sdk/client-ec2";
2
+ import { VpcCheck } from '../types';
3
+
4
+ async function checkVpcExists(regions: string[]): Promise<VpcCheck[]> {
5
+ let vpcValidation: VpcCheck[] = []
6
+ for (const region of regions){
7
+ const ec2Client = new EC2Client({ region });
8
+ const command = new DescribeVpcsCommand({});
9
+ try {
10
+ const response = await ec2Client.send(command);
11
+ if(response.Vpcs){
12
+ if (response.Vpcs.length > 0) {
13
+ const vpcFound: VpcCheck = {
14
+ region: region,
15
+ vpcFound: true
16
+ }
17
+ vpcValidation.push(vpcFound)
18
+ }
19
+ else{
20
+ const vpcFound: VpcCheck = {
21
+ region: region,
22
+ vpcFound: false
23
+ }
24
+ vpcValidation.push(vpcFound)
25
+ }
26
+ } else {
27
+ const vpcFound: VpcCheck = {
28
+ region: region,
29
+ vpcFound: false
30
+ }
31
+ vpcValidation.push(vpcFound)
32
+ }
33
+ } catch (error) {
34
+ console.log(`Error: ${error}`);
35
+ }
36
+ finally {
37
+ ec2Client.destroy();
38
+ }
39
+ }// end for
40
+ return vpcValidation;
41
+ };
42
+
43
+ export default checkVpcExists;
@@ -0,0 +1,14 @@
1
+
2
+ import { Task } from '../types';
3
+ import * as fs from 'fs';
4
+
5
+ async function createAsanaImport(tasks: Task[]): Promise<void> {
6
+ let csv:string = '"Task", "Description", "Status" \r\n'
7
+ for(const task of tasks){
8
+ csv += `"cfat - ${task.title}", "${task.detail} - Remediation Link: ${task.remediationLink}", "Not Started" \r\n`
9
+ }
10
+ fs.writeFileSync('./asana-import.csv', csv);
11
+ return
12
+ }
13
+
14
+ export default createAsanaImport;