Building an ABAC Policy Using APIs and Java SDK From Machina Tools
Everything you need to get started building your own ABAC policy.
Join the DZone community and get the full member experience.
Join For Free
Determining what data a user, application, or device can access can be one of the most important decisions an organization faces. You don’t have to be a healthcare or financial institution to be responsible for customer data. But to maintain customer trust, your organization may want to treat all customer data as such.
The data access problem is complex. Elements of policy may be driven by IT, human resources, legal, or even by finance. Policies might be enforced at different points depending on where data travels and how it is consumed. Policies might be enforced at the network layer through remote-access systems, at the database layer, within cloud infrastructure, or at endpoints like email and files. Most of these platforms inherently implement a permissive security policy.
The issue developers face is how to protect data consistently and uniformly across applications, repositories, workloads, networks, and infrastructure. In this post, I’ll show how in Java you can define key attributes that can be used by policy rules to control access to data. I’ll also walk through methods for writing policy rules in XACML and show how those rules can be passed through API calls to populate policies in your environment.
You may also like: S3 and AWS Java SDK 2.0: Look Before You Leap.
Describing Data Using Key Attributes
Key attributes are fundamental to controlling access to data through policy. You can think of attributes as "tags" that you can associate with data objects. These attributes are generally programmer-defined and can be used by policy rules at the policy enforcement point (PEP) to allow or deny access to data. For example, you can define attributes that indicate:
Data classification can be Confidential, Restricted, or Top Secret.
Data includes personally identifiable information (PII), such as social security number, phone number, employee salary, and so on.
Data can only be accessed from a specified location.
Embargo or expiration date and time (date and time before which data should not be accessible, and date and time after which data should not be accessible).
Setting Attributes Using the Java SDK
SDKs in Ionic's Machina Tools support widely used languages including Java, Javascript, C/C++, C#, and Python. Using these SDKs, you can map attributes to data objects that are associated with keys with just a few lines of code. Let’s examine how you might implement this in Java.
// define fixed attributes
KeyAttributesMap fixedAttributes = new KeyAttributesMap();
fixedAttributes.put("data-type", asList("Finance"));
fixedAttributes.put("region", asList("North America"));
// define mutable attributes
KeyAttributesMap mutableAttributes = new KeyAttributesMap();
mutableAttributes.put("classification", asList("Restricted"));
mutableAttributes.put("designated-owner", asList("joe@hq.example.com"));
// create new key with fixed and mutable attributes
CreateKeysResponse.Key createdKey = null;
try {
createdKey = agent.createKey(fixedAttributes, mutableAttributes).getKeys().get(0);
} catch(IonicException e) {
System.out.println(e.getMessage());
System.exit(1);
}
Here, we’ve created two fixed attributes that remain constant and two mutable attributes that you can update throughout the application’s lifecycle. The fixed attributes designate that a data-type
is associated with financial data and is related to a region
, North America
. The example passes these attributes as parameters to the createKey()
method.
At this point, Machina will create a new key, map the defined attributes to the key and return it, along with an identifier that allows you to reference the key later. As an aside, you can also create your own identifier to reference the key and its related attributes.
Now, when an application attempts to access data associated with that key, policy rules defined in Machina will evaluate these attribute-value pairs in the context of a data policy and make a decision to release or deny access.
Once you’ve created your attributes, you’ll want to test them against a policy. Machina offers two methods for creating policy rules:
Declaratively, using the Data Policy Builder in Machina Console.
Programmatically, by passing policy rules through the request body of an API call.
I’ll examine both methods in a moment, but first, let’s first look at how you might construct policy rules in XACML and why.
XACML and Attribute-Based Access Controls
Recognizing the data access control problem, OASIS set out to create a common policy language that would allow organizations of enterprise-scale to manage the enforcement of all elements of their security policy in all components of their information systems. That language is eXtensible Access Control Markup Language (XACML).
XACML is an XML schema that standardizes the attribute-based access control (ABAC) model. Unlike role-based access control (RBAC) that assigns users to roles and provides access through those roles, ABAC combines various attributes together within policy rules to control access at a very granular level.
Those attributes can be anything from a location, a condition or resource, to a type of data, a device, or an API endpoint. This allows for an infinitely granular level of control over not only who or what application can access data, but when, where and under what conditions.
Elements of a Policy
The three properties of a policy are:
A target.
A rule-combining algorithm-identifier.
A set of rules.
When authoring policy to support data protection, Ionic recommends that you define policies around characteristics of data and write rules for accessing that type of data. Let's start with an example of a policy written in plain English:
"Ensure that data classified as sensitive or very-sensitive is only accessed in country Switzerland."
For readability and ease of processing later, let’s convert that XML into JSON. The policy might look something like this:
{
"policyId": "sensitive-local-only",
"description": "country must be Switzerland for sensitive data access",
"ruleCombiningAlgId": "first-applicable",
"target": {
"anyOf": [
{
"allOf": [
{
"matchId": "string-at-least-one-member-of",
"args": [
{ "value": "sensitive" },
{ "value": "very-sensitive" },
{ "category": "resource", "id": "classification" }
]
}
]
}
]
},
"rules": [
{
"ruleId": "rule1",
"effect": "Permit",
"description": "Permit when located in country Switzerland ",
"condition": {
"functionId": "string-at-least-one-member-of",
"args": [
{ "value": "XYZ" },
{ "category": "environment", "id": "location-country" }
]
}
},
{
"ruleId": "rule2",
"effect": "Deny",
"description": "Deny otherwise",
"condition": {}
}
]
}
The construction of simple or complex conditions using the functions provided by Machina policy applied against the attributes available in a decision request is what makes XACML and the policy engine flexible and powerful.
Using the Policy Builder
Both developers and policy administrators can create these policy rules using the Data Policy Builder in Machina Console. The Data Policy Builder provides an easy-to-use GUI interface for building policy rules, as shown below.
To get you started, we’ve created a quickstart guide to the Data Policy Builder. The guide shows how to use the Machina Console to create a Group, add a user to that group, and create and test a data policy.
Machina Tools — APIs
I started with the SDKs because they offer the simplest means for introducing data policies into your application. During development you can use Machina Console to build and test your policy rules. However, there may be times when you need to populate policy packages directly into your environment. That’s where the Policies API comes in.
The Policies API allows developers to construct policy rules using JSON, and pass the resulting object to Machina via an API call. This latter approach allows you to populate policies into your environment programmatically.
The general format for the REST API is:
POST /v2/{tenant_id}/policies
The REST call will require that you insert a Base_url (e.g., https://api.ionic.com) at the beginning of the string. The request header for this API takes an authorization token and a content type at a minimum. The request body is a JSON object that defines the policy, as I have done above. Putting it together into a POST request might look something like:
POST https://api.ionic.com/v2/555555555555555555555555/policies
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
Content-Type: application/json
{
"policyId": "sensitive-local-only",
"description": "country must be XYZ for sensitive data access",
"ruleCombiningAlgId": "first-applicable",
"target": {
"anyOf": [
{
"allOf": [
{
"matchId": "string-at-least-one-member-of",
"args": [
{ "value": "sensitive" },
{ "value": "very-sensitive" },
{ "category": "resource", "id": "classification" }
]
}
]
}
]
},
"rules": [
{
"ruleId": "rule1",
"effect": "Permit",
"description": "Permit when located in country XYZ",
"condition": {
"functionId": "string-at-least-one-member-of",
"args": [
{ "value": "XYZ" },
{ "category": "environment", "id": "location-country" }
]
}
},
{
"ruleId": "rule2",
"effect": "Deny",
"description": "Deny otherwise",
"condition": {}
}
]
}
As previously noted, you can use the Data Policy Builder to generate the XACML functions for you. You can then cut and paste the resulting JSON policies from the console output and paste directly into the request body of your API calls.
Use Cases
Now that you’ve seen the various methods you can use to protect data using Java and ABAC, let’s look at some use cases you can apply these methods to. You’ll find all of the source code for these sample apps on Github.
Structured Data
Protecting structured data in databases is a challenging problem. This Java application shows how you can add data access controls to any JVM application using JDBC and the Java SDK.
Cloud Storage
How do you protect data at rest within one of the big three Cloud Service Providers (CSPs)?
The Cloud Copy Tool is a Java demo tool showing how you can move unprotected data stored on AWS, GCS, or Azure and protect and store that data as it is copied to one of the other cloud service providers.
HIPAA and PHI
Healthcare organizations, by and large, withhold disclosing protected health information (PHI) outside of their own clinics as a means of complying with HIPAA requirements. In a future post, I’ll show how developers can allow or deny access to PHI based on user roles that include the patient, doctor, and healthcare insurer. Data is stored in a DynamoDB running on AWS.
Lambda Function for Protecting PII
BigID is a tool that scans your data and reports occurrences of personally identifiable information (PII) in your data sets. This AWS Lambda function takes the results of a BigID scan and applies data protection controls based on data residency, data sensitivity, and personal data attribute findings. Thus, the Lambda function provides an example of protecting data using consistent policy enforcement across multiple deployment architectures.
Machine Data and Log4j
As we know, machines are capable of generating petabytes of log data that may include passwords and other sensitive data. This Apache Log4j file appender encrypts log messages as they are written to the file output stream.
GDPR
Likewise, EU General Data Protection Regulations (GDPR) obligate significant operational changes for companies to come into compliance. Learn how with this informative blog post.
Summary
Mandates like GDPR exemplify how fluid policy can be. Machina allows you to centralize policy decision and enforcement points so that policy changes can be effected at a single enforcement point. This centralization also means developers can control data access without having to hard code policy into their applications. Developers can simply tag data with metadata that can be interpreted by policy rules.
Once described, that data remains protected wherever it travels. When an application attempts to access that data, Ionic Machina will evaluate rules based on the attributes you create, and a real-time decision will be made to allow or deny access.
Further Reading
Opinions expressed by DZone contributors are their own.
Comments