OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.


Help: OASIS Mailing Lists Help | MarkMail Help

xacml message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]

Subject: Attributes of relations code sample


I have written a small sample for the attributes of relations discussion.

The example has contracts for customers who can access resources from locations specified in the contracts. Each contract may have multiple locations, but only one resource. The contract also has a limit for the number of accesses purchased and accesses are logged into an audit log.

An access policy would like to check that there exists a contract for the customer and resource in question, such that the contract has not been spent up and the location from where the access is done is permitted by the contract.

I did this as a code sample, using the "PIP approach" for attributes of relations. I have pasted the code at the end of this email. I ran the code sample using PostgreSQL (an open source database engine), so you may need to tweak it a bit if you port it to something else.

The tables look like this:

Table contract:
 contract_id |   customer   |  resource   | use_limit

Table contract_locations:
 contract_id | allowed_location

Table usage:
 contract_id | log_entry

The program will create some random records. The parameters, as they are now create about 700k something usage records.

At the end of the program you will find an example query for how a context handler can query a PIP using the customer, resource and location as keys from the XACML request.

This works quite well and the query returns the number of contracts which exist. It could be modified also to return one of the contract ids instead, which might be more useful.

This is a small and simple example, but I think this is already complex enough to break the iterator approach proposed by Steven. The iterators will construct the cross product using higher order functions, leading to millions of entries to traverse in the PDP.

Steven, could you have a look at the example and say if you think I am mistaken. Also, what will the iterators look like in this case? Did you implement a PoC already? What kind of performance do you see?

I believe that any solution to this problem has to be something which can be executed at the data source, so that the data does not need to be pulled. Also, it would be good if the language is something which can be easily translated into something like SQL for implementation. However, a special language would have the benefit of visibility, though it would be a lot of design effort in duplicating something which already works.

With apologies to Mohammad, I have not yet had the time to read the SQL profile proposal. I will do so asap.

Best regards,

package com.axiomatics.demo.relations;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
import java.util.Random;

public class CreateData {

    private static final String[] locations =
        {"London", "Tokyo", "New York", "Paris", "Milan"};

    public static void main(String[] args) throws Exception {
        String url = "jdbc:postgresql://localhost/relationsdb";
        Properties props = new Properties();
        Connection conn = DriverManager.getConnection(url, props);

        // Create tables

        String table_contract = "CREATE TABLE contract ("
                + "contract_id INTEGER,"
                + "customer VARCHAR(20),"
                + "resource VARCHAR(20),"
                + "use_limit INTEGER)";
        PreparedStatement ps0 = conn.prepareStatement(table_contract);
        try {
        } finally {

        String table_usage = "CREATE TABLE usage ("
                + "contract_id INTEGER, log_entry VARCHAR(20))";
        ps0 = conn.prepareStatement(table_usage);
        try {
        } finally {

String table_contract_locations = "CREATE TABLE contract_locations ("
                + "contract_id INTEGER, allowed_location VARCHAR(10))";
        ps0 = conn.prepareStatement(table_contract_locations);
        try {
        } finally {

        // Create data

        int locationSelector = 0;

        // These determine the size of the data set
        int numContracts = 10000;
        int maxLimit = 200;

        // These determine the spread in the random data created
        int numCustomers = numContracts / 10;
        int numResources = 20;

        Random random = new Random(System.currentTimeMillis());

        for(int contract = 0; contract < numContracts; contract++) {
            int limit = random.nextInt(maxLimit);
            String customer = "customer_" + random.nextInt(numCustomers);
            String resource = "resource_" + random.nextInt(numResources);

            String createContract = "INSERT INTO contract (contract_id," +
                    " customer, resource, use_limit) VALUES (?,?,?,?)";
            PreparedStatement ps1 = conn.prepareStatement(createContract);

            try {
                ps1.setInt(1, contract);
                ps1.setString(2, customer);
                ps1.setString(3, resource);
                ps1.setInt(4, limit);

            } finally {

            int numUseForContract = random.nextInt(limit+1);
            // 50% probability that the contract has been used maximum
            // number of times
            if(random.nextInt(2) == 0) {
                numUseForContract = limit;
for(int useCount = 0; useCount < numUseForContract; useCount++) {

String createUsegeRecord = "INSERT INTO usage (contract_id," +
                        " log_entry) VALUES (?,?)";
PreparedStatement ps2 = conn.prepareStatement(createUsegeRecord);

                try {
                    ps2.setInt(1, contract);
                    ps2.setString(2, "Used: " + useCount);

                } finally {


            // For simplicity add three locations for each contract
            for(int i = 0; i < 3; i++) {
String createUsegeRecord = "INSERT INTO contract_locations (contract_id," +
                        " allowed_location) VALUES (?,?)";
PreparedStatement ps2 = conn.prepareStatement(createUsegeRecord);

                try {
                    ps2.setInt(1, contract);
ps2.setString(2, locations[locationSelector%locations.length]);

                } finally {

            if(contract%(numContracts/1000) == 0) {
System.out.println(((double) contract)/numContracts*100.0 + "% done");

// Here is a sample query to see how many a valid contracts there exist
        // for customer_0 in London for resource_0
        String customer = "customer_0";
        String resource = "resource_0";
        String location = "London";
        String query = "select count(distinct contract.contract_id)" +
                "FROM contract, contract_locations where" +
                " contract.contract_id=contract_locations.contract_id" +
                " and contract_locations.allowed_location=?" +
                " and contract.customer=? and contract.resource=?" +
                " and (select count(*) from usage" +
" where usage.contract_id=contract.contract_id)<contract.use_limit";
        PreparedStatement ps2 = conn.prepareStatement(query);

        try {
            ps2.setString(1, location);
            ps2.setString(2, customer);
            ps2.setString(3, resource);

            ResultSet rs = ps2.executeQuery();

            int result = rs.getInt(1);
System.out.println("The number of valid contracts is " + result);
        } finally {

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]