mirror of
https://github.com/prowler-cloud/prowler.git
synced 2025-12-19 05:17:47 +00:00
chore: script to generate AWS accounts list from AWS Org for bulk provisioning (#8903)
This commit is contained in:
@@ -114,7 +114,8 @@
|
||||
"group": "Tutorials",
|
||||
"pages": [
|
||||
"user-guide/tutorials/prowler-app-sso-entra",
|
||||
"user-guide/tutorials/bulk-provider-provisioning"
|
||||
"user-guide/tutorials/bulk-provider-provisioning",
|
||||
"user-guide/tutorials/aws-organizations-bulk-provisioning"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
---
|
||||
title: 'AWS Organizations Bulk Provisioning in Prowler'
|
||||
---
|
||||
|
||||
Prowler offers an automated tool to discover and provision all AWS accounts within an AWS Organization. This streamlines onboarding for organizations managing multiple AWS accounts by automatically generating the configuration needed for bulk provisioning.
|
||||
|
||||
The tool, `aws_org_generator.py`, complements the [Bulk Provider Provisioning](./bulk-provider-provisioning) tool and is available in the Prowler repository at: [util/prowler-bulk-provisioning](https://github.com/prowler-cloud/prowler/tree/master/util/prowler-bulk-provisioning)
|
||||
|
||||
<Note>
|
||||
Native support for bulk provisioning AWS Organizations and similar multi-account structures directly in the Prowler UI/API is on the official roadmap.
|
||||
|
||||
Track progress and vote for this feature at: [Bulk Provisioning in the UI/API for AWS Organizations](https://roadmap.prowler.com/p/builk-provisioning-in-the-uiapi-for-aws-organizations-and-alike)
|
||||
</Note>
|
||||
|
||||
{/* TODO: Add screenshot of the tool in action */}
|
||||
|
||||
## Overview
|
||||
|
||||
The AWS Organizations Bulk Provisioning tool simplifies multi-account onboarding by:
|
||||
|
||||
* Automatically discovering all active accounts in an AWS Organization
|
||||
* Generating YAML configuration files for bulk provisioning
|
||||
* Supporting account filtering and custom role configurations
|
||||
* Eliminating manual entry of account IDs and role ARNs
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Requirements
|
||||
|
||||
* Python 3.7 or higher
|
||||
* AWS credentials with Organizations read access
|
||||
* ProwlerRole (or custom role) deployed across all target accounts
|
||||
* Prowler API key (from Prowler Cloud or self-hosted Prowler App)
|
||||
* For self-hosted Prowler App, remember to [point to your API base URL](./bulk-provider-provisioning#custom-api-endpoints)
|
||||
* Learn how to create API keys: [Prowler App API Keys](../providers/prowler-app-api-keys)
|
||||
|
||||
### Deploying ProwlerRole Across AWS Organizations
|
||||
|
||||
Before using the AWS Organizations generator, deploy the ProwlerRole across all accounts in the organization using CloudFormation StackSets.
|
||||
|
||||
<Note>
|
||||
**Follow the official documentation:**
|
||||
[Deploying Prowler IAM Roles Across AWS Organizations](../providers/aws/organizations#deploying-prowler-iam-roles-across-aws-organizations)
|
||||
|
||||
**Key points:**
|
||||
|
||||
* Use CloudFormation StackSets from the management account
|
||||
* Deploy to all organizational units (OUs) or specific OUs
|
||||
* Use an external ID for enhanced security
|
||||
* Ensure the role has necessary permissions for Prowler scans
|
||||
</Note>
|
||||
|
||||
### Installation
|
||||
|
||||
Clone the repository and install required dependencies:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/prowler-cloud/prowler.git
|
||||
cd prowler/util/prowler-bulk-provisioning
|
||||
pip install -r requirements-aws-org.txt
|
||||
```
|
||||
|
||||
### AWS Credentials Setup
|
||||
|
||||
Configure AWS credentials with Organizations read access:
|
||||
|
||||
* **Management account credentials**, or
|
||||
* **Delegated administrator account** with `organizations:ListAccounts` permission
|
||||
|
||||
Required IAM permissions:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"organizations:ListAccounts",
|
||||
"organizations:DescribeOrganization"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Prowler API Key Setup
|
||||
|
||||
Configure your Prowler API key:
|
||||
|
||||
```bash
|
||||
export PROWLER_API_KEY="pk_example-api-key"
|
||||
```
|
||||
|
||||
To create an API key:
|
||||
|
||||
1. Log in to Prowler Cloud or Prowler App
|
||||
2. Click **Profile** → **Account**
|
||||
3. Click **Create API Key**
|
||||
4. Provide a descriptive name and optionally set an expiration date
|
||||
5. Copy the generated API key (it will only be shown once)
|
||||
|
||||
For detailed instructions, see: [Prowler App API Keys](../providers/prowler-app-api-keys)
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Generate Configuration for All Accounts
|
||||
|
||||
To generate a YAML configuration file for all active accounts in the organization:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py -o aws-accounts.yaml --external-id prowler-ext-id-2024
|
||||
```
|
||||
|
||||
This command:
|
||||
|
||||
1. Lists all ACTIVE accounts in the organization
|
||||
2. Generates YAML entries for each account
|
||||
3. Saves the configuration to `aws-accounts.yaml`
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Fetching accounts from AWS Organizations...
|
||||
Found 47 active accounts in organization
|
||||
Generated configuration for 47 accounts
|
||||
|
||||
Configuration written to: aws-accounts.yaml
|
||||
|
||||
Next steps:
|
||||
1. Review the generated file: cat aws-accounts.yaml | head -n 20
|
||||
2. Run bulk provisioning: python prowler_bulk_provisioning.py aws-accounts.yaml
|
||||
```
|
||||
|
||||
### Review Generated Configuration
|
||||
|
||||
Review the generated YAML configuration:
|
||||
|
||||
```bash
|
||||
head -n 20 aws-accounts.yaml
|
||||
```
|
||||
|
||||
**Example output:**
|
||||
|
||||
```yaml
|
||||
- provider: aws
|
||||
uid: '111111111111'
|
||||
alias: Production-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::111111111111:role/ProwlerRole
|
||||
external_id: prowler-ext-id-2024
|
||||
|
||||
- provider: aws
|
||||
uid: '222222222222'
|
||||
alias: Development-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::222222222222:role/ProwlerRole
|
||||
external_id: prowler-ext-id-2024
|
||||
```
|
||||
|
||||
### Dry Run Mode
|
||||
|
||||
Test the configuration without writing a file:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
--external-id prowler-ext-id-2024 \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Using a Specific AWS Profile
|
||||
|
||||
Specify an AWS profile when multiple profiles are configured:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--profile org-management-admin \
|
||||
--external-id prowler-ext-id-2024
|
||||
```
|
||||
|
||||
### Excluding Specific Accounts
|
||||
|
||||
Exclude the management account or other accounts from provisioning:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--external-id prowler-ext-id-2024 \
|
||||
--exclude 123456789012,210987654321
|
||||
```
|
||||
|
||||
Common exclusion scenarios:
|
||||
|
||||
* Management account (requires different permissions)
|
||||
* Break-glass accounts (emergency access)
|
||||
* Suspended or archived accounts
|
||||
|
||||
### Including Only Specific Accounts
|
||||
|
||||
Generate configuration for specific accounts only:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--external-id prowler-ext-id-2024 \
|
||||
--include 111111111111,222222222222,333333333333
|
||||
```
|
||||
|
||||
### Custom Role Name
|
||||
|
||||
Specify a custom role name if not using the default `ProwlerRole`:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--role-name ProwlerExecutionRole \
|
||||
--external-id prowler-ext-id-2024
|
||||
```
|
||||
|
||||
### Custom Alias Format
|
||||
|
||||
Customize account aliases using template variables:
|
||||
|
||||
```bash
|
||||
# Use account name and ID
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--alias-format "{name}-{id}" \
|
||||
--external-id prowler-ext-id-2024
|
||||
|
||||
# Use email prefix
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--alias-format "{email}" \
|
||||
--external-id prowler-ext-id-2024
|
||||
```
|
||||
|
||||
Available template variables:
|
||||
|
||||
* `{name}` - Account name
|
||||
* `{id}` - Account ID
|
||||
* `{email}` - Account email
|
||||
|
||||
### Additional Role Assumption Options
|
||||
|
||||
Configure optional role assumption parameters:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--role-name ProwlerRole \
|
||||
--external-id prowler-ext-id-2024 \
|
||||
--session-name prowler-scan-session \
|
||||
--duration-seconds 3600
|
||||
```
|
||||
|
||||
## Complete Workflow Example
|
||||
|
||||
<Steps>
|
||||
<Step title="Deploy ProwlerRole Using StackSets">
|
||||
1. Log in to the AWS management account
|
||||
2. Open CloudFormation → StackSets
|
||||
3. Create a new StackSet using the [Prowler role template](https://github.com/prowler-cloud/prowler/blob/master/permissions/templates/cloudformation/prowler-scan-role.yml)
|
||||
4. Deploy to all organizational units
|
||||
5. Use a unique external ID (e.g., `prowler-org-2024-abc123`)
|
||||
|
||||
{/* TODO: Add screenshot of CloudFormation StackSets deployment */}
|
||||
</Step>
|
||||
|
||||
<Step title="Generate YAML Configuration">
|
||||
Configure AWS credentials and generate the YAML file:
|
||||
|
||||
```bash
|
||||
# Using management account credentials
|
||||
export AWS_PROFILE=org-management
|
||||
|
||||
# Generate configuration
|
||||
python aws_org_generator.py \
|
||||
-o aws-org-accounts.yaml \
|
||||
--external-id prowler-org-2024-abc123 \
|
||||
--exclude 123456789012
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Fetching accounts from AWS Organizations...
|
||||
Using AWS profile: org-management
|
||||
Found 47 active accounts in organization
|
||||
Generated configuration for 46 accounts
|
||||
|
||||
Configuration written to: aws-org-accounts.yaml
|
||||
|
||||
Next steps:
|
||||
1. Review the generated file: cat aws-org-accounts.yaml | head -n 20
|
||||
2. Run bulk provisioning: python prowler_bulk_provisioning.py aws-org-accounts.yaml
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Review Generated Configuration">
|
||||
Verify the generated YAML configuration:
|
||||
|
||||
```bash
|
||||
# View first 20 lines
|
||||
head -n 20 aws-org-accounts.yaml
|
||||
|
||||
# Check for unexpected accounts
|
||||
grep "uid:" aws-org-accounts.yaml
|
||||
|
||||
# Verify role ARNs
|
||||
grep "role_arn:" aws-org-accounts.yaml | head -5
|
||||
|
||||
# Count accounts
|
||||
grep "provider: aws" aws-org-accounts.yaml | wc -l
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Bulk Provisioning">
|
||||
Provision all accounts to Prowler Cloud or Prowler App:
|
||||
|
||||
```bash
|
||||
# Set Prowler API key
|
||||
export PROWLER_API_KEY="pk_example-api-key"
|
||||
|
||||
# Run bulk provisioning with connection testing
|
||||
python prowler_bulk_provisioning.py aws-org-accounts.yaml
|
||||
```
|
||||
|
||||
**With custom options:**
|
||||
|
||||
```bash
|
||||
python prowler_bulk_provisioning.py aws-org-accounts.yaml \
|
||||
--concurrency 10 \
|
||||
--timeout 120
|
||||
```
|
||||
|
||||
**Successful 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: Connected
|
||||
|
||||
Done. Success: 47 Failures: 0
|
||||
```
|
||||
|
||||
{/* TODO: Add screenshot of successful bulk provisioning output */}
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Command Reference
|
||||
|
||||
### Full Command-Line Options
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o OUTPUT_FILE \
|
||||
--role-name ROLE_NAME \
|
||||
--external-id EXTERNAL_ID \
|
||||
--session-name SESSION_NAME \
|
||||
--duration-seconds SECONDS \
|
||||
--alias-format FORMAT \
|
||||
--exclude ACCOUNT_IDS \
|
||||
--include ACCOUNT_IDS \
|
||||
--profile AWS_PROFILE \
|
||||
--region AWS_REGION \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "No AWS credentials found"
|
||||
|
||||
**Solution:** Configure AWS credentials using one of these methods:
|
||||
|
||||
```bash
|
||||
# Method 1: AWS CLI configure
|
||||
aws configure
|
||||
|
||||
# Method 2: Environment variables
|
||||
export AWS_ACCESS_KEY_ID=your-key-id
|
||||
export AWS_SECRET_ACCESS_KEY=your-secret-key
|
||||
|
||||
# Method 3: Use AWS profile
|
||||
export AWS_PROFILE=org-management
|
||||
```
|
||||
|
||||
### Error: "Access denied to AWS Organizations API"
|
||||
|
||||
**Cause:** Current credentials don't have permission to list organization accounts.
|
||||
|
||||
**Solution:**
|
||||
|
||||
* Ensure management account credentials are used
|
||||
* Verify IAM permissions include `organizations:ListAccounts`
|
||||
* Check IAM policies for Organizations access
|
||||
|
||||
### Error: "AWS Organizations is not enabled"
|
||||
|
||||
**Cause:** The account is not part of an organization.
|
||||
|
||||
**Solution:** This tool requires an AWS Organization. Create one in the AWS Organizations console or use standard bulk provisioning for standalone accounts.
|
||||
|
||||
### No Accounts Generated After Filters
|
||||
|
||||
**Cause:** All accounts were filtered out by `--exclude` or `--include` options.
|
||||
|
||||
**Solution:** Review filter options and verify account IDs are correct:
|
||||
|
||||
```bash
|
||||
# List all accounts in organization
|
||||
aws organizations list-accounts --query "Accounts[?Status=='ACTIVE'].[Id,Name]" --output table
|
||||
```
|
||||
|
||||
### Connection Test Failures During Bulk Provisioning
|
||||
|
||||
**Cause:** ProwlerRole may not be deployed correctly or credentials are invalid.
|
||||
|
||||
**Solution:**
|
||||
|
||||
* Verify StackSet deployment status in CloudFormation
|
||||
* Check role trust policy includes correct external ID
|
||||
* Test role assumption manually:
|
||||
|
||||
```bash
|
||||
aws sts assume-role \
|
||||
--role-arn arn:aws:iam::123456789012:role/ProwlerRole \
|
||||
--role-session-name test \
|
||||
--external-id prowler-ext-id-2024
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### Use External ID
|
||||
|
||||
Always use an external ID when assuming cross-account roles:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--external-id $(uuidgen | tr '[:upper:]' '[:lower:]')
|
||||
```
|
||||
|
||||
The external ID must match the one configured in the ProwlerRole trust policy across all accounts.
|
||||
|
||||
### Exclude Sensitive Accounts
|
||||
|
||||
Exclude accounts that shouldn't be scanned or require special handling:
|
||||
|
||||
```bash
|
||||
python aws_org_generator.py \
|
||||
-o aws-accounts.yaml \
|
||||
--external-id prowler-ext-id \
|
||||
--exclude 123456789012,111111111111 # management, break-glass accounts
|
||||
```
|
||||
|
||||
### Review Generated Configuration
|
||||
|
||||
Always review the generated YAML before provisioning:
|
||||
|
||||
```bash
|
||||
# Check for unexpected accounts
|
||||
grep "uid:" aws-org-accounts.yaml
|
||||
|
||||
# Verify role ARNs
|
||||
grep "role_arn:" aws-org-accounts.yaml | head -5
|
||||
|
||||
# Count accounts
|
||||
grep "provider: aws" aws-org-accounts.yaml | wc -l
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Bulk Provider Provisioning" icon="terminal" href="/user-guide/tutorials/bulk-provider-provisioning">
|
||||
Learn how to bulk provision providers in Prowler.
|
||||
</Card>
|
||||
<Card title="Prowler App" icon="pen-to-square" href="/user-guide/tutorials/prowler-app">
|
||||
Detailed instructions on how to use Prowler.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -17,14 +17,18 @@ The Bulk Provider Provisioning tool automates the creation of cloud providers in
|
||||
* Testing connections to verify successful authentication
|
||||
* Processing multiple providers concurrently for efficiency
|
||||
|
||||
<Tip>
|
||||
**Using AWS Organizations?** For organizations with many AWS accounts, use the automated [AWS Organizations Bulk Provisioning](./aws-organizations-bulk-provisioning) tool to automatically discover and generate configuration for all accounts in your organization.
|
||||
</Tip>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Requirements
|
||||
|
||||
* Python 3.7 or higher
|
||||
* Prowler API token (from Prowler Cloud or self-hosted Prowler App)
|
||||
* Prowler API key (from Prowler Cloud or self-hosted Prowler App)
|
||||
* For self-hosted Prowler App, remember to [point to your API base URL](#custom-api-endpoints)
|
||||
* Learn how to create API keys: [Prowler App API Keys](../providers/prowler-app-api-keys)
|
||||
* Authentication credentials for target cloud providers
|
||||
|
||||
### Installation
|
||||
@@ -39,28 +43,21 @@ pip install -r requirements.txt
|
||||
|
||||
### Authentication Setup
|
||||
|
||||
Configure your Prowler API token:
|
||||
Configure your Prowler API key:
|
||||
|
||||
```bash
|
||||
export PROWLER_API_TOKEN="your-prowler-api-token"
|
||||
export PROWLER_API_KEY="pk_example-api-key"
|
||||
```
|
||||
|
||||
To obtain an API token programmatically:
|
||||
To create an API key:
|
||||
|
||||
```bash
|
||||
export PROWLER_API_TOKEN=$(curl --location 'https://api.prowler.com/api/v1/tokens' \
|
||||
--header 'Content-Type: application/vnd.api+json' \
|
||||
--header 'Accept: application/vnd.api+json' \
|
||||
--data-raw '{
|
||||
"data": {
|
||||
"type": "tokens",
|
||||
"attributes": {
|
||||
"email": "your@email.com",
|
||||
"password": "your-password"
|
||||
}
|
||||
}
|
||||
}' | jq -r .data.attributes.access)
|
||||
```
|
||||
1. Log in to Prowler Cloud or Prowler App
|
||||
2. Click **Profile** → **Account**
|
||||
3. Click **Create API Key**
|
||||
4. Provide a descriptive name and optionally set an expiration date
|
||||
5. Copy the generated API key (it will only be shown once)
|
||||
|
||||
For detailed instructions, see: [Prowler App API Keys](../providers/prowler-app-api-keys)
|
||||
|
||||
## Configuration File Structure
|
||||
|
||||
@@ -340,11 +337,11 @@ Done. Success: 2 Failures: 0
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Invalid API Token
|
||||
### Invalid API Key
|
||||
|
||||
```
|
||||
Error: 401 Unauthorized
|
||||
Solution: Verify your PROWLER_API_TOKEN or --token parameter
|
||||
Solution: Verify your PROWLER_API_KEY environment variable or --api-key parameter
|
||||
```
|
||||
|
||||
### Network Timeouts
|
||||
|
||||
@@ -19,6 +19,7 @@ A Python script to bulk-provision cloud providers in Prowler Cloud/App via REST
|
||||
- **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
|
||||
|
||||
@@ -48,32 +49,105 @@ This two-step approach follows the Prowler API design where providers and their
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. Get your Prowler API token:
|
||||
- **Prowler Cloud:** Generate token at https://api.prowler.com
|
||||
- **Self-hosted Prowler App:** Generate token in your local instance
|
||||
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_TOKEN=$(curl --location 'https://api.prowler.com/api/v1/tokens' \
|
||||
--header 'Content-Type: application/vnd.api+json' \
|
||||
--header 'Accept: application/vnd.api+json' \
|
||||
--data-raw '{
|
||||
"data": {
|
||||
"type": "tokens",
|
||||
"attributes": {
|
||||
"email": "your@email.com",
|
||||
"password": "your-password"
|
||||
}
|
||||
}
|
||||
}' | jq -r .data.attributes.access)
|
||||
export PROWLER_API_KEY="pk_example-api-key"
|
||||
```
|
||||
|
||||
For detailed instructions on creating API keys, see: https://docs.prowler.com/user-guide/providers/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_TOKEN="your-prowler-token"
|
||||
export PROWLER_API_KEY="pk_example-api-key"
|
||||
export PROWLER_API_BASE="https://api.prowler.com/api/v1" # Optional, defaults to Prowler Cloud
|
||||
```
|
||||
|
||||
@@ -168,7 +242,7 @@ python prowler_bulk_provisioning.py providers.yaml \
|
||||
|--------|-------------|---------|
|
||||
| `input_file` | YAML file with provider entries | Required |
|
||||
| `--base-url` | API base URL | `https://api.prowler.com/api/v1` |
|
||||
| `--token` | Bearer token | `PROWLER_API_TOKEN` env var |
|
||||
| `--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` |
|
||||
@@ -241,8 +315,8 @@ The Prowler API supports the following authentication methods for GCP:
|
||||
# OR inline:
|
||||
# inline_json:
|
||||
# type: "service_account"
|
||||
# project_id: "your-project"
|
||||
# private_key_id: "key-id"
|
||||
# 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"
|
||||
@@ -379,10 +453,10 @@ python prowler_bulk_provisioning.py providers.yaml --dry-run
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Invalid API Token**
|
||||
1. **Invalid API Key**
|
||||
```
|
||||
Error: 401 Unauthorized
|
||||
Solution: Check your PROWLER_API_TOKEN or --token parameter
|
||||
Solution: Check your PROWLER_API_KEY environment variable or --api-key parameter
|
||||
```
|
||||
|
||||
2. **Network Timeouts**
|
||||
|
||||
333
util/prowler-bulk-provisioning/aws_org_generator.py
Executable file
333
util/prowler-bulk-provisioning/aws_org_generator.py
Executable file
@@ -0,0 +1,333 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
AWS Organizations Account Generator for Prowler Bulk Provisioning
|
||||
|
||||
Generates YAML configuration for all accounts in an AWS Organization,
|
||||
ready to be used with prowler_bulk_provisioning.py.
|
||||
|
||||
Prerequisites:
|
||||
- ProwlerRole (or custom role) must be deployed across all accounts
|
||||
- AWS credentials with Organizations read access (typically management account)
|
||||
- See: https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/aws/organizations/#deploying-prowler-iam-roles-across-aws-organizations
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
try:
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError, NoCredentialsError
|
||||
except ImportError:
|
||||
sys.exit(
|
||||
"boto3 is required. Install with: pip install boto3\n"
|
||||
"Or install all dependencies: pip install -r requirements-aws-org.txt"
|
||||
)
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
sys.exit("PyYAML is required. Install with: pip install pyyaml")
|
||||
|
||||
|
||||
def get_org_accounts(
|
||||
profile: Optional[str] = None, region: Optional[str] = None
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Retrieve all accounts from AWS Organizations.
|
||||
|
||||
Args:
|
||||
profile: AWS CLI profile name
|
||||
region: AWS region (defaults to us-east-1 for Organizations)
|
||||
|
||||
Returns:
|
||||
List of account dictionaries with id, name, email, and status
|
||||
"""
|
||||
try:
|
||||
session = boto3.Session(profile_name=profile, region_name=region or "us-east-1")
|
||||
client = session.client("organizations")
|
||||
|
||||
accounts = []
|
||||
paginator = client.get_paginator("list_accounts")
|
||||
|
||||
for page in paginator.paginate():
|
||||
for account in page["Accounts"]:
|
||||
# Only include ACTIVE accounts
|
||||
if account["Status"] == "ACTIVE":
|
||||
accounts.append(
|
||||
{
|
||||
"id": account["Id"],
|
||||
"name": account["Name"],
|
||||
"email": account["Email"],
|
||||
"status": account["Status"],
|
||||
}
|
||||
)
|
||||
|
||||
return accounts
|
||||
|
||||
except NoCredentialsError:
|
||||
sys.exit(
|
||||
"No AWS credentials found. Configure credentials using:\n"
|
||||
" - AWS CLI: aws configure\n"
|
||||
" - Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY\n"
|
||||
" - IAM role if running on EC2/ECS/Lambda"
|
||||
)
|
||||
except ClientError as e:
|
||||
error_code = e.response["Error"]["Code"]
|
||||
if error_code == "AccessDeniedException":
|
||||
sys.exit(
|
||||
"Access denied to AWS Organizations API.\n"
|
||||
"Ensure you are using credentials from the management account\n"
|
||||
"with permissions to call organizations:ListAccounts"
|
||||
)
|
||||
elif error_code == "AWSOrganizationsNotInUseException":
|
||||
sys.exit(
|
||||
"AWS Organizations is not enabled for this account.\n"
|
||||
"This script requires an AWS Organization to be set up."
|
||||
)
|
||||
else:
|
||||
sys.exit(f"AWS API error: {e}")
|
||||
except Exception as e:
|
||||
sys.exit(f"Unexpected error listing accounts: {e}")
|
||||
|
||||
|
||||
def generate_yaml_config(
|
||||
accounts: List[Dict[str, Any]],
|
||||
role_name: str = "ProwlerRole",
|
||||
external_id: Optional[str] = None,
|
||||
session_name: Optional[str] = None,
|
||||
duration_seconds: Optional[int] = None,
|
||||
alias_format: str = "{name}",
|
||||
exclude_accounts: Optional[List[str]] = None,
|
||||
include_accounts: Optional[List[str]] = None,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Generate YAML configuration for Prowler bulk provisioning.
|
||||
|
||||
Args:
|
||||
accounts: List of account dictionaries from get_org_accounts
|
||||
role_name: IAM role name (default: ProwlerRole)
|
||||
external_id: External ID for role assumption (optional but recommended)
|
||||
session_name: Session name for role assumption (optional)
|
||||
duration_seconds: Session duration in seconds (optional)
|
||||
alias_format: Format string for alias (supports {name}, {id}, {email})
|
||||
exclude_accounts: List of account IDs to exclude
|
||||
include_accounts: List of account IDs to include (if set, only these are included)
|
||||
|
||||
Returns:
|
||||
List of provider configurations ready for YAML export
|
||||
"""
|
||||
exclude_accounts = exclude_accounts or []
|
||||
include_accounts = include_accounts or []
|
||||
|
||||
providers = []
|
||||
|
||||
for account in accounts:
|
||||
account_id = account["id"]
|
||||
|
||||
# Apply filters
|
||||
if include_accounts and account_id not in include_accounts:
|
||||
continue
|
||||
if account_id in exclude_accounts:
|
||||
continue
|
||||
|
||||
# Format alias using template
|
||||
alias = alias_format.format(
|
||||
name=account["name"], id=account_id, email=account["email"]
|
||||
)
|
||||
|
||||
# Build role ARN
|
||||
role_arn = f"arn:aws:iam::{account_id}:role/{role_name}"
|
||||
|
||||
# Build credentials section
|
||||
credentials: Dict[str, Any] = {"role_arn": role_arn}
|
||||
|
||||
if external_id:
|
||||
credentials["external_id"] = external_id
|
||||
|
||||
if session_name:
|
||||
credentials["session_name"] = session_name
|
||||
|
||||
if duration_seconds:
|
||||
credentials["duration_seconds"] = duration_seconds
|
||||
|
||||
# Build provider entry
|
||||
provider = {
|
||||
"provider": "aws",
|
||||
"uid": account_id,
|
||||
"alias": alias,
|
||||
"auth_method": "role",
|
||||
"credentials": credentials,
|
||||
}
|
||||
|
||||
providers.append(provider)
|
||||
|
||||
return providers
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to generate AWS Organizations YAML configuration."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate Prowler bulk provisioning YAML from AWS Organizations",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Basic usage - generate YAML for all accounts
|
||||
python aws_org_generator.py -o aws-accounts.yaml
|
||||
|
||||
# Use custom role name and external ID
|
||||
python aws_org_generator.py -o aws-accounts.yaml \\
|
||||
--role-name ProwlerExecutionRole \\
|
||||
--external-id my-external-id-12345
|
||||
|
||||
# Use specific AWS profile
|
||||
python aws_org_generator.py -o aws-accounts.yaml \\
|
||||
--profile org-management
|
||||
|
||||
# Exclude specific accounts (e.g., management account)
|
||||
python aws_org_generator.py -o aws-accounts.yaml \\
|
||||
--exclude 123456789012,210987654321
|
||||
|
||||
# Include only specific accounts
|
||||
python aws_org_generator.py -o aws-accounts.yaml \\
|
||||
--include 111111111111,222222222222
|
||||
|
||||
# Custom alias format
|
||||
python aws_org_generator.py -o aws-accounts.yaml \\
|
||||
--alias-format "{name}-{id}"
|
||||
|
||||
Prerequisites:
|
||||
1. Deploy ProwlerRole across all accounts using CloudFormation StackSets:
|
||||
https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/aws/organizations/#deploying-prowler-iam-roles-across-aws-organizations
|
||||
|
||||
2. Ensure AWS credentials have Organizations read access:
|
||||
- organizations:ListAccounts
|
||||
- organizations:DescribeOrganization (optional)
|
||||
""",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output",
|
||||
default="aws-org-accounts.yaml",
|
||||
help="Output YAML file path (default: aws-org-accounts.yaml)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--role-name",
|
||||
default="ProwlerRole",
|
||||
help="IAM role name deployed across accounts (default: ProwlerRole)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--external-id",
|
||||
help="External ID for role assumption (recommended for security)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--session-name", help="Session name for role assumption (optional)"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--duration-seconds",
|
||||
type=int,
|
||||
help="Session duration in seconds (optional, default: 3600)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--alias-format",
|
||||
default="{name}",
|
||||
help="Alias format template. Available: {name}, {id}, {email} (default: {name})",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--exclude",
|
||||
help="Comma-separated list of account IDs to exclude",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--include",
|
||||
help="Comma-separated list of account IDs to include (if set, only these are processed)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--profile",
|
||||
help="AWS CLI profile name (uses default credentials if not specified)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--region",
|
||||
help="AWS region (default: us-east-1, Organizations is global but needs a region)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Print configuration to stdout without writing file",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Parse exclude/include lists
|
||||
exclude_accounts = (
|
||||
[acc.strip() for acc in args.exclude.split(",")] if args.exclude else []
|
||||
)
|
||||
include_accounts = (
|
||||
[acc.strip() for acc in args.include.split(",")] if args.include else []
|
||||
)
|
||||
|
||||
print("Fetching accounts from AWS Organizations...")
|
||||
if args.profile:
|
||||
print(f"Using AWS profile: {args.profile}")
|
||||
|
||||
# Get accounts from Organizations
|
||||
accounts = get_org_accounts(profile=args.profile, region=args.region)
|
||||
|
||||
if not accounts:
|
||||
print("No active accounts found in organization.")
|
||||
return
|
||||
|
||||
print(f"Found {len(accounts)} active accounts in organization")
|
||||
|
||||
# Generate YAML configuration
|
||||
providers = generate_yaml_config(
|
||||
accounts=accounts,
|
||||
role_name=args.role_name,
|
||||
external_id=args.external_id,
|
||||
session_name=args.session_name,
|
||||
duration_seconds=args.duration_seconds,
|
||||
alias_format=args.alias_format,
|
||||
exclude_accounts=exclude_accounts,
|
||||
include_accounts=include_accounts,
|
||||
)
|
||||
|
||||
if not providers:
|
||||
print("No providers generated after applying filters.")
|
||||
return
|
||||
|
||||
print(f"Generated configuration for {len(providers)} accounts")
|
||||
|
||||
# Output YAML
|
||||
yaml_content = yaml.dump(
|
||||
providers, default_flow_style=False, sort_keys=False, allow_unicode=True
|
||||
)
|
||||
|
||||
if args.dry_run:
|
||||
print("\n--- Generated YAML Configuration ---\n")
|
||||
print(yaml_content)
|
||||
else:
|
||||
with open(args.output, "w", encoding="utf-8") as f:
|
||||
f.write(yaml_content)
|
||||
print(f"\nConfiguration written to: {args.output}")
|
||||
print("\nNext steps:")
|
||||
print(f" 1. Review the generated file: cat {args.output} | head -n 20")
|
||||
print(
|
||||
f" 2. Run bulk provisioning: python prowler_bulk_provisioning.py {args.output}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
49
util/prowler-bulk-provisioning/examples/aws-org-example.yaml
Normal file
49
util/prowler-bulk-provisioning/examples/aws-org-example.yaml
Normal file
@@ -0,0 +1,49 @@
|
||||
# Example AWS Organizations Output
|
||||
#
|
||||
# This is an example of what aws_org_generator.py produces when run against
|
||||
# an AWS Organization. This file can be directly used with prowler_bulk_provisioning.py
|
||||
#
|
||||
# Generated with:
|
||||
# python aws_org_generator.py -o aws-org-accounts.yaml \
|
||||
# --role-name ProwlerRole \
|
||||
# --external-id prowler-ext-id-12345
|
||||
|
||||
- provider: aws
|
||||
uid: '111111111111'
|
||||
alias: Production-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::111111111111:role/ProwlerRole
|
||||
external_id: prowler-ext-id-12345
|
||||
|
||||
- provider: aws
|
||||
uid: '222222222222'
|
||||
alias: Development-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::222222222222:role/ProwlerRole
|
||||
external_id: prowler-ext-id-12345
|
||||
|
||||
- provider: aws
|
||||
uid: '333333333333'
|
||||
alias: Staging-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::333333333333:role/ProwlerRole
|
||||
external_id: prowler-ext-id-12345
|
||||
|
||||
- provider: aws
|
||||
uid: '444444444444'
|
||||
alias: Security-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::444444444444:role/ProwlerRole
|
||||
external_id: prowler-ext-id-12345
|
||||
|
||||
- provider: aws
|
||||
uid: '555555555555'
|
||||
alias: Logging-Account
|
||||
auth_method: role
|
||||
credentials:
|
||||
role_arn: arn:aws:iam::555555555555:role/ProwlerRole
|
||||
external_id: prowler-ext-id-12345
|
||||
@@ -7,7 +7,7 @@ Use with extreme caution. There is no undo.
|
||||
|
||||
Environment:
|
||||
PROWLER_API_BASE (default: https://api.prowler.com/api/v1)
|
||||
PROWLER_API_TOKEN (required unless --token is provided)
|
||||
PROWLER_API_KEY (required unless --api-key is provided)
|
||||
|
||||
Usage:
|
||||
python nuke_providers.py --confirm
|
||||
@@ -39,12 +39,14 @@ import requests
|
||||
# ----------------------------- CLI / Utils --------------------------------- #
|
||||
|
||||
|
||||
def env_or_arg(token_arg: Optional[str]) -> str:
|
||||
"""Get API token from argument or environment variable."""
|
||||
token = token_arg or os.getenv("PROWLER_API_TOKEN")
|
||||
if not token:
|
||||
sys.exit("Missing API token. Set --token or PROWLER_API_TOKEN.")
|
||||
return token
|
||||
def env_or_arg(api_key_arg: Optional[str]) -> str:
|
||||
"""Get API key from argument or environment variable."""
|
||||
api_key = api_key_arg or os.getenv("PROWLER_API_KEY")
|
||||
if not api_key:
|
||||
sys.exit(
|
||||
"Missing API key. Set --api-key or PROWLER_API_KEY environment variable."
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def normalize_base_url(url: str) -> str:
|
||||
@@ -63,14 +65,14 @@ class ApiClient:
|
||||
"""HTTP client for Prowler API."""
|
||||
|
||||
base_url: str
|
||||
token: str
|
||||
api_key: str
|
||||
verify_ssl: bool = True
|
||||
timeout: int = 60
|
||||
|
||||
def _headers(self) -> Dict[str, str]:
|
||||
"""Generate HTTP headers for API requests."""
|
||||
return {
|
||||
"Authorization": f"Bearer {self.token}",
|
||||
"Authorization": f"Api-Key {self.api_key}",
|
||||
"Content-Type": "application/vnd.api+json",
|
||||
"Accept": "application/vnd.api+json",
|
||||
}
|
||||
@@ -266,7 +268,9 @@ def main():
|
||||
help="API base URL (default: env PROWLER_API_BASE or Prowler Cloud SaaS)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--token", default=None, help="Bearer token (default: PROWLER_API_TOKEN)"
|
||||
"--api-key",
|
||||
default=None,
|
||||
help="Prowler API key (default: PROWLER_API_KEY env variable)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--filter-provider",
|
||||
@@ -307,12 +311,12 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
token = env_or_arg(args.token)
|
||||
api_key = env_or_arg(args.api_key)
|
||||
base_url = normalize_base_url(args.base_url)
|
||||
|
||||
client = ApiClient(
|
||||
base_url=base_url,
|
||||
token=token,
|
||||
api_key=api_key,
|
||||
verify_ssl=not args.insecure,
|
||||
timeout=args.timeout,
|
||||
)
|
||||
|
||||
@@ -132,12 +132,14 @@ def load_items(path: Path) -> List[Dict[str, Any]]:
|
||||
sys.exit(f"Unsupported input file type: {ext}")
|
||||
|
||||
|
||||
def env_or_arg(token_arg: Optional[str]) -> str:
|
||||
"""Get API token from argument or environment variable."""
|
||||
token = token_arg or os.getenv("PROWLER_API_TOKEN")
|
||||
if not token:
|
||||
sys.exit("Missing API token. Set --token or PROWLER_API_TOKEN.")
|
||||
return token
|
||||
def env_or_arg(api_key_arg: Optional[str]) -> str:
|
||||
"""Get API key from argument or environment variable."""
|
||||
api_key = api_key_arg or os.getenv("PROWLER_API_KEY")
|
||||
if not api_key:
|
||||
sys.exit(
|
||||
"Missing API key. Set --api-key or PROWLER_API_KEY environment variable."
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def normalize_base_url(url: str) -> str:
|
||||
@@ -395,14 +397,14 @@ class ApiClient:
|
||||
"""HTTP client for Prowler API."""
|
||||
|
||||
base_url: str
|
||||
token: str
|
||||
api_key: str
|
||||
verify_ssl: bool = True
|
||||
timeout: int = 60
|
||||
|
||||
def _headers(self) -> Dict[str, str]:
|
||||
"""Generate HTTP headers for API requests."""
|
||||
return {
|
||||
"Authorization": f"Bearer {self.token}",
|
||||
"Authorization": f"Api-Key {self.api_key}",
|
||||
"Content-Type": "application/vnd.api+json",
|
||||
"Accept": "application/vnd.api+json",
|
||||
}
|
||||
@@ -564,7 +566,9 @@ def main():
|
||||
help="API base URL (default: env PROWLER_API_BASE or Prowler Cloud SaaS).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--token", default=None, help="Bearer token (default: PROWLER_API_TOKEN)."
|
||||
"--api-key",
|
||||
default=None,
|
||||
help="Prowler API key (default: PROWLER_API_KEY env variable).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--providers-endpoint",
|
||||
@@ -600,7 +604,7 @@ def main():
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
token = env_or_arg(args.token)
|
||||
api_key = env_or_arg(args.api_key)
|
||||
base_url = normalize_base_url(args.base_url)
|
||||
|
||||
items = load_items(Path(args.input_file))
|
||||
@@ -610,7 +614,7 @@ def main():
|
||||
|
||||
client = ApiClient(
|
||||
base_url=base_url,
|
||||
token=token,
|
||||
api_key=api_key,
|
||||
verify_ssl=not args.insecure,
|
||||
timeout=args.timeout,
|
||||
)
|
||||
|
||||
11
util/prowler-bulk-provisioning/requirements-aws-org.txt
Normal file
11
util/prowler-bulk-provisioning/requirements-aws-org.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
# AWS Organizations Generator Dependencies
|
||||
#
|
||||
# This extends the base requirements.txt for the AWS Organizations generator
|
||||
|
||||
# Include base dependencies
|
||||
-r requirements.txt
|
||||
|
||||
# AWS SDK for Python
|
||||
boto3>=1.26.0
|
||||
|
||||
# Note: PyYAML is already included in requirements.txt
|
||||
Reference in New Issue
Block a user