cloudlist

repository·dev·Indexed 21 days ago

https://github.com/projectdiscovery/cloudlist

A multi-cloud asset discovery tool for Attack Surface Management (ASM) that aggregates assets from various cloud providers into a centralized list. It supports keyless authentication (e.g., AWS IRSA, GCP workload identity), multiple output formats, and provides two discovery approaches for GCP: Organization-Level Asset API for comprehensive audits and Individual Service APIs for fast, project-specific scans.

Tokens
10.3K
Snippets
27
Records
35
Agent score
73%

What's inside cloudlist

  1. Overview of Cloudlist

    dev

    Cloudlist is a multi-cloud tool designed for blue teams to augment Attack Surface Management (ASM) efforts. It allows for maintaining a centralized list of assets across multiple cloud providers with minimal configuration.

    Key capabilities include:

    • Listing cloud assets using multiple configurations.
    • Support for multiple cloud providers.
    • Keyless authentication support (e.g., AWS IRSA / instance profiles, GCP workload identity).
    • Support for multiple output formats and filters.
    • Extensibility for adding new providers.
    • stdout support for integration into tool pipelines.
  2. How Cloudlist providers and resources work together

    dev

    Cloudlist is an asset discovery tool that gathers information from multiple providers (e.g., AWS, GCP, DigitalOcean) using their specific APIs.

    • Providers: Each provider implements the schema.Provider interface. The core logic resides in the Resources() method, which returns a list of discovered assets.
    • Resources: A resource represents a single cloud unit (like an EC2 instance or a DNS record) belonging to an organization. Every resource must provide either an IP address or a DNS name.

    Providers return a schema.Resource structure, which includes metadata such as whether the asset is Public or Private, the Provider name, the resource ID, and various IP/DNS fields.

    // Resource is a cloud resource belonging to the organization
    type Resource struct {
    	Public       bool   `json:"public"` 
    	Provider     string `json:"provider"` 
    	ID           string `json:"id,omitempty"` 
    	PublicIPv4    string `json:"public_ipv4,omitempty"` 
    	PublicIPv6    string `json:"public_ipv6,omitempty"` 
    	PrivateIpv4   string `json:"private_ipv4,omitempty"` 
    	PrivateIpv6   string `json:"private_ipv6,omitempty"` 
    	DNSName       string `json:"dns_name,omitempty"` 
    }
  3. Compare GCP discovery approaches: Organization-Level vs. Individual Service APIs

    dev

    Cloudlist offers two ways to discover GCP assets. Choose based on your scope and speed requirements:

    1. Organization-Level Asset API: Best for comprehensive organization-wide audits. It uses the Cloud Asset Inventory API to cover 220+ resources across the entire organization. It is slower (~45s) but provides much broader coverage.
    2. Individual Service APIs: Best for fast, project-specific scans. It uses individual GCP service APIs to discover 67 resources per project. It is faster (~23s) but limited to accessible projects.

    Extended Metadata: The Organization-Level approach supports an optional 'Extended Metadata' feature. If you provide additional service-specific permissions, Cloudlist fetches more detailed data. If permissions are missing, it gracefully degrades to basic Asset API data.

    | Feature | Organization-Level Asset API | Individual Service APIs |
    |---------|----------------------------|------------------------|
    | **Scope** | All projects in organization | Accessible projects only |
    | **Speed** | Slower (~45s) | Faster (~23s) |
    | **Coverage** | 220+ resources across org | 67 resources per project |
    | **Required Permissions** | Cloud Asset Inventory roles | Individual service permissions |
    | **Best For** | Comprehensive org audits | Fast project-specific scans |
    | **Extended Metadata** | Optional with additional permissions | Always available |
  4. Configure Google Cloud Platform (GCP) provider

    dev

    GCP discovery supports two approaches: Individual Service APIs (project-level) and the Organization-Level Asset API.

    Authentication can be done via Traditional Static Credentials (Service Account JSON) or Short-lived Credentials (recommended). Short-lived credentials use the Service Account Credentials API to generate temporary tokens (up to 1 hour), reducing reliance on static keys.

  5. GCP Asset Discovery Approaches

    dev

    Cloudlist provides two distinct methods for discovering assets within Google Cloud Platform (GCP):

    1. Organization-Level Asset API: Provides comprehensive, organization-wide discovery by utilizing the Cloud Asset Inventory API.
    2. Individual Service APIs: Provides faster, project-specific discovery by querying individual GCP service APIs directly.

    For detailed setup instructions, required permissions, and service account configuration, refer to the docs/GCP_ASSET_API.md file in the repository.

  6. Setup Developer Workflow (Zero Keys) for GCP

    dev

    For local development, you can use your own user identity to impersonate a service account without managing any JSON key files.

    1. Authenticate your local environment using Application Default Credentials (ADC).
    2. Grant your user account the roles/iam.serviceAccountTokenCreator role on the target service account.
    3. Run cloudlist with a configuration that enables use_short_lived_credentials.
    # One-time authentication
    gcloud auth application-default login
    
    # Grant your user account permission to impersonate the service account
    gcloud iam service-accounts add-iam-policy-binding \
      cloudlist@project.iam.gserviceaccount.com \
      --member="user:your-email@company.com" \
      --role="roles/iam.serviceAccountTokenCreator"
    
    # Run cloudlist
    cloudlist -config config.yaml
  7. Setup CI/CD with Minimal Permissions for GCP

    dev

    In CI/CD environments, use a minimal-permission service account that is only allowed to impersonate the powerful target service account. This limits the blast radius if the CI key is compromised.

    1. Create a minimal service account for CI.
    2. Grant that minimal account the roles/iam.serviceAccountTokenCreator role on the target service account.
    3. Generate a key for the minimal account and provide it to the CI environment via source_credentials.
    - provider: gcp
      id: ci-discovery
      use_short_lived_credentials: true
      service_account_email: "powerful-sa@project.iam.gserviceaccount.com"
      source_credentials: "minimal-ci-sa.json"
      token_lifetime: "3600s"
    # Create minimal CI service account
    gcloud iam service-accounts create minimal-ci-sa \
      --display-name="Minimal CI Service Account"
    
    # Grant impersonation permission
    gcloud iam service-accounts add-iam-policy-binding \
      powerful-sa@project.iam.gserviceaccount.com \
      --member="serviceAccount:minimal-ci-sa@project.iam.gserviceaccount.com" \
      --role="roles/iam.serviceAccountTokenCreator"
    
    # Create key for CI
    gcloud iam service-accounts keys create minimal-ci-sa.json \
      --iam-account=minimal-ci-sa@project.iam.gserviceaccount.com
  8. How to add a new provider to Cloudlist

    dev

    Follow these steps to integrate a new cloud service provider into Cloudlist:

    1. Implement the provider logic: Add the new provider code in the pkg/providers directory.
    2. Register the provider: Update the nameToProvider function (located in pkg/inventory/inventory.go) by adding a new case statement that calls your provider's initialization function (e.g., return myprovider.New(block)).
    3. Test: Verify the provider integration works as expected.
    4. Document: Add usage instructions, including required configuration keys and setup steps, to the PROVIDERS.md file.
  9. Use Short-lived Credentials for GCP

    dev

    To enable short-lived credentials, set use_short_lived_credentials: true and provide a service_account_email.

    Configuration Options:

    • use_short_lived_credentials (bool): Enable short-lived token generation (default: false).
    • service_account_email (string, required): Target service account to impersonate.
    • source_credentials (string, optional): Path to source credentials file (uses ADC if not provided).
    • token_lifetime (string, optional): Token lifetime (e.g., "3600s" or "1h"). Range: 1s to 3600s. Default: "3600s".
    • project_ids (list, optional): Limits enumeration to specific projects.
    • exclude_project_ids (list, optional): Excludes specific projects from organization-wide discovery (mutually exclusive with project_ids).

    Requirements:

    • Source credentials need roles/iam.serviceAccountTokenCreator on the target service account.
    • Target service account needs appropriate viewer roles (Compute, DNS, Storage, etc.).
    • Service Account Credentials API must be enabled.
    - provider: gcp
      id: dev-discovery
      use_short_lived_credentials: true
      service_account_email: "cloudlist@project.iam.gserviceaccount.com"
  10. Set up Individual Service API discovery for GCP

    dev

    To use the Individual Service API approach, you must create a service account and grant it project-level permissions for each specific service you wish to scan.

    1. Create Service Account

    gcloud iam service-accounts create cloudlist-sa \
        --display-name="CloudList Individual Services" \
        --description="Service account for individual service API discovery"
    
    SA_EMAIL="cloudlist-sa@YOUR-PROJECT-ID.iam.gserviceaccount.com"
    PROJECT_ID="YOUR-PROJECT-ID"

    2. Grant Project-Level Permissions

    Grant the service account the specific viewer roles required for the services you want to discover. For example:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/compute.viewer"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/dns.reader"
    # ... repeat for other services

    3. Configuration

    Unlike the Organization-Level approach, do not provide an organization_id. The absence of this key triggers the Individual Service API mode.

    - provider: gcp
      id: project-discovery
      # No organization_id = uses individual service APIs
      gcp_service_account_key: |
        {
          "type": "service_account",
          "project_id": "your-project-id",
          ...
        }
  11. Setup GKE Workload Identity for GCP

    dev

    For GKE, you can use Workload Identity to achieve a 'Zero Secrets' setup where no credentials exist in your configuration files. This involves binding a Kubernetes Service Account (KSA) to a GCP Service Account.

    - provider: gcp
      id: workload-discovery
      use_short_lived_credentials: true
      service_account_email: "cloudlist@project.iam.gserviceaccount.com"
    # Enable workload identity on cluster
    gcloud container clusters update CLUSTER_NAME \
      --workload-pool=PROJECT_ID.svc.id.goog
    
    # Bind Kubernetes service account to GCP service account
    gcloud iam service-accounts add-iam-policy-binding \
      cloudlist@PROJECT_ID.iam.gserviceaccount.com \
      --role=roles/iam.workloadIdentityUser \
      --member="serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
    
    # Configure workload identity on deployment
    kubectl annotate serviceaccount KSA_NAME \
      iam.gke.io/gcp-service-account=cloudlist@PROJECT_ID.iam.gserviceaccount.com
  12. Set up Organization-Level GCP Asset discovery

    dev

    To perform organization-wide discovery, you must create a service account and grant it permissions at the organization level.

    1. Create Service Account

    gcloud iam service-accounts create asset-viewer-sa \
        --display-name="CloudList Asset Viewer" \
        --description="Service account for organization-level asset discovery"
    
    # Note the email for the next steps
    SA_EMAIL="asset-viewer-sa@YOUR-PROJECT-ID.iam.gserviceaccount.com"
    ORG_ID="YOUR-ORGANIZATION-ID"

    2. Grant Organization-Level Permissions

    Required Roles:

    • roles/cloudasset.viewer (Core Asset API access)
    • roles/resourcemanager.viewer (To list projects in the organization)

    Optional Roles (for Extended Metadata):

    • roles/compute.viewer (Compute instances)
    • roles/cloudfunctions.viewer (Cloud Functions)
    • roles/storage.objectViewer (Cloud Storage)
    • roles/run.viewer (Cloud Run)
    • roles/dns.reader (DNS records)
    • roles/container.viewer (GKE)

    Commands:

    # Required
    gcloud organizations add-iam-policy-binding $ORG_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/cloudasset.viewer"
    
    gcloud organizations add-iam-policy-binding $ORG_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/resourcemanager.viewer"
    
    # Optional (Example: Compute)
    gcloud organizations add-iam-policy-binding $ORG_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/compute.viewer"

    3. Generate Key

    gcloud iam service-accounts keys create asset-viewer-key.json \
        --iam-account=$SA_EMAIL
    # Required
    gcloud organizations add-iam-policy-binding $ORG_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/cloudasset.viewer"
    
    gcloud organizations add-iam-policy-binding $ORG_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="roles/resourcemanager.viewer"