Integrating Protected Systems with SGNL using Access APIs

SGNL - Architecture

SGNL seamlessly integrates with Systems of Record using resilient and high-performance connectors, ingesting relevant data into a central graph directory. This data encompasses all information pertinent to defining organizational policies, including identity data such as users and groups from Okta or Azure Active Directory, as well as other organizational details from CRM systems, ticket/case management systems, and so on. Protected Systems, which are applications, make authorization requests using our Access APIs to the SGNL Policy Engine. The Policy Engine then renders an authorization decision based on the data within the graph directory and the policies configured, subsequently returning this decision to the control point or the application itself.

SGNL offers customers the Access API suite, which allows them to request authorization decisions, obtain detailed information about the assets that authorized principals can access, or identify the principals allowed to access a specific asset according to the configured policy. In the following section, we will examine each API within the Access API suite and discuss how developers can make calls to each API and the responses they can expect to receive.

Prerequisites

  • A SGNL Client
  • A SGNL User Account with Admin privileges
  • At least 1 system of record integrated to SGNL, containing principals and (optionally) assets that will be evaluated in access evaluations
  • (Optional) 1 or more policies that you want assigned to the integration
  • A Protected System configured with an Authentication Token. More information about configuring protected systems can be found on our Protected System Help page

SGNL Access API Suite

The following sections illustrate a scenario where John Doe, a support engineer, is assigned a Jira issue. The SGNL policies enforce that only users within the support group, and to whom an issue is assigned, are granted read and write permissions. Consequently, John Doe has read and write access to the Jira issue assigned to him, while access to all other Jira issues remains restricted.

Access API

At the heart of the SGNL Access API suite is the Access API, which addresses the following fundamental question that most organizations have with regards to access to protected assets:

Can this Principal perform this Action on this Asset?

Based on business context at the time of the request and configured policy, the Access API returns a clear “Allow” or “Deny” response.

cURL Request

curl --location 'https://access.sgnlapis.cloud/access/v2/evaluations' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <Authentication Token for the Protected System>' \
--data-raw '{
   "principal": {
       "id": "john.doe@acme.com"
   },
   "queries": [
       {
           "action": "read",
           "assetId": "Issue-314"
       },
       {
           "action": "write",
           "assetId": "Issue-314"
       },
       {
           "action": "read",
           "assetId": "Issue-1618"
       }
   ]
}'

cURL Response

{
   "decisions": [
       {
           "action": "read",
           "assetId": "Issue-314",
           "decision": "Allow"
       },
       {
           "action": "write",
           "assetId": "Issue-314",
           "decision": "Allow"
       },
       {
           "action": "read",
           "assetId": "Issue-1618",
           "decision": "Deny"
       }
   ],
   "evaluationDuration": 9,
   "issuedAt": "2023-11-08T02:53:56.562262241Z",
   "principalId": "john.doe@acme.com"
}

Sample Python Code

import requests
import json

# The API endpoint
url = "https://access.sgnlapis.cloud/access/v2/evaluations"

# The headers for the request
headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer <Authentication Token for the Protected System>'
}

# The JSON data payload
payload = json.dumps({
    "principal": {
        "id": "john.doe@acme.com"
    },
    "queries": [
        {"action": "read", "assetId": "Issue-314"},
        {"action": "write", "assetId": "Issue-314"},
        {"action": "read", "assetId": "Issue-1618"}
    ]
})

# Make the POST request
response = requests.post(url, headers=headers, data=payload)

# Check if the request was successful
if response.ok:
    # Process and print results
    response_data = response.json()
    for decision in response_data.get('decisions', []):
        print(f"{response_data['principalId']}, {decision['assetId']}, {decision['action']}, {decision['decision']}")
else:
    print(f"Failed to get a valid response, status code: {response.status_code}")

For those who prefer Node.js, SGNL provides an Node.js SDK. The SGNL Access API documentation can be found on our API Documentation Page

