Skip to content
All projects

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
GitHub
3
Clouds covered by the public code
7
Collectors by resource type
49
Audit actions tracked (16 alert immediately)

At a glance

AWSGCPTencentCross-account roleiamfirewallinstanceloadbalancervpcaudit_logunusedCommon schemaGoogle SheetsSlackTelegramImmediate alerts on critical eventsMonthly archive
Audit sheets are copied to CSV once a month into year and month folders.

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

Critical event rulesAWSGCPTencentAttachUserPolicyCreateAccessKeyStopInstancesTerminateInstancesModifyInstanceAttributeSetIamPolicyCreateServiceAccountKeyinstances.stopinstances.deleteinstances.setMachineTypeAttachUserPolicyAttachUserPoliciesCreateApiKeyStopInstancesTerminateInstancesResetInstancesTypeChange the rules in critical_events.yamlSlackTelegram
Only events on the list go to Slack and Telegram right away.
Finding unused resourcesElastic IPSecurity GroupEBS volumeNot attached to anythingAttached to no network interfaceAttached to no instanceFOUNDFOUNDFOUNDGCP and Tencent are checked for idle resources the same way
GCP and Tencent are checked the same way for idle IPs, disks, and firewalls.

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
  - TerminateInstances

What 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.

Related field notes

Open to work · Cloud infrastructure and security

Choose a theme

Click a badge to switch to that theme on the same content. Dragging only swings it.

Back to the front page →