aws_truncate.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. #!/usr/bin/env python3
  2. # See also
  3. # https://stackoverflow.com/questions/39272744/when-to-use-a-boto3-client-and-when-to-use-a-boto3-resource
  4. # https://stackoverflow.com/questions/1661275/disable-boto-logging-without-modifying-the-boto-files
  5. #
  6. from pprint import pprint as pp
  7. import sys
  8. import logging
  9. logger = logging.getLogger()
  10. logger.addHandler(logging.StreamHandler())
  11. logger.setLevel(logging.DEBUG)
  12. logging.getLogger('botocore').setLevel(logging.WARN)
  13. logging.getLogger('boto3').setLevel(logging.WARN)
  14. import boto3
  15. import boto3.session
  16. import botocore.config
  17. #AWS_PROFILE="dev"
  18. #boto3.setup_default_session(profile_name=AWS_PROFILE)
  19. config = {
  20. "cloudformation": True,
  21. "apigateway": True,
  22. "iot": True,
  23. "elasticbeanstalk": True,
  24. "lambda": True,
  25. "ec2": True,
  26. "ec2-elb": True,
  27. "ec2-autoscaling": True,
  28. "ec2-instance": True,
  29. "ec2-volumes": True,
  30. "ec2-security-group": True,
  31. "ec2-eip": True,
  32. "ec2-images": True,
  33. "ec2-keypairs": True,
  34. "ec2-snapshots": True,
  35. "s3": True,
  36. "dynamodb": True,
  37. "rds": True,
  38. "iam": True,
  39. "iam-group": True,
  40. "iam-user": True,
  41. "iam-role": True,
  42. "iam-policy": True,
  43. }
  44. ASKED_FOR_DELETION = True
  45. # https://stackoverflow.com/questions/33332050/getting-the-current-user-account-id-in-boto3
  46. account_id = boto3.client('sts').get_caller_identity().get('Account')
  47. def ask_for_delete():
  48. if not ASKED_FOR_DELETION:
  49. return True
  50. logger.info(" Please confirm with 'yes'")
  51. choice = input().lower()
  52. if choice == "yes":
  53. logger.info(" ... Done")
  54. return True
  55. return False
  56. # Get regions for service
  57. def get_region(service_name):
  58. """
  59. https://stackoverflow.com/questions/38451032/how-to-list-available-regions-with-boto3-python
  60. """
  61. return boto3.session.Session().get_available_regions(service_name)
  62. ##
  63. # CloudFormation
  64. if config["cloudformation"]:
  65. for region in get_region("cloudformation"):
  66. logger.info("# CloudFormation\tregion: {}".format(region))
  67. client = boto3.client("cloudformation", region_name=region)
  68. for stack in client.list_stacks(
  69. StackStatusFilter=[
  70. 'CREATE_IN_PROGRESS',
  71. 'CREATE_FAILED',
  72. 'CREATE_COMPLETE',
  73. 'ROLLBACK_IN_PROGRESS',
  74. 'ROLLBACK_FAILED',
  75. 'ROLLBACK_COMPLETE',
  76. 'DELETE_FAILED',
  77. 'UPDATE_IN_PROGRESS',
  78. 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS',
  79. 'UPDATE_COMPLETE',
  80. 'UPDATE_ROLLBACK_IN_PROGRESS',
  81. 'UPDATE_ROLLBACK_FAILED',
  82. 'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS',
  83. 'UPDATE_ROLLBACK_COMPLETE',
  84. 'REVIEW_IN_PROGRESS',
  85. ]
  86. )["StackSummaries"]:
  87. stack_name = stack["StackName"]
  88. logger.info(" + Delete: {}".format(stack_name))
  89. if ask_for_delete():
  90. client.delete_stack(StackName=stack_name)
  91. ##
  92. # API Gateway
  93. if config["apigateway"]:
  94. for region in get_region("apigateway"):
  95. logger.info("# API Gateway\tregion: {}".format(region))
  96. client = boto3.client("apigateway", region_name=region)
  97. is_first_api = True
  98. for api in client.get_rest_apis()["items"]:
  99. logger.info(" + Delete: {}".format(api["name"]))
  100. if ask_for_delete():
  101. if is_first_api:
  102. is_first_api = False
  103. else:
  104. time.sleep(50)
  105. client.delete_rest_api(
  106. restApiId=api["id"]
  107. )
  108. ##
  109. # IoT
  110. if config["iot"]:
  111. for region in get_region("iot"):
  112. logger.info("# IoT - Things\tregion: {}".format(region))
  113. client = boto3.client("iot", region_name=region)
  114. for thing in client.list_things()["things"]:
  115. thing_name = thing["thingName"]
  116. logger.info(" + Delete: {}".format(thing_name))
  117. if ask_for_delete():
  118. client.delete_thing(thingName=thing_name)
  119. ##
  120. # ElasticBeanstalk
  121. if config["elasticbeanstalk"]:
  122. for region in get_region("elasticbeanstalk"):
  123. logger.info("# ElasticBeanstalk\tregion: {}".format(region))
  124. client = boto3.client("elasticbeanstalk", region_name=region)
  125. for app in client.describe_applications()["Applications"]:
  126. app_name = app["ApplicationName"]
  127. logger.info(" + Delete: {}".format(app_name))
  128. if ask_for_delete():
  129. client.delete_application(
  130. ApplicationName=app_name,
  131. TerminateEnvByForce=True
  132. )
  133. ##
  134. # Lambda
  135. if config["lambda"]:
  136. for region in get_region("lambda"):
  137. logger.info("# Lambda\tregion: {}".format(region))
  138. client = boto3.client("lambda", region_name=region)
  139. for function in client.list_functions()["Functions"]:
  140. function_name = function["FunctionName"]
  141. logger.info(" + Delete: {}".format(function_name))
  142. if ask_for_delete():
  143. client.delete_function(
  144. FunctionName=function_name
  145. )
  146. ##
  147. # EC2
  148. if config["ec2"]:
  149. if config["ec2-elb"]:
  150. for region in get_region("elb"):
  151. logger.info("# EC2 - ElasticLoadBalancing\tregion: {}".format(region))
  152. client = boto3.client("elbv2", region_name=region)
  153. for lb in client.describe_load_balancers()["LoadBalancers"]:
  154. lb_name = lb["LoadBalancerName"]
  155. logger.info(" + Delete: {}".format(lb_name))
  156. if ask_for_delete():
  157. client.delete_load_balancer(
  158. LoadBalancerArn=lb["LoadBalancerArn"]
  159. )
  160. if config["ec2-autoscaling"]:
  161. for region in get_region("autoscaling"):
  162. logger.info("# EC2 - AutoScaling \tregion: {}".format(region))
  163. client = boto3.client("autoscaling", region_name=region)
  164. for group in client.describe_auto_scaling_groups()["AutoScalingGroups"]:
  165. group_name = group["AutoScalingGroupName"]
  166. logger.info(" + Delete (group): {}".format(group_name))
  167. if ask_for_delete():
  168. client.delete_auto_scaling_group(
  169. AutoScalingGroupName=group_name,
  170. ForceDelete=True
  171. )
  172. for config in client.describe_launch_configurations()["LaunchConfigurations"]:
  173. config_name = config["LaunchConfigurationName"]
  174. logger.info(" + Delete (launch conf): {}".format(config_name))
  175. if ask_for_delete():
  176. client.delete_launch_configuration(
  177. LaunchConfigurationName=config_name
  178. )
  179. if config["ec2-instance"]:
  180. for region in get_region("ec2"):
  181. logger.info("# EC2 - Instance\tregion: {}".format(region))
  182. client = boto3.resource("ec2", region_name=region)
  183. instances = client.instances.filter(
  184. Filters=[
  185. {
  186. 'Name': 'instance-state-name',
  187. 'Values': [
  188. 'pending',
  189. 'running',
  190. 'shutting-down',
  191. 'stopping',
  192. 'stopped',
  193. ]
  194. }
  195. ]
  196. )
  197. for instance in instances:
  198. logger.info(" + Delete: {}".format(instance.id))
  199. if ask_for_delete():
  200. instance.terminate()
  201. if config["ec2-volumes"]:
  202. for region in get_region("ec2"):
  203. logger.info("# EC2 - Volumes\tregion: {}".format(region))
  204. client = boto3.resource("ec2", region_name=region)
  205. # http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.ServiceResource.volumes
  206. for volume in client.volumes.filter(Filters=[{'Name': 'status', 'Values': [
  207. 'creating',
  208. 'available',
  209. #'in-use'
  210. 'error',
  211. ]}]):
  212. logger.info(" + Delete: {}".format(volume.id))
  213. if ask_for_delete():
  214. volume.delete()
  215. if config["ec2-security-group"]:
  216. for region in get_region("ec2"):
  217. logger.info("# EC2 - Security Group\tregion: {}".format(region))
  218. client = boto3.resource("ec2", region_name=region)
  219. for security_groups in client.security_groups.all():
  220. logger.info(" + Delete: {} | {}".format(security_groups.group_name, security_groups.id))
  221. if ask_for_delete():
  222. security_groups.delete()
  223. if config["ec2-eip"]:
  224. for region in get_region("ec2"):
  225. logger.info("# EC2 - Elastic IPs\tregion: {}".format(region))
  226. client = boto3.client("ec2", region_name=region)
  227. for ip in client.describe_addresses()["Addresses"]:
  228. logger.info(" + Delete: {} [{}]".format(
  229. ip["PublicIp"],
  230. ip["AllocationId"],
  231. ))
  232. if ask_for_delete():
  233. client.release_address(
  234. AllocationId=ip["AllocationId"],
  235. PublicIp=ip["PublicIp"],
  236. DryRun=False
  237. )
  238. if config["ec2-images"]:
  239. for region in get_region("ec2"):
  240. logger.info("# EC2 - Images\tregion: {}".format(region))
  241. client = boto3.resource("ec2", region_name=region)
  242. for image in client.images.filter(Owners=['self']): # .all():
  243. logger.info(" + Delete: {}\t\tHint: Has delay!".format(image.id))
  244. if ask_for_delete():
  245. # http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Image.deregister
  246. image.deregister(DryRun=False)
  247. if config["ec2-keypairs"]:
  248. for region in get_region("ec2"):
  249. logger.info("# EC2 - Keypairs\tregion: {}".format(region))
  250. client = boto3.client("ec2", region_name=region)
  251. for keypair in client.describe_key_pairs()["KeyPairs"]:
  252. keypair_name = keypair["KeyName"]
  253. logger.info(" + Delete: {}".format(keypair_name))
  254. if ask_for_delete():
  255. client.delete_key_pair(KeyName=keypair_name)
  256. if config["ec2-snapshots"]:
  257. for region in get_region("ec2"):
  258. logger.info("# EC2 - Snapshots\tregion: {}".format(region))
  259. client = boto3.resource("ec2", region_name=region)
  260. for snapshot in client.snapshots.filter(OwnerIds=[account_id]):
  261. logger.info(" + Delete: {}".format(snapshot.id))
  262. if ask_for_delete():
  263. snapshot.delete()
  264. ##
  265. # S3
  266. if config["s3"]:
  267. logger.info("# S3")
  268. s3 = boto3.resource('s3')
  269. for bucket in s3.buckets.all():
  270. logger.info(" + Delete: {}".format(bucket.name))
  271. if ask_for_delete():
  272. for key in bucket.objects.all():
  273. key.delete()
  274. bucket.delete()
  275. ##
  276. # DynamoDB
  277. if config["dynamodb"]:
  278. # http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html
  279. for region in get_region("dynamodb"):
  280. logger.info("# DynamoDB \tregion: {}".format(region))
  281. client = boto3.client("dynamodb", region_name=region)
  282. for table in client.list_tables()["TableNames"]:
  283. logger.info(" + Delete (table): {}".format(table))
  284. if ask_for_delete():
  285. client.delete_table(
  286. TableName=table
  287. )
  288. # BUG: https://github.com/boto/boto3/issues/1542
  289. if region == "eu-west-3":
  290. continue
  291. for backup in client.list_backups()["BackupSummaries"]:
  292. logger.info(" + Delete (backup): {} [{}]".format(
  293. backup["TableName"],
  294. backup["BackupCreationDateTime"],
  295. ))
  296. if ask_for_delete():
  297. client.delete_backup(
  298. BackupArn=backup["BackupArn"]
  299. )
  300. ##
  301. # RDS
  302. if config["rds"]:
  303. # http://boto3.readthedocs.io/en/latest/reference/services/rds.html
  304. for region in get_region("rds"):
  305. logger.info("# RDS \tregion: {}".format(region))
  306. client = boto3.client("rds", region_name=region)
  307. for instance in client.describe_db_instances()["DBInstances"]:
  308. logger.info(" + Delete (instance): {} [{}]".format(
  309. instance["DBInstanceIdentifier"],
  310. instance["Engine"],
  311. ))
  312. if ask_for_delete():
  313. client.delete_db_instance(
  314. DBInstanceIdentifier=instance["DBInstanceIdentifier"],
  315. SkipFinalSnapshot=True,
  316. )
  317. for snap in client.describe_db_snapshots()["DBSnapshots"]:
  318. # Can not delete automated snapshots
  319. if snap["SnapshotType"] == "automated":
  320. continue
  321. logger.info(" + Delete (instance - snapshots): {} [{} | {} | {}]".format(
  322. snap["DBSnapshotIdentifier"],
  323. snap["SnapshotCreateTime"],
  324. snap["Engine"],
  325. snap["SnapshotType"],
  326. ))
  327. if ask_for_delete():
  328. client.delete_db_snapshot(
  329. DBSnapshotIdentifier=snap["DBSnapshotIdentifier"],
  330. )
  331. for cluster in client.describe_db_clusters()["DBClusters"]:
  332. logger.info(" + Delete (cluster): {}".format(
  333. cluster["DBClusterIdentifier"]
  334. ))
  335. if ask_for_delete():
  336. client.delete_db_cluster(
  337. DBClusterIdentifier=cluster["DBClusterIdentifier"],
  338. SkipFinalSnapshot=True,
  339. )
  340. for snap in client.describe_db_cluster_snapshots()["DBClusterSnapshots"]:
  341. logger.info(" + Delete (cluster - snapshots): {} [{}]".format(
  342. snap["DBClusterSnapshotIdentifier"],
  343. snap["SnapshotCreateTime"],
  344. ))
  345. if ask_for_delete():
  346. client.delete_db_cluster_snapshot(
  347. DBClusterSnapshotIdentifier=snap["DBClusterSnapshotIdentifier"],
  348. )
  349. ##
  350. # IAM
  351. if config["iam"]:
  352. if config["iam-group"]:
  353. logger.info("# IAM - Group")
  354. resource = boto3.resource('iam')
  355. client = boto3.client('iam')
  356. for group in resource.groups.all():
  357. logger.info(" + Delete: {}".format(group.name))
  358. if ask_for_delete():
  359. for user in client.get_group(GroupName=group.name)["Users"]:
  360. client.remove_user_from_group(
  361. GroupName=group.name,
  362. UserName=user["UserName"]
  363. )
  364. for policy in client.list_attached_group_policies(GroupName=group.name)["AttachedPolicies"]:
  365. client.detach_group_policy(
  366. GroupName=group.name,
  367. PolicyArn=policy["PolicyArn"]
  368. )
  369. group.delete()
  370. if config["iam-user"]:
  371. # https://gist.github.com/xxxVxxx/9648264fd6f41bbb1f65
  372. logger.info("# IAM - User")
  373. resource = boto3.resource('iam')
  374. for user in resource.users.all():
  375. logger.info(" + Delete: {}".format(user.user_name))
  376. if ask_for_delete():
  377. for key in user.access_keys.all():
  378. key.delete()
  379. user.delete()
  380. if config["iam-role"]:
  381. logger.info("# IAM - Role")
  382. resource = boto3.resource('iam')
  383. client = boto3.client('iam')
  384. for role in resource.roles.all():
  385. logger.info(" + Delete: {}".format(role.name))
  386. if ask_for_delete():
  387. for policy in client.list_attached_role_policies(RoleName=role.name)["AttachedPolicies"]:
  388. client.detach_role_policy(
  389. RoleName=role.name,
  390. PolicyArn=policy["PolicyArn"]
  391. )
  392. role.delete()
  393. if config["iam-policy"]:
  394. logger.info("# IAM - Policy")
  395. resource = boto3.resource('iam')
  396. client = boto3.client('iam')
  397. for policy in resource.policies.filter(Scope="Local"):
  398. logger.info(" + Delete: {}".format(policy.policy_name))
  399. if ask_for_delete():
  400. for version in client.list_policy_versions(PolicyArn=policy.arn)["Versions"]:
  401. if not version["IsDefaultVersion"] == True:
  402. client.delete_policy_version(
  403. PolicyArn=policy.arn,
  404. VersionId=version["VersionId"]
  405. )
  406. policy.delete()