Skip to content

Commit 4a30461

Browse files
committed
add pipe to extract trustinfo from entity attribute
1 parent 5144000 commit 4a30461

File tree

4 files changed

+209
-0
lines changed

4 files changed

+209
-0
lines changed

src/pyff/builtins.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from pyff.samlmd import (
3232
annotate_entity,
3333
discojson_sp_t,
34+
discojson_sp_attr_t,
3435
discojson_t,
3536
entitiesdescriptor,
3637
find_in_document,
@@ -1044,6 +1045,36 @@ def _discojson_sp(req, *opts):
10441045
return json.dumps(res)
10451046

10461047

1048+
@pipe(name='discojson_sp_attr')
1049+
def _discojson_sp_attr(req, *opts):
1050+
"""
1051+
1052+
Return a json representation of the trust information
1053+
1054+
.. code-block:: yaml
1055+
discojson_sp_attr:
1056+
1057+
SP Entities can carry trust information as a base64 encoded json blob
1058+
as an entity attribute with name `http://refeds.org/entity-selection-profile`.
1059+
The schema of this json is the same as the one produced above from XML
1060+
with the pipe `discojson_sp`, and published at:
1061+
1062+
https://github.com/TheIdentitySelector/thiss-mdq/blob/master/trustinfo.schema.json
1063+
1064+
:param req: The request
1065+
:param opts: Options (unusued)
1066+
:return: returns a JSON doc
1067+
1068+
"""
1069+
1070+
if req.t is None:
1071+
raise PipeException("Your pipeline is missing a select statement.")
1072+
1073+
res = discojson_sp_attr_t(req)
1074+
1075+
return json.dumps(res)
1076+
1077+
10471078
@pipe
10481079
def sign(req: Plumbing.Request, *_opts):
10491080
"""

src/pyff/samlmd.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import json
12
import traceback
3+
from base64 import b64decode
24
from copy import deepcopy
35
from datetime import datetime, timedelta, timezone
46
from str2bool import str2bool
@@ -1044,6 +1046,37 @@ def discojson_sp_t(req):
10441046
return d
10451047

10461048

1049+
def discojson_sp_attr(e):
1050+
1051+
attribute = "http://refeds.org/entity-selection-profile"
1052+
b64_trustinfos = entity_attribute(e, attribute)
1053+
if b64_trustinfos is None:
1054+
return None
1055+
1056+
sp = {}
1057+
sp['entityID'] = e.get('entityID', None)
1058+
sp['profiles'] = {}
1059+
1060+
for b64_trustinfo in b64_trustinfos:
1061+
str_trustinfo = b64decode(b64_trustinfo.encode('ascii'))
1062+
trustinfo = json.loads(str_trustinfo.decode('utf8'))
1063+
sp['profiles'].update(trustinfo['profiles'])
1064+
1065+
return sp
1066+
1067+
1068+
def discojson_sp_attr_t(req):
1069+
d = []
1070+
t = req.t
1071+
1072+
for e in iter_entities(t):
1073+
sp = discojson_sp_attr(e)
1074+
if sp is not None:
1075+
d.append(sp)
1076+
1077+
return d
1078+
1079+
10471080
def sha1_id(e):
10481081
return hash_id(e, 'sha1')
10491082

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:xrd="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:pyff="http://pyff.io/NS" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ser="http://eidas.europa.eu/metadata/servicelist" xmlns:eidas="http://eidas.europa.eu/saml-extensions" xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport" xmlns:samla="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init" xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" xmlns:wayf="http://sdss.ac.uk/2006/06/WAYF" xmlns:req-attr="urn:oasis:names:tc:SAML:protcol:ext:req-attr" Name="test">
3+
<md:EntityDescriptor entityID="https://example.com/shibboleth">
4+
<md:Extensions>
5+
<mdrpi:RegistrationInfo registrationAuthority="http://www.swamid.se/" registrationInstant="2015-02-11T11:09:51Z">
6+
<mdrpi:RegistrationPolicy xml:lang="en">http://swamid.se/policy/mdrps</mdrpi:RegistrationPolicy>
7+
</mdrpi:RegistrationInfo>
8+
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
9+
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/>
10+
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
11+
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha224"/>
12+
<alg:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
13+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"/>
14+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"/>
15+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
16+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224"/>
17+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
18+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"/>
19+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
20+
<alg:SigningMethod Algorithm="http://www.w3.org/2009/xmldsig11#dsa-sha256"/>
21+
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/>
22+
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
23+
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
24+
<mdattr:EntityAttributes>
25+
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="http://macedir.org/entity-category">
26+
<saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
27+
</saml:Attribute>
28+
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="http://refeds.org/entity-selection-profile">
29+
<saml:AttributeValue>ewogICJwcm9maWxlcyI6IHsKICAgICJpbmNvbW1vbi13YXlmaW5kZXIiOiB7CiAgICAgICAic3RyaWN0IjogdHJ1ZSwKICAgICAgICJlbnRpdGllcyI6IFsKICAgICAgICAgewogICAgICAgICAgICJzZWxlY3QiOiAiaHR0cHM6Ly9tZHEuaW5jb21tb24ub3JnL2VudGl0aWVzIiwKICAgICAgICAgICAibWF0Y2giOiAibWRfc291cmNlIiwKICAgICAgICAgICAiaW5jbHVkZSI6IHRydWUKICAgICAgICAgfQogICAgICAgXQogICAgfQogIH0KfQ==</saml:AttributeValue>
30+
</saml:Attribute>
31+
</mdattr:EntityAttributes>
32+
</md:Extensions>
33+
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
34+
<md:Extensions>
35+
<init:RequestInitiator Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://cpauth.icos-cp.eu/saml/login"/>
36+
<mdui:UIInfo>
37+
<mdui:DisplayName xml:lang="en">Carbon Portal authentication service</mdui:DisplayName>
38+
<mdui:DisplayName xml:lang="sv">Kolportalens autentiseringstjänst</mdui:DisplayName>
39+
<mdui:Description xml:lang="en">Single Sign On for services of ICOS Carbon Portal. Maintained by the Carbon Portal team at Physical Geography department (nateko.lu.se).</mdui:Description>
40+
<mdui:Description xml:lang="sv">Single Sign On tjänst för ICOS Kolportalen. Hanteras av Carbon Portal teamet på INES (nateko.lu.se).</mdui:Description>
41+
<mdui:PrivacyStatementURL xml:lang="en">https://cpauth.icos-cp.eu/saml/privacyStatement</mdui:PrivacyStatementURL>
42+
<mdui:InformationURL xml:lang="en">https://www.icos-cp.eu/</mdui:InformationURL>
43+
<mdui:InformationURL xml:lang="sv">https://www.icos-cp.eu/</mdui:InformationURL>
44+
<mdui:PrivacyStatementURL xml:lang="sv">https://cpauth.icos-cp.eu/saml/privacyStatement</mdui:PrivacyStatementURL>
45+
</mdui:UIInfo>
46+
</md:Extensions>
47+
<md:KeyDescriptor>
48+
<ds:KeyInfo>
49+
<ds:KeyName>cpauth.icos-cp.eu</ds:KeyName>
50+
<ds:X509Data>
51+
<ds:X509SubjectName>CN=cpauth.icos-cp.eu</ds:X509SubjectName>
52+
<ds:X509Certificate>MIIEJzCCAw+gAwIBAgIJANC3VWNs7fbTMA0GCSqGSIb3DQEBCwUAMIGpMQswCQYD
53+
VQQGEwJTRTERMA8GA1UECAwIU2vDg8KlbmUxDTALBgNVBAcMBEx1bmQxGzAZBgNV
54+
BAoMEklDT1MgQ2FyYm9uIFBvcnRhbDEfMB0GA1UECwwWQXV0aGVudGljYXRpb24g
55+
U2VydmljZTEaMBgGA1UEAwwRY3BhdXRoLmljb3MtY3AuZXUxHjAcBgkqhkiG9w0B
56+
CQEWD2luZm9AaWNvcy1jcC5ldTAeFw0xNTAyMDUxMjI0MzZaFw0yNTAyMDIxMjI0
57+
MzZaMIGpMQswCQYDVQQGEwJTRTERMA8GA1UECAwIU2vDg8KlbmUxDTALBgNVBAcM
58+
BEx1bmQxGzAZBgNVBAoMEklDT1MgQ2FyYm9uIFBvcnRhbDEfMB0GA1UECwwWQXV0
59+
aGVudGljYXRpb24gU2VydmljZTEaMBgGA1UEAwwRY3BhdXRoLmljb3MtY3AuZXUx
60+
HjAcBgkqhkiG9w0BCQEWD2luZm9AaWNvcy1jcC5ldTCCASIwDQYJKoZIhvcNAQEB
61+
BQADggEPADCCAQoCggEBAM2QN1jaZJeuPAH+4sVMZKk7vg4JIbUuTMKk0+KIAg5M
62+
XiVsRiEUjY+LtIncrvA/kf2CIySI0WkbwZMjcDd03hNj4kLWhuyxfOCwDO6DsUbG
63+
MbyI6HIYWXJp5ljfEEFgtMqT3dDtD5vwq8h4Zy20ukxOoIokKczrAvn4JjkMsj6Z
64+
0CEAFBC29o4E8PWQbUBgvt6Z+2ao+RHMLD7nZVBx98Occ9KfnYnDDd9Oi1XFe009
65+
zaSbcqY2RpN8I9hcW/KQf3KnGW5xZ5dr4rhGklCkYr+h0W3xKu+hin8bk91t1Dkr
66+
gaKl/N7M3Oof3k+7ZBlwaV97es5InWCeNgDxCGkBRNsCAwEAAaNQME4wHQYDVR0O
67+
BBYEFDcD7MVudooGaNRYqXBYqQi3VzGxMB8GA1UdIwQYMBaAFDcD7MVudooGaNRY
68+
qXBYqQi3VzGxMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABS02eZS
69+
weXGMJ2fEIy2JH0VhCbjuX/rz+8Hfh9LjzNb3QwKHuwP83yvPqRulV9FYmvOoK8T
70+
fMou5aW0mZ+QgJNKOrxY5vFxUq6pn3OiYbBu3m1C9ajbU/nx2evzt4+qUwTfHFb+
71+
ZgXpOtmxRekFzVvGZ18BSPJKwAAqqZ11X7skT/NwEAhbgplVPv9WkDmDzqNvHqQJ
72+
nyRgD2ZqUPU9nEOjGy0gI07dciVcYZQ+CiZeSECIWgQwjDEBDuwMCVAZA6gfdz6C
73+
KJuN+RUSKPEcxPxle1MiB4MU0ei5X4xUbvLWKn9Ok7TOXg2BpnMAv6eON1wVo0Aa
74+
D265cqy6Le/toVg=</ds:X509Certificate>
75+
</ds:X509Data>
76+
</ds:KeyInfo>
77+
<md:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes128-gcm"/>
78+
<md:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes192-gcm"/>
79+
<md:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes256-gcm"/>
80+
<md:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
81+
<md:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes192-cbc"/>
82+
<md:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
83+
<md:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
84+
<md:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep"/>
85+
<md:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
86+
</md:KeyDescriptor>
87+
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://cpauth.icos-cp.eu/saml/SAML2/POST" index="1" isDefault="true"/>
88+
<md:AttributeConsumingService index="1">
89+
<md:ServiceName xml:lang="en">ICOS Carbon Portal SAML service</md:ServiceName>
90+
<md:ServiceName xml:lang="sv">ICOS Kolportalens SAML tjänst</md:ServiceName>
91+
<md:RequestedAttribute FriendlyName="givenName" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
92+
<md:RequestedAttribute FriendlyName="sn" Name="urn:oid:2.5.4.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
93+
<md:RequestedAttribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
94+
</md:AttributeConsumingService>
95+
</md:SPSSODescriptor>
96+
<md:Organization>
97+
<md:OrganizationName xml:lang="en">ICOS Carbon Portal</md:OrganizationName>
98+
<md:OrganizationName xml:lang="sv">ICOS Kolportalen</md:OrganizationName>
99+
<md:OrganizationDisplayName xml:lang="en">Carbon Portal</md:OrganizationDisplayName>
100+
<md:OrganizationDisplayName xml:lang="sv">Kolportalen</md:OrganizationDisplayName>
101+
<md:OrganizationURL xml:lang="en">https://www.icos-cp.eu/</md:OrganizationURL>
102+
<md:OrganizationURL xml:lang="sv">https://www.icos-cp.eu/</md:OrganizationURL>
103+
</md:Organization>
104+
<md:ContactPerson contactType="technical">
105+
<md:GivenName>Oleg</md:GivenName>
106+
<md:SurName>Mirzov</md:SurName>
107+
<md:EmailAddress>mailto:[email protected]</md:EmailAddress>
108+
</md:ContactPerson>
109+
<md:ContactPerson contactType="administrative">
110+
<md:GivenName>Alex</md:GivenName>
111+
<md:SurName>Vermeulen</md:SurName>
112+
<md:EmailAddress>mailto:[email protected]</md:EmailAddress>
113+
</md:ContactPerson>
114+
</md:EntityDescriptor></md:EntitiesDescriptor>

src/pyff/test/test_pipeline.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,3 +757,34 @@ def test_discojson_sp(self):
757757
pass
758758
finally:
759759
shutil.rmtree(tmpdir)
760+
761+
def test_discojson_sp_trustinfo_in_attr(self):
762+
with patch.multiple("sys", exit=self.sys_exit):
763+
tmpdir = tempfile.mkdtemp()
764+
os.rmdir(tmpdir) # lets make sure 'store' can recreate it
765+
try:
766+
self.exec_pipeline("""
767+
- load:
768+
- file://%s/metadata/test-sp-trustinfo-in-attr.xml
769+
- select
770+
- discojson_sp_attr
771+
- publish:
772+
output: %s/disco_sp_attr.json
773+
raw: true
774+
update_store: false
775+
""" % (self.datadir, tmpdir))
776+
fn = "%s/disco_sp_attr.json" % tmpdir
777+
assert os.path.exists(fn)
778+
with open(fn, 'r') as f:
779+
sp_json = json.load(f)
780+
781+
assert 'https://example.com/shibboleth' in str(sp_json)
782+
example_sp_json = sp_json[0]
783+
assert 'incommon-wayfinder' in example_sp_json['profiles']
784+
tinfo = example_sp_json['profiles']['incommon-wayfinder']
785+
assert tinfo['entities'][0] == {'select': 'https://mdq.incommon.org/entities', 'match': 'md_source', 'include': True}
786+
assert tinfo['strict']
787+
except IOError:
788+
pass
789+
finally:
790+
shutil.rmtree(tmpdir)

0 commit comments

Comments
 (0)