Implementing Adaptive Access Management with OPA

Increase economies of scale by using human-readable policies and data from business systems of record

Aldo Pietropaolo, Director of Solutions Engineering, SGNL
March 1, 2023
Follow us on

Open Policy Agent (OPA) is an open-source component that is used to add fine-grained authorization capabilities to various components including applications. It implements access control based on policies written in a language called Rego. Data required to determine the access decision is typically obtained through the context of the request and locally available data on the compute node running OPA.

This architecture is a step forward in access management. It brings a more expressive policy language (Rego) and enables fine-grained access control. However, this architecture does not inherently provide centralized policy management and cannot make decisions based on data elsewhere in the organization. It also does not provide a way to audit all access decisions centrally. SGNL complements OPA by enabling these features.

SGNL provides just-in-time access by building a dynamic graph directory through continuous data ingestion from systems of record. Using human readable policies, access control is enforced consistently and easily across internal and SaaS apps. The SGNL solution also enables comprehensive policy and compliance audits. By integrating OPA with SGNL, you can readily leverage all these features in your existing OPA-based applications.

With OPA and SGNL, you can extend the power of OPA with enterprise-scale continuous adaptive access management.

How Does OPA Work

OPA is straightforward to implement in a distributed “in application Go library”, sidecar, or server model. OPA takes in a query with JSON key/value pairs, executes the Rego policy, and returns a decision.

OPA enables developers to decouple the rules and policy and externalize authorization decisions away from an application. While this idea is excellent, it is still challenging to scale, monitor, and control in an enterprise environment.

Benefits of Using SGNL For OPA

Here are the benefits of using SGNL with OPA:

  1. Business Data Driven Continuous Authorization. Any changes recorded in an organization’s business systems of record are automatically and rapidly reflected in access decisions.

  2. Real-time Audit and Comprehensive Reporting. All access decisions are logged centrally with reasons for granting or denying access.

  3. Centralized Human Readable Policies. Human readable policies using reusable snippets enable organizations to scale policies without losing manageability.

  4. Consistent Decisions Across All Apps. Any application enforcing access using SGNL provides the same decisions consistently based on managed human readable policy along with the context of the request.

  5. Contextual Authorization Decisions. Any access decision is determined considering the context of the request. If the same user using the same app is requesting access to different data, the request may be allowed or denied based on the user’s need or business justification to access the specific data.

How Does SGNL Work

SGNL continuously ingests authorization data to a central repository via resilient and performant connectors. Once data is available, users can quickly author human-readable policies for granting or denying access to applications and sensitive data. By implementing a centralized approach, SGNL provides consistency in centralized policy management, audit logging, and reporting across all assets an organization desires to protect. These capabilities ( and more) comprise SGNL’s enterprise-ready just-in-time access management platform.

Instead of having to write Rego rules to evaluate policy, you simply select policy snippets from the user interface and graphically build a human-readable policy.

Example of an actual executable policy in the SGNL UI:

In this policy, SGNL evaluates whether a user in the engineering department has an active ServiceNow case assigned to write to an AWS S3 bucket. This human-readable policy is evaluated when an OPA instance calls the SGNL Access Service with an authorization query. You will see an example of the OPA Rego policy in the integration section of this article.

OPA and SGNL Integration

We have integrated OPA with SGNL for externalizing complex relationship-based access control decisions to the SGNL policy engine. In this configuration, SGNL is ingesting data from Okta and ServiceNow. SGNL automatically establishes the appropriate relationships between Okta users, ServiceNow users, and active assigned cases.

SGNL and OPA Architecture.

With SGNL, you can integrate your sources of record and synchronize the authorization data you need to evaluate human-readable policies. This diagram shows an example of SGNL ingesting data from HRIS, IDP, AD/AAD, and SalesForce. In this article, we also use ServiceNow to ingest data on active and assigned cases to any user.

The OPA Rego policy implements the httpd.send built-in function to send an authorization request to SGNL for policy evaluation. The SGNL Access Service response looks like the following:

{
  "decisions": [
    {
      "action": "Write",
      "assetId": "{{asset id}}",
      "decision": "Deny"
    }
  ],
  "evaluationDuration": "6.075625ms",
  "issuedAt": "2023-02-28T20:35:50.760129172Z",
  "principalId": "{{principal id}}"
}

The OPA engine interprets the Deny or Allow decisions and returns the appropriate Rego policy evaluation result (true/false). See the Rego policy below for more details.

Sample Code

This Go example shows how to integrate OPA as a library and call the SGNL API using the http.send built-in function.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/open-policy-agent/opa/rego"
)

func main() {

	// Set Go context for Rego
	ctx := context.Background()

	// Construct a Rego object that can be prepared or evaluated.
	r := rego.New(
		rego.Query("data.example.authz.allow"),
		rego.Load([]string{os.Args[1]}, nil))

	// Create a prepared query that can be evaluated.
	query, err := r.PrepareForEval(ctx)
	if err != nil {
		log.Fatal(err)
	}

	// Input map to evaluate against policy.
	// There is no input since we are delegating
	// authorization decisions to SGNL.

	input := map[string]interface{}{
		"values": map[string]interface{}{},
	}

	// Evaluate OPA policy through SGNL Access
	// Service API and get the results.

	results, err := query.Eval(ctx, rego.EvalInput(input))

	// The Rego results set contains a helper function to
	// determine if there is a true/false in expression evaluation.

	if err != nil {
		log.Fatal(err)
	}

	if !results.Allowed() {
		fmt.Println("SGNL:OPA Authorization decision is Deny.")
	} else {
		fmt.Println("SGNL:OPA Authorization decision is Allow.")
	}
}

Sample Rego Policy

This Rego policy calls the SGNL Access Service with a principal, asset, and action. There is no need to send an input document. SGNL holds all data and relationships centrally.

package sgnl.authz

default allow := false

allow {
	response := http.send({
		"method": "POST",
		"url": "{{SGNL access service URL}}",
		"tls_use_system_certs": true,
		"headers": {
			"Authorization": "Bearer {{SGNL token}}",
			"Content-type": "application/json",
		},
		"body": {
			"principal": {
				"id": "{{principal id}}"
			},
			"queries": [{
				"assetId": "{{asset Id}}",
				"action": "Write"
			}]
		},
		"force_cache": false,
		"force_json_decode" : true
	})
	response.body.decisions[0].decision = "Allow"
}

Once the call to the SGNL Access Service API completes, the Rego policy engine checks to see if the SGNL response is an allow or deny. The SGNL decision is in the body of the HTTP response object and the JSON decisions array.

Conclusion

Using this SGNL and OPA integration, developers can now leverage a centralized access management policy platform for making complex just-in-time authorization decisions using continuously updated identity, application, and business data. This approach reduces the effort to develop and maintain complex applications, infrastructure, and data access policies.

SGNL also provides central audit logs and access policy debugging and testing capabilities to make policy authoring easier.

Best practices and the latest security trends delivered to your inbox