Cloud Harvester
Cloud-agnostic harvesting for AWS and Azure inventories. The collect() entry point fans out to built-in collectors across compute, containers/serverless, networking and edge, storage, databases, identity/security, and observability; limit scope with providers or inject your own boto3/Azure clients.
Every record is normalized into a Resource dataclass with fields like id, provider, kind, resource (service), name, region, status, network_id, subnetwork_id, tags, and the raw source payload for downstream use. Resources also include cloud-agnostic graph fields: scope, placements, relationships, and addresses.
Quickstart
import boto3
from azure.identity import ClientSecretCredential
from cloud_harvester import collect
# AWS: static credentials (replace with real values)
aws_session = boto3.Session(
aws_access_key_id="FAKEAWSACCESSKEY123",
aws_secret_access_key="FAKEAWSSECRETKEY456",
)
# Azure: service principal credentials (replace with real values)
azure_credential = ClientSecretCredential(
tenant_id="00000000-0000-0000-0000-000000000000",
client_id="11111111-1111-1111-1111-111111111111",
client_secret="fake-azure-client-secret",
)
azure_subscription_id = "22222222-2222-2222-2222-222222222222"
# Collect from both providers with injected sessions/credentials
result = collect(
providers=["aws", "azure"],
aws_session=aws_session,
azure_credential=azure_credential,
azure_subscription_id=azure_subscription_id,
)
for res in result.resources:
print(res.to_dict())
for err in result.errors:
print(err.provider, err.collector, err.region, err.error_code, err.error_message)
collect() returns a CollectionResult with two fields:
resources: List[Resource]— every resource successfully gathered.errors: List[CollectorError]— one entry per collector invocation that raised. Each entry carries theprovider,collectorname,region(AWS only;Nonefor global/Azure collectors), anerror_codeparsed from the underlying exception when possible (botocoreClientError.response["Error"]["Code"]for AWS,azure.core.exceptions.HttpResponseError.error.codefor Azure), and the rawerror_message. Failures are still logged atERROR, but the structured list is the canonical surface for callers that want to show users what went wrong (e.g. anAccessDeniedon a specific collector/region).
AWS collection scans all enabled regions by default. To limit AWS scope, pass an explicit region list:
result = collect(
providers=["aws"],
aws_session=aws_session,
aws_regions=["eu-west-1", "us-east-1"],
)
If aws_regions is omitted, Cloud Harvester discovers and scans all enabled AWS
regions. You can also set CLOUD_HARVESTER_AWS_REGIONS to a comma-separated
list.
Collectors run concurrently by default. To tune API pressure, pass
max_workers or set CLOUD_HARVESTER_MAX_WORKERS:
result = collect(
providers=["aws"],
aws_session=aws_session,
max_workers=8,
)
Logging
Cloud Harvester uses Python's standard logging module. Enable INFO logs to see
provider progress, AWS region discovery, per-region collector progress, collector
result counts, and collector failures:
import logging
logging.basicConfig(level=logging.INFO)
Credentials
-
AWS: In the AWS console, create or reuse an IAM role/user with read permissions. Minimum managed policies to attach:
ReadOnlyAccessAmazonEC2ReadOnlyAccessAmazonEKSMCPReadOnlyAccessGenerate access keys, then either:- Export
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, andAWS_SESSION_TOKEN(if temporary credentials), or - Store them in an
AWS_PROFILEand pointAWS_PROFILE/CLOUD_HARVESTER_AWS_PROFILEat it. Optionally setCLOUD_HARVESTER_AWS_REGIONSto limit collection to specific regions. If it is omitted, Cloud Harvester discovers and scans all enabled account regions.
-
Azure: Create an App Registration (service principal) in Microsoft Entra ID and assign it the required RBAC roles on your subscription (Reader, Security Reader, Key Vault Reader). Capture:
tenant_id,client_id,client_secretfrom the service principalsubscription_idfor the target subscription If Azure AD collectors are needed, add Microsoft Graph app permissions (e.g.,Directory.Read.All) and have an admin grant consent.
Either setAZURE_SUBSCRIPTION_ID/AZURE_TENANT_ID(orCLOUD_HARVESTER_*) or pass aClientSecretCredentialcreated from these values.
Metadata
Release files for cloud-harvester 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cloud_harvester-0.2.1.tar.gz | 43.1 kB | Without provenance | Details for cloud_harvester-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cloud_harvester-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for cloud_harvester-0.2.1-py3-none-any.whl |
Total release size: 95.9 kB
Release files / cloud_harvester-0.2.1.tar.gz
| Download URL | cloud_harvester-0.2.1.tar.gz |
|---|---|
| Size | 43.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
939b689fe85d5810b5e982f886dffe783d7011a401192a8c5a825616cf4e5171
|
|
BLAKE2b-256 checksum How to use checksums |
6dcdd0ab20530d0905c2b22ea8239cf47a5d58780c7d06a1b0b5a03684d2759c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Release files / cloud_harvester-0.2.1-py3-none-any.whl
| Download URL | cloud_harvester-0.2.1-py3-none-any.whl |
|---|---|
| Size | 52.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
51c64e8b863334a990d1e95659d463c127ca3a5b323187d048626d3bdbc26eee
|
|
BLAKE2b-256 checksum How to use checksums |
9bc681d2fd7ee2b41ea3e4246ddc3437a415eb2eaa74ba21b5cdbe81ee68ce45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Security for cloud-harvester 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.