XPath with hiearchical matching - xpath

** Edited for clarification **
I've inherited a bunch of xml documents (configuration files) that resemble the following structure (element names changes and structured simplified for the sake of brevity.
<containers>
<container id="c1">
<ports>
<port id="p2"/>
</ports>
<rules>
<!--
Within a container, a rule must refer to a port
declared within the same container.
A rule cannot refer to a port that does not
exist in the enclosing container.
-->
<rule id="r1" portId="p1"/><!-- p1 is not in c1, but in c2, bad -->
<rule id="r2" portId="p2"/><!-- this is good -->
<rule id="r3" portId="p3"/><!-- p3 is nowhere, bad -->
</rules>
</container>
<container id="c2">
<ports>
<port id="p1"/>
<port id="p2"/>
</ports>
<rules>
<rule id="r1" portId="p1"/>
</rules>
</container>
</containers>
A container can have points and rules (point and rule ids can be duplicated among containers; they just need to be unique within a container.)
The requirement is that if a rule references a point id, that point id must be defined within the enclosing container.
I need to search for rules within containers that, by mistake reference non-existing points.
I have xpath expressions that can find a rule that points to a non-existing point (unfortunately for the entire xml document.)
//*/rule/#portId[not( . = //*/port/#id)]
The rule applies to the entire document, it is not contained within containers.
That is, this xpath expression would detect that the rule r3 in container c1 refers to a port p3 that does not exist anywhere in the document.
However, this same xpath expression would not detect that rule r1 in container c1 refers to a port p2 that is not in container c1. Why? Because this xpath expression will match it with port p2 in container c2.
My xpath expression would not detect this.
Granted, I could do this with several xpath expressions and glue code between them (say, by applying the xpath expression to each container) but I was hoping if it is possible to use one single xpath expression starting from the root element instead.
Any advice?

Another option using the ancestor:: axis...
//rule[not(#portId = ancestor::container//port/#id)]

Try this one.
//rule[#portId[not(. = ./parent::rule/parent::rules/parent::container/*/port/#id)]]
This seems to work for me. Tested on:
<containers>
<container id="c1">
<ports>
<port id="p2"/>
<port id="p4"/>
</ports>
<rules>
<!--
Within a container, a rule must refer to a port
declared within the same container.
A rule cannot refer to a port that does not
exist in the enclosing container.
-->
<rule id="r1" portId="p1"/><!-- p1 is not in c1, but in c2, bad -->
<rule id="r2" portId="p2"/><!-- this is good -->
<rule id="r3" portId="p3"/><!-- p3 is nowhere, bad -->
</rules>
</container>
<container id="c2">
<ports>
<port id="p1"/>
<port id="p2"/>
</ports>
<rules>
<rule id="r1" portId="p1"/>
<rule id="r2" portId="p4"/>
</rules>
</container>
</containers>
using this online processor.
Got the following output
Element='<rule id="r1" portId="p1"/>'
Element='<rule id="r3" portId="p3"/>'
Element='<rule id="r2" portId="p4"/>'

Related

Maven Versions Plugin Not Ignoring 4 part version numbers e.g 19.2.1.3

Hi I'm using a maven version plugin rules file to exclude certain versions.
<?xml version="1.0" encoding="UTF-8"?>
<ruleset xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" comparisonMethod="maven" xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 https://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<ignoreVersions>
<ignoreVersion type="regex">.*[aA]lpha.*</ignoreVersion> <!-- Ignore any version containing Alpha or alpha -->
<ignoreVersion type="regex">.*\..*\.SP.*</ignoreVersion> <!-- Ignore any version where the incremental value starts with SP e.g. 1.2.SP3 -->
<ignoreVersion type="regex">.*\..*\..*\..*</ignoreVersion> <!-- Ignore any version that has 4 parts, e.g. 12.0.3.1 -->
</ignoreVersions>
<rules>
<rule groupId="org.springframework.boot">
<ignoreVersions>
<ignoreVersion type="regex">2.6.*</ignoreVersion>
</ignoreVersions>
</rule>
<rule groupId="io.micrometer">
<ignoreVersions>
<ignoreVersion type="regex">1.8.*</ignoreVersion>
</ignoreVersions>
</rule>
<rule groupId="org.apache.tomcat.embed">
<ignoreVersions>
<ignoreVersion type="regex">10.*</ignoreVersion>
</ignoreVersions>
</rule>
<rule groupId="au.com.dius.pact.provider">
<ignoreVersions>
<ignoreVersion type="regex">4.3.*</ignoreVersion>
</ignoreVersions>
</rule>
<rule groupId="au.com.dius.pact.consumer">
<ignoreVersions>
<ignoreVersion type="regex">4.3.*</ignoreVersion>
</ignoreVersions>
</rule>
</rules>
</ruleset>
The 3rd line is trying to exclude any version that has 4 parts. Sadly this regex is not working.
Have anyone cracked this issue.
Many thanks in advance
Richard
Update: Running the mvn command locally, I was getting:
Failed to execute goal org.codehaus.mojo:versions-maven-plugin:2.8.1:use-latest-releases (default-cli) on project : Execution default-cli of goal org.codehaus.mojo:versions-maven-plugin:2.8.1:use-latest-releases failed: Invalid segment, 1, for the 1 segment version: '11.5.7.0'
The version number was set as a property value and not hard-coded in the <dependency> tag. Putting the version number within the <depenedency> tag, the reg ex worked. However, if your project has a transitive dependency version that has four parts, the regex will not work for these. Sadly, MVN dependency:tree does not reveal the source of the transitive dependencies.

URL rewrite from trailing string to GET variable

