Back to all guides
ContX IQ

ContX IQ guide

What is needed to configure ContX IQ: CIQ policies, CIQ Knowledge Queries and CIQ Execution Queries.

Deliver the right data, at the right time, in the right context.

The feature involves policies, knowledge queries and execution queries.

Creating a CIQ Policy:

An authorization admin defines the rules and mechanisms for dynamically upserting and retrieving data, ensuring that users, systems, and services are granted access in the right context and at the right time. They select specific nodes and relationships, then apply static or partial filters to them. Crucially, one node must always be designated as the Subject node, though different policies can have different Subject nodes. Filters aren't required for every node or relationship. These chosen nodes, relationships, and their filters collectively define the criteria for queries within the policy.

A static filter is a property filter on a node or relationship where the target value is already provided, e.g., group.property.status = 'active' , while partial filters are filters where the target value is provided at evaluation time, e.g., user.property.email = $user_email.

A policy is restricted to a single subject type. If there are 2 subjects (e.g., Person and _Application), 2 policies will need to be created.

Creating a Knowledge Query:

Queries are built using a policy as a guide. Think of the policy as defining what's required (i.e., how the subject and resources should be connected to each other in the graph, and the filters on those nodes and relationships) and what's allowed, while the query tells the system what to do (e.g., retrieve/create/update/delete data). An administrator first picks a policy, then defines how to read, add, or remove data according to the policy. Finally, this combined query and policy are converted into Cypher code.

CIQ Policies and CIQ Knowledge queries are configuration which can be created with Terraform (indykite_authorization_policy and indykite_knowledge_query resources on Terraform) or REST Api (openapi documentation).

They need ServiceAccount credentials, created in the IndyKite Hub or the REST Config API.

Schema example

CIQ Policy Syntax

