mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-04 02:04:06 +00:00
feat: add AI skills pack for Claude Code and OpenCode (#9728)
Co-authored-by: Rubén De la Torre Vico <ruben@prowler.com> Co-authored-by: Adrián Jesús Peña Rodríguez <adrianjpr@gmail.com> Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
This commit is contained in:
co-authored by
Rubén De la Torre Vico
Adrián Jesús Peña Rodríguez
Pepe Fagoaga
parent
42ae5b6e3e
commit
7f2fa275c6
@@ -0,0 +1,257 @@
|
||||
---
|
||||
name: prowler-sdk-check
|
||||
description: >
|
||||
Creates Prowler security checks following SDK architecture patterns.
|
||||
Trigger: When user asks to create a new security check for any provider (AWS, Azure, GCP, K8s, GitHub, etc.)
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: prowler-cloud
|
||||
version: "1.0"
|
||||
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
---
|
||||
|
||||
## Check Structure
|
||||
|
||||
```
|
||||
prowler/providers/{provider}/services/{service}/{check_name}/
|
||||
├── __init__.py
|
||||
├── {check_name}.py
|
||||
└── {check_name}.metadata.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step-by-Step Creation Process
|
||||
|
||||
### 1. Prerequisites
|
||||
|
||||
- **Verify check doesn't exist**: Search `prowler/providers/{provider}/services/{service}/`
|
||||
- **Ensure provider and service exist** - create them first if not
|
||||
- **Confirm service has required methods** - may need to add/modify service methods to get data
|
||||
|
||||
### 2. Create Check Files
|
||||
|
||||
```bash
|
||||
mkdir -p prowler/providers/{provider}/services/{service}/{check_name}
|
||||
touch prowler/providers/{provider}/services/{service}/{check_name}/__init__.py
|
||||
touch prowler/providers/{provider}/services/{service}/{check_name}/{check_name}.py
|
||||
touch prowler/providers/{provider}/services/{service}/{check_name}/{check_name}.metadata.json
|
||||
```
|
||||
|
||||
### 3. Implement Check Logic
|
||||
|
||||
```python
|
||||
from prowler.lib.check.models import Check, Check_Report_{Provider}
|
||||
from prowler.providers.{provider}.services.{service}.{service}_client import {service}_client
|
||||
|
||||
class {check_name}(Check):
|
||||
"""Ensure that {resource} meets {security_requirement}."""
|
||||
def execute(self) -> list[Check_Report_{Provider}]:
|
||||
"""Execute the check logic.
|
||||
|
||||
Returns:
|
||||
A list of reports containing the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
for resource in {service}_client.{resources}:
|
||||
report = Check_Report_{Provider}(metadata=self.metadata(), resource=resource)
|
||||
report.status = "PASS" if resource.is_compliant else "FAIL"
|
||||
report.status_extended = f"Resource {resource.name} compliance status."
|
||||
findings.append(report)
|
||||
return findings
|
||||
```
|
||||
|
||||
### 4. Create Metadata File
|
||||
|
||||
See complete schema below and `assets/` folder for complete templates.
|
||||
For detailed field documentation, see `references/metadata-docs.md`.
|
||||
|
||||
### 5. Verify Check Detection
|
||||
|
||||
```bash
|
||||
poetry run python prowler-cli.py {provider} --list-checks | grep {check_name}
|
||||
```
|
||||
|
||||
### 6. Run Check Locally
|
||||
|
||||
```bash
|
||||
poetry run python prowler-cli.py {provider} --log-level ERROR --verbose --check {check_name}
|
||||
```
|
||||
|
||||
### 7. Create Tests
|
||||
|
||||
See `prowler-test-sdk` skill for test patterns (PASS, FAIL, no resources, error handling).
|
||||
|
||||
---
|
||||
|
||||
## Check Naming Convention
|
||||
|
||||
```
|
||||
{service}_{resource}_{security_control}
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `ec2_instance_public_ip_disabled`
|
||||
- `s3_bucket_encryption_enabled`
|
||||
- `iam_user_mfa_enabled`
|
||||
|
||||
---
|
||||
|
||||
## Metadata Schema (COMPLETE)
|
||||
|
||||
```json
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "{check_name}",
|
||||
"CheckTitle": "Human-readable title",
|
||||
"CheckType": [
|
||||
"Software and Configuration Checks/AWS Security Best Practices",
|
||||
"Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices"
|
||||
],
|
||||
"ServiceName": "{service}",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low|medium|high|critical",
|
||||
"ResourceType": "AwsEc2Instance|Other",
|
||||
"ResourceGroup": "security|compute|storage|network",
|
||||
"Description": "**Bold resource name**. Detailed explanation of what this check evaluates and why it matters.",
|
||||
"Risk": "What happens if non-compliant. Explain attack vectors, data exposure risks, compliance impact.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://docs.aws.amazon.com/..."
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws {service} {command} --option value",
|
||||
"NativeIaC": "```yaml\nResources:\n Resource:\n Type: AWS::{Service}::{Resource}\n Properties:\n Key: value # This line fixes the issue\n```",
|
||||
"Other": "1. Console steps\n2. Step by step",
|
||||
"Terraform": "```hcl\nresource \"aws_{service}_{resource}\" \"example\" {\n key = \"value\" # This line fixes the issue\n}\n```"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Detailed recommendation for remediation.",
|
||||
"Url": "https://hub.prowler.com/check/{check_name}"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"identity-access",
|
||||
"encryption",
|
||||
"logging",
|
||||
"forensics-ready",
|
||||
"internet-exposed",
|
||||
"trust-boundaries"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
```
|
||||
|
||||
### Required Fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `Provider` | Provider name: aws, azure, gcp, kubernetes, github, m365 |
|
||||
| `CheckID` | Must match class name and folder name |
|
||||
| `CheckTitle` | Human-readable title |
|
||||
| `Severity` | `low`, `medium`, `high`, `critical` |
|
||||
| `ServiceName` | Service being checked |
|
||||
| `Description` | What the check evaluates |
|
||||
| `Risk` | Security impact of non-compliance |
|
||||
| `Remediation.Code.CLI` | CLI fix command |
|
||||
| `Remediation.Recommendation.Text` | How to fix |
|
||||
|
||||
### Severity Guidelines
|
||||
|
||||
| Severity | When to Use |
|
||||
|----------|-------------|
|
||||
| `critical` | Direct data exposure, RCE, privilege escalation |
|
||||
| `high` | Significant security risk, compliance violation |
|
||||
| `medium` | Defense-in-depth, best practice |
|
||||
| `low` | Informational, minor hardening |
|
||||
|
||||
---
|
||||
|
||||
## Check Report Statuses
|
||||
|
||||
| Status | When to Use |
|
||||
|--------|-------------|
|
||||
| `PASS` | Resource is compliant |
|
||||
| `FAIL` | Resource is non-compliant |
|
||||
| `MANUAL` | Requires human verification |
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### AWS Check with Regional Resources
|
||||
|
||||
```python
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.s3.s3_client import s3_client
|
||||
|
||||
class s3_bucket_encryption_enabled(Check):
|
||||
def execute(self) -> list[Check_Report_AWS]:
|
||||
findings = []
|
||||
for bucket in s3_client.buckets.values():
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=bucket)
|
||||
if bucket.encryption:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"S3 bucket {bucket.name} has encryption enabled."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"S3 bucket {bucket.name} does not have encryption enabled."
|
||||
findings.append(report)
|
||||
return findings
|
||||
```
|
||||
|
||||
### Check with Multiple Conditions
|
||||
|
||||
```python
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
|
||||
|
||||
class ec2_instance_hardened(Check):
|
||||
def execute(self) -> list[Check_Report_AWS]:
|
||||
findings = []
|
||||
for instance in ec2_client.instances:
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=instance)
|
||||
|
||||
issues = []
|
||||
if instance.public_ip:
|
||||
issues.append("has public IP")
|
||||
if not instance.metadata_options.http_tokens == "required":
|
||||
issues.append("IMDSv2 not enforced")
|
||||
|
||||
if issues:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Instance {instance.id} {', '.join(issues)}."
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Instance {instance.id} is properly hardened."
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Verify detection
|
||||
poetry run python prowler-cli.py {provider} --list-checks | grep {check_name}
|
||||
|
||||
# Run check
|
||||
poetry run python prowler-cli.py {provider} --log-level ERROR --verbose --check {check_name}
|
||||
|
||||
# Run with specific profile/credentials
|
||||
poetry run python prowler-cli.py aws --profile myprofile --check {check_name}
|
||||
|
||||
# Run multiple checks
|
||||
poetry run python prowler-cli.py {provider} --check {check1} {check2} {check3}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- **Templates**: See [assets/](assets/) for complete check and metadata templates (AWS, Azure, GCP)
|
||||
- **Documentation**: See [references/metadata-docs.md](references/metadata-docs.md) for official Prowler Developer Guide links
|
||||
@@ -0,0 +1,20 @@
|
||||
# Example: AWS S3 Bucket Encryption Check
|
||||
# Source: prowler/providers/aws/services/s3/s3_bucket_default_encryption/
|
||||
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.s3.s3_client import s3_client
|
||||
|
||||
|
||||
class s3_bucket_default_encryption(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for bucket in s3_client.buckets.values():
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=bucket)
|
||||
if bucket.encryption:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"S3 Bucket {bucket.name} has Server Side Encryption with {bucket.encryption}."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"S3 Bucket {bucket.name} does not have Server Side Encryption enabled."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "s3_bucket_default_encryption",
|
||||
"CheckTitle": "Check if S3 buckets have default encryption (SSE) enabled or use a bucket policy to enforce it.",
|
||||
"CheckType": [
|
||||
"Data Protection"
|
||||
],
|
||||
"ServiceName": "s3",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:s3:::bucket_name",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsS3Bucket",
|
||||
"ResourceGroup": "storage",
|
||||
"Description": "Check if S3 buckets have default encryption (SSE) enabled or use a bucket policy to enforce it.",
|
||||
"Risk": "Amazon S3 default encryption provides a way to set the default encryption behavior for an S3 bucket. This will ensure data-at-rest is encrypted.",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws s3api put-bucket-encryption --bucket <bucket_name> --server-side-encryption-configuration '{\"Rules\": [{\"ApplyServerSideEncryptionByDefault\": {\"SSEAlgorithm\": \"AES256\"}}]}'",
|
||||
"NativeIaC": "https://docs.prowler.com/checks/aws/s3-policies/s3_14-data-encrypted-at-rest#cloudformation",
|
||||
"Other": "",
|
||||
"Terraform": "https://docs.prowler.com/checks/aws/s3-policies/s3_14-data-encrypted-at-rest#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure that S3 buckets have encryption at rest enabled.",
|
||||
"Url": "https://aws.amazon.com/blogs/security/how-to-prevent-uploads-of-unencrypted-objects-to-amazon-s3/"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"encryption"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Example: Azure Storage Secure Transfer Check
|
||||
# Source: prowler/providers/azure/services/storage/storage_secure_transfer_required_is_enabled/
|
||||
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.storage.storage_client import storage_client
|
||||
|
||||
|
||||
class storage_secure_transfer_required_is_enabled(Check):
|
||||
def execute(self) -> list[Check_Report_Azure]:
|
||||
findings = []
|
||||
for subscription, storage_accounts in storage_client.storage_accounts.items():
|
||||
for storage_account in storage_accounts:
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=storage_account
|
||||
)
|
||||
report.subscription = subscription
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Storage account {storage_account.name} from subscription {subscription} has secure transfer required enabled."
|
||||
if not storage_account.enable_https_traffic_only:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Storage account {storage_account.name} from subscription {subscription} has secure transfer required disabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "storage_secure_transfer_required_is_enabled",
|
||||
"CheckTitle": "Ensure that all data transferred between clients and your Azure Storage account is encrypted using the HTTPS protocol.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "storage",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AzureStorageAccount",
|
||||
"ResourceGroup": "storage",
|
||||
"Description": "Ensure that all data transferred between clients and your Azure Storage account is encrypted using the HTTPS protocol.",
|
||||
"Risk": "Requests to the storage account sent outside of a secure connection can be eavesdropped",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az storage account update --name <STORAGE_ACCOUNT_NAME> --https-only true",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/StorageAccounts/secure-transfer-required.html",
|
||||
"Terraform": "https://docs.prowler.com/checks/azure/azure-networking-policies/ensure-that-storage-account-enables-secure-transfer"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable data encryption in transit.",
|
||||
"Url": ""
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"encryption"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Example: GCP Cloud Storage Bucket Versioning Check
|
||||
# Source: prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/
|
||||
|
||||
from prowler.lib.check.models import Check, Check_Report_GCP
|
||||
from prowler.providers.gcp.services.cloudstorage.cloudstorage_client import (
|
||||
cloudstorage_client,
|
||||
)
|
||||
|
||||
|
||||
class cloudstorage_bucket_versioning_enabled(Check):
|
||||
"""Ensure Cloud Storage buckets have Object Versioning enabled."""
|
||||
|
||||
def execute(self) -> list[Check_Report_GCP]:
|
||||
findings = []
|
||||
for bucket in cloudstorage_client.buckets:
|
||||
report = Check_Report_GCP(metadata=self.metadata(), resource=bucket)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Bucket {bucket.name} does not have Object Versioning enabled."
|
||||
)
|
||||
|
||||
if bucket.versioning_enabled:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Bucket {bucket.name} has Object Versioning enabled."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"Provider": "gcp",
|
||||
"CheckID": "cloudstorage_bucket_versioning_enabled",
|
||||
"CheckTitle": "Cloud Storage buckets have Object Versioning enabled",
|
||||
"CheckType": [],
|
||||
"ServiceName": "cloudstorage",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "storage.googleapis.com/Bucket",
|
||||
"ResourceGroup": "storage",
|
||||
"Description": "Google Cloud Storage buckets are evaluated to ensure that Object Versioning is enabled.",
|
||||
"Risk": "Buckets without Object Versioning enabled cannot recover previous object versions after accidental deletion or overwrites.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/CloudStorage/enable-versioning.html",
|
||||
"https://cloud.google.com/storage/docs/object-versioning"
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "gcloud storage buckets update gs://<BUCKET_NAME> --versioning",
|
||||
"NativeIaC": "",
|
||||
"Other": "1) Open Google Cloud Console -> Storage -> Buckets\n2) Select the bucket\n3) Click 'Edit bucket' -> 'Protection'\n4) Enable 'Object versioning'\n5) Save",
|
||||
"Terraform": "resource \"google_storage_bucket\" \"example\" {\n versioning {\n enabled = true\n }\n}"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Object Versioning on Cloud Storage buckets to protect against accidental data loss.",
|
||||
"Url": "https://hub.prowler.com/check/cloudstorage_bucket_versioning_enabled"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"resilience"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Check Documentation
|
||||
|
||||
## Local Documentation
|
||||
|
||||
For detailed check development patterns, see:
|
||||
|
||||
- `docs/developer-guide/checks.mdx` - Complete guide for creating security checks
|
||||
- `docs/developer-guide/check-metadata-guidelines.mdx` - Metadata writing standards and best practices
|
||||
- `docs/developer-guide/configurable-checks.mdx` - Using audit_config for configurable checks
|
||||
- `docs/developer-guide/renaming-checks.mdx` - Guidelines for renaming existing checks
|
||||
|
||||
## Contents
|
||||
|
||||
The documentation covers:
|
||||
- Check structure and naming conventions
|
||||
- Metadata schema and field descriptions
|
||||
- Check implementation patterns per provider
|
||||
- Configurable check parameters
|
||||
- Check renaming procedures
|
||||
Reference in New Issue
Block a user