Cloudsplaining
Cloudsplaining is an AWS IAM Security Assessment tool that identifies violations of least privilege in AWS IAM policies. It scans all policies in an AWS account or a single policy file and generates a risk-prioritized HTML report and a triage worksheet. The library is currently at version 0.8.2 and maintains an active release cadence with frequent updates and bug fixes.
Warnings
- breaking Version 0.8.0 dropped support for Python 3.8. Users on Python 3.8 must upgrade their Python environment to 3.9 or higher to use Cloudsplaining 0.8.0 and above.
- gotcha Cloudsplaining requires AWS credentials configured in the environment (e.g., via AWS CLI, environment variables like `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`) and the IAM permission `iam:GetAccountAuthorizationDetails` to download account details. Without these, the `cloudsplaining download` command will fail.
- gotcha Cloudsplaining can generate false positives, as it does not inherently understand the context of all IAM policies in your environment (e.g., intended broad permissions for specific automation roles). It is recommended to create and utilize an 'exclusions file' to filter out these known false positives.
- gotcha The `--flag-all-risky-actions` (or `flag_all_risky_actions=True` in the library) option changes how Cloudsplaining identifies risky actions. By default, it considers resource constraints or conditions. When this flag is enabled, it will flag all risky actions regardless of whether resource ARN constraints or conditions are used, leading to more verbose output.
Install
-
pip install cloudsplaining
Imports
- scan_account_authorization_details
from cloudsplaining.command.scan import scan_account_authorization_details
Quickstart
import os
import json
from cloudsplaining.command.scan import scan_account_authorization_details
from cloudsplaining.shared.exclusions import DEFAULT_EXCLUSIONS, Exclusions
# NOTE: For a real scan, you would first generate an account authorization details JSON file.
# This typically requires AWS credentials configured (e.g., via AWS CLI or environment variables)
# and the `iam:GetAccountAuthorizationDetails` permission.
# Example CLI command: `cloudsplaining download --output-file account_authorization_details.json`
# For this example, we'll use a dummy file path and content.
dummy_auth_details_path = "account_authorization_details.json"
# In a real scenario, this would be a large JSON file downloaded from AWS.
# Example: https://github.com/salesforce/cloudsplaining/blob/master/examples/files/iam-results-example.json
dummy_auth_details_content = {
"UserDetailList": [],
"GroupDetailList": [],
"RoleDetailList": [
{
"Path": "/",
"RoleName": "TestRoleWithFullS3",
"RoleId": "AROAJEXAMPLEAAAEK",
"Arn": "arn:aws:iam::123456789012:role/TestRoleWithFullS3",
"CreateDate": "2023-01-01T00:00:00Z",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
]
},
"AttachedManagedPolicies": [
{
"PolicyName": "AmazonS3FullAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
],
"InstanceProfileList": []
}
],
"ManagedPolicyDetailList": [],
"ContextKeyDetailList": []
}
with open(dummy_auth_details_path, "w") as f:
json.dump(dummy_auth_details_content, f)
# Create an empty exclusions object for this quickstart (you might load from a file)
# An exclusions file is recommended for production use to filter out false positives.
exclusions = Exclusions(DEFAULT_EXCLUSIONS)
# Scan the account authorization details file programmatically
try:
print(f"Scanning {dummy_auth_details_path}...")
html_report_string = scan_account_authorization_details(
input_file=dummy_auth_details_path,
exclusions=exclusions,
flag_all_risky_actions=False, # Set to True to flag all risky actions regardless of resource constraints
# You can also set other parameters like 'high_priority_only' or 'severity'
)
# The HTML report content is returned as a string.
# In a real application, you might save this to a file or serve it.
# For this example, we'll just print a snippet.
print("Scan complete. HTML report (snippet):\n")
print(html_report_string[:500] + "...")
# Clean up dummy file
os.remove(dummy_auth_details_path)
except Exception as e:
print(f"An error occurred during scan: {e}")
if os.path.exists(dummy_auth_details_path):
os.remove(dummy_auth_details_path)