Skip to main content

Deployment-Wide Data Access Control

Explains the logic for granting access to deployment-wide data, such as tables without tenant columns. Access is granted to the platform tenant or in

Overview

The DeploymentWideAccess component is a security control that determines whether a caller has permission to read deployment-wide data. This includes data in tables that do not have a tenant column, such as the proxy topology configuration or the generic ingest dead-letter queue.

This control is necessary in a multi-tenant environment to enforce data isolation. It ensures that a regular tenant cannot access shared, operational data that belongs to the platform itself.

Access is granted under two specific conditions:

  1. The caller is authenticated as the platform operator (i.e., the PLATFORM_TENANT_ID is bound to the request thread).
  2. The deployment is a single-tenant installation. In this case, the caller is authenticated as the DEFAULT_TENANT_ID, and the system verifies that no other tenants exist besides the reserved platform tenant.

In all other scenarios—such as a request from a regular tenant in a multi-tenant deployment, an anonymous request, or if the system cannot verify the tenant count—access is denied. This "fail-closed" approach prioritizes data security.

How It Works

The access decision is made by the static method DeploymentWideAccess.allowed(JdbcTemplate jdbc). It follows a strict sequence of checks based on the tenant context bound to the current request thread.

flowchart TD
    A[Start] --> B{Is a tenant context bound?};
    B -- No --> Z[Access Denied];
    B -- Yes --> C{Is tenant the Platform Tenant?};
    C -- Yes --> Y[Access Granted];
    C -- No --> D{Is tenant the Default Tenant?};
    D -- No --> Z;
    D -- Yes --> E[Query DB: Is this a single-tenant deployment?];
    subgraph "Database Check"
        direction LR
        E -- Query Fails --> F[Log warning & Deny Access];
        E -- Result is true --> Y;
        E -- Result is false --> Z;
    end

The logical flow is as follows:

  1. Check for Tenant Context: The system first retrieves the current tenant's UUID from the TenantContext. If no tenant is bound to the request, access is immediately denied.
  2. Check for Platform Tenant: If a tenant is bound, the system checks if its ID matches TenantContext.PLATFORM_TENANT_ID. If it does, access is granted. The platform operator always has deployment-wide visibility.
  3. Check for Default Tenant: If the caller is not the platform tenant, the system checks if its ID matches TenantContext.DEFAULT_TENANT_ID. If it is any other tenant, access is denied.
  4. Verify Single-Tenant Deployment: If the caller is the default tenant, the system performs a database query to confirm that the deployment is effectively single-tenant. It checks if the DEFAULT_TENANT_ID is the only tenant in the s2r_tenant registry, aside from the reserved PLATFORM_TENANT_ID.
  5. Grant or Deny Based on Query:
    • If the query confirms it is a single-tenant deployment, access is granted.
    • If the query indicates other tenants exist, access is denied.
    • If the database query fails for any reason, access is denied, and a warning is logged.

NOTE

The tenant count includes all tenants registered in the s2r_tenant table, including those that are suspended or soft-deleted. The presence of a disabled tenant is sufficient to make the deployment multi-tenant for the purpose of this access check.

Single-Tenant Verification Query

To determine if a deployment is single-tenant, the allowed method executes the following SQL query. This query is only run when the caller is authenticated as the DEFAULT_TENANT_ID.

select count(*) = 1 and coalesce(bool_or(id = ?), false)
  from s2r_tenant
 where id <> ?

The query is executed with two parameters:

  1. The first ? is bound to TenantContext.DEFAULT_TENANT_ID.
  2. The second ? is bound to TenantContext.PLATFORM_TENANT_ID.

This query performs two checks in one:

  • where id <> ?: It filters out the platform tenant from the count.
  • count(*) = 1: It checks if exactly one tenant remains.
  • coalesce(bool_or(id = ?), false): It confirms that the one remaining tenant is indeed the default tenant.

The query returns true only if both conditions are met, confirming a single-tenant deployment.

API Reference

The DeploymentWideAccess class provides a single static method for checking permissions.

DeploymentWideAccess.allowed()

Checks if the tenant bound to the current thread is permitted to read deployment-wide data.

  • Method Signature: public static boolean allowed(JdbcTemplate jdbc)
  • Return Value:
    • true: Access is granted.
    • false: Access is denied.
  • Parameters:
NameTypeDescription
jdbcJdbcTemplateThe JDBC template used to query the tenant registry if a database check is required. If null when a check is needed, access is denied.

IMPORTANT

This method is designed to never throw an exception. In case of database errors during the tenant count, it will catch the exception, log a warning, and return false.

Troubleshooting

Access Denied Due to Tenant Count Failure

If the DeploymentWideAccess.allowed() method returns false unexpectedly for the default tenant, check the service logs for a warning message.

  • Condition: A RuntimeException occurs during the execution of the DEFAULT_IS_ONLY_TENANT_SQL query against the s2r_tenant table.
  • Log Message: S2R-TENANCY deployment-wide access denied: tenant count failed ({ExceptionName})
  • Effect: Access is denied (false is returned). This is a "fail-closed" safety mechanism to prevent unauthorized data access in case of system malfunction.
  • Cause: This can be caused by database connectivity issues, insufficient permissions for the service's database user, or other database-level problems.
Tagsguides

All SOAP-to-REST docs