GithubHelp home page GithubHelp logo

Comments (21)

cdanger avatar cdanger commented on August 19, 2024 2

... The developer then must have knowing how AuthZForce works and it should be as easy as possible. It also would only work with AuthZForce. What if someone want to switch to another XACML-Framework?

Indeed. This is why, at the end of my previous comment, I suggested the alternative to have an intermediate processing/generation tool (based on XSLT for example) that can take as input a XACML-like policy format but with SpEL expressions in the way you want; and from that, generate two things:

  1. the corresponding valid standard-compliant XACML (3.0) policy that can work with any XACML-3.0-compliant framework (like AuthzForce), where SpEL expressions have been replaced with identifiers (variable names so to speak) that are valid anyURIs, to comply with XACML schema;
  2. the PEP configuration (such as a Request template or smarter Spring config file) in your own favorite format, independent of the XACML framework, that contains the corresponding Attribute-to-SpEL-expression mappings, automatically derived from the input policy. This way, the PEP does not send all possible stuff in the Request, but only the attributes used/declared in the policy.

What if I introduce a new DataType and FunctionId?

<Apply FunctionId="spring:xacml:function:evaluateSpringExpression">
  <AttributeValue DataType="spring:xacml:dataType:spel">context.someObject.someProperty != null</AttributeValue>
</Apply>

(Assuming that PEP and PDP are in the same system/JVM...)
Yes, if you are fine with SpEL in Apply elements only, you can do that with a new Function instead of AttributeProvider indeed. Besides, you can use the standard string datatype instead of making a new one, that's fine too. So if you are good to go with that solution for now, I will update the wiki page on Functions (some aspects have changed with latest API so it may not be completely up-to-date).