{
  "meta": {
    "policy_version": "1.0-ciq"
  },
  "subject": {
    "type": "<string>"
  },
  "condition": {
    "cypher": "<string>",
    "filter":
    [{
      "operator": "<string>",
      "attribute" : "<string>",
      "value": "<any>",
      "operands": [
        {
          "operator": "<string>",
          "attribute": "<string>",
          "value": "<any>",
          "operands" : [{...}]
        }
      ]
    }],
    "token_filter" : {
      "operator" : "<string>",
      "attribute" : "<string>",
      "value": "<any>",
      "operands" : [
        {
          "operator": "<string>",
          "attribute": "<string>",
          "value": "<any>",
          "operands" : [{...}],
          "advice" : {
            "error" : "<string>",
            "error_description" : "<string>"
          }
        }
      ],
      "advice" : {
        "error" : "<string>",
        "error_description" : "<string>"
      }
    }
  },
  "allowed_upserts": {
    "nodes": {
      "existing_nodes": [
        "<string>"
      ],
      "node_types": [
        "<string>"
      ]
    },
    "relationships": {
      "existing_relationships": [
        "<string>"
      ],
      "relationship_types": [
        {
          "type": "<string>",
          "source_node_label": "<string>",
          "target_node_label": "<string>"
        }
      ]
    }
  },
  "allowed_deletes": {
    "nodes": ["<string>"],
    "relationships": ["<string>"]
  },
  "allowed_reads": {
    "nodes": [
      "<string>"
    ],
    "relationships": [
      "<string>"
    ],
    "aggregate_values": [
      "<string>"
    ]
  }
}
  1. meta: The metadata for the policy.
    1. policy_version: The policy syntax version. The current version is 1.0-ciq. (Nothing to do with a version of a policy created by a customer.)
  1. subject: The subject for the policy.
    1. type: The node type for the subject.
    When a new Application with new credentials is created, _Application and _AppAgent nodes are created in the IKG. This allows the use of the _Application as an authenticated subject. When the subject type in the policy is "_Application", we add a parameter in the filter with attribute: subject.external_id and value: $_appId (reserved value), which matches the external_id property of the application node in the IKG.
  1. condition: The condition (requirements) for the policy to be satisfied.
    1. cypher: The Cypher query defines the relevant nodes and the relationships that connect them. It may consist of MATCH, OPTIONAL MATCH, WHERE, and WITH clauses, and WITH clauses may include aggregate functions (for example, COLLECT({username: usernameProp.value}) AS usernames). These clauses specify the graph patterns to match and any filters applied to them, including inline property filters such as MATCH (user:User {id: 1234}), where {id: 1234} acts as an inline constraint. Each node and relationship used in the query must be assigned a variable name if it needs to be referenced later; any element without a variable name cannot be referenced elsewhere in the CIQ query.
    1. filter
      1. operator: The operator for the partial/static filter. The following operators are supported:
        • NOT: Negates the nested filter in operands. operands must contain exactly one entry.
        • AND: Computes a conjunction of the nested filters in operands. operands must contain one or more entries.
        • OR: Computes a disjunction of the nested filters in operands. operands must contain one or more entries.
        • =: Checks that attribute EQUALS value.
        • <>: Checks that attribute is NOT EQUAL to value.
        • >: Checks that attribute is GREATER THAN value.
        • <: Checks that attribute is LESS THAN value.
        • >=: Checks that attribute is GREATER THAN OR EQUAL to value.
        • <=: Checks that attribute is LESS THAN OR EQUAL to value.
        • IN: Checks the attribute is IN value (e.g., value in array).
        • =~: Checks the attribute matches the string regex provided in value.
        • STARTS WITH: Checks the attribute is a string value starting with value.
        • ENDS WITH: Checks the attribute is a string value ending with value.
        • IS NULL: Checks the attribute is not present or NULL.
        • IS NOT NULL: Checks the attribute is present and NOT NULL.
      1. attribute: The attribute for comparison for the partial/static filter. attribute must be omitted if operator is either of AND, OR, or NOT. attribute follows the naming convention:
        • $token.<property name>: A property on the requestor token (e.g., $token.acr).
        • <variable name>.<attribute name>: An attribute on a resource node or a relationship (e.g., user.external_id).
        • <node variable name>.property.<attribute name>: An attribute on a node (e.g., user.property.email).
        • <node variable name>.property.<attribute name>.metadata.<metadata attribute name>: A metadata attribute for a property node (e.g., user.property.email.metadata.source).
      1. value: The value for the partial/static filter. value can either be hardcoded or set as a variable. If value is set as a parameter, then it must be a name starting with $ (e.g., "$username"). value must be omitted if operator is either of AND, OR, or NOT.
      1. operands: Array of nested filters. operands must be omitted if it is empty.
    1. token_filter: The token filter works similar to the filter above, however this filter only works with $token values.
      1. operator, attribute, value, operands: See above
      1. advice: The step up advice from the individual filters that were not satisfied for the token filter. It is based on the optional Advice of Condition structure. The advice is returned in the response body context to the called with the Www-Authenticate header with advice error "insufficient_user_authentication".
        1. error: The name of the error for the individual filter.
        1. error_description: The description for the error.
  1. allowed_upserts: The upserts allowed by the derived queries. allowed_upserts must be omitted if it is empty.
    1. nodes: The nodes to upsert. nodes must be omitted if it is empty.
      1. existing_nodes: The list of node variables, that were specified in cypher above, that the derived queries can update. Since the node variable is specified in the cypher, it must already exist in the IKG. existing_nodes must be omitted if it is empty.
      1. node_types: The array of node labels specifying the types of nodes that the derived queries can create in the IKG. node_types must be omitted if it is empty.
    1. relationships: The relationships to upsert. relationships must be omitted if it is empty.
      1. existing_relationships: The list of relationship variables, that were specified in cypher above, that the derived queries can update. Since the relationship variable is specified in the cypher, it must already exist in the IKG. existing_relationships must be omitted if it is empty.
      1. relationship_types: The array or relationship types that the derived queries can create in the IKG. relationship_types must be omitted if it is empty.
        1. type: The type of the relationship.
        1. source_node_label: The label for the source node for the relationship.
        1. target_node_label: The label for the target node for the relationship.
  1. allowed_deletes: The deletes allowed by the derived queries. allowed_deletes must be omitted if is is empty.
    1. nodes: The list of nodes (using names like person, person.*), that are mentioned in cypher above, that the derived queries can delete from the IKG. person.* is the wildcard.
    1. relationships: The list of relationships (like r1, r1.*), that are mentioned in cypher above, that the derived queries can delete from the IKG. r1* is the wildcard.
  1. allowed_reads: The nodes and relationships that derived queries can present as a result.
    1. nodes: The list of node variables, specified in cypher above, that the derived query can present as a result.
      Example: "allowed_reads": { "nodes": [ "subject", "subject.*", "person", "person.*" ] }
      It means that in the CIQ Knowledge Query you will be able to use: either subject, person or subject.something, person.property.something. person.* is the wildcard.
      So for example: "nodes": [ "subject", "person" ] }
    1. relationships: The list of relationship variables, specified in cypher above, that the derived query can present as a result.
    1. aggregate_values: The list of variables introduced through aggregate functions in the cypher above, that the derived query can present as a result.

CIQ Knowledge Query Syntax

