Overview
Gluu is not really a great place to store policies. While you can express policies in Gluu Server RPT interception scripts, if you have more then a few policies, this approach does not scale. For a long time, we’ve recommended using a product that makes it easier to manage your policies. Axiomatics is one of the leaders in this field. This blog is an overview of a demo we did for the European Identity Conference. We will describe how we protected an API with the Gluu Gateway, and delegated policy evaluation to the Axiomatics Policy Server.
Prerequisites
- Axiomatic Policy server:
Returns authorization decisions based on attribute and contextual policies - Gluu ServerCommunity Edition 3.1.6 Acts as the UMA Authorization Server
- Gluu Gateway 2.0: Acts as the policy enforcement point–requiring the presence of certain UMA scopes to grant access to an API
- oxd UMA Client and Resource Server middleware API’s–installed as a dependency of Gluu Gateway
Configuration
Configure service and route The first step is to configure the service and route in Kong, which controls the basic proxying behavior to the upstream API. This can be done using the Gluu Gateway Admin UI. For more details, see the Gluu Gateway docs on adding routes.
Configure plugins The second step is to configure the Kong plugins. More details see the Gluu Gateway docs on adding a plugin.
Basically, you need to configure the API gateway to require the presence of an UMA RPT token with a certain scope before it proxies to a certain API. For this, Kong uses the gluu-uma-auth and gluu-uma-pep plugins. See the plugin docs for more details.Protect Resources In the Gluu Gateway admin Web UI, you can specify which URI patterns are protected. In our example, we used
/users/?? GET POST PUT DELETE
which is protected by thewith-claims
UMA scope. GG 2.0 supports wild card characters. The??
tells GG to protect all the resources which are in the/users
folder (path). See the Gluu Gateway docs on resource wildcards for more details.Configure UMA Scope in Gluu Server The Gluu Server needs to know about this scope. In our example, you’ll can add the scope
with-claims
using the Gluu Server Admin Console (i.e. oxTrust) and then associate it with theuma_rpt_policy
policy.- Call XACML PDP from Script
Update the script foruma_rpt_policy
to call the Axiomatic policy endpoint. Below is the sample code to call the Axiomatic Policy API in theauthorize
function ofuma_rpt_policy
policy. Note we send the Request, Resource, Action and Environment to the PDP for a policy decision.def authorize(self, context): country = context.getClaim("country") city = context.getClaim("city") parameters = """{ "Request": {"AccessSubject": {"Attribute": [{"AttributeId": "country","Value": "%s"}, {"AttributeId": "city","Value": "%s"}]}, "Resource": {"Attribute": [{"AttributeId": "document_id","Value": "companypolicy"}]}, "Action": {"Attribute": [{"AttributeId": "idaction","Value": "view"}]}, "Environment": {"Attribute": [{"AttributeId": "isAllowed","Value": true }]}} }""" % (country, city) creds = bytearray("client_id:secret",'utf-8') encodedCreds = Base64.getEncoder().encodeToString(creds); basicAuth = "Basic "+ encodedCreds url = URL("http://localhost:4080/authorize") conn = url.openConnection() conn.setDoOutput(True) conn.setRequestMethod("POST") conn.setRequestProperty("Content-type", "application/xacml+json") conn.setRequestProperty ("Authorization", basicAuth) conn.getOutputStream().write(bytearray(parameters, 'utf-8')) if conn.getResponseCode() != 200: print "Failed!!" print conn.getResponseCode() print conn.getResponseMessage() else: print "Success!!" print conn.getResponseCode() print conn.getResponseMessage() instr = conn.getInputStream() instrreader = InputStreamReader(instr) breader = BufferedReader(instrreader) output = breader.readLine() jsonResult = "" while output != None: if output != None: jsonResult += output output = breader.readLine() break print jsonResult conn.disconnect() jobj1 = JSONObject(jsonResult) jarr1 = jobj1.get("Response") jobj2 = jarr1.get(0) decision = jobj2.get("Decision") print decision if decision == "Permit": print "Axiomatics Authorization successful..." return True print "Axiomatics Authorization failed..." return False
Conclusion
Now the web page or API is protected, and requests will only be allowed to users from a certain city and country as defined by policies in Axiomatics! How to define policies in Axiomatics is out of scope for this disucssion, but see their website and documentation for more info.