The Zurich release has arrived! Interested in new features and functionalities? Click here for more

David Skowronek
ServiceNow Employee
ServiceNow Employee

ServiceNow Table API. It is available baseline for all tables, easy to use ... and not so easy to grant/deny access and control what records and attributes can be used by each integration. Giving baseline roles, such as cmdb_read for CMDB, itil to access (many) Task tables etc., provide too much access for external integrations. Creating custom roles and access controls (ACLs) are not flexible at scale.

 

The challenge is to ensure the need-to-know principle for external integrations without heavy development using a configuration-type, data-driven approach.

 

The presented solution is a custom development that requires:

  • 3 custom Tables (can be implemented with single custom table as well)
  • 1 custom Scripted Web Service
  • 1 custom Role
  • Transaction log (custom, optional)
  • Rate Limit Rules (baseline, optional)

What would be the outcome? The standard integration solution enabling a Table API-like data access with allow-listing of Tables, Attributes and Records that external integration can read, without use-case specific development.

 

Data Model

 

The following diagram represents the data model with custom tables (highlighted with light-red background) and their dependencies to other baseline tables.

Subscription Table API.jpeg

 

Security

 

The entire solution shall be implemented as a Scoped Application, with the following roles as a minimum:

  • <scope_name>.api_user, providing access to the Scripted WebService (API) itself
  • <scope_name>.admin, with access to the backend configuration of the table/account subscriptions

 

Custom Tables

 

Data Table Configuration

 

This record contains the specification of allow-listed attributes that can be shared for the selected table (class). It is a generic configuration record that says: "only the selected attributes from this table can be shared through an integration". There can be more than one record for a single table (class), as there may be a need to share different data with different vendors. In this situation, it is important to subscribe only one Data Table Configuration to a single Vendor.

 

Data Table Configuration.JPG

 

Attribute Data type Note
Number Auto-number, prefix DTC Read-only
Table Reference to Table [sys_db_object] Mandatory
Description String (4000)  
Attributes List, reference to Dictionary Entry [sys_dictionary] Mandatory, showing only attributes related to the selected Table, without Collection and Empty attributes
Chunk size Integer Mandatory, default: 1000
Active True/False  

 

 

Account Subscription

 

This record contains a list of Data Table Configuration subscribed to a single Vendor Integration Account (user account). In practice, it defines what Tables, Record and Attributes are accessible for the specified Integration Account.

 

Account Subscription.JPG

 

Attribute Data type Note
Number Auto-number, prefix DTS Read-only
Integration Account Reference to User [sys_user] Mandatory
Description String (4000)  
Active True/False  
Subscribed tables Related list to Subscribed Table  

 

 

Subscribed Table

 

This record contains the configuration of the Data Table Configuration record for a subscribed Integration account. The key element is a Data filter that restricts what records belong to the Vendor and should be returned.

 

Subscribed Table.JPG

 

Attribute Data type Note
Number Auto-number, prefix SUB Read-only
Account Subscription Reference to Account Subscription Mandatory
Data Table Configuration Reference to Data Table Configuration Mandatory
Active True/False  
Data filter Conditions

The Data Filter should target a table specified in Data Table Configuration.Table attribute

 

Scripted Web Service

 

A custom Scripted Web Service should consume the configuration tables mentioned above. The Web Service should be an entry point for all integrations, protected by the custom role <scope_name>.api_user. The custom role should be the only one role granted to the external integration account.

 

The following methods should be part of the custom Scripted Web Service:

  • getSubscriptions, providing a list of subscribed tables and their attributes
  • getData, providing the data itself

 

getSubscriptions Method

 

The getSubscriptions method returns a complete list of subscribed Tables and Attributes, for the given Integration Account. There are no input parameters needed. The Scripted REST Resource will read tables subscribed to the Account used and provide:

  • List of tables (Data Table Configuration.Table)
  • For each Table list of Attributes (Data Table Configuration.Attributes)

 

Example of the returned JSON:

 

 