{
  "filter":
  {
    "operator": "<string>",
    "attribute": "<string>",
    "value": "<any>",
    "operands": [
      {
        "operator": "<string>",
        "attribute": "<string>",
        "value": "<any>",
        "operands" : [{..}]
      }
    ]
  },
  "upsert_nodes": [
    {
      "name": "<string>",
      "type": "<string>",
      "external_id": "<string>",
      "properties": [
        {
          "type": "<string>",
          "value": "<any>",
          "metadata": [
	          {
		          "type": "<string>",
		          "value": "<any>"
	          }
          ]
        }
      ]
    }
  ],
  "upsert_relationships": [
    {
      "name": "<string>",
      "source": "<string>",
      "target": "<string>",
      "type": "<string>",
      "properties": [
        {
          "type": "<string>",
          "value": "<any>"
        }
      ]
    }
  ],
  "delete_nodes": ["<string>"],
  "delete_relationships": ["<string>"],
  "nodes": ["<string>"],
  "relationships": ["<string>"],
  "aggregate_values": ["<string>"]
}

  1. filter: Similar to the filter for the policy. See above for details. filter must be omitted if it is empty.
  1. upsert_nodes: The array of nodes to upsert. upsert_nodes must be omitted it is empty.
    1. name: The variable name for the node to upsert. If updating an existing node in the IKG (i.e., the node that was mentioned in the policy cypher), then name should match the variable name in the policy cypher. If creating a new node in the IKG, then name must be distinct from other variables names mentioned in the policy and query.
    1. label: The label for the node to upsert.
    1. external_id: The external_id for the node. external_id can be hardcoded in the query or parameterized (variable name staring with $). external_id must be present if creating a new node in the IKG, otherwise it must be omitted.
    1. properties: The array of properties for the node to upsert. properties must be omitted if it is empty.
      1. type: The name of the type of the property. type must be hardcoded.
      1. value: The value for the property. value can either by hardcoded to parameterized (variable name starting with $).
  1. upsert_relationships: The array of relationships to upsert. upsert_relationships must be omitted if it is empty.
    1. name: The variable name of the relationship to upsert. If updating an existing relationship in the IKG (i.e., the relationship was mentioned in the policy cypher), then name should match the variable name in the policy cypher. If creating a new relationship in the IKG, thenname must be distinct from other variables names mentioned in the policy and query.
    1. source: The node variable name for the source node of the relationship. source must be empty if updating an existing relationship.
    1. target: The node variable node for the target node of the relationship. target must be empty if updating an existing relationship.
    1. type: The type of the relationship. type must be empty if updating an existing relationship.
    1. properties: The array of properties for the relationship to upsert. properties must be omitted if it is empty.
      1. type: The name of the type of the property. type must be hardcoded.
      1. value: The value for the property. value can either by hardcoded to parameterized (variable name starting with $).
      1. metadata: The array of property metadata. metadata must be omitted if it is empty.
        1. type: The name of the type of metadata. type must be hardcoded.
        1. value: The value for the metadata. value can either be hardcoded or parameterized (variable name starting with $).
  1. delete_nodes: Array of nodes variable names for the nodes the query will delete. The entries in delete_nodes must match node variables names in the policy cypher (like car, car.property.model).
  1. delete_relationships: Array of relationship variable names for the relationships the query will delete. The entries in delete_relationships must match relationship variable names in the policy cypher (like r1, r1.status).
    The following properties cannot be deleted: _service, create_time, external_id, id, type, update_time.
  1. nodes: Array of node variables names that the query will return as a result. The entries in nodes must match node variables names mentioned in the policy cypher or names in upsert_nodes.
  1. relationships: Array of relationship variable names that the query will return as a result. The entries in relationships must match relationship variable names mentioned in the policy cypher or names in upsert_relationships.
  1. aggregate_values: Array of variables introduced through an aggregate function in the policy cypher that the query will return as a result.

CIQ Execution Query Syntax

The CIQ Execution Queries are REST API requests, referencing the id or the name of the stored CIQ Knowledge Query. A request pass the required input parameters, representing the values for each partial filter variable in the CIQ Knowledge query and the CIQ policy, and the CIQ Knowledge gid or name. The request will convert the CIQ Knowledge query and the CIQ policy into a cypher, execute it and return the result. The result contains the values for the variables defined in nodes and relationships in the CIQ Knowledge Query.

Endpoint: POST /contx-iq/v1/execute

They need AppAgent credentials created in the IndyKite Hub, using the REST endpoints or using Terraform for your Project / Application.

APIKey authentication with Key: X-IK-ClientKey and value: AppAgent credentials token.

If the subject type in the policy is anything other than "_Application", then the request also needs a third party bearer token.

When the subject is _Application, the $_appId input does not need to be provided in the CIQ Execution Query and is automatically assigned the subject.external_id value (external_id property in the Application node).

Request example:

{
  "id": "knowledge_query_gid",
  "input_params": {
   "subject_external_id": "subject_external_id_value",
   "token_sub": "token_sub_value",
   "license_number": "license_number_value"
  }
}

Response example:

{
  "data": [
    {
      "nodes": {
        "company.external_id": "companyParking",
        "payment.external_id": "cb123",
        "subject.external_id": "subject_external_id_value"
      }
    },
    {
      "relationships": {
       .....
      }
    }....
  ]
}