def fromXML(cls, elem): """Parse ElementTree element into a SAML XACMLAuthzDecisionQuery object @type elem: ElementTree.Element @param elem: XML element containing the AuthzDecisionQuery @rtype: saml.saml2.core.AuthzDecisionQuery @return: AuthzDecisionQuery object """ if not ElementTree.iselement(elem): raise TypeError("Expecting %r input type for parsing; got %r" % (ElementTree.Element, elem)) if QName.getLocalPart(elem.tag) != cls.DEFAULT_ELEMENT_LOCAL_NAME: raise XMLTypeParseError("No \"%s\" element found" % cls.DEFAULT_ELEMENT_LOCAL_NAME) # Unpack attributes from top-level element attributeValues = [] for attributeName in (cls.VERSION_ATTRIB_NAME, cls.ISSUE_INSTANT_ATTRIB_NAME, cls.ID_ATTRIB_NAME): attributeValue = elem.attrib.get(attributeName) if attributeValue is None: raise XMLTypeParseError('No "%s" attribute found in "%s" ' 'element' % (attributeName, cls.DEFAULT_ELEMENT_LOCAL_NAME)) attributeValues.append(attributeValue) authzDecisionQuery = XACMLAuthzDecisionQuery() authzDecisionQuery.version = SAMLVersion(attributeValues[0]) if authzDecisionQuery.version != SAMLVersion.VERSION_20: raise NotImplementedError("Parsing for %r is implemented for " "SAML version %s only; version %s is " "not supported" % (cls, SAMLVersion(SAMLVersion.VERSION_20), SAMLVersion(authzDecisionQuery.version))) authzDecisionQuery.issueInstant = SAMLDateTime.fromString( attributeValues[1]) authzDecisionQuery.id = attributeValues[2] for childElem in elem: localName = QName.getLocalPart(childElem.tag) if localName == Issuer.DEFAULT_ELEMENT_LOCAL_NAME: # Parse Issuer authzDecisionQuery.issuer = IssuerElementTree.fromXML(childElem) elif localName == Request.ELEMENT_LOCAL_NAME: # Create XACML context request from Request element. authzDecisionQuery.xacmlContextRequest = \ RequestElementTree.fromXML(childElem) else: raise XMLTypeParseError("Unrecognised XACMLAuthzDecisionQuery child " "element \"%s\"" % localName) return authzDecisionQuery
def fromXML(cls, elem): if not ElementTree.iselement(elem): raise TypeError("Expecting %r input type for parsing; got %r" % (ElementTree.Element, elem)) if QName.getLocalPart(elem.tag) != cls.DEFAULT_ELEMENT_LOCAL_NAME: raise XMLTypeParseError("No \"%s\" element found" % cls.DEFAULT_ELEMENT_LOCAL_NAME) authzDecisionStatement = XACMLAuthzDecisionStatement() for childElem in elem: localName = QName.getLocalPart(childElem.tag) if localName == Response.ELEMENT_LOCAL_NAME: # Create XACML context request from Response element. authzDecisionStatement.xacmlContextResponse = \ ResponseElementTree.fromXML(childElem) elif localName == Request.ELEMENT_LOCAL_NAME: # Create XACML context request from Request element. authzDecisionStatement.xacmlContextRequest = \ RequestElementTree.fromXML(childElem) else: raise XMLTypeParseError("Unrecognised XACMLAuthzDecisionQuery child " "element \"%s\"" % localName) return authzDecisionStatement
def fromXML(cls, elem): """Parse ElementTree ESG Group/Role attribute element into a SAML ESGFGroupRoleAttributeValue object @type elem: ElementTree.Element @param elem: Attribute value as ElementTree XML element @rtype: saml.saml2.core.ESGFGroupRoleAttributeValue @return: SAML ESG Group/Role Attribute value """ # Update namespace map for the Group/Role type referenced. if not Config.use_lxml: ElementTree._namespace_map[cls.DEFAULT_NS] = cls.DEFAULT_PREFIX if not ElementTree.iselement(elem): raise TypeError("Expecting %r input type for parsing; got %r" % (ElementTree.Element, elem)) localName = QName.getLocalPart(elem.tag) if localName != cls.DEFAULT_ELEMENT_LOCAL_NAME: raise XMLTypeParseError("No \"%s\" element found" % cls.DEFAULT_ELEMENT_LOCAL_NAME) # Check for group/role child element if len(elem) == 0: raise XMLTypeParseError('Expecting "%s" child element to "%s" ' 'element' % (cls.TYPE_LOCAL_NAME, cls.DEFAULT_ELEMENT_LOCAL_NAME)) childElem = elem[0] childLocalName = QName.getLocalPart(childElem.tag) if childLocalName != cls.TYPE_LOCAL_NAME: raise XMLTypeParseError("No \"%s\" element found" % cls.TYPE_LOCAL_NAME) attributeValue = ESGFGroupRoleAttributeValue() groupName = childElem.attrib.get(cls.GROUP_ATTRIB_NAME) if groupName is None: raise XMLTypeParseError('No "%s" attribute found in Group/Role ' 'attribute element' % cls.GROUP_ATTRIB_NAME) attributeValue.group = groupName roleName = childElem.attrib.get(cls.ROLE_ATTRIB_NAME) if roleName is None: roleName = cls.DEFAULT_ROLE_NAME attributeValue.role = roleName return attributeValue
def toXML(cls, attributeValue): """Create an XML representation of the input SAML ESG Group/Role type Attribute Value @type attributeValue: ndg.security.common.saml_utils.esgf.ESGFGroupRoleAttributeValue @param attributeValue: Group/Role Attribute Value to be represented as an ElementTree Element @rtype: ElementTree.Element @return: ElementTree Element """ elem = AttributeValueElementTreeBase.toXML(attributeValue) if not isinstance(attributeValue, ESGFGroupRoleAttributeValue): raise TypeError("Expecting %r type; got: %r" % (ESGFGroupRoleAttributeValue, type(attributeValue))) if not Config.use_lxml: ElementTree._namespace_map[attributeValue.namespaceURI ] = attributeValue.namespacePrefix tag = str(QName.fromGeneric(cls.TYPE_NAME)) groupRoleElem = etree.makeEtreeElement(tag, cls.DEFAULT_ELEMENT_NAME.prefix, cls.DEFAULT_ELEMENT_NAME.namespaceURI) groupRoleElem.set(cls.GROUP_ATTRIB_NAME, attributeValue.group) groupRoleElem.set(cls.ROLE_ATTRIB_NAME, attributeValue.role) elem.append(groupRoleElem) return elem
def factoryMatchFunc(cls, elem): """Match function used by AttributeValueElementTreeFactory to determine whether the given attribute is ESGFGroupRoleAttributeValue type @type elem: ElementTree.Element @param elem: Attribute value as ElementTree XML element @rtype: ndg.security.common.saml_utils.etree.ESGFGroupRoleAttributeValue or None @return: SAML ESGF Group/Role Attribute Value class if elem is an Group/role type element or None if if doesn't match this type """ # Group/role element is a child of the AttributeValue element if len(elem) == 0: return None childLocalName = QName.getLocalPart(elem[0].tag) if childLocalName != cls.TYPE_LOCAL_NAME: raise XMLTypeParseError('No "%s" child element found in ' 'AttributeValue' % cls.TYPE_LOCAL_NAME) if cls.GROUP_ATTRIB_NAME in elem[0].attrib and \ cls.ROLE_ATTRIB_NAME in elem[0].attrib: return cls return None
def toXML(cls, xacmlAuthzDecisionStatement): if not isinstance(xacmlAuthzDecisionStatement, XACMLAuthzDecisionStatement): raise TypeError("Expecting %r class got %r" % (XACMLAuthzDecisionStatement, type(xacmlAuthzDecisionStatement))) if not xacmlAuthzDecisionStatement.xacmlContextResponse: raise AttributeError("No xacmlContextResponse has been set for the " "XACMLAuthzDecisionStatement") tag = str(QName.fromGeneric(cls.DEFAULT_ELEMENT_NAME)) elem = etree.makeEtreeElement(tag, cls.DEFAULT_ELEMENT_NAME.prefix, cls.DEFAULT_ELEMENT_NAME.namespaceURI) xacmlContextResponseElem = ResponseElementTree.toXML( xacmlAuthzDecisionStatement.xacmlContextResponse) elem.append(xacmlContextResponseElem) if xacmlAuthzDecisionStatement.xacmlContextRequest: xacmlContextRequestElem = RequestElementTree.toXML( xacmlAuthzDecisionStatement.xacmlContextRequest) elem.append(xacmlContextRequestElem) return elem
def _make_xacml_context_request(cls, httpMethod, resourceURI, resourceContents, subjectID, subjectIdFormat, actions=None): """Create a XACML Request. Include post data as resource content if the HTTP method is POST. :type httpMethod: str :param httpMethod: HTTP method :type resourceURI: str :param resourceURI: resource URI :type resourceContents: basestr :param resourceContents: resource contents XML as string :type subjectID: str :param subjectID: subject ID :type subjectIdFormat: str :param subjectIdFormat: subject ID format :type actions: list of str :param actions: actions """ if actions is None: actions = [] if httpMethod == 'GET': ### TODO Should action be related to HTTP method? return cls._createXacmlProfileRequestCtx(subjectIdFormat, subjectID, resourceURI, None, actions) elif httpMethod == 'POST': resourceContentsElem = ElementTree.XML(resourceContents) tag = str( QName(XacmlContextBase.XACML_2_0_CONTEXT_NS, XacmlResource.RESOURCE_CONTENT_ELEMENT_LOCAL_NAME)) resourceContent = etree.makeEtreeElement( tag, XacmlContextBase.XACML_2_0_CONTEXT_NS_PREFIX, XacmlContextBase.XACML_2_0_CONTEXT_NS) resourceContent.append(resourceContentsElem) request = cls._createXacmlProfileRequestCtx( subjectIdFormat, subjectID, resourceURI, resourceContent, actions) return request
def toXML(cls, xacmlAuthzDecisionQuery): """Create an XML representation of the input SAML Authorization Decision Query object @type xacmlAuthzDecisionQuery: saml.saml2.core.AuthzDecisionQuery @param xacmlAuthzDecisionQuery: SAML Authorization Decision Query @rtype: ElementTree.Element @return: Attribute Query as ElementTree XML element """ if not isinstance(xacmlAuthzDecisionQuery, XACMLAuthzDecisionQuery): raise TypeError("Expecting %r class got %r" % (XACMLAuthzDecisionQuery, type(xacmlAuthzDecisionQuery))) if not xacmlAuthzDecisionQuery.xacmlContextRequest: raise AttributeError("No xacmlContextRequest has been set for the " "XACMLAuthzDecisionQuery") issueInstant = SAMLDateTime.toString(xacmlAuthzDecisionQuery.issueInstant) attrib = { cls.ID_ATTRIB_NAME: xacmlAuthzDecisionQuery.id, cls.ISSUE_INSTANT_ATTRIB_NAME: issueInstant, # Nb. Version is a SAMLVersion instance and requires explicit cast cls.VERSION_ATTRIB_NAME: str(xacmlAuthzDecisionQuery.version), } tag = str(QName.fromGeneric(cls.DEFAULT_ELEMENT_NAME)) elem = etree.makeEtreeElement(tag, cls.DEFAULT_ELEMENT_NAME.prefix, cls.DEFAULT_ELEMENT_NAME.namespaceURI, **attrib) issuerElem = IssuerElementTree.toXML(xacmlAuthzDecisionQuery.issuer) elem.append(issuerElem) requestElem = RequestElementTree.toXML( xacmlAuthzDecisionQuery.xacmlContextRequest) elem.append(requestElem) return elem
def __call__(self, environ, start_response): """Check for and parse a SOAP SAML Attribute Query and return a SAML Response :type environ: dict :param environ: WSGI environment variables dictionary :type start_response: function :param start_response: standard WSGI start response function """ # Ignore non-matching path if environ['PATH_INFO'] not in (self.mountPath, self.mountPath + '/'): return self._app(environ, start_response) # Ignore non-POST requests if environ.get('REQUEST_METHOD') != 'POST': return self._app(environ, start_response) soapRequestStream = environ.get('wsgi.input') if soapRequestStream is None: raise SOAPQueryInterfaceMiddlewareError('No "wsgi.input" in ' 'environ') # TODO: allow for chunked data contentLength = environ.get('CONTENT_LENGTH') if contentLength is None: raise SOAPQueryInterfaceMiddlewareError('No "CONTENT_LENGTH" in ' 'environ') contentLength = int(contentLength) if contentLength <= 0: raise SOAPQueryInterfaceMiddlewareError('"CONTENT_LENGTH" in ' 'environ is %d' % contentLength) soapRequestTxt = soapRequestStream.read(contentLength) # Parse into a SOAP envelope object soapRequest = SOAPEnvelope() soapRequest.parse(StringIO(soapRequestTxt)) log.debug("SOAPQueryInterfaceMiddleware.__call__: received SAML " "SOAP Query: %s", soapRequestTxt) queryElem = soapRequest.body.elem[0] # Create a response with basic attributes if provided in the # initialisation config samlResponse = self._initResponse() try: queryType = QName.getLocalPart(queryElem.tag) if queryType == XACMLAuthzDecisionQuery.DEFAULT_ELEMENT_LOCAL_NAME: # Set up additional ElementTree parsing for XACML profile. etree_xacml_profile.setElementTreeMap() samlQuery = self.deserialiseXacmlProfile(queryElem) else: samlQuery = self.deserialise(queryElem) except UnknownAttrProfile, e: log.exception("%r raised parsing incoming query: %s" % (type(e), traceback.format_exc())) samlResponse.status.statusCode.value = \ StatusCode.UNKNOWN_ATTR_PROFILE_URI