# How MCP-OpenStack-Ops Ensures Project Isolation and Tenant Security at the Operational Level

> Learn how MCP-OpenStack-Ops guarantees project isolation and tenant security by integrating ownership validation into the OpenStack SDK, safeguarding your resources at the operational level.

- Repository: [JungJungIn/mcp-openstack-ops](https://github.com/call518/mcp-openstack-ops)
- Tags: architecture
- Published: 2026-02-26

---

**MCP-OpenStack-Ops enforces strict project isolation by embedding security checks directly into the OpenStack SDK connection layer, ensuring every resource operation validates ownership against the authenticated tenant ID before execution.**

The `call518/mcp-openstack-ops` repository implements a defense-in-depth security model that prevents cross-tenant resource leakage across compute, network, storage, and identity services. By centralizing project scoping logic in the connection layer, the framework guarantees that no operation can unintentionally access resources belonging to another tenant, even if underlying SDK configurations vary.

## Core Security Architecture in the Connection Layer

All tenant security guarantees originate in **[`src/mcp_openstack_ops/connection.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/connection.py)**, which exposes three critical mechanisms used uniformly across every service module.

### Current Project Identification

The `get_current_project_id()` function extracts the authenticated project ID from the OpenStack token or performs a fallback name-lookup, making the tenant context globally available to all subsequent operations.

- **Source location:** [`connection.py#L43-L71`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/connection.py#L43-L71)
- **Return value:** The active project ID string used for all ownership comparisons
- **Usage pattern:** Stored in `conn.current_project_id` and referenced by identity and network services

### Resource Ownership Validation

The `validate_resource_ownership(resource, resource_type)` function compares the `project_id` or `tenant_id` of any OpenStack resource against the current project ID. Public resources (flavors, public images) bypass validation via an `is_public` flag, while any project mismatch triggers a warning and returns **false**.

- **Source location:** [`connection.py#L78-L106`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/connection.py#L78-L106)
- **Security behavior:** Returns boolean ownership status; logs warnings on cross-tenant access attempts
- **Public resource handling:** Automatically allows shared resources like flavors and public images

### Secure Lookup Helpers

The `find_resource_by_name_or_id()` and `get_project_scoped_resources()` functions combine resource discovery with immediate ownership validation. These helpers first locate resources by name or ID, then invoke `validate_resource_ownership()` to ensure only tenant-owned resources are returned to service modules.

- **Source location:** [`connection.py#L124-L165`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/connection.py#L124-L165)
- **Validation chain:** Every lookup automatically filters cross-tenant resources before they reach business logic
- **Error handling:** Returns `None` for inaccessible resources, preventing accidental operations

## Service-Level Isolation Enforcement

All service implementations import these connection-layer helpers and apply them before any Create, Read, Update, or Delete (CRUD) operation.

### Compute Service Isolation

In **[`src/mcp_openstack_ops/services/compute.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/compute.py)**, the `get_instance_details()` function retrieves servers using `conn.compute.servers(details=True, all_projects=False)`, then explicitly validates each instance:

- **Validation call:** `validate_resource_ownership(server, "Instance")` for every server object
- **Source location:** [`compute.py#L48-L61`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/compute.py#L48-L61)
- **Filtering logic:** Only instances passing the ownership test are included in the final result set

### Identity and Network Security

The identity service functions (`get_user_list()`, `get_role_assignments()`, `set_project()`) rely on `conn.current_project_id` to filter role assignments and project-specific actions. Similarly, network, storage, image, monitoring, and load-balancer services use `get_current_project_id()` or `get_project_scoped_resources()` to scope all listings and modifications to the active tenant.

- **Identity enforcement:** [`identity.py#L133-L197`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/identity.py#L133-L197)
- **Cross-service consistency:** Every `set_*` and `get_*` function exposes a tenant-aware interface without requiring manual filter parameters

## Automated Security Verification

The project isolation mechanisms are continuously validated by **[`test_project_isolation.py`](https://github.com/call518/mcp-openstack-ops/blob/main/test_project_isolation.py)**, which confirms:

1. Successful connection establishment and project ID extraction
2. Ownership validation on instances, networks, and volumes
3. Secure lookup behavior proving cross-tenant resources remain invisible

- **Test coverage:** [`test_project_isolation.py#L42-L63`](https://github.com/call518/mcp-openstack-ops/blob/main/test_project_isolation.py#L42-L63)
- **Verification method:** Automated assertions that `validate_resource_ownership()` returns `False` for non-owned resources

## Practical Implementation Examples

The following patterns demonstrate how MCP-OpenStack-Ops maintains tenant security in production code:

```python
from mcp_openstack_ops.connection import (
    get_current_project_id,
    validate_resource_ownership,
    find_resource_by_name_or_id,
)

# Retrieve the authenticated project ID used for all ownership checks

project_id = get_current_project_id()
print(f"Current project ID: {project_id}")

# Validate instance ownership before processing

from mcp_openstack_ops.services.compute import get_instance_details

instances = get_instance_details(limit=5)["instances"]
for inst in instances:
    is_owned = validate_resource_ownership(inst, "Instance")
    print(f"Instance {inst['name']} owned by tenant: {is_owned}")

# Securely lookup network by name with automatic tenant validation

from mcp_openstack_ops.services.network import get_network_details

network = find_resource_by_name_or_id(
    conn.network.networks(),
    "private-net",
    "Network",
)
if network:
    print(f"Network {network.name} accessible in current tenant")
else:
    print("Network not found or belongs to different project")

```

## Summary

- **Centralized validation:** All tenant security logic resides in [`src/mcp_openstack_ops/connection.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/connection.py), preventing code duplication and inconsistent enforcement.
- **Explicit ownership checks:** The `validate_resource_ownership()` function compares resource `project_id` against the authenticated tenant for every operation.
- **Secure lookup abstraction:** Helper functions `find_resource_by_name_or_id()` and `get_project_scoped_resources()` combine discovery with validation, ensuring only owned resources are returned.
- **Public resource bypass:** Shared resources like flavors and public images are automatically allowed while tenant-specific data remains protected.
- **Automated testing:** [`test_project_isolation.py`](https://github.com/call518/mcp-openstack-ops/blob/main/test_project_isolation.py) continuously verifies that cross-tenant access is impossible across compute, network, and storage services.

## Frequently Asked Questions

### How does MCP-OpenStack-Ops prevent accidental access to other tenants' resources?

MCP-OpenStack-Ops implements explicit resource ownership validation in `validate_resource_ownership()`, which compares the `project_id` of every OpenStack resource against the authenticated tenant ID extracted by `get_current_project_id()`. This check runs automatically through secure lookup helpers before any resource is returned to service logic, ensuring cross-tenant resources are filtered out regardless of SDK configuration.

### What happens when the system encounters a public resource like a shared flavor or image?

Public resources are automatically allowed through the ownership validation layer. The `validate_resource_ownership()` function detects the `is_public` flag on resources like flavors and public images, bypassing the project ID comparison while still protecting tenant-specific data. This preserves standard OpenStack behavior for shared infrastructure components.

### Can service developers accidentally bypass the project isolation mechanisms?

No. All high-level service functions (compute, network, storage, identity) import and use the secure lookup helpers (`find_resource_by_name_or_id`, `get_project_scoped_resources`) from [`connection.py`](https://github.com/call518/mcp-openstack-ops/blob/main/connection.py). These helpers enforce validation automatically, so developers cannot return unvalidated resources without explicitly circumventing the entire service architecture.

### How is the project isolation security model tested and verified?

The repository includes [`test_project_isolation.py`](https://github.com/call518/mcp-openstack-ops/blob/main/test_project_isolation.py), which automates verification that only resources matching the authenticated project ID are accessible. The test suite exercises `get_current_project_id()`, `validate_resource_ownership()`, and the secure lookup helpers across instances, networks, and volumes to confirm that cross-tenant resources remain invisible and inaccessible.