A minor issue though is that you need to get some SpEL EvaluationContext like out-of-the-box StandardEvaluationContext to evaluate a SpEL expression, as far as I understand. Assuming one is created before calling the PDP, when the PDP engine calls the Function during policy evaluation, you can get back this SpEL context only via AuthzForce's own EvaluationContext in FunctionCall#evaluate(EvaluationContext). The easier way to get the SpEL EvaluationContext is to pass it in a special Attribute to the DecisionRequest to PDP#evaluate(...) with DecisionRequestBuilder's putNamedAttribute(...), i.e. with a custom AttributeDatatype and wrapped inside a custom AttributeValue. For an example, see TestXacmlPolicyAttributeValue which wraps a policy in a AttributeValue (you don't need the static inner Factory class in your case). Then you can get it back via AuthzForce's EvaluationContext#getNamedAttributeValue(...)

from core.

cdanger avatar cdanger commented on August 19, 2024

Requester info (e.g. username of current principal), requested action (e.g. method call parameters), requested resource, etc. are part of the authorization request context known by the PEP, therefore your PEP code should pass all this info as Attributes in the Request argument to the PDP evaluate() method at runtime.

An AttributeDesignator only defines the full identifier (Category/AttributeId/Issuer) to look up the Attribute value(s) in the Request during evaluation. So the AttributeId is just an ID of the Attribute to look up, not the definition of the actual value. You should use generic (and standard if possible) IDs such as urn:oasis:names:tc:xacml:1.0:subject:subject-id in the AttributeDesignator. Then, for all requests, in the request attribute with this ID (attribute category would be urn:oasis:names:tc:xacml:1.0:subject-category:access-subject), you could set the AttributeValue using SpEL evaluation of ${principal.username} for instance in your PEP code. You can find something similar in EmbeddedPdpBasedAuthzInterceptor#createRequest(...) method but using CXF framework with principal.getName() for instance.

In my opinion, a better way to solve the problem is to use this SpEL in a Request template file (format of your choice) that would be used by the PEP code to build the actual Request to PDP at runtime. Just for example, if using standard XACML/XML format, it would look like this (I just show an example of SpEL in the AttributeValue of subject-id, but in a real example, you would have other Attributes for action-id and resource-id at least):

<?xml version="1.0" encoding="utf-8"?>
<Request  ReturnPolicyIdList="false" CombinedDecision="false" xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
  <Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
    <Attribute IncludeInResult="false" AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${principal.username}</AttributeValue>
    </Attribute>
  </Attributes>
...
</Request

With a template engine, it can really get powerful, but if you are looking for something simple and performant with basic AttributeCategory/Id-to-SpEL-expression mapping, you can use a much simpler format. It's up to you.

from core.

benkuly avatar benkuly commented on August 19, 2024

Firstly thank you for all your detailed answers!

I agree that using attributeId for the definition of the value wasn't a good idea.
Passing all known attributes into the Request (because the PEP doesnt't know which of the attributes are needed) will not be a performant solution (especially when using serialization and deserialization of the large request).

Do you mean with templates the "request filter" described in the wiki?
If I understood it right, then the Request could be preprocessed and the SpEL values evaluated. I actually have something similar to that at a higher level (more abstract). The developer e.g. can do this with annotations (this example is simplified):
@AttributeValue(category=Category.SUBJECT, attributeId="...:subject-id", value="${principal.username}")
But: The developer should not care about in the code which framework is used for ABAC and which attributes the framework (here XACML) and it's policies needs. So also using such an annotation isn't really a good way. What if the policy changes and needs one more attribute? Then the dev also have to change the passed attributes.
That is why I want to solve this with PIP's and SpEL.

from core.

cdanger avatar cdanger commented on August 19, 2024

OK, I get your point. In that case, using a SpEL-AttributeProvider could do it, and I'd recommend putting the SpEL expressions in the AttributeProvider's configuration. The configuration would define Attribute-to-SpEL-expression mappings. For example, if you want to use SpEL expression ${principal.username} for the value of the subject-id attribute, i.e. for evaluating <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" .../> in the XACML policy, you can have an AttributeProvider's configuration looking like this:

<tns:attributeProvider id="test" xmlns:tns="http://authzforce.github.io/core/xmlns/pdp/6.0" xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" xmlns:test="http://authzforce.github.io/core/xmlns/test/3"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="test:TestAttributeProvider">
	<Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
		<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
			<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${principal.username}</AttributeValue>
		</Attribute>
	</Attributes>
...
</tns:attributeProvider>

Note that I am actually using TestAttributeProvider configuration format (XSD), except the AttributeValue is a SpEL expression. So you could reuse it and most of the code of TestAttributeProvider (the one used as an example on the AttributeProviders wiki page).

Now back to your initial question: how to pass something like a context object into a request so that an SpEL-AttributeProvider could use it?
The way to pass such thing to an AttributeProvider is through the EvaluationContext argument of AttributeProvider#get(...) method. The Evaluation Context is initialized with content coming from DecisionRequest#get*() methods - especially getNamedAttributes() - on the DecisionRequest arg to PDP#evaluate(...). In your case, if you want something back from the request through EvaluationContext, you put it in this DecisionRequest, for example with help of DecisionRequestBuilder#putNamedAttributeIfAbsent(...), as shown on the README page. But you cannot pass anything as a named attribute value (or with extra code).
What is the type of the context object you want to pass?*

from core.

benkuly avatar benkuly commented on August 19, 2024

Thank you!

That solutions comes closer to what I need.
Did I understand it right, that the developer then have to write it`s own AttributeProvider xml configuration to use and define own SpEL expressions?

The context object could be everything. It depends on what the dev wants to secure. If it's a method invocation, then e.g. MethodInvocation. But meahwhile I realized that passing it to the request isn't a good idea. There would be many unused informations in a request that have to serialized, when I want to start using a remote PDP.

Is there no way that the dev can use SpEL within policies and the PEP is in a sort also a PIP, because he knows the context informations.

from core.

cdanger avatar cdanger commented on August 19, 2024

Did I understand it right, that the developer then have to write it`s own AttributeProvider xml configuration to use and define own SpEL expressions?

Yes, still better than putting them in the policy. There are several issues against putting SpEL in XACML policy directly. Just to name a few:

  1. It would break XACML schema validation, making the policy invalid. For instance, if you put it in AttributeId, AttributeId is defined as XML type anyURI. But SpEL expressions are not anyURIs, as far as I know, maybe in some cases they happen to be, but not by definition.
  2. The same AttributeDesignator (same Category/AttributeId) may be reused many times in a policy and I imagine SpEL expressions can be complex/big. So the more occurrences of a given AttributeDesignator, the harder and more error-prone it gets to keep SpEL expressions in sync everywhere it occurs in the policy. For example, if you are defining a RBAC policy, you will reuse the subject-role attribute as many times as they are roles. God knows how many roles you can have. Same thing for action-id attribute, you will repeat it potentially as many times as they are method/operations to control access to. This is why, at some point, the developer will prefer to just define mappings like: for Attribute A (i.e. AttributeDesignator/Category C, AttributeId Y, (optional) Issuer I), use SpEL expression E. Therefore, you guarantee that no matter where it occurs in the policy, and even better, no matter in which policy it occurs, if you have multiple policies (e.g. with Policy(Set)IdReferences) the same mapping applies for a given Attribute.

To sum up, if not in the policy, these mappings have to be configured somewhere. Why not in the AttributeProvider's config file? Where else?

...when I want to start using a remote PDP

You lost me there. I was assuming the PEP and PDP in the same system/JVM from the start. If the PDP is remote, I don't see how you'ill be able to access the request context like method invocation info occuring on the PEP side from the PDP, unless you put the info in the XACML Request to the PDP. Well, if the developer is responsible for the policy and the PEP(s), he/she can configure the PEP(s) to send only useful info for policy evaluation.

I may be raving here, but another solution is to make a generation tool, the input to which would be a policy in a XACML-like/XACML-extended format of your choice/invention (but likely not strictly valid XACML), where you can put the SpEL expressions the way you want; and the ouput of which would be:

  1. The valid XACML policy (to be processed by AuthzForce PDP) where SpEL expressions have been replaced with XACML-valid attribute identifiers.
  2. The PEP configuration file, making sure the PEP uses the right SpEL expressions for the right attributes according to the policy above, when creating the Request to the PDP.

from core.

benkuly avatar benkuly commented on August 19, 2024

Yes, still better than putting them in the policy.

You're right, but I'm still sceptical. The developer then must have knowing how AuthZForce works and it should be as easy as possible. It also would only work with AuthZForce. What if someone want to switch to another XACML-Framework?

You lost me there. I was assuming the PEP and PDP in the same system/JVM from the start. If the PDP is remote, I don't see how you'ill be able to access the request context like method invocation info occuring on the PEP side from the PDP, unless you put the info in the XACML Request to the PDP.

Yes. Primarily the PEP and PDP are on the same machine. But I want to leave the door open for e.g. Spring Cloud in the future. And then PEP and PDP could be different systems.
I thought that could be possible when PEP and the context handler are one construct. In this way:

  • a) a PIP would have enough informations to evaluate SpEL expressions. But if there is no possibility to write them into a policy, then this is no option.
  • b) a PIP could dynamically evaluate the AttributeDesignator anyURI's that are related to the security-context. E.g. attributeId="spring:securityContext:someObject:someProperty". Via reflection the value could be located.