Asset Search API

The Asset Search API shifts the focus to the “what” instead of the “who”. It allows organizations to answer the following question:

What Assets can this Principal perform this Action on?

The Asset Search API is crafted for this purpose. It returns the set of organizational assets a principal (user or system) can access. The response also contains all attributes of the assets allowing the caller to take further action on the response.

cURL Request

curl --location 'https://access.sgnlapis.cloud/access/v2/search' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <Authentication Token for the Protected System>' \
--data-raw '{
   "principal": {
       "id": "john.doe@acme.comi"
   },
   "queries": [
       {
           "action": "read"
       }
   ]
}'

cURL Response

{
    "decisions": [
        {
            "action": "read",
            "assetAttributes": {
                "fields__assignee__displayName": "John Doe",
                "fields__assignee__email": "john.doe@acme.com",
                "fields__assignee__timeZone": "America/Los_Angeles",
                "fields__priority__id": "3",
                "fields__priority__name": "Medium",
                "fields__status__name": "Approved Active",
                "fields__status__statusCategory__name": "In Progress",
                "fields__summary": "Issue Summary goes here",
                "id": "10075",
                "key": "Issue-314",
                "self": "https://sgnl01.atlassian.net/rest/api/3/issue/10075"
            },
            "assetId": "Issue-314",
            "decision": "Allow"
        }
    ],
    "evaluationDuration": 561,
    "issuedAt": "2023-11-08T03:22:38.002077146Z",
    "principalId": "john.doe@acme.com"
}

The Python code for this API will be similar to the one shown for the Access API, with the main difference being the resource URL and response schema. The SGNL Asset Search API documentation can be found on our API Documentation Page

Principal Search API

Sometimes, organizations need to flip the perspective and ask the question:

Which Principals can perform this Action on this Asset?

The Principal Search API is crafted for this purpose. It returns the set of principals (users or systems) that are permitted by policy to perform the specified actions on the asset. The response also contains all attributes of the principal allowing the caller to take further action on the response.

cURL Request

curl --location 'https://access.sgnlapis.cloud/access/v2/search/principals' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <Authentication Token for the Protected System>' \
--data '{
   "queries": [{
       "action": "read",
       "assetId": "Jira-314"
      
   }]
}'

cURL Response

We see that two decisions have been returned by the Principal Search API. One for John Doe because there is a policy to allow users in the Engineering department read access to the Jira issue assigned to them. The second user allowed read access belongs to the Customer Support department.

{
    "decisions": [
        {
            "action": "read",
            "assetId": "Issue-314",
            "decision": "Allow",
            "principalAttributes": {
                "id": "00u3lfyyhvzycNQ7s1d7",
                "profile__department": "Engineering",
                "profile__email": "john.doe@acme.com",
                "profile__firstName": "John",
                "profile__lastName": "Doe",
                "profile__login": "john.doe@acme.com",
                "profile__managerId": "00u3l9uuweKaafPXr1d7",
                "status": "ACTIVE"
            },
            "principalId": "john.doe@acme.com"
        },
        {
            "action": "read",
            "assetId": "10075",
            "decision": "Allow",
            "principalAttributes": {
                "id": "00u4uuhxg6zEaMabV1d7",
                "profile__department": "Customer Support",
                "profile__email": "alejandro.bacong@acme.com",
                "profile__firstName": "Alejandro",
                "profile__lastName": "Bacong",
                "profile__login": "alejandro.bacong@acme.com",
                "status": "ACTIVE"
            },
            "principalId": "alejandro.bacong@acme.com"
        }
    ],
    "evaluationDuration": 472,
    "issuedAt": "2023-11-08T04:47:13.441399713Z"
}

The Python code for this API is similar to the one shown for the Access API, with the main differences being the resource URL, the body sent in the request and response schema. The SGNL Principal Search API documentation can be found on our API Documentation Page