Data Access Controls
Squid's data access control model is fundamentally different from traditional table-based access. Instead of granting access to tables and then restricting columns, Squid uses database views to define precisely what data is available.
Views: The First Line of Defense
Squid does not directly access ServiceNow tables. All data access goes through ServiceNow database views.
Why Views Provide Security
- Explicit Column Selection - Only columns defined in the view are accessible
- No Accidental Exposure - New table columns don't automatically appear
- Join Control - You decide which related data to include
- Single Point of Control - Change the view, change all dependent configurations
View-Based Column Security
Consider a cmdb_ci_server table with 100+ columns. Your view might only expose:
| Exposed in View | Hidden (Not in View) |
|---|---|
| sys_id | u_internal_cost |
| name | comments |
| asset_tag | work_notes |
| sys_class_name | u_sensitive_data |
| manufacturer | correlation_id |
| location | discovery_credentials |
Columns not in the view simply don't exist from Squid's perspective.
View Fields: Additional Column Filtering
Beyond the view definition, each table in a view can have View Fields defined:
- If View Fields are defined: Only those fields are returned
- If View Fields are empty: All columns from that table in the view are returned
This provides an additional layer of column-level control without modifying the view itself.
View Filters: Row-Level Security
While views control which columns are accessible, view filters control which rows are returned.
What is a View Filter?
A view filter is an encoded query that Squid applies to every request using that configuration. It cannot be overridden or bypassed by the caller.
Configuration: cmdb_ci_server_production
View Filter: base_install_status=1^base_operational_status=1
(only production, operational servers)
View Filter vs User-Provided encodedQuery
| Aspect | View Filter | User encodedQuery |
|---|---|---|
| Defined By | Squid Administrator | API Caller |
| Can Be Bypassed | No | N/A (it's caller input) |
| Operator Restrictions | None | Yes (restricted operators blocked) |
| Purpose | Security restriction | Query flexibility |
How Filters Combine
When a configuration has a view filter and the caller provides an encodedQuery:
Final Query = View Filter AND User encodedQuery
Example:
View Filter: base_install_status=1
User Query: base_name=webserver01
Combined: base_install_status=1^base_name=webserver01
The view filter is always applied, ensuring security restrictions cannot be bypassed.
Creating Effective View Filters
Good view filters for security:
# Restrict to active/operational items only
base_install_status=1^base_operational_status!=6
# Restrict to specific company
base_company=e7c1f3d53790200044e0bfc8bcbe5deb
# Restrict to non-confidential classifications
base_u_confidentialityNOT INtop_secret,confidential
# Time-based restriction (only items updated in last year)
base_sys_updated_on>=javascript:gs.daysAgo(365)
View filters can use restricted operators (like javascript:) because they are administrator-defined, not user input. Use this power responsibly.
Configuration-Level Data Controls
Each Squid configuration provides several data access controls:
Control: Database View
Defines which view (and thus which columns) are available.
Database View: u_cmdb_ci_server_squid
Primary Database View Prefix: base
Control: Excluded Database View Prefixes
Sometimes views include tables for joining or filtering purposes, but you don't want those columns in the output.
# View includes cmdb_rel_team for filtering, but exclude from output
Excluded Database View Prefixes: rel
Control: Is Root
Controls whether a configuration can be directly requested or only accessed via references.
| Is Root | Direct API Call | Via Reference |
|---|---|---|
| true | ✅ Allowed | ✅ Allowed |
| false | ❌ Blocked | ✅ Allowed |
Use case: Allow sys_user_group data when referenced by a CI, but prevent direct export of all user groups.
Control: Allow Inline Relations
Inline relations can cause extreme database load (potentially millions of queries). This setting controls whether inline rendering is permitted.
Allow Inline Relations: false # Protect against performance attacks
Control: Limit
Maximum entities returned per request. Essential when inline relations are enabled.
Limit: 1000 # Prevent runaway queries
Data Flow Through Security Layers
┌─────────────────────────────────────────────────────────────────┐
│ Requested: cmdb_ci_server │
│ Query: ?encodedQuery=base_name=web* │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Step 1: Load Configuration │
│ • Database View: u_cmdb_ci_server_squid │
│ • View Filter: base_install_status=1 │
│ • Primary Prefix: base │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Step 2: Validate User Query │
│ • Check for forbidden operators (^NQ) → Block if found │
│ • Check for restricted operators → Block if restricted │
│ • Validate sys_id format if provided │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Step 3: Build Final Query │
│ • Start with View Filter: base_install_status=1 │
│ • Append user query: ^base_name=web* │
│ • Final: base_install_status=1^base_name=web* │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Step 4: Execute Query Against View │
│ • Query: u_cmdb_ci_server_squid │
│ • Only columns in view are accessible │
│ • Only rows matching combined filter returned │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Step 5: Process Results │
│ • Apply View Fields filtering (if defined) │
│ • Exclude specified prefixes from output │
│ • Resolve references using reference configurations │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Return JSON Response │
│ (only permitted data) │
└─────────────────────────────────────────────────────────────────┘
Practical Examples
Example 1: Restricting by Classification
Requirement: Only export non-confidential servers
Configuration: cmdb_ci_server_public
Database View: u_cmdb_ci_server_squid
View Filter: base_u_classification!=confidential^base_u_classification!=restricted
Example 2: Department-Specific Configuration
Requirement: HR department should only see HR-managed assets
Configuration: cmdb_ci_hr_assets
Database View: u_cmdb_ci_computer_squid
View Filter: base_managed_by_group=hr_asset_management_sys_id
Roles: hr_data_access
Example 3: Time-Bound Data Access
Requirement: Only export recently updated items (data freshness)
Configuration: cmdb_ci_server_recent
Database View: u_cmdb_ci_server_squid
View Filter: base_sys_updated_on>=javascript:gs.daysAgo(90)
Example 4: Multi-Tenant Isolation
Requirement: Different customers see only their data
Configuration: cmdb_ci_server_customer_a
View Filter: base_company=customer_a_sys_id
Roles: customer_a_access
Configuration: cmdb_ci_server_customer_b
View Filter: base_company=customer_b_sys_id
Roles: customer_b_access
Related Topics
- ServiceNow ACLs - Alternative/additional access control
- Query Security - Protecting against query manipulation
- Authorization - Who can access configurations