image

What if I introduce a new DataType and FunctionId?

<Apply FunctionId="spring:xacml:function:evaluateSpringExpression">
	<AttributeValue DataType="spring:xacml:dataType:spel">context.someObject.someProperty != null</AttributeValue>
</Apply>

In that way there is no need of an PIP, but still the problem: how could the PDP get the relevant context-information without (de)serialize all the possible stuff (in the case of seperate PDP and PEP).

I'm not as professinal in XACML as you are, so maybe my ideas are silly. Thank you very much, that you still help me! And sorry for my bad english.

from core.

benkuly avatar benkuly commented on August 19, 2024

Is there something like a context handler, that is seperated from the PIP like in the flowchart of my last post?

Otherwise I will try and compare some of your ideas in the next weeks and make the repository public as soon as all tests are passed.
Thanks!

from core.

cdanger avatar cdanger commented on August 19, 2024

Well, the boxes in the flowchart are logical/abstract entities that may not map to a single Java thing in AuthzForce. In particular, the context handler have many functions implemented in different parts of AuthzForce :

  • Request (3) / request notification (4) / Response context (11) / response (12):
    • When using AuthzForce internal request/response types directly (DecisionRequest and DecisionResult interface implementations), they are handled by one of the evaluate(request) methods of the PdpEngine (interface) implementation in use, e.g. BasePdpEngine#evaluate(request) usually.
    • When using other types of request/response, typically data serialization formats such as XACML/XML or XACML/JSON, they are handled by a PdpEngineInOutAdapter (interface) implementation that wraps some RequestPreprocessor (interface) and ResultPostprocessor (interface) implementations around the PdpEngine to process request/response into/out of it respectively from/to the different formats (see PdpEngineAdapters class for example).
  • Attribute queries (5) / attributes (10): handled by a EvaluationContext (interface) implementation, e.g. the IndividualDecisionRequestContext class nested in BasePdpEngine.
  • Attribute query (6) / attribute (8): this occurs when the attribute is not already present in EvaluationContext. Handled by DesignatedAttributeProvider (interface) implementations. There may be one getting attributes from a LDAP directory, another one getting them from a relational database, etc.

