OpenConext implementation of a XACML based PDP engine for access policy enforcement including a GUI for maintaining policies
- Java 11
- Maven 3
- MySQL 5.5+
- npm 5.4.2
- NodeJS v8.7.0 (best managed with
nvm
, current version in .node-version
Connect to your local mysql database: mysql -uroot
Execute the following:
CREATE DATABASE pdpserver DEFAULT CHARACTER SET latin1;
create user 'root'@'localhost';
grant all on pdpserver.* to 'root'@'localhost';
This project uses Spring Boot and Maven. To run locally, type:
cd pdp-server
mvn spring-boot:run -Drun.jvmArguments="-Dspring.profiles.active=dev"
When developing, it's convenient to just execute the applications main-method, which is in PdpApplication. Don't forget to set the active profile to dev otherwise the application uses the real VOOT client on the test environment.
cd pdp-gui
Initial setup if you do:
npm install
Add new dependencies to devDependencies
:
npm install ${dep} --dev
To build:
npm run webpack
To run locally:
npm run local
Browse to the application homepage.
There are (slow) integration tests for PdpApplication where various decisions are tested against a full-blown running Spring app. See PdpEngineTest
If you want to test individual Policies with specific Request / Response JSON then use the (much faster) StandAlonePdpEngineTest
If you want to test policies against a full test system (e.g. the VM) then you can use the Mujina API to add or reset attributes:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X PUT -d '{"value": ["hero"]}' "https://mujina-idp.vm.openconext.org/api/attributes/urn:mace:dir:attribute-def:eduPersonAffiliation"
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST "https://mujina-idp.vm.openconext.org/api/reset"
The XACML framework works with policies defined in XML. We store the policies as XML strings in the database. However to effectively let XACML evaluate policies we need to convert them to the internal XACML format - see OpenConextEvaluationContextFactory.
Working with XML on the pdp-gui does not work well and we want to keep the pdp-gui simple. Therefore the PdpPolicyDefinition is used as an intermediate format for policies that is easy to work with for the pdp-gui and also enables the server to transform it easily into the desired - yet very complex - XML format.
Using the internal XACML Policy class hierarchy for communication back and forth with the client was not an option because of the cyclic dependencies in the hierarchy (and not desirable because of the complexity it would have caused).
See this image
Read this section for a in-depth security overview.
The policies that can be created are limited in functionality:
- All string comparisons are
urn:oasis:names:tc:xacml:1.0:function:string-equal
- Every EngineBlock policy has exactly one Permit rule and one Deny rule
- Every Stepup policy has multiple Permits rules and no Deny rule
- The target of the policy is limited to exactly one SPENtityID and zero or more IDPEntityIDs
- A EngineBlock policy is either a Deny policy or a Permit policy
- A Stepup policy is always a Permit policy with one final / last Permit without any obligation
- All policies have a RuleCombiningAlgId of
urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable
- All attributes with the same name are treated with the logical OR operator
- All attributes with a different name are exclusively treated with the logical OR or AND operator depending on the type of policy
- Rule targets if not empty only can contain the attributes of the category
urn:oasis:names:tc:xacml:1.0:subject-category:access-subject
- The combining set of policies has the policy combining algorithm
urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-overrides
The Admin GUI has no restrictions in the accessibility of policies. The external API for trusted applications restricts access to policies based on the Identity Provider and the possible associated Service Provider(s) of the user and the corresponding Service and Identity Provider(s) of the policy. See this image for an overview of the logic applied in determining accessibility.
We don't provide flyway migrations to load initial policies.
However if you start up the application with the spring.profiles.active=dev then all the policies
in the folder OpenConext-pdp/pdp-server/src/main/resources/xacml/policies
are added to the database. Do note that any other policies already in the database are deleted.
The pdp-server needs to access the metadata of Identity and Service providers from Manage. In production modus the content is read (and periodically refreshed) from the API exposed by Manage
In any other modus the content is read from the file system:
On its classpath, the application has an application.properties file that contains configuration defaults that are convenient when developing.
When the application actually gets deployed to a meaningful platform, it is pre-provisioned with ansible and the application.properties depends on environment specific properties in the group_vars. See the project OpenConext-deploy and the role pdp for more information.
For details, see the Spring Boot manual.
The API can be tested with cUrl. See WebSecurityConfig for the security rules. When starting in dev modus the mock Shib headers are added automatically.
curl -ik -H "Content-Type: application/json" http://localhost:8080/pdp/api/internal/policies
curl -ik --user "pdp_admin:secret" -H "Content-Type: application/json" -H "X-IDP-ENTITY-ID: http://mock-idp" -H "X-UNSPECIFIED-NAME-ID: test" -H "X-DISPLAY-NAME: okke" http://localhost:8080/pdp/api/protected/policies
curl -ik -X POST --data-binary @./src/test/resources/xacml/requests/test_request_sab_policy.json --user "pdp_admin:secret" -H "Content-Type: application/json" http://localhost:8080/pdp/api/decide/policy
The OpenConext-pdp project heavily uses the PD framework https://github.com/apache/incubator-openaz. This repo is cloned in https://github.com/OpenConext/incubator-openaz-openconext and changes - e.g. distribution management, some bug fixes and minor optimizations - are pushed to openconext/develop branch in https://github.com/OpenConext/incubator-openaz-openconext.
To pull in changes from upstream run ./git-fetch-upstream.sh