mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
feat(gcp): add retry to avoid quota limit errors (#8412)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
This commit is contained in:
committed by
GitHub
parent
fc69e195e4
commit
196c17d44d
@@ -50,6 +50,49 @@ The GCP provider implementation follows the general [Provider structure](./provi
|
||||
- **Location:** [`prowler/providers/gcp/lib/`](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/gcp/lib/)
|
||||
- **Purpose:** Helpers for argument parsing, mutelist management, and other cross-cutting concerns.
|
||||
|
||||
## Retry Configuration
|
||||
|
||||
GCP services implement automatic retry functionality for rate limiting errors (HTTP 429). This is configured centrally and must be included in all API calls:
|
||||
|
||||
### Required Implementation
|
||||
|
||||
```python
|
||||
from prowler.providers.gcp.config import DEFAULT_RETRY_ATTEMPTS
|
||||
|
||||
# In discovery.build()
|
||||
client = discovery.build(
|
||||
service, version, credentials=credentials,
|
||||
num_retries=DEFAULT_RETRY_ATTEMPTS
|
||||
)
|
||||
|
||||
# In request.execute()
|
||||
response = request.execute(num_retries=DEFAULT_RETRY_ATTEMPTS)
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
- **Default Value**: 3 attempts (configurable in `prowler/providers/gcp/config.py`)
|
||||
- **Command Line Flag**: `--gcp-retries-max-attempts` for runtime configuration
|
||||
- **Error Types**: HTTP 429 and quota exceeded errors
|
||||
- **Backoff Strategy**: Exponential backoff with randomization
|
||||
|
||||
### Example Service Implementation
|
||||
|
||||
```python
|
||||
def _get_instances(self):
|
||||
for project_id in self.project_ids:
|
||||
try:
|
||||
client = discovery.build(
|
||||
"compute", "v1", credentials=self.credentials,
|
||||
num_retries=DEFAULT_RETRY_ATTEMPTS
|
||||
)
|
||||
request = client.instances().list(project=project_id)
|
||||
response = request.execute(num_retries=DEFAULT_RETRY_ATTEMPTS)
|
||||
# Process response...
|
||||
except Exception as error:
|
||||
logger.error(f"{error.__class__.__name__}: {error}")
|
||||
```
|
||||
|
||||
## Specific Patterns in GCP Services
|
||||
|
||||
The generic service pattern is described in [service page](./services.md#service-structure-and-initialisation). You can find all the currently implemented services in the following locations:
|
||||
@@ -69,6 +112,7 @@ The best reference to understand how to implement a new service is following the
|
||||
- Resource discovery and attribute collection can be parallelized using `self.__threading_call__`, typically by region/zone or resource.
|
||||
- All GCP resources are represented as Pydantic `BaseModel` classes, providing type safety and structured access to resource attributes.
|
||||
- Each GCP API calls are wrapped in try/except blocks, always logging errors.
|
||||
- **Retry Configuration**: All `request.execute()` calls must include `num_retries=DEFAULT_RETRY_ATTEMPTS` for automatic retry on rate limiting errors (HTTP 429).
|
||||
- Tags and additional attributes that cannot be retrieved from the default call should be collected and stored for each resource using dedicated methods and threading.
|
||||
|
||||
## Specific Patterns in GCP Checks
|
||||
|
||||
@@ -671,6 +671,16 @@ prowler azure --az-cli-auth --subscription-ids <subscription ID 1> <subscription
|
||||
prowler gcp --project-ids <Project ID 1> <Project ID 2> ... <Project ID N>
|
||||
```
|
||||
|
||||
- **GCP Retry Configuration**
|
||||
|
||||
To configure the maximum number of retry attempts for Google Cloud SDK API calls, use the `--gcp-retries-max-attempts` flag:
|
||||
|
||||
```console
|
||||
prowler gcp --gcp-retries-max-attempts 5
|
||||
```
|
||||
|
||||
This is useful when experiencing quota exceeded errors (HTTP 429) to increase the number of automatic retry attempts.
|
||||
|
||||
#### Kubernetes
|
||||
|
||||
Prowler enables security scanning of Kubernetes clusters, supporting both **in-cluster** and **external** execution.
|
||||
|
||||
95
docs/tutorials/gcp/retry-configuration.md
Normal file
95
docs/tutorials/gcp/retry-configuration.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# GCP Retry Configuration in Prowler
|
||||
|
||||
Prowler's GCP Provider uses Google Cloud Python SDK's integrated retry mechanism to automatically retry API calls when encountering rate limiting errors (HTTP 429).
|
||||
|
||||
## Quick Configuration
|
||||
|
||||
### Using Command Line Flag (Recommended)
|
||||
```bash
|
||||
prowler gcp --gcp-retries-max-attempts 5
|
||||
```
|
||||
|
||||
### Using Configuration File
|
||||
Modify `prowler/providers/gcp/config.py`:
|
||||
```python
|
||||
DEFAULT_RETRY_ATTEMPTS = 5 # Default: 3
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
- **Automatic Detection**: Handles HTTP 429 and quota exceeded errors
|
||||
- **Exponential Backoff**: Each retry uses randomized exponential backoff
|
||||
- **Centralized Config**: All GCP services use the same retry configuration
|
||||
- **Transparent**: No additional code needed in services
|
||||
|
||||
## Error Examples Handled
|
||||
|
||||
```
|
||||
HttpError 429 when requesting https://cloudresourcemanager.googleapis.com/v1/projects/vms-uat-eiger:getIamPolicy?alt=json returned "Quota exceeded for quota metric 'Read requests' and limit 'Read requests per minute'"
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Client-Level Configuration
|
||||
```python
|
||||
from prowler.providers.gcp.config import DEFAULT_RETRY_ATTEMPTS
|
||||
|
||||
client = discovery.build(
|
||||
service, version, credentials=credentials,
|
||||
num_retries=DEFAULT_RETRY_ATTEMPTS
|
||||
)
|
||||
```
|
||||
|
||||
### Request-Level Configuration
|
||||
```python
|
||||
response = request.execute(num_retries=DEFAULT_RETRY_ATTEMPTS)
|
||||
```
|
||||
|
||||
## Services with Retry Support
|
||||
|
||||
All major GCP services are covered:
|
||||
- Cloud Resource Manager, Compute Engine, IAM
|
||||
- BigQuery, KMS, Cloud Storage, Monitoring
|
||||
- DNS, Logging, Cloud SQL, GKE, API Keys, DataProc
|
||||
|
||||
## Validation
|
||||
|
||||
### Debug Logging
|
||||
```bash
|
||||
prowler gcp --log-level DEBUG --log-file debuglogs.txt --project-id your-project-id
|
||||
```
|
||||
|
||||
### Check for Retry Messages
|
||||
```bash
|
||||
grep -i "sleeping\|retry\|quota exceeded" debuglogs.txt
|
||||
```
|
||||
|
||||
### Expected Output
|
||||
```
|
||||
"Sleeping 1.52 seconds before retry 1 of 3"
|
||||
"Sleeping 3.23 seconds before retry 2 of 3"
|
||||
```
|
||||
|
||||
## Testing in Real Environment
|
||||
|
||||
1. **Reduce API Quotas** in GCP Console:
|
||||
- APIs & Services > Quotas
|
||||
- Reduce "Read requests per minute" for Compute Engine API
|
||||
- Reduce "Policy Read Requests per minute" for IAM API
|
||||
|
||||
2. **Run Prowler** with debug logging
|
||||
3. **Monitor logs** for retry messages
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If experiencing rate limiting:
|
||||
1. Use `--gcp-retries-max-attempts` flag to increase attempts
|
||||
2. Request quota increases from Google Cloud support
|
||||
3. Optimize scanning to reduce simultaneous API calls
|
||||
4. Verify retry functionality with debug logging
|
||||
|
||||
## Official References
|
||||
|
||||
- [Google Cloud Python Client Libraries](https://cloud.google.com/python/docs)
|
||||
- [Google Cloud Quotas](https://cloud.google.com/docs/quotas)
|
||||
- [Google API Core Retry](https://googleapis.dev/python/google-api-core/latest/retry.html)
|
||||
Reference in New Issue
Block a user