from core.

benkuly avatar benkuly commented on August 19, 2024

The ABAC/XACML-Integration for Spring Security is getting ready soon and I found a solution for my problem:

I map my security context to an identifier and put this identifier as an attribut to the request context. Then I write an AttributeProvider (PIP), that should resolve all missing attributes by asking my context handler (like an the flowchart above).
The new problem is, that the AttributeProvider only knows if he can resolve the missing Attribute to an existing Attribute on runtime when get(final AttributeFqn attributeGUID, final BagDatatype<AV> returnDatatype, final EvaluationContext context) get called. So it could be possible that he can't resolve it and he also can never return sth. to getProvidedAttributes().
Where should I start?

from core.

cdanger avatar cdanger commented on August 19, 2024

Do you mean: Where should I start to implement the AttributeProvider?
See the dedicated wiki page. The recommended way is to start with a separate Maven project and XML schema for your AttributeProvider's configuration. This configuration should enable the user/integrator to define (or control somehow) which XACML Attribute(s) will be provided by the AttributeProvider, so that he/she can make sure they can be used in the policy.

from core.

benkuly avatar benkuly commented on August 19, 2024

I mean that currently it seems not easy to write an own AttributeProvider that is not based on DesignatedAttributeProvider and I dont't know where to start without writing a new ExpressionFactory.
Important: Actually I use AuthZForce completely without XSD and XML because I personally believe that this is not a good way to integrate it in Spring Boot with .properties-files etc.

from core.

cdanger avatar cdanger commented on August 19, 2024

OK, I guess you want to use the BasePdpEngine(ExpressionFactory, RootPolicyProvider, ...) constructor to instantiate the PDP (without using XML). So yes indeed, you need an ExpressionFactory. You can use the default implementation (DepthLimitingExpressionFactory) like in the code of PdpEngineConfiguration constructor:

xacmlExpressionFactory = new DepthLimitingExpressionFactory(attValFactoryRegistry, functionRegistry,
attProviderFactories, maxVarRefDepth, enableXPath, strictAttributeIssuerMatch);

The argument that matters to you here is attProviderFactories which is where the AttributeProviders come in. It's a list of CloseableDesignatedAttributeProvider.DependencyAwareFactory. So in order to plug-in your new AttributeProvider directly (without using XML stuff), just make your AttributeProvider's factory class implement this DependencyAwareFactory interface. For that, you don't need XML, so you can handle the configuration in your own way. Make sure that your implementation of getDependencies() returns the special attribute (designator) holding the security context, that you mentioned in your second to last comment. This will tell the PDP engine that your AttributeProvider requires / depends on this attribute to work.

from core.

benkuly avatar benkuly commented on August 19, 2024

Thank you for the explanation, but I already did that a month ago and it works perfect :-)

The point is, that implementing DependencyAwareFactory will cause that I must use CloseableDesignatedAttributeProvider as AttributeProvider implementation. The DepthLimitingExpressionFactory doensn't allow to use completely custom AttributeProvider without the getProvidedAttributes()-method, but that's what I need.

from core.

cdanger avatar cdanger commented on August 19, 2024

