> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prowler.com/llms.txt
> Use this file to discover all available pages before exploring further.

# StackIT Provider

This page details the [StackIT Cloud](https://www.stackit.de/) provider implementation in Prowler.

By default, Prowler audits a single StackIT project per scan. To configure it, provide the project ID and either a service account key file path or inline service account key JSON.

## StackIT Provider Classes Architecture

The StackIT provider implementation follows the general [Provider structure](/developer-guide/provider). This section focuses on the StackIT-specific implementation, highlighting how the generic provider concepts are realized for StackIT in Prowler. For a full overview of the provider pattern, base classes, and extension guidelines, see [Provider documentation](/developer-guide/provider).

### `StackitProvider` (Main Class)

* **Location:** [`prowler/providers/stackit/stackit_provider.py`](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/stackit/stackit_provider.py)
* **Base Class:** Inherits from `Provider` (see [base class details](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/common/provider.py)).
* **Purpose:** Central orchestrator for StackIT-specific logic, API authentication, credential validation, and configuration.
* **Key StackIT Responsibilities:**
  * Initializes StackIT SDK authentication via a service account key file or inline service account key JSON. The SDK mints and refreshes access tokens internally.
  * Validates the service account credentials and project ID (UUID format validation).
  * Loads and manages configuration, mutelist, and fixer settings.
  * Provides properties and methods for downstream StackIT service classes to access credentials, identity, and configuration data.

### Data Models

* **Location:** [`prowler/providers/stackit/models.py`](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/stackit/models.py)
* **Purpose:** Define structured data for StackIT identity and output configuration.
* **Key StackIT Models:**
  * `StackITIdentityInfo`: Holds StackIT identity metadata, including project ID and project name (fetched automatically from Resource Manager API).
  * `StackITOutputOptions`: Customizes default output filenames so StackIT reports include the audited project ID.
  * IaaS resource models such as `SecurityGroup` and `SecurityGroupRule` are defined in the IaaS service module.

### StackIT Services

* **Location:** [`prowler/providers/stackit/services/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/stackit/services)
* **Purpose:** Implement StackIT service clients and resource collection logic following the generic [service pattern](/developer-guide/services#service-base-class).
* **Current Implementation:** The `IaaSService` collects security groups, rules, and network interface usage across supported StackIT regions.

### Exception Handling

* **Location:** [`prowler/providers/stackit/exceptions/exceptions.py`](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/stackit/exceptions/exceptions.py)
* **Purpose:** Custom exception classes for StackIT-specific error handling, such as credential validation, API connection, and configuration errors.
* **Key Exception Classes:**
  * `StackITBaseException`: Base exception for all StackIT provider errors.
  * `StackITCredentialsError`: Raised when credentials are invalid or missing.
  * `StackITInvalidProjectIdError`: Raised when project ID is invalid or not in UUID format.
  * `StackITAPIError`: Raised when StackIT API calls fail.

## Authentication

### Service Account Creation and Key Generation

StackIT uses service account keys for API authentication. Service account keys are RSA key-pair based and provide secure, short-lived access tokens.

### Creating a Service Account Key

#### Method 1: Via StackIT Portal

1. **Navigate to Service Accounts**
   * Go to the [StackIT Portal](https://portal.stackit.cloud/)
   * Select your project
   * Click on **Service Accounts** in the left sidebar

2. **Create or Select Service Account**
   * If you don't have a service account, click **Create Service Account**
   * Provide a name and description
   * Assign necessary permissions:
     * For IaaS security checks: `iaas.viewer` or `project.owner`
     * For comprehensive audits: `project.owner`

3. **Generate Service Account Key**
   * Select your service account
   * Navigate to **Service Account Keys**
   * Click **Create key**
   * Choose one of the following options:
     * **STACKIT-generated key pair** (Recommended): Let STACKIT automatically generate an RSA key-pair
     * **User-provided key pair**: Upload your own RSA 2048 public key

4. **Download and Save the Key**
   * Download the generated service account key file (JSON format)
   * **Important**: Save the key securely - it contains your private key and will only be available once
   * Store the key file in a secure location (e.g., `~/.stackit/sa_key.json`)

#### Method 2: Via StackIT CLI

```bash theme={null}
# Install STACKIT CLI (if not already installed)
# Follow instructions at: https://github.com/stackitcloud/stackit-cli

# Create service account key (STACKIT-generated)
stackit service-account key create --email my-service-account@example.com

# Or create with your own RSA 2048 public key
# First, generate your RSA key pair:
openssl genrsa -out private-key.pem 2048
openssl rsa -in private-key.pem -pubout -out public-key.pem

# Then create the key with your public key:
stackit service-account key create \
  --email my-service-account@example.com \
  --public-key "$(cat public-key.pem)"
```

### Finding Your Project ID

Your StackIT project ID is a UUID that can be found:

1. In the StackIT Portal URL when viewing your project: `https://portal.stackit.cloud/projects/{PROJECT_ID}/...`
2. In the project settings page
3. Using the StackIT CLI: `stackit project list`

### Passing the Service Account Key to Prowler

Prowler accepts the service account credentials in two equivalent forms; both go through the same StackIT SDK flow and refresh access tokens internally.

#### Option 1: Key File Path (key persisted on disk)

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"
export STACKIT_PROJECT_ID="12345678-1234-1234-1234-123456789abc"

prowler stackit
```

Or as CLI flags:

```bash theme={null}
prowler stackit \
  --stackit-service-account-key-path ~/.stackit/sa-key.json \
  --stackit-project-id 12345678-1234-1234-1234-123456789abc
```

#### Option 2: Inline Key Content (CI/CD, secret managers)

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY="$(vault kv get -field=key stackit/sa)"
export STACKIT_PROJECT_ID="12345678-1234-1234-1234-123456789abc"

prowler stackit
```

Prefer the environment variable over the matching `--stackit-service-account-key` CLI flag; passing the secret on the command line leaks it through process listings and shell history.

### Credential Lookup Order

Prowler resolves credentials in this order:

1. **Command-line arguments**:
   * `--stackit-service-account-key`
   * `--stackit-service-account-key-path`
   * `--stackit-project-id`
2. **Environment variables**:
   * `STACKIT_SERVICE_ACCOUNT_KEY`
   * `STACKIT_SERVICE_ACCOUNT_KEY_PATH`
   * `STACKIT_PROJECT_ID`

When both the inline key and the key file path are set, the inline content takes precedence.

## Configuration

### Command-Line Arguments

StackIT-specific command-line arguments:

| Argument                             | Description                                                                                             | Required | Default                             |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------- |
| `--stackit-service-account-key-path` | Path to a StackIT service account key JSON file                                                         | Yes\*    | `$STACKIT_SERVICE_ACCOUNT_KEY_PATH` |
| `--stackit-service-account-key`      | Inline JSON content of a StackIT service account key (preferred env var: `STACKIT_SERVICE_ACCOUNT_KEY`) | Yes\*    | `$STACKIT_SERVICE_ACCOUNT_KEY`      |
| `--stackit-project-id`               | StackIT project ID (UUID format)                                                                        | Yes\*    | `$STACKIT_PROJECT_ID`               |
| `--stackit-region`                   | StackIT region(s) to scan                                                                               | No       | All available regions               |

\* Required unless provided via environment variables.

### Input Validation

The StackIT provider performs comprehensive input validation:

* **Service Account Credentials**:
  * At least one of `service_account_key_path` (file path) or `service_account_key` (inline JSON) must be supplied; both empty raises `StackITNonExistentTokenError`
  * When both are provided the inline content takes precedence
  * The key file path is logged as-is; the inline content is redacted in the credentials box

* **Project ID**:
  * Must not be empty
  * Must be a valid UUID format (e.g., `12345678-1234-1234-1234-123456789abc`)
  * Validated using Python's UUID constructor

Invalid credentials will result in clear error messages before any API calls are made.

## Available Services

### IaaS (Infrastructure as a Service)

* **Service Class:** `IaaSService`
* **Location:** [`prowler/providers/stackit/services/iaas/iaas_service.py`](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/stackit/services/iaas/iaas_service.py)
* **SDK:** Uses the [stackit-iaas](https://pypi.org/project/stackit-iaas/) Python SDK
* **Purpose:** Manages IaaS resources including security groups, servers, and network interfaces.

**Supported Resources:**

* Security Groups and Rules
* Servers (Virtual Machines)
* Network Interfaces (NICs)

**Key Features:**

* Automatic discovery of all security groups in the project
* Security rule parsing with support for unrestricted access detection
* Network interface analysis to determine whether security groups are in use
* By default, reports only security groups attached to at least one NIC; `--scan-unused-services` includes unused security groups too

## Available Checks

The StackIT provider currently implements 4 security checks focused on network security:

### 1. iaas\_security\_group\_ssh\_unrestricted

* **Severity:** High
* **Description:** Detects security groups that allow unrestricted SSH access (port 22) from the internet.
* **Risk:** Unrestricted SSH access increases the attack surface and risk of brute-force attacks.
* **Detection Logic:**
  * Checks for ingress rules allowing TCP port 22
  * Flags rules with `ip_range=None` or `ip_range="0.0.0.0/0"` or `ip_range="::/0"`
  * Reports security groups attached to NICs by default, or all security groups when `--scan-unused-services` is enabled

### 2. iaas\_security\_group\_rdp\_unrestricted

* **Severity:** High
* **Description:** Detects security groups that allow unrestricted RDP access (port 3389) from the internet.
* **Risk:** Unrestricted RDP access enables potential unauthorized remote desktop access.
* **Detection Logic:**
  * Checks for ingress rules allowing TCP port 3389
  * Flags unrestricted IP ranges (None, 0.0.0.0/0, ::/0)
  * Reports security groups attached to NICs by default, or all security groups when `--scan-unused-services` is enabled

### 3. iaas\_security\_group\_database\_unrestricted

* **Severity:** High
* **Description:** Detects security groups that allow unrestricted access to common database ports.
* **Monitored Ports:**
  * MySQL: 3306
  * PostgreSQL: 5432
  * MongoDB: 27017
  * Redis: 6379
  * SQL Server: 1433
  * CouchDB: 5984
* **Risk:** Unrestricted database access can lead to data breaches and unauthorized data access.

### 4. iaas\_security\_group\_all\_traffic\_unrestricted

* **Severity:** Critical
* **Description:** Detects security groups that allow all traffic from the internet.
* **Detection Logic:**
  * Checks for rules with `port_range=None` (all ports)
  * Checks for rules with port range covering 0-65535 or 1-65535
  * Flags unrestricted IP ranges
  * Critical security misconfiguration requiring immediate remediation

### Important Implementation Notes

**Self-Referencing Security Group Rules:**

Security group rules with `remoteSecurityGroupId` set are automatically filtered out from unrestricted access checks. These rules only allow traffic from instances within the same security group (self-referencing), not from the internet, and are therefore not flagged as security risks.

**Rule Display Names:**

All findings include user-friendly rule descriptions when available. If a security group rule has a description field set (the name shown in the StackIT UI), it will be displayed in the finding message along with the rule ID:

* With description: `'Allow SSH from office' (sgr-abc123)`
* Without description: `'sgr-abc123'`

**Network Interface (NIC) Usage Filtering:**

The IaaS service lists project NICs and records the security group IDs attached to them. Checks use that signal to decide whether a security group is in use:

1. **Default behavior:** Report security groups attached to at least one NIC.
2. **`--scan-unused-services`:** Report every security group, including unused ones.
3. **FAIL logic:** Internet exposure is driven by security group rules that allow unrestricted source ranges, not by the presence of a public IP on the NIC.

**Unrestricted IP Ranges:**

The StackIT API represents "unrestricted" in two ways:

* **`ip_range=null`**: No IP restriction specified (implicit unrestricted)
* **`ip_range="0.0.0.0/0"` or `"::/0"`**: Explicitly configured to allow all IPs

Both are flagged as unrestricted. A `null` value is **more permissive** than an explicit range and applies to all protocols/ports if other fields are also `null`.

## Requirements

### Python Version

* **Minimum:** Python 3.10+
* **Reason:** The StackIT SDK requires Python 3.10 or higher

### Dependencies

The StackIT provider requires the following Python packages (automatically installed with Prowler):

* **stackit-core** (v0.2.0): Core SDK for StackIT API authentication and configuration
* **stackit-iaas** (v1.4.0): IaaS service SDK for managing compute resources
* **stackit-resourcemanager** (v0.8.0): Resource Manager SDK for fetching project metadata (e.g., project names)

These dependencies are defined in `pyproject.toml` and installed automatically with:

```bash theme={null}
poetry install
```

**Note:** The `stackit-resourcemanager` package enables automatic retrieval of project names for display in reports. If this package is not available, Prowler will still function normally but project names will be empty in the output.

## Region Support

### Supported Regions

* **Available Regions:** `eu01` (Germany South) and `eu02` (Austria West)
* **Default:** All scans use both `eu01` and `eu02` regions by default.

### Multi-Region Scanning

Prowler supports scanning multiple StackIT regions in a single execution. By default, it will scan all regions defined in the `stackit_regions_by_service.json` configuration file.

### CLI Argument

You can specify which regions to scan using the `--stackit-region` argument:

```bash theme={null}
# Scan only eu01
prowler stackit --stackit-region eu01

# Scan both eu01 and eu02
prowler stackit --stackit-region eu01 eu02
```

### Implementation Details

* **Regional Clients:** Prowler generates a separate API client for each audited region.
* **Service Iteration:** Each service (e.g., IaaS) iterates through the regional clients to fetch and audit resources.
* **Identity Tracking:** The `audited_regions` are stored in the identity model for reporting.

### Future Enhancements

As StackIT adds more regions, they can be easily added to Prowler by updating the `prowler/providers/stackit/stackit_regions_by_service.json` file without requiring code changes.

## Command Examples

### Scan Specific Regions

Scan only the `eu01` region:

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --stackit-region eu01
```

Scan multiple regions:

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --stackit-region eu01 eu02
```

### Scan Specific Checks

Run only SSH unrestricted check:

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --checks iaas_security_group_ssh_unrestricted
```

### Scan All Security Group Checks

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --services iaas
```

### Output Formats

Generate JSON output:

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --output-formats json
```

Generate HTML report:

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --output-formats html
```

## Known Limitations

### Current Limitations

1. **Single Project Scope**: Only one project can be scanned at a time
2. **Service Coverage**: Only the IaaS service is currently implemented
3. **Check Coverage**: Limited to security group network security checks (4 checks total)
4. **No Compliance Frameworks**: Compliance framework mappings are not yet implemented

### Planned Enhancements

* Multi-project scanning capability
* Additional IaaS checks (volume encryption, server public IP exposure, backup status)
* Compliance framework mappings (CIS, custom StackIT best practices)
* StackIT CLI remediation examples in metadata

## Troubleshooting

### Authentication Errors

**Error:** `StackIT service account key was rejected`

**Solutions:**

1. Re-issue the service account key in the StackIT Portal
2. Verify the service account key file or inline JSON content is complete
3. Check that the service account has the necessary permissions (`iaas.viewer` or `project.owner`)
4. Ensure the service account key is provided through `STACKIT_SERVICE_ACCOUNT_KEY_PATH`, `STACKIT_SERVICE_ACCOUNT_KEY`, or the matching CLI arguments

**Error:** `StackIT credentials not found or are invalid`

**Solutions:**

1. Ensure the project ID and one service account credential source are provided
2. Check that credentials are set via environment variables or command-line arguments
3. Verify there are no extra spaces or newlines in the credentials

**Error:** `Invalid StackIT project ID format`

**Solutions:**

1. Verify the project ID is a valid UUID format: `12345678-1234-1234-1234-123456789abc`
2. Copy the project ID directly from the StackIT Portal
3. Ensure there are no extra spaces or quotes around the UUID

### API Connection Errors

**Error:** `Failed to connect to StackIT API`

**Solutions:**

1. Check your internet connection
2. Verify the StackIT API endpoint is accessible from your network
3. Check if there are any firewall rules blocking HTTPS connections
4. Review the full error message for specific API error codes

**Error:** `HTTP 403 Forbidden`

**Solutions:**

1. Verify the service account has the correct permissions
2. Ensure the project ID is correct and you have access to it
3. Check that the service account is enabled (not disabled or expired)
4. Verify the service account key has not been revoked

**Error:** `HTTP 404 Not Found`

**Solutions:**

1. Verify the project ID exists and is correct
2. Check that the IaaS service is enabled in your project
3. Ensure you're using the correct region (eu01)

### Empty Results

**Issue:** No security groups or findings reported

**Solutions:**

1. Verify that security groups exist in your project
2. Check that the IaaS service is properly configured
3. Ensure the service account has `iaas.viewer` permission
4. Check Prowler logs for any API errors (use `--log-level DEBUG`)

### Debug Mode

Enable debug logging for detailed troubleshooting:

```bash theme={null}
export STACKIT_SERVICE_ACCOUNT_KEY_PATH="$HOME/.stackit/sa-key.json"

prowler stackit \
  --stackit-project-id "your-project-id" \
  --log-level DEBUG
```

This will show:

* API authentication details (with inline service account keys redacted)
* Resource discovery progress
* Security rule parsing details
* Any API errors or warnings

## Specific Patterns in StackIT Services

The generic service pattern is described in [service page](/developer-guide/services#service-structure-and-initialisation). You can find all the currently implemented services in the following locations:

* Directly in the code, in location [`prowler/providers/stackit/services/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/stackit/services)
* In the [Prowler Hub](https://hub.prowler.com/) for a more human-readable view.

The best reference to understand how to implement a new service is following the [service implementation documentation](/developer-guide/services#adding-a-new-service) and taking other StackIT services as reference.

### StackIT Service Common Patterns

* Services communicate with StackIT using the StackIT Python SDK, you can find the documentation [here](https://github.com/stackitcloud/stackit-sdk-python).
* Service constructors receive a `StackitProvider` instance and use it to access credentials, identity, and configuration.
* The provider builds StackIT SDK `Configuration` objects from the service account key path or inline key content.
* Resource containers **must** be initialized in the constructor, typically as lists or dictionaries.
* Do not manipulate `os.environ` for credentials inside services. Use the provider session and SDK configuration helpers.
* All StackIT resources are represented as Pydantic `BaseModel` classes, providing type safety and structured access to resource attributes.
* StackIT SDK calls are wrapped in try/except blocks, with specific handling for API errors, always logging errors.
* **Centralized Error Handling**: Use `provider.handle_api_error(exception)` for consistent authentication error detection across all services.
* **SDK Warning Suppression**: StackIT SDK prints deprecation warnings to stderr - use the `suppress_stderr()` context manager during SDK initialization and API calls.
* **Unrestricted Access Detection**: In StackIT API, `None` values mean "allow all" (more permissive than explicit 0.0.0.0/0).
  * `protocol=None` → All protocols allowed
  * `ip_range=None` → All source IPs allowed (unrestricted!)
  * `port_range=None` → All ports allowed
  * `remote_security_group_id` set → Only allows traffic from the same security group (not unrestricted!)

### IaaS Service Specific Patterns

**Security Group Discovery:**

```python theme={null}
# List all security groups
security_groups = client.list_security_groups(
    project_id=self.project_id,
    region=region,
)

# List network interfaces to determine security group usage
nics = client.list_project_nics(
    project_id=self.project_id,
    region=region,
)

# Checks report in-use security groups by default. Use --scan-unused-services
# to include security groups that are not attached to any NIC.
```

**Centralized Authentication Error Handling:**

```python theme={null}
def _handle_api_call(self, api_function, *args, **kwargs):
    """Wrapper for API calls with centralized error handling."""
    try:
        with suppress_stderr():  # Suppress SDK warnings
            return api_function(*args, **kwargs)
    except Exception as e:
        # Use centralized error handler from provider
        self.provider.handle_api_error(e)  # Detects 401 and raises StackITInvalidTokenError
```

**Unrestricted Access Detection:**

```python theme={null}
def is_unrestricted(rule):
    """Check if a rule allows unrestricted access."""
    # Filter out self-referencing rules
    if rule.remote_security_group_id is not None:
        return False
    # Check for unrestricted IP ranges
    return rule.ip_range is None or rule.ip_range in ["0.0.0.0/0", "::/0"]

def is_tcp(rule):
    """Check if a rule applies to TCP protocol."""
    # None means all protocols (including TCP)
    return rule.protocol is None or rule.protocol.lower() in ["tcp", "all"]

def includes_port(rule, port):
    """Check if a rule includes a specific port."""
    # None means all ports
    if rule.port_range is None:
        return True
    return rule.port_range.min <= port <= rule.port_range.max
```

## Specific Patterns in StackIT Checks

The StackIT checks pattern is described in [checks page](/developer-guide/checks). You can find all the currently implemented checks:

* Directly in the code, within each service folder, each check has its own folder named after the name of the check. (e.g. [`prowler/providers/stackit/services/iaas/iaas_security_group_ssh_unrestricted/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/stackit/services/iaas/iaas_security_group_ssh_unrestricted))
* In the [Prowler Hub](https://hub.prowler.com/) for a more human-readable view.

The best reference to understand how to implement a new check is following the [check creation documentation](/developer-guide/checks#creating-a-check) and taking other similar StackIT checks as reference.

### Check Report Class

The `CheckReportStackIT` class models a single finding for a StackIT resource in a check report. It is defined in [`prowler/lib/check/models.py`](https://github.com/prowler-cloud/prowler/blob/master/prowler/lib/check/models.py) and inherits from the generic `Check_Report` base class.

#### Purpose

`CheckReportStackIT` extends the base report structure with StackIT-specific fields, enabling detailed tracking of the resource, project, and location associated with each finding.

#### Constructor and Attribute Population

When you instantiate `CheckReportStackIT`, you must provide the check metadata and a resource object. The class will attempt to automatically populate its StackIT-specific attributes from the resource, using the following logic:

* **`resource_id`**:
  * Uses `resource.id` if present.
  * Otherwise, uses `resource.resource_id` if present.
  * Defaults to an empty string if none are available.

* **`resource_name`**:
  * Uses `resource.name` if present.
  * Defaults to an empty string if not available.

* **`project_id`**:
  * Uses `resource.project_id` if present.
  * Defaults to an empty string if not available (should be set in check logic).

* **`location`**:
  * Uses `resource.region` if present.
  * Otherwise, uses `resource.location` if present.
  * Defaults to an empty string if not available.

If the resource object does not contain the required attributes, you must set them manually in the check logic.

Other attributes are inherited from the `Check_Report` class, from which you **always** have to set the `status` and `status_extended` attributes in the check logic.

#### Example Usage

```python theme={null}
from prowler.lib.check.models import CheckReportStackIT

report = CheckReportStackIT(
    metadata=self.metadata(),
    resource=security_group
)
report.status = "FAIL"
report.status_extended = f"Security group {security_group.name} allows unrestricted SSH access from the internet."
report.resource_id = security_group.id
report.resource_name = security_group.name
report.project_id = security_group.project_id
report.location = security_group.region
```

### Common Check Pattern

```python theme={null}
from prowler.lib.check.models import Check, CheckReportStackIT
from prowler.providers.stackit.services.iaas.iaas_client import iaas_client

class iaas_security_group_ssh_unrestricted(Check):
    """Check if IaaS security groups allow unrestricted SSH access."""

    def execute(self):
        findings = []

        for security_group in iaas_client.security_groups:
            if not (iaas_client.scan_unused_services or security_group.in_use):
                continue

            report = CheckReportStackIT(
                metadata=self.metadata(),
                resource=security_group
            )
            report.status = "PASS"
            report.status_extended = f"Security group {security_group.name} does not allow unrestricted SSH access."

            # Check each rule
            for rule in security_group.rules:
                if (rule.is_ingress() and
                    rule.is_tcp() and
                    rule.includes_port(22) and
                    rule.is_unrestricted()):
                    report.status = "FAIL"
                    report.status_extended = f"Security group {security_group.name} allows unrestricted SSH access from the internet."
                    break

            findings.append(report)

        return findings
```

## Resources

### Official StackIT Documentation

* **StackIT Portal**: [https://portal.stackit.cloud/](https://portal.stackit.cloud/)
* **StackIT Documentation**: [https://docs.stackit.cloud/](https://docs.stackit.cloud/)
* **StackIT API Documentation**: [https://docs.api.eu01.stackit.cloud/](https://docs.api.eu01.stackit.cloud/)

### Python SDK

* **StackIT Python SDK (GitHub)**: [https://github.com/stackitcloud/stackit-sdk-python](https://github.com/stackitcloud/stackit-sdk-python)
* **stackit-core (PyPI)**: [https://pypi.org/project/stackit-core/](https://pypi.org/project/stackit-core/)
* **stackit-iaas (PyPI)**: [https://pypi.org/project/stackit-iaas/](https://pypi.org/project/stackit-iaas/)
* **IaaS Models**: [https://github.com/stackitcloud/stackit-sdk-python/tree/main/services/iaas/src/stackit/iaas/models](https://github.com/stackitcloud/stackit-sdk-python/tree/main/services/iaas/src/stackit/iaas/models)

### Prowler Resources

* **Provider Implementation**: [`prowler/providers/stackit/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/stackit/)
* **IaaS Service**: [`prowler/providers/stackit/services/iaas/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/stackit/services/iaas/)
* **Prowler Hub**: [https://hub.prowler.com/](https://hub.prowler.com/)
* **GitHub Issues**: [https://github.com/prowler-cloud/prowler/issues](https://github.com/prowler-cloud/prowler/issues)

## Contributing

If you'd like to contribute to the StackIT provider:

1. **Add New Checks**: Follow the [check creation guide](/developer-guide/checks#creating-a-check) and use existing StackIT checks as templates
2. **Enhance Services**: Implement additional IaaS resource discovery or add new services
3. **Improve Documentation**: Add metadata enhancements, CLI remediation examples, or Terraform code samples
4. **Report Issues**: Submit bug reports or feature requests on [GitHub](https://github.com/prowler-cloud/prowler/issues)

### Quick Start for Contributors

1. **Install dependencies**: `poetry install` (includes stackit-core and stackit-iaas)
2. **Set credentials**: Export `STACKIT_SERVICE_ACCOUNT_KEY_PATH` and `STACKIT_PROJECT_ID`
3. **Run checks**: `prowler stackit`
4. **View code**: Start in `prowler/providers/stackit/`
5. **Add checks**: Create new check directories under `services/iaas/`
6. **Run tests**: `poetry run pytest tests/providers/stackit/ -v`

### Code Quality Standards

The StackIT provider should follow the same quality expectations as the rest of the Prowler SDK:

* Keep service and check logic covered by unit tests.
* Redact inline service account keys from generated output.
* Keep documentation aligned with the implemented services and checks.
* Follow existing provider, service, and check patterns before adding StackIT-specific abstractions.
