Files
prowler/util/prowler-bulk-provisioning/README.md
2025-10-27 09:20:37 +01:00

497 lines
14 KiB
Markdown

# Prowler Provider Bulk Provisioning
A Python script to bulk-provision cloud providers in Prowler Cloud/App via REST API. This tool streamlines the process of adding multiple cloud providers to Prowler by reading configuration from YAML and making API calls with concurrency and retry support.
## Supported Providers
- **AWS** (Amazon Web Services)
- **Azure** (Microsoft Azure)
- **GCP** (Google Cloud Platform)
- **Kubernetes**
- **M365** (Microsoft 365)
- **GitHub**
## Features
- **Concurrent Processing:** Configurable concurrency for faster bulk operations
- **Retry Logic:** Built-in retry mechanism for handling temporary API failures
- **Dry-Run Mode:** Test configuration without making actual API calls
- **Flexible Authentication:** Supports various authentication methods per provider
- **Error Handling:** Comprehensive error reporting and validation
- **Connection Testing:** Built-in provider connection verification
- **AWS Organizations Support:** Automated YAML generation for all accounts in an AWS Organization
## How It Works
The script uses a two-step process to provision providers in Prowler:
1. **Provider Creation:** Creates the provider with basic information (provider type, UID, alias)
2. **Secret Creation:** Creates and links authentication credentials as a separate secret resource
This two-step approach follows the Prowler API design where providers and their credentials are managed as separate but linked resources, providing better security and flexibility.
## Installation
### Requirements
- Python 3.7 or higher
- Required packages (install via requirements.txt)
### Setup
1. Clone or navigate to the Prowler repository:
```bash
cd contrib/other-contrib/provider-bulk-importer
```
2. Install dependencies:
```bash
pip install -r requirements.txt
```
3. Get your Prowler API key:
- **Prowler Cloud:** Create an API key at https://api.prowler.com
- **Self-hosted Prowler App:** Create an API key in your local instance
- Click **Profile** → **Account** → **Create API Key**
```bash
export PROWLER_API_KEY="pk_example-api-key"
```
For detailed instructions on creating API keys, see: https://docs.prowler.com/user-guide/tutorials/prowler-app-api-keys
## AWS Organizations Integration
For organizations with many AWS accounts, use the included `aws_org_generator.py` script to automatically generate configuration for all accounts in your AWS Organization.
**📖 Full Guide:** See [AWS Organizations Bulk Provisioning Tutorial](https://docs.prowler.com/user-guide/tutorials/aws-organizations-bulk-provisioning) for complete documentation, examples, and troubleshooting.
### Prerequisites
Before using the AWS Organizations generator, deploy the ProwlerRole across all accounts using CloudFormation StackSets:
**Documentation:** [Deploying Prowler IAM Roles Across AWS Organizations](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/aws/organizations/#deploying-prowler-iam-roles-across-aws-organizations)
### Quick Start
1. Install additional dependencies:
```bash
pip install -r requirements-aws-org.txt
```
2. Generate YAML configuration for all organization accounts:
```bash
python aws_org_generator.py -o aws-accounts.yaml --external-id example-external-id
```
3. Run bulk provisioning:
```bash
python prowler_bulk_provisioning.py aws-accounts.yaml
```
### AWS Organizations Generator Options
```bash
python aws_org_generator.py -o aws-accounts.yaml \
--role-name ProwlerRole \
--external-id my-external-id \
--exclude 123456789012 \
--profile org-management
```
| Option | Description | Default |
|--------|-------------|---------|
| `-o, --output` | Output YAML file path | `aws-org-accounts.yaml` |
| `--role-name` | IAM role name across accounts | `ProwlerRole` |
| `--external-id` | External ID for role assumption | None (recommended) |
| `--session-name` | Session name for role assumption | None |
| `--duration-seconds` | Session duration in seconds | None |
| `--alias-format` | Alias template: `{name}`, `{id}`, `{email}` | `{name}` |
| `--exclude` | Comma-separated account IDs to exclude | None |
| `--include` | Comma-separated account IDs to include | None |
| `--profile` | AWS CLI profile name | Default credentials |
| `--region` | AWS region | `us-east-1` |
| `--dry-run` | Print to stdout without writing | `False` |
### Examples
**Generate config for all accounts with custom external ID:**
```bash
python aws_org_generator.py -o aws-accounts.yaml --external-id prowler-2024-abc123
```
**Exclude management account:**
```bash
python aws_org_generator.py -o aws-accounts.yaml \
--external-id prowler-ext-id \
--exclude 123456789012
```
**Use specific AWS profile:**
```bash
python aws_org_generator.py -o aws-accounts.yaml \
--profile org-admin \
--external-id prowler-ext-id
```
**Custom alias format:**
```bash
python aws_org_generator.py -o aws-accounts.yaml \
--alias-format "{name}-{id}" \
--external-id prowler-ext-id
```
## Configuration
### Environment Variables
```bash
export PROWLER_API_KEY="pk_example-api-key"
export PROWLER_API_BASE="https://api.prowler.com/api/v1" # Optional, defaults to Prowler Cloud
```
### Provider Configuration Files
Create a configuration file (YAML recommended) listing the providers to add:
#### YAML Format (Recommended)
```yaml
# providers.yaml
- provider: aws
uid: "123456789012" # AWS Account ID
alias: "prod-root"
auth_method: role # role | credentials
credentials:
role_arn: "arn:aws:iam::123456789012:role/ProwlerScan"
external_id: "ext-abc123" # optional
session_name: "prowler-bulk" # optional
duration_seconds: 3600 # optional
- provider: aws
uid: "210987654321"
alias: "dev"
auth_method: credentials # long/short-lived keys
credentials:
access_key_id: "AKIA..."
secret_access_key: "..."
session_token: "..." # optional
- provider: azure
uid: "00000000-1111-2222-3333-444444444444" # Subscription ID
alias: "sub-eastus"
auth_method: service_principal
credentials:
tenant_id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
client_id: "ffffffff-1111-2222-3333-444444444444"
client_secret: "..."
- provider: gcp
uid: "my-gcp-project-id" # Project ID
alias: "gcp-prod"
auth_method: service_account # Service Account authentication
credentials:
service_account_key_json_path: "./gcp-key.json"
- provider: kubernetes
uid: "my-eks-context" # kubeconfig context name
alias: "eks-prod"
auth_method: kubeconfig
credentials:
kubeconfig_path: "~/.kube/config"
- provider: m365
uid: "contoso.onmicrosoft.com" # Domain ID
alias: "contoso"
auth_method: service_principal
credentials:
tenant_id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
client_id: "ffffffff-1111-2222-3333-444444444444"
client_secret: "..."
- provider: github
uid: "my-org" # organization or username
alias: "gh-org"
auth_method: personal_access_token # oauth_app_token | github_app
credentials:
token: "ghp_..."
```
## Usage
### Basic Usage
```bash
python prowler_bulk_provisioning.py providers.yaml
```
### Advanced Usage
```bash
python prowler_bulk_provisioning.py providers.yaml \
--base-url https://api.prowler.com/api/v1 \
--providers-endpoint /providers \
--concurrency 6 \
--timeout 120
```
### Command Line Options
| Option | Description | Default |
|--------|-------------|---------|
| `input_file` | YAML file with provider entries | Required |
| `--base-url` | API base URL | `https://api.prowler.com/api/v1` |
| `--api-key` | Prowler API key | `PROWLER_API_KEY` env var |
| `--providers-endpoint` | Providers API endpoint | `/providers` |
| `--concurrency` | Number of concurrent requests | `5` |
| `--timeout` | Per-request timeout in seconds | `60` |
| `--insecure` | Disable TLS verification | `False` |
| `--dry-run` | Print payloads without sending | `False` |
| `--test-provider` | Test connection after creating each provider (true/false) | `true` (enabled by default) |
| `--test-provider-only` | Only test connections for existing providers (skip creation) | `False` |
### Self-hosted Prowler App
For self-hosted installations:
```bash
python prowler_bulk_provisioning.py providers.yaml \
--base-url http://localhost:8080/api/v1
```
## Provider-Specific Configuration
### AWS Authentication Methods
#### IAM Role (Recommended)
```yaml
- provider: aws
uid: "123456789012"
alias: "prod"
auth_method: role
credentials:
role_arn: "arn:aws:iam::123456789012:role/ProwlerScan"
external_id: "optional-external-id"
```
#### Access Keys
```yaml
- provider: aws
uid: "123456789012"
alias: "dev"
auth_method: credentials
credentials:
access_key_id: "AKIA..."
secret_access_key: "..."
session_token: "..." # optional for temporary credentials
```
### Azure Authentication
```yaml
- provider: azure
uid: "subscription-uuid"
alias: "azure-prod"
auth_method: service_principal
credentials:
tenant_id: "tenant-uuid"
client_id: "client-uuid"
client_secret: "client-secret"
```
### GCP Authentication
The Prowler API supports the following authentication methods for GCP:
#### Method 1: Service Account JSON (Recommended)
```yaml
- provider: gcp
uid: "project-id"
alias: "gcp-prod"
auth_method: service_account # or 'service_account_json'
credentials:
service_account_key_json_path: "/path/to/key.json"
# OR inline:
# inline_json:
# type: "service_account"
# project_id: "example-project"
# private_key_id: "example-key-id"
# private_key: "-----BEGIN PRIVATE KEY-----\n..."
# client_email: "service-account@project.iam.gserviceaccount.com"
# client_id: "1234567890"
# auth_uri: "https://accounts.google.com/o/oauth2/auth"
# token_uri: "https://oauth2.googleapis.com/token"
# auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs"
# client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/..."
```
#### Method 2: OAuth2 Credentials
```yaml
- provider: gcp
uid: "project-id"
alias: "gcp-prod"
auth_method: oauth2 # or 'adc' for Application Default Credentials
credentials:
client_id: "123456789012345678901.apps.googleusercontent.com"
client_secret: "GOCSPX-xxxxxxxxxxxxxxxxx"
refresh_token: "1//0exxxxxxxxxxxxxxxxx"
```
### Kubernetes Authentication
```yaml
- provider: kubernetes
uid: "context-name"
alias: "k8s-prod"
auth_method: kubeconfig
credentials:
kubeconfig_path: "~/.kube/config"
# OR
# kubeconfig_inline: |
# apiVersion: v1
# clusters: ...
```
### Microsoft 365 Authentication
```yaml
- provider: m365
uid: "domain.onmicrosoft.com"
alias: "m365-tenant"
auth_method: service_principal
credentials:
tenant_id: "tenant-uuid"
client_id: "client-uuid"
client_secret: "client-secret"
```
### GitHub Authentication
#### Personal Access Token
```yaml
- provider: github
uid: "organization-name"
alias: "gh-org"
auth_method: personal_access_token
credentials:
token: "ghp_..."
```
#### GitHub App
```yaml
- provider: github
uid: "organization-name"
alias: "gh-org"
auth_method: github_app
credentials:
app_id: "123456"
private_key_path: "/path/to/private-key.pem"
# OR
# private_key_inline: "-----BEGIN RSA PRIVATE KEY-----\n..."
```
## Connection Testing
The script includes built-in connection testing to verify that providers can successfully authenticate with their respective cloud services.
By default, the script tests connections immediately after creating providers:
```bash
python prowler_bulk_provisioning.py providers.yaml
```
This will:
1. Create the provider
2. Add credentials
3. Test the connection
4. Report connection status
To skip connection testing, use:
```bash
python prowler_bulk_provisioning.py providers.yaml --test-provider false
```
### Test Existing Providers
Test connections for already existing providers without creating new ones:
```bash
python prowler_bulk_provisioning.py providers.yaml --test-provider-only
```
This is useful for:
- Verifying existing provider configurations
- Debugging authentication issues
- Regular connection health checks
- Testing after credential updates
### Example Output
```
[1] ✅ Created provider (id=db9a8985-f9ec-4dd8-b5a0-e05ab3880bed)
[1] ✅ Created secret (id=466f76c6-5878-4602-a4bc-13f9522c1fd2)
[1] ✅ Connection test: Connected
[2] ✅ Created provider (id=7a99f789-0cf5-4329-8279-2d443a962676)
[2] ✅ Created secret (id=c5702180-f7c4-40fd-be0e-f6433479b126)
[2] ❌ Connection test: Not connected
```
## Advanced Features
### Dry Run Mode
Test your configuration without making API calls:
```bash
python prowler_bulk_provisioning.py providers.yaml --dry-run
```
## Troubleshooting
### Common Issues
1. **Invalid API Key**
```
Error: 401 Unauthorized
Solution: Check your PROWLER_API_KEY environment variable or --api-key parameter
```
2. **Network Timeouts**
```
Error: Request timeout
Solution: Increase --timeout value or check network connectivity
```
3. **Invalid Provider Configuration**
```
Error: Each item must include 'provider' and 'uid'
Solution: Verify all required fields are present in your config file
```
4. **File Not Found Errors**
```
Error: No such file or directory
Solution: Check file paths for credentials files (JSON keys, kubeconfig, etc.)
```
## Examples
See the `examples/` directory for sample configuration files:
- `examples/simple-providers.yaml` - Basic example with minimal configuration
## Support
For issues and questions:
1. Check the [Prowler documentation](https://docs.prowler.com)
2. Review the [API documentation](https://api.prowler.com/api/v1/docs)
3. Open an issue in the [Prowler repository](https://github.com/prowler-cloud/prowler)
## License
This tool is part of the Prowler project and follows the same licensing terms.