This method is there for a reason. Just to understand why you are unable to implement it, could you explain how does one know which XACML attributes will be provided by your AttributeProvider (in a given configuration), in terms of Attribute Category, AttributeId, Datatype, etc. ? What are the configuration parameters? An example would be very welcome.

from core.

benkuly avatar benkuly commented on August 19, 2024

As mentioned previously the devs, who will use my Spring-ABAC-Framework should not take care of the specific XACML-Framework (e.g. AuthZForce).
There are options for the devs (e.g. config files or classes) to e.g. map SpEL Expressions to AttributeDesignators. The attributes are provided by a central PIP of my Framework. Because the attribute mapping ideally should be configurable on runtime, my PIP never knows if or if not there will be a value for an attribute query.

My PIP now only need to be connected to the PDP-Framework (in AuthZForce AttributeProvider). And that's why getProvidedAttributes() can't be used.

If something isn't clear let me know.

from core.

cdanger avatar cdanger commented on August 19, 2024

Just to clarify: you want to enable the devs to use your ABAC framework without using any XACML-specific stuff; except that if they want to configure the mappings of SpEL expressions to attributes, they have to use XACML AttributeDesignators (for the latter). Am I correct?
Then one more question: are you not using XACML for policies at all? Your own policy language then?

from core.

benkuly avatar benkuly commented on August 19, 2024

Not without using XACML stuff but without using XACML-Framework related stuff like AuthZForce's AttributeProvider.
For the SpEL mapping there is a class named RequestAttributeMetadata that is very similar to AttributeDesignator.
I think XACML is perfect as policy language, so I didn't defined an own one. If someone want his own language, he can integrate it very easily and only has to change the policies and not the PEP or PIP stuff

from core.

cdanger avatar cdanger commented on August 19, 2024

In that case, it does not seem difficult to implement getProvidedAttributes(). From the SpEL mappings, you know the list of AttributeDesignators potentially provided - i.e. supported - by the AttributeProvider. This is all you need to return in getProvidedAttributes(). It does not matter if some of them are never used in the policies (and therefore not actually provided/used at runtime). What matters is that your AttributeProvider can provide them if requested (by some policy evaluation), using the SpEL-to-XACML-attribute mappings defined in configuration. (I realize I may have to rename this method to getSupportedAttributes at some point to make it less ambiguous.) By the way, AttributeDesignator is standard XACML, not AuthzForce-specific, so there's nothing wrong with using it if you want stay framework-agnostic. And if you still use XACML policies, you have to use AttributeDesignator anyway. (In AuthzForce, the corresponding Java class is directly derived from the standard XACML schema using JAXB, like in AT&T implementation.)

from core.

benkuly avatar benkuly commented on August 19, 2024

In that case, it does not seem difficult to implement getProvidedAttributes(). From the SpEL mappings, you know the list of AttributeDesignators potentially provided - i.e. supported - by the AttributeProvider. This is all you need to return in getProvidedAttributes(). It does not matter if some of them are never used in the policies (and therefore not actually provided/used at runtime). What matters is that your AttributeProvider can provide them if requested (by some policy evaluation), using the SpEL-to-XACML-attribute mappings defined in configuration.

And this will also work, when someone adds an attribute mapping on runtime? I'm asking that because I'm also planning an integrated online tool to create and edit the XACML policies and the attribute mappings on rumtine without a restart of the application.

By the way, AttributeDesignator is standard XACML, not AuthzForce-specific, so there's nothing wrong with using it if you want stay framework-agnostic. And if you still use XACML policies, you have to use AttributeDesignator anyway.

Yeah I know that, but I implemented an ABAC-API for Spring that is completely independent from XACML. If the dev chooses XACML as one possible implementation for this API, he ideally only has to define the policies in XACML, the mapping is independent of it. If he switches to another implementation, he only needs to migrate the policies.

from core.

cdanger avatar cdanger commented on August 19, 2024

It will work fine if you re-instantiate the PDP engine after changing the attribute mapping. There may be a more efficient way, but at this point, I think I cannot help you efficiently unless I can see some code. Could you share the source code, even in early prototype stage ?

Anyway, this is a quite ambitious and promising goal you have here 👍

from core.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.