This document deals with advanced functions that go beyond the basic capabilities detailed in the SGNL Policy Snippet Reference. There are 2 advanced snippet capabilities that are available in the SGNL product today, these include:
To simplify builing these more advanced Snippets, both types are included as Snippet Templates in the SGNL Snippet Builder, enabling SGNL Administrators to create these types of Snippets with a single click and providing the specific business logic desired.
SGNL supports the ability to evaluate an IP Address that was provided during an access evaluation to a resolved location. Various granularites of resolution are available, including:
Property | Description | Example Value | Query Field Name Attribute |
City | The City resolved from the IP Address presented in the Access Evaluation. | “San Francisco” | principal.ipAddress.location.city |
State/Province/Region | The region resolved from the IP Address presented in the Access Evaluation. | “CA” | principal.ipAddress.location.region |
Country | The Country (as an alpha-2 ISO 3166-2 code) resolved from the IP Address presented in the Access Evaluation. | “US” | principal.ipAddress.location.country |
Postal/Zip Code | The Postal Code resolved from the IP Address presented in the Access Evaluation. | “94101” | principal.ipAddress.location.postalCode |
TimeZone | The TimeZone of the location that was resolved from the IP Address that was presented in the Access Evaluation | “America/Los_Angeles” | principal.ipAddress.location.timezone |
For production use-cases, SGNL recommends a granularity of Country as the preferred resolution, however SGNL Customers may choose a different resolution granularity depending on their needs/use-case.
Countries are resolved to their 2 character ISO 3166-2 alpha-2 code. The most straightforward example is available to SGNL Administrators as part of our Snippet Templates - it checks to see if the request is coming from a specific country and matches if that’s the case.
To evaluate location as part of an Access Decision, include the ipAddress
field and value in the access evaluation
{
"principal": {
"id": "alejandro@wholesalechips.co",
"ipAddress": "69.181.81.65",
"deviceId": "48:65:ee:17:7e:0b"
},
"queries": [
{
"action": "access",
"assetId": "11754"
}
]
}
The Snippet Template using the United States as the Country is below:
{
"condition": {
"predicate": {
"lhs": {
"queryFieldName": "principal.ipAddress.location.country"
},
"op": "EqualTo",
"rhs": {
"string": "US"
}
}
},
"description": "User is physically located in the United States"
}
You’re able to use combinations of AND
, OR
, and NOT
as detailed in the Policy Snippet Reference, say you wanted to match the snippet if a request was coming from Australia or New Zealand:
{
"condition": {
"or": [
{
"predicate": {
"lhs": {
"queryFieldName": "principal.ipAddress.location.country"
},
"op": "EqualTo",
"rhs": {
"string": "AU"
}
}
},
{
"predicate": {
"lhs": {
"queryFieldName": "principal.ipAddress.location.country"
},
"op": "EqualTo",
"rhs": {
"string": "NZ"
}
}
}
]
},
"description": "User is physically located in Australia or New Zealand"
}
Where this becomes most powerful is dynamically verifying that a given Principal is in the same location as a specific piece of data that they are trying to access. One we hear frequently at SGNL is the location of an Account in Salesforce. Salesforce has adopted ISO 3166 codes as the standard for Country Picklists and thus allows dynamic comparison between as principal’s current location and the location of Salesforce Data.
Note: The Attribute ID below represents a Salesforce Account’s
{
"nodes": [
{
"entityId": "{{Salesforce Account Entity ID}}",
"nodeName": "sfdcAccount",
"queryFieldName": "assetId"
}
],
"condition": {
"and": [
{
"predicate": {
"lhs": {
"queryFieldName": "principal.ipAddress.location.country"
},
"op": "EqualTo",
"rhs": {
"attributeId": "{{Attribute ID for the 'Billing Country' attribute on Salesforce Accounts}}",
"nodeName": "sfdcAccount"
}
}
}
]
}
"description": "Principal Location Matches Customer Location"
}
SGNL supports the ability to evaluate the time an Access Evaluation as context in making an access decision. A range of operations are available to evaluate and compare time, as well as to craft snippets that can look at durations and more. Temporal Snippets allow a range of expressions and functions, which we’ll cover in this section.
There are a number of operators that you’ll encounter when working with Temporal Snippets, including:
Operator | Description | Example Value to provide to Operator |
ToTimezone | Convert a DateTime attribute to a specific TimeZone | America/Los_Angeles |
GetField | Get a specific portion of a DateTime to perform some operation on | See Below |
Add | Add some period of time to an attribute of type DateTime | 8 Hours |
Subtract | Subtract some period of time to an attribute of type DateTime | 8 Hours |
LessThanOrEqualTo | When working with DateTime attributes, serves as a function to check if one DateTime is before another DateTime | 17 (5pm) |
GreaterThanOrEqualTo | When working with DateTime attributes, serves as a function to check if one DateTime is after another DateTime | 8 (8am) |
When comparing Dates and Times, you’ll likely find the need to just compare or evaluate just one part of the Date or Time, in these cases, you’ll use the operator GetField
, fields that are availble with this operator include:
Available Fields | Description | Sample Value |
Second | The second | 45 |
Minute | The minute | 31 |
Hour | The hour of the day, expressed in 24-hour time | 17 |
Day | The day of the month | 22 |
Month | The month of the year | 12 |
Year | The year | 2024 |
DayOfWeek | The ISO8601 Day of the Week (1 is Monday, 7 is Sunday) | 5 |
Offset | The Offset from UTC time, with Z as the shorthand for UTC time | +10:00 |
The easiest way to create your first Temporal Snippet is to create a new Condition Snippet and use our Snippet Templates to select ‘During Business Hours’, by default this snippet localizes to your current timezone. This snippet uses the current time of the request to evaluate whether it was made during US Pacific Time Business Hours, from Monday to Friday.
{
"condition": {
"and": [
{
"predicate": {
"lhs": {
"expr": {
"lhs": {
"expr": {
"lhs": {
"queryFieldName": "time.now"
},
"op": "ToTimezone",
"rhs": {
"string": "America/Los_Angeles"
}
}
},
"op": "GetField",
"rhs": {
"string": "Hour"
}
}
},
"op": "GreaterThanOrEqualTo",
"rhs": {
"integer": 9
}
}
},
{
"predicate": {
"lhs": {
"expr": {
"lhs": {
"expr": {
"lhs": {
"queryFieldName": "time.now"
},
"op": "ToTimezone",
"rhs": {
"string": "America/Los_Angeles"
}
}
},
"op": "GetField",
"rhs": {
"string": "Hour"
}
}
},
"op": "LessThanOrEqualTo",
"rhs": {
"integer": 17
}
}
},
{
"predicate": {
"lhs": {
"expr": {
"lhs": {
"expr": {
"lhs": {
"queryFieldName": "time.now"
},
"op": "ToTimezone",
"rhs": {
"string": "America/Los_Angeles"
}
}
},
"op": "GetField",
"rhs": {
"string": "DayOfWeek"
}
}
},
"op": "LessThanOrEqualTo",
"rhs": {
"integer": 5
}
}
}
]
},
"description": "During US PST Business Hours - Monday to Friday",
}
Let’s say you wanted to create a snippet that checked to see if a ServiceNow Case assigned to a ServiceNow User was still in it’s approved window of time
{
"condition": {
"expr": {
"lhs": {
"queryFieldName": "time.now"
},
"op": "LessThanOrEqualTo",
"rhs": {
"attributeId": "{{DateTime Due Date of an Approved ServiceNow Case}}",
"nodeName": "snowCase"
}
}
},
"nodes": [
{
"entityId": "{{ServiceNow User Entity ID}}",
"nodeName": "snowUser",
"queryFieldName": "principalId"
},
{
"entityId": "{{ServiceNow Case Entity ID}}",
"nodeName": "snowCase"
}
],
"relationships": [
{
"fromNodeName": "snowCase",
"relationshipName": "AssignedTo",
"toNodeName": "snowUser",
"transitive": true,
"undirected": false
}
],
"description": "Approved ServiceNow Case is not expired",
}
Let’s say you wanted to evaluate whether a JIRA Change Request was in it’s approval window, and you had the “Time of Approval” and the “Length of Approval” values stored on the JIRA ticket:
{
"condition": {
"expr": {
"lhs": {
"queryFieldName": "time.now"
},
"op": "LessThanOrEqualTo",
"rhs": {
"expr": {
"lhs": {
"attributeId": "{{JIRA Issue Approved Time Attribute}}",
"nodeName": "jiraIssue"
},
"op": "Add",
"rhs": {
"attributeId": "{{JIRA Issue Length of Approval Attribute}}",
"nodeName": "jiraIssue"
}
}
}
}
},
"nodes": [
{
"entityId": "{{JIRA User Entity ID}}",
"nodeName": "jiraUser",
"queryFieldName": "principalId"
},
{
"entityId": "{{JIRA Issue Entity ID}}",
"nodeName": "jiraIssue"
}
],
"relationships": [
{
"fromNodeName": "jiraIssue",
"relationshipName": "AssignedTo",
"toNodeName": "jiraUser",
"transitive": false,
"undirected": false
}
],
"description": "Approved JIRA Issue is in its approval window"
}
SGNL also supports the dynamic evaluation of durations against dates and times or other durations. This is particularly useful if you want to understand whether some amount of time has passed that should change the result of policy evaluation. SGNL uses ISO8601 Duration Formats to perform the evaluation using the operators above.
Some example durations that might be useful:
An arbitrarily complex example:
With that, say you wanted to see if a ServiceNow Case has been closed for less than 14 days:
{
"condition": {
"expr": {
"lhs": {
"expr": {
"lhs": {
"queryFieldName": "time.now"
},
"op": "Subtract",
"rhs": {
"duration": "P14D"
}
}
},
"op": "LessThanOrEqualTo",
"rhs": {
"attributeId": "{{closedTime Attribute ID}}",
"nodeName": "snowCase"
}
}
},
"description": "Ensure a Case assigned to the User has not been closed for more than 14 days",
"nodes": [
{
"entityId": "{{Service Now Case Entity ID}}",
"nodeName": "snowCase"
},
{
"entityId": "{{Service Now User Entity ID}}",
"nodeName": "snowUser",
"queryFieldName": "principalId"
}
],
"relationships": [
{
"fromNodeName": "snowCase",
"relationshipName": "AssignedTo",
"toNodeName": "snowUser",
"transitive": false,
"undirected": false
}
],
}