Search code examples
pythonxmlvalidationlxmlxacml

Can XACML be validated by lxml in Python?


So, I am writing a small program to read an XACML request, validate if it is valid XACML, and then subsequently check the code towards a policy.

In this endeavor I found the lxml parser, which can validate .xml files towards a .xsd file. Therefore I wget'ed the relevant schemas and tried them both in the validator (http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-policy-schema-os.xsd, and http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-context-schema-os.xsd), to compare to my request.xml files containing an XACML request. The problem that I am encountering is that my program returns false for the validation, meaning that it is not valid, althoug by all accounts it SHOULD be. The code in question is listed below, as well as the input command, and the error.

import os
import sys
from ndg import *
from lxml import etree

def checkCorrectXACML(xml_path: str, xsd_path: str) -> bool:
    input_schema = etree.parse(xsd_path)
    schema = etree.XMLSchema(input_schema)
    request = etree.parse(xml_path)
    result = schema.validate(request)
    return result

def checkPolicy(request):
    status: bool
    return status

def readRequest():
    request = str(sys.argv[1])
    if(checkCorrectXACML(request, '/home/foo/Documents/xacml.xsd') == True):
        return request
    else:
        raise Exception('Invalid XACML')

def evaluateRequest():
    request = readRequest()
    status = checkPolicy(request)
    return status



def main():
    if(len(sys.argv) == 2):
        returnResponse = evaluateRequest()
        return returnResponse
    else:
        raise Exception('You need to provide a request path')

if __name__ == '__main__':
    main()

Error:

File "/home/foo/Documents/XACXML.py", line 22, in readRequest raise Exception('Invalid XACML') Exception: Invalid XACML

Command:

python3 XACML.py /home/foo/Desktop/Request1.xml

Request1.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Request
      xmlns="urn:oasis:names:tc:xacml:1.0:context"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="urn:oasis:names:tc:xacml:1.0:context
        cs-xacml-schema-context-01.xsd">
    <Subject>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
              DataType="http://www.w3.org/2001/XMLSchema#string">
            <AttributeValue>External user</AttributeValue>
        </Attribute>
    </Subject>
    <Resource>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
              DataType="http://www.w3.org/2001/XMLSchema#anyURI">
            <AttributeValue>http://some.url/foo</AttributeValue>
        </Attribute>
    </Resource>
    <Action>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
              DataType="http://www.w3.org/2001/XMLSchema#string">
            <AttributeValue>read</AttributeValue>
        </Attribute>
    </Action>
</Request>


Solution

  • Thanks to Martin Honnen that pointed out that the namespace of the XACML didn't match the namespace for the schema. Using a request with a similar namespace solved the issue. Here is an example of an X(AC)ML sample that did in fact work, both with xmllint and in the script.

    The problem was therefore the xmlns

    <?xml version="1.0" encoding="UTF-8"?>
    <Request 
        xmlns="urn:oasis:names:tc:xacml:2.0:context:schema:os" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation=" urn:oasis:names:tc:xacml:2.0:context:schema:os 
          http://docs.oasis-open.org/xacml/access_control-xacml-2.0-context-schema-os.xsd">
      <Subject 
          SubjectCategory="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
        <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
            DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="xacml20.interop.com">
          <AttributeValue>000000</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:subject:user-name"
            DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="xacml20.interop.com">
          <AttributeValue>Some name</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:subject:buy-num-shares"
            DataType="http://www.w3.org/2001/XMLSchema#integer"
            Issuer="xacml20.interop.com">
          <AttributeValue>0000</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:subject:buy-offer-price"
            DataType="http://www.w3.org/2001/XMLSchema#integer"    
            Issuer="xacml20.interop.com">
          <AttributeValue>1</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:subject:req-credit-ext-approval"
            DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="xacml20.interop.com">
          <AttributeValue>false</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:subject:req-trade-approval"
            DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="xacml20.interop.com">
          <AttributeValue>false</AttributeValue>
        </Attribute>
      </Subject>
      <Resource>
        <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" 
            DataType="http://www.w3.org/2001/XMLSchema#string">
          <AttributeValue>Astring</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:resource:owner-id" 
            DataType="http://www.w3.org/2001/XMLSchema#string">
          <AttributeValue>000000</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:resource:owner-name" 
            DataType="http://www.w3.org/2001/XMLSchema#string">
          <AttributeValue>Somename</AttributeValue>
        </Attribute>
        
        <!-- WE GET THIS VIA THE ATTRIBUTE LOCATOR 
        <Attribute AttributeId="urn:xacml:2.0:interop:example:resource:account-status"
            DataType="http://www.w3.org/2001/XMLSchema#string">
          <AttributeValue>Active</AttributeValue>
        </Attribute>
         -->
        
        <Attribute AttributeId="urn:xacml:2.0:interop:example:resource:credit-line"
            DataType="http://www.w3.org/2001/XMLSchema#integer">
          <AttributeValue>15000</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:resource:current-credit"
            DataType="http://www.w3.org/2001/XMLSchema#integer">
          <AttributeValue>10000</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:xacml:2.0:interop:example:resource:trade-limit"
            DataType="http://www.w3.org/2001/XMLSchema#integer">
          <AttributeValue>10000</AttributeValue>
        </Attribute>
      </Resource>
      <Action>
        <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
            DataType="http://www.w3.org/2001/XMLSchema#string">
          <AttributeValue>Buy</AttributeValue>
        </Attribute>
      </Action>
      <Environment/>
    </Request>