PF-05 · Multi-cloud · Python
Multi-cloud asset and audit automation
A Python tool that collects assets, permissions, and audit logs from AWS, GCP, and Tencent Cloud into one schema, and alerts on risky events.
- Role
- Design and implementation
- Period
- Personal project · released Nov 2026
- Cloud
- AWS · GCP · Tencent
- Scale
- 3 clouds · 7 collectors · 49 audit actions
- Key tech
- Python · boto3 · Google Cloud SDK · Tencent Cloud SDK · Google Sheets · Slack · Telegram
- 3
- Clouds covered by the public code
- 7
- Collectors by resource type
- 49
- Audit actions tracked (16 alert immediately)
At a glance
Problem
Each cloud returns the same concept in a different shape. Comparing permissions or firewalls meant reading three formats by hand.
Approach
Each account is reached through a cross-account role such as STS AssumeRole. Seven collectors, one per resource type, feed a single data class per resource. Output goes to Google Sheets and CSV, and 16 critical events alert Slack and Telegram immediately based on critical_events.yaml.
Result
The production tool behind this code checked four clouds including Azure every day before dawn, removed several days of manual month-end review, and together with Terraform defaults and CI gates helped raise the remediation rate from 60% to over 85%.
Up close
One schema per resource
What this code does: A data class for IAM data that lines up account information from the three clouds in the same fields: cloud, project, user, group, permission, creation time, access key, last login, and password change time. frozen=True makes each record immutable once created, and the sheet value “IAM” sets the sheet it exports to. Collection code differs per cloud, but because every result lands in this shape, the permissions of all three clouds can be compared side by side in one table.
@dataclass(frozen=True)
class IamRecord(Record):
sheet: ClassVar[str] = "IAM"
cloud: str
project: str
project_id: str
user_name: str
user_id: str
user_group: str = ""
permission: str = ""
user_creation_time: str = ""
access_key: str = ""
access_key_creation_time: str = ""
last_login: str = ""
password_last_changed: str = ""
Critical events as data
What this code does: A settings file that lists high-risk events per cloud by name (excerpt). High-impact actions such as attaching policies, creating keys, stopping or deleting servers, and changing machine types appear under aws, gcp, and tencent with each cloud’s own event names, and when a collected audit event matches the list, Slack and Telegram are alerted at once. Because the list lives outside the code, changing a rule never requires touching Python.
aws:
- AttachUserPolicy
- CreateAccessKey
- StopInstances
- TerminateInstances
- ModifyInstanceAttribute
gcp:
- SetIamPolicy
- CreateServiceAccountKey
- v1.compute.instances.stop
- v1.compute.instances.delete
- v1.compute.instances.setMachineType
tencent:
- AttachUserPolicy
- AttachUserPolicies
- CreateApiKey
- StopInstances
- TerminateInstancesWhat I learned
When running several clouds together, the biggest cost was not collecting data but people lining up different formats by hand. Collection differs per cloud, but normalizing the results into one data class per resource lets permissions or firewalls be compared in the same columns, and adding a cloud means adding a collector. Keeping the critical event list as data (critical_events.yaml) instead of code mattered too: a security reviewer can read and change the rules without reading Python, and rule changes never mix with code changes. Some paths were verified only with mocks, not live accounts, which taught me that how far automation can be trusted is set by how much of it was actually checked.