Skip to content

Commit a0c8cb2

Browse files
Merge pull request #483 from skoranda/mdq_check_signature
Enable signature verification for MDQ
2 parents 05195ff + 8bf0e5c commit a0c8cb2

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

docs/howto/config.rst

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -183,25 +183,40 @@ the client key in an HTTPS session.
183183
metadata
184184
^^^^^^^^
185185

186-
Contains a list of places where metadata can be found. This can be either
187-
a file accessible on the server the service runs on, or somewhere on the net.::
186+
Contains a list of places where metadata can be found. This can be
187+
188+
* a local file accessible on the server the service runs on
189+
* a remote URL serving aggregate metadata
190+
* a metadata query protocol (MDQ) service URL
191+
192+
For example::
188193

189194
"metadata" : {
190195
"local": [
191-
"metadata.xml", "vo_metadata.xml"
192-
],
196+
"metadata.xml",
197+
"vo_metadata.xml",
198+
],
193199
"remote": [
194200
{
195-
"url":"https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2",
196-
"cert":"kalmar2.cert"
197-
}],
201+
"url": "https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2",
202+
"cert": "kalmar2.cert",
203+
},
204+
],
205+
"mdq": [
206+
{
207+
"url": "http://mdq.ukfederation.org.uk/",
208+
"cert": "ukfederation-mdq.pem",
209+
},
210+
],
198211
},
199212

200-
The above configuration means that the service should read two local
201-
metadata files, and on top of that load one from the net. To verify the
202-
authenticity of the file downloaded from the net, the local copy of the
203-
public key should be used.
204-
This public key must be acquired by some out-of-band method.
213+
The above configuration means that the service should read two aggregate local
214+
metadata files, one aggregate metadata file from a remote server, and query a
215+
remote MDQ server. To verify the authenticity of the metadata aggregate
216+
downloaded from the remote server and the MDQ server local copies of the
217+
metadata signing certificates should be used. These public keys must be
218+
acquired by some secure out-of-band method before being placed on the local
219+
file system.
205220

206221
organization
207222
^^^^^^^^^^^^

src/saml2/mdstore.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -779,32 +779,52 @@ def load(self, *args, **kwargs):
779779

780780

781781
class MetaDataMDX(InMemoryMetaData):
782-
""" Uses the md protocol to fetch entity information
782+
"""
783+
Uses the MDQ protocol to fetch entity information.
784+
The protocol is defined at:
785+
https://datatracker.ietf.org/doc/draft-young-md-query-saml/
783786
"""
784787

785788
@staticmethod
786789
def sha1_entity_transform(entity_id):
787790
return "{{sha1}}{}".format(
788791
hashlib.sha1(entity_id.encode("utf-8")).hexdigest())
789792

790-
def __init__(self, url, entity_transform=None):
793+
def __init__(self, url=None, security=None, cert=None,
794+
entity_transform=None, **kwargs):
791795
"""
792796
:params url: mdx service url
797+
:params security: SecurityContext()
798+
:params cert: certificate used to check signature of signed metadata
793799
:params entity_transform: function transforming (e.g. base64,
794800
sha1 hash or URL quote
795801
hash) the entity id. It is applied to the entity id before it is
796802
concatenated with the request URL sent to the MDX server. Defaults to
797803
sha1 transformation.
798804
"""
799-
super(MetaDataMDX, self).__init__(None, '')
805+
super(MetaDataMDX, self).__init__(None, **kwargs)
806+
if not url:
807+
raise SAMLError('URL for MDQ server not specified.')
808+
800809
self.url = url.rstrip('/')
801810

802811
if entity_transform:
803812
self.entity_transform = entity_transform
804813
else:
805-
806814
self.entity_transform = MetaDataMDX.sha1_entity_transform
807815

816+
self.cert = cert
817+
self.security = security
818+
819+
# We assume that the MDQ server will return a single entity
820+
# described by a single <EntityDescriptor> element. The protocol
821+
# does allow multiple entities to be returned in an
822+
# <EntitiesDescriptor> element but we will not currently support
823+
# that use case since it is unlikely to be leveraged for most
824+
# flows.
825+
self.node_name = "%s:%s" % (md.EntityDescriptor.c_namespace,
826+
md.EntityDescriptor.c_tag)
827+
808828
def load(self, *args, **kwargs):
809829
# Do nothing
810830
pass
@@ -906,8 +926,17 @@ def load(self, *args, **kwargs):
906926
key = args[1]
907927
_md = MetaDataLoader(self.attrc, args[1], **_args)
908928
elif typ == "mdq":
909-
key = args[1]
910-
_md = MetaDataMDX(args[1])
929+
if 'url' in kwargs:
930+
key = kwargs['url']
931+
url = kwargs['url']
932+
cert = kwargs.get('cert')
933+
security = self.security
934+
entity_transform = kwargs.get('entity_transform', None)
935+
_md = MetaDataMDX(url, security, cert, entity_transform)
936+
else:
937+
key = args[1]
938+
url = args[1]
939+
_md = MetaDataMDX(url)
911940
else:
912941
raise SAMLError("Unknown metadata type '%s'" % typ)
913942
_md.load()

0 commit comments

Comments
 (0)