I've searched for this, but can't seem to come up with the right search terms to find - seems it would be a common question.
WIMP, IIS version is 8
I want to come up with a rewrite rule:
Incoming URL: http://example.com/1a2b3cdef
Rewritten to: http://example.com?p=1a2b3cdef
Note, the start of this url will always be "http://example.com/" (not the real domain name), that will never change.
From there my default document of index.php will retrieve the GET variable p.
Any help is greatly appreciated.
This is the configuration that can be applied in web.config.
<defaultDocument>
<files>
<add value="index.php" />
</files>
</defaultDocument>
<rewrite>
<rules>
<rule name="rewrite" enabled="true">
<match url="^[_0-9a-z]+" />
<action type="Rewrite" url="?p={R:0}" />
</rule>
</rules>
</rewrite>

web.config using an absolute path

I need to use a rewrite rule for a url(www.example.org/download.php) to hit another file called download.php, that is not in my root directory, but located in C:/repo/other_directory/test/download.php, however, it is not working. I have to use an absolute path in the rule. Any help on this would be greatly appreciated. My code is below:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Imported Rule placestoswim" stopProcessing="true">
<match url="download.php" ignoreCase="false" />
<action type="Rewrite" url="C:/repo/other_directory/test/download.php" appendQueryString="false" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I dont think this will work the url paramter of a rewrite is expecting a URL not a file system path.
If you cant move that location, can you create a virtual directory inside your existing site called downloads, and point its web root at your immovable folder C:/repo/other_directory/test/? Then in your web.config setup a rewrite to use this newly created path ~/downloads/download.php as the destination for your rewrite for ~/downloads.php

Fine grained access control with XACML 3.0 for an XML document

I want to express a fine-grained access control use case with XACML 3.0 for an XML document but I don't know whether I can use a full XPath expression like
for $a in fn:distinct-values(sales/clientid)return (fn:sum(sales[clientid = $a]/value)
This my XML:
<?xml version="1.0"?>
<database>
<sales>
<salesid>1</salesid>
<clientid>1</clientid>
<value>1000</value>
</sales>
<sales>
<salesid>2</salesid>
<clientid>1</clientid>
<value>10000</value>
</sales>
<sales>
<salesid>3</salesid>
<clientid>2</clientid>
<value>500</value>
</sales>
<client>
<clientid>1</clientid>
<nom>a</nom>
</client>
<client>
<clientid>2</clientid>
<nom>b</nom>
</client>
</database>
How can I limit the access to the clients who have a sales value less than 10,000?
As I understand your requirement, you need to apply XACML policy based on the xml schema as described above. The sample xml needed to be in XACML request else if you are planning to read from xml as repository you may need to write a custom PIP.
You can achieve the XPath based policy design for the same, provided that the xml input for the client details is available in XACML request inside element as below sample:
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
<Content>
<client id="xxxx">
<sales id="yyyy">
<value>1234</value>
</sales>
</client>
</Content>
</Attributes>
Then you can create the policy based for your use case as below sample:
<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" xmlns:xacml="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="sample-xpath-policy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
<Description>Sample XPath policy</Description>
<PolicyDefaults>
<XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116</XPathVersion>
</PolicyDefaults>
<Rule Effect="Permit" RuleId="Rule-1">
<Target>
<AnyOf>
<AllOf>
<Match MatchId="urn:oasis:names:tc:xacml:1.0:function:integer-less-than">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">10000</AttributeValue><AttributeSelector MustBePresent="false" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" Path="/client/sales/value/text()" DataType="http://www.w3.org/2001/XMLSchema#integer"/>
</Match>
</AllOf>
</AnyOf>
</Target>
</Rule>
<Rule RuleId="rule2" Effect="Deny">
<Description>Deny rule</Description>
</Rule>
</Policy>

XACML Resources

I am trying to write a code that will enable user access of content from a website based on security roles. Thus some users can see all the content, and some can only see urls with certain extensions.
Most of my code works, but I have trouble with the access for the 3 subcategories.
<Rule Effect="Permit" RuleId="accesses">
<Description>Permission for lower clearance</Description>
<Target>
<Resources>
<Resource>
<ResourceMatch
MatchId="urn:oasis:names:tc:xacml:1.0:function:regexp-string-match">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">home.html
</AttributeValue>
<ResourceAttributeDesignator
AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="policy-admin#website.com"
MustBePresent="true" />
</ResourceMatch>
</Resource>
<Resource>
<ResourceMatch
MatchId="urn:oasis:names:tc:xacml:1.0:function:regexp-string-match">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">localweather.html
</AttributeValue>
<ResourceAttributeDesignator
AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="policy-admin#website.com"
MustBePresent="true" />
</ResourceMatch>
</Resource>
<Resource>
<ResourceMatch
MatchId="urn:oasis:names:tc:xacml:1.0:function:regexp-string-match">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">about.html
</AttributeValue>
<ResourceAttributeDesignator
AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="policy-admin#website.com"
MustBePresent="true" />
</ResourceMatch>
</Resource>
</Resources>
</Target>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:regexp-string-match">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
<SubjectAttributeDesignator AttributeId="AccessLevel"
DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="policy-admin#website.com"
MustBePresent="true" />
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Clear</AttributeValue>
</Apply>
</Apply>
</ Condition >
</Rule>
I have these 3 resources, and when I run the program, I get an "indeterminate" response. Can I only have 1 resource per rule? Is something else throwing an exception?
You can have tree resources for in target. According to the your rule, they would act as "OR". Please check with your XACML request, may be you are sending request that is not matching with policy (policy has MustBePresent="true it means, if attribute is not there, PDP would create a indeterminate error). Please change them to "false" and see.
It was actually a condition problem. The resources were all leaf-level files. I didn't have the right set of user attribute values for my policy. I compared it against my LDAP schema and got it working.

Resources