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.
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 the with-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 the uma_rpt_policy
policy.
uma_rpt_policy
to call the Axiomatic policy endpoint. Below is the sample code to call the Axiomatic Policy API in the authorize
function of uma_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
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.