{"result": [
    {
      "table_name": "cmdb_ci_win_server",
      "display_name" : "Windows Server",
      "url": "<URL to the interface>",
      "attributes": "name,install_status,operational_status,fqdn"
    },
    {
      "table_name": "cmdb_ci_service_discovered",
      "display_name" : "Application Service",
      "url": "<URL to the interface>",
      "attributes": "name,operational_status,busines_criticality,change_control,assignment_group"
    }
]}

 

 

 

getData Method

 

The getData method returns data for the selected Table and defined Attributes. This interface internally calls the baseline Table API of the given table (https://<instance_name>.service-now.com/api/now/table/<table_name>?<parameters>), with additional parameters (sysparm_fields, sysparm_limit etc.) based on the configuration tables. The getData Resource should expect the following input parameters:

 

Parameter Data type Notes
table_name String Mandatory
page_index Integer Optional, default: 0
last_update DateTime Optional
filter String

Optional (encoded query)

 

Once executed, the getData method should call the internal Table API to provide values:

  • The input parameter "table_name", together with the account used for integration, is used to identify the "Subscribed Table";
  • if the required table is NOT subscribed, HTTP 403 (Forbidden) response is returned;
  • if the required table IS subscribed, the baseline Table API call should be constructed and executed with an internal account having the necessary permissions (e.g. admin-level account).

 

The baseline Table API call should be constructed as follows:

 

URL parameter Value Note
sysparm_display_value all  
sysparm_exclude_reference_link true  
sysparm_suppress_pagination_header true  
sysparm_fields Subscribed Table.Data Table Configuration.Attributes  
sysparm_limit Subscribed Table.Data Table Configuration.Chunk size  
sysparm_offset page_index (input parameter)  
sysparm_query Subscribed Table.Data Filter + <filter (input parameter)> + sys_updated_on>=<last_update (input parameter)> + ORDERBY sys_created_on

Records must always be sorted to provide consistent results due to pagination. For this reason, sorting is based on the sys_created_on value. Part of the query "sys_updated_on" is added only when "last_update" is provided as the input parameter; otherwise, do not include it. When the custom „filter“ value is provided, ensuring that no „^NQ“ (new query) condition is part of the value is essential. Otherwise, it may override the specified record filter.

 

The baseline Table API response content should be returned by the getData method. This ensures the same response structure as the baseline Table API provides.

 

Example of returned JSON with two records and two attributes (install_status, name), equivalent to the following baseline Table API call: https://<instance_name>.service-now.com/api/now/table/cmdb_ci_server?sysparm_display_value=all&syspa...

 

 

{"result": [
    {
        "install_status": {
            "display_value": "Installed",
            "value": "1"
        },
        "name": {  
            "display_value": "Service-now Production Sacramento",
            "value": "Service-now Production Sacramento"
        }
    },
    {
        "install_status": {
            "display_value": "Installed",
            "value": "1"
        },
        "name": {
            "display_value": "Service-now Production San Diego",
            "value": "Service-now Production San Diego"
        }
    }
]}

 

 

Optional Features

There are two main optional features that should be considered:

 

Logging of all transactions

 

For the audit purpose, it is recommended to log all inbound transactions, optionally including the response provided.

 

Rate limits

 

To ensure the performance of your instance, you may consider the implementation of  Rate Limits (https://docs.servicenow.com/bundle/tokyo-application-development/page/integrate/inbound-rest/concept...). With Rate Limits in place, you may prevent excessive data extraction and overload of semaphores.

 

Conclusion

 

The presented solution is custom development. However, once developed, it allows granular data-driven access control for external integrations. There is no need to develop integration-specific ACLs or other security controls. Develop once, use many times – control by the data directly in production.

Comments
Tapio Silvera
Tera Explorer

Hi, @David Skowronek 
Great looking design.
Since this is designed as a scoped application, I assume you have implemented this?
Would you be able to share the application?

David Skowronek
ServiceNow Employee
ServiceNow Employee

Hello, @Tapio Silvera . Unfortunately, I cannot share the implemented solution. I has been implemented by several customers, but always inside their own scope.

Version history
Last update:
‎07-31-2023 02:55 AM
Updated by:
Contributors