[doc] New bits of documentation

This commit is contained in:
Mikaël Ates 2011-10-20 22:27:41 +02:00
parent 960ae678f9
commit 937e6b8183
13 changed files with 665 additions and 432 deletions

View File

@ -22,9 +22,9 @@ the user session.
Attributes can thus be proxyfied during SSO with Authentic2
configured as a SAML2 proxy.
The namespace of attributes received from another SAML2 IdP or pushed in the
assertion given in to service providers can be configured per attribute or per
service provider.
The namespace of attributes received from another SAML2 IdP and of attributes
pushed in the assertion given to service providers can be configured per
attribute or per service provider.
By default, the namespace and format of attributes in assertion is conformant
to the SAMLV2.0 X500/LDAP Attribute profile::
@ -50,8 +50,8 @@ profile can also be used, for instance::
Configuration
=============
Configure sources of attributes
-------------------------------
Configure local sources of attributes
-------------------------------------
The source of attributes for authentic2 are of two kinds. The LDAP sources and
the user django profile.
@ -123,8 +123,8 @@ user alias in source is created for the user:
.. image:: pictures/alias_in_source_saved.png
:width: 800 px
Configure attributes pushed to SAML2 service providers in SSO response
----------------------------------------------------------------------
Configure attributes from local sources pushed to SAML2 service providers in SSO response
-----------------------------------------------------------------------------------------
Reminder:
@ -206,65 +206,188 @@ __________________________________________
.. image:: pictures/policy_pull_renamed.png
:width: 800 px
Handle attributes provided by other Identity providers, proxy attributes
------------------------------------------------------------------------
Handle attributes provided by other Identity providers and pushed to SAML2 service providers in SSO response (proxy attributes)
-------------------------------------------------------------------------------------------------------------------------------
Link to configure first Authentic as a sp to have attributes in session
To have these kind of attributes to forward, authentic must be configured as a
SAML2 service provider, see the corresponding administration page
:ref:`config_saml2_idp`.
Add a source if mapping set to true
Forward all attributes in session without any modification
__________________________________________________________
Create or modify an attribute policy activating the option 'Forward attributes from push sources' and save.
**No other option below must be used.**
.. image:: pictures/attr_policy_forward.png
:width: 800 px
**Attach policy to the service provider if it is not yet the case.**
**No need to deal with namespace here.**
Filter attributes from source only
__________________________________
Here, you want to forward **all** attributes of selected source of attributes.
First of all you need to create objects corresponding to the sources of
attributes.
**The name of the source object must be the entity ID of the SAML2
identity provider.**
1. Go to http[s]://your.domain.com/admin/attribute_aggregator/attributesource/add/
2. Set the name (No need to change the namespace)
.. image:: pictures/attr_source_idp.png
:width: 800 px
3. Save
.. image:: pictures/attr_source_idp_saved.png
:width: 800 px
Then create or modify an attribute policy activating the option **'Forward attributes from push sources'**.
You then select the source you want to forward attributes through the selection box and you save.
.. image:: pictures/attr_policy_filter_source.png
:width: 800 px
**Attach policy to the service provider if it is not yet the case.**
**No need to deal with namespace here.**
Modify namespace of attributes forwarded when attributes forwarded are not filtered or when filtered according to the source
____________________________________________________________________________________________________________________________
The system needs to 'recognise the attributes' to perform the mapping.
For this, you need to indicate the namespace of attributes received per source
if the namespace is not the one of Authentic2 (X500/LDAP and extensions edu*
and supann).
In other words if the source provides attributes in a different namespace, you
need to create objects corresponding to the sources of attributes and indicate
there the right namespace. By default, the only other supported namespace is
http://schemas.xmlsoap.org/ws/2005/05/identity/claims.
.. image:: pictures/attr_source_idp_claims.png
:width: 800 px
Then create or modify an attribute policy activating the options 'Forward attributes from push sources',
**'Map attributes from push sources'**. You also choose the output namespace expected with the
parameters **'Output name format'** and **'Output namespace'**.
.. image:: pictures/attr_policy_map_ns.png
:width: 800 px
Remind that the default namespace is X500/LDAP + edu* + supann and the only other supported namespace is
http://schemas.xmlsoap.org/ws/2005/05/identity/claims.
**Attach policy to the service provider if it is not yet the case.**
Filter attributes with a list of attributes, with or without choosing the source
________________________________________________________________________________
The system needs to 'recognise the attributes' to filter the attributes
according to a list of attributes.
For this, you need to indicate the namespace of attributes received per source
if the namespace is not the one of Authentic2 (X500/LDAP and extensions edu*
and supann).
In other words if the source provides attributes in a different namespace, you
need to create objects corresponding to the sources of attributes and indicate
there the right namespace. By default, the only other supported namespace is
http://schemas.xmlsoap.org/ws/2005/05/identity/claims.
.. image:: pictures/attr_source_idp_claims.png
:width: 800 px
You then create an attribute list as described in section *'Create a named list of attribute items'*.
Then create or modify an attribute policy activating the option **'Forward attributes from push sources'**.
You then associate the list of attributes.
.. image:: pictures/attr_policy_filter_attributes.png
:width: 800 px
If you want to also filter according to the source you can configure it as defined in section *'Filter attributes from source only'*. You can also choose to filter
with the source indicate per attribute item of the list. For this select the option **'Filter source of filtered attributes'**.
.. image:: pictures/attr_policy_filter_attributes_source.png
:width: 800 px
.. image:: pictures/attribute_item.png
:width: 800 px
The default name format is BASIC. You can however change the name format and namespace with the option **'Map attributes from push sources'** and the parameters **'Output name format'** and **'Output namespace'**.
Using the option **'Map attributes of filtered attributes'** the output name format and namespace are the ones indicated per attribute item of the list.
.. image:: pictures/attr_policy_filter_attributes_map.png
:width: 800 px
.. image:: pictures/attribute_item.png
:width: 800 px
Push manually (writing bits of code) attributes to SAML2 service providers in SSO response
------------------------------------------------------------------------------------------
In idp/signals.py connect to the add_attributes_to_response signal::
add_attributes_to_response.connect(your_function)
Your function must return an attribute dictionnary as follows::
dic = {}
attributes = {}
attributes[name] = (value1, value2, )
attributes[(name, format)] = (value1, value2, )
attributes[(name, format, nickname)] = (value1, value2, )
dic['attributes'] = attributes
return dic
*format* must be in (lasso.SAML2_ATTRIBUTE_NAME_FORMAT_URI,
lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC)
You can use the attributes form the local source and the attributes in the
session that are pushed by other identity providers.
Attributes in the session are in::
request.session['multisource_attributes']
See the page :ref:`attributes_in_session`.
If you want to use local source of attributes and use mapping capabilities
of the UserAttributeProfile see the page :ref:`attribute_management_explained`.
Use the file idp/attributes.py as an exemple.
Modifying supported namespaces and attribute name mappings
==========================================================
TBD
The mapping is defined in the file attribute_aggregatore/mapping.py
Explanation (Draft)
===================
The manual modification of this file is necessary to extend the default schema
and mappings.
Attribute aggegrator module
---------------------------
Add new namespaces in ATTRIBUTE_NAMESPACES.
The core attribute management is based on the attribute aggregator module.
To extend the default schema add key/value in ATTRIBUTE_MAPPING, for instance::
Intro
_____
"displayName": {
"oid": "2.16.840.1.113730.3.1.241",
"display_name": _("displayName"),
"type": "http://www.w3.org/2001/XMLSchema#string",
"syntax": "1.3.6.1.4.1.1466.115.121.1.15",
},
Attribute aggregator provides a main Model class called UserAttributeProfile,
functions to load attributes and extract attributes.
The mapping between attribute namespaces is built-in and depends on a unique
file (mapping.py).
A main schema is defined and is based on LDAP/X500 for naming. The support
of http://schemas.xmlsoap.org/ws/2005/05/identity/claims is partly complete.
Source of attributes are connected with attribute loading functions using
signals.
FAQ
___
Why not use the Django User profile?
The django user profile needs to define attributes as class attributes and
then support form filling or mapping with LDAP.
That is useful and may be used, especially because the profile can be used as
a source of attribute to load in the attribute_aggregator profile.
The attribute_aggregator profile allow to load multivalued attributes from any
source supported (LDAP, Django profile and attributes in Django session for
now) from any namespace defined in mapping.py (LDAP/X500 and claims for now).
The profile can be loaded giving a source or a list of attribute, or can be
from any known source, or with a dictionnary.
Attributes can be extracted with many functions in any namespace supported.
Quick explanation
_________________
The schema is defined in mapping.py and is made of definitions like this::
Add mapping of attribute name extending attribute entries in ATTRIBUTE_MAPPING,
for instance::
"sn": {
"oid": "2.5.4.4",
@ -276,7 +399,7 @@ The schema is defined in mapping.py and is made of definitions like this::
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims": {
"identifiers":
[
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
],
"friendly_names":
[
@ -285,379 +408,3 @@ The schema is defined in mapping.py and is made of definitions like this::
}
}
},
The profile store all the data in a text field taht contains a cPickle list of
instances of the class AttributeData.
The profile is attached to a user and then can be created or loaded with::
profile = load_or_create_user_profile(user=user)
User may be None to create a temporary profile for an anonymous user. But
that need a DB cleaning function not implemented.
The model *UserAttributeProfile*
________________________________
The model 'UserAttributeProfile' can be attached to a user and then persist
(as a Model).
When the profile is loaded, all data stored are removed expect if the
the data has an expiration date later.
The profile provide several methods to store and extract attributes.
All the methods to add attributes are based on a main one accepting a
dictionnary of attribute is parameters 'load_by_dic()'. The other methods
('load_listed_attributes()', 'load_greedy()') send a signal with a list of
attributes (listed_attributes_call) or not (any_attributes_call) to grab a
dictionnary. The list is given with the definition name, oid or friendly name
of the attribute in the system namespace.
Into the dictionnary, attributes are given with their name, oid or friendly
name in the default namespace or with their name in a namepsace. An expiration
date can also be given (ISO8601 format), if none, attribute will be deleted at
next profile loading. The dictionnary format is as follows::
attributes = dict()
data_from_source = list()
a1 = dict()
a1['oid'] = definition_name
Or
a1['definition'] = definition_name
definition may be the definition name like 'gn'
or an alias like 'givenName'
Or
a1['name'] = attribute_name_in_ns
a1['namespace'] = ns_name
a1['expiration_date'] = date
a1['values'] = list_of_values
data_from_source.append(a1)
...
data_from_source.append(a2)
attributes[source_name] = data_from_source
Getters are defined to extract data from a profile. Only AttributeData
instances are extracted that assume that any attribute namespace can be used.
* get_data_of_definition(definition)
Return a list of AttributeData instances corresponding to the definition
given.
* get_freshest_data_of_definition(definition)
Return the freshest AttributeData instance. If multiple with no or same exp
date, random. Should use the creation date soon.
* get_data_of_source
Return a list of AttributeData instances corresponding to the source given.
* get_data_of_source_by_name
Idem but source name is given, not a Source instance.
* get_data_of_definition_and_source
Return a list of AttributeData instances corresponding to the definition and
source given.
* get_data_of_definition_and_source_by_name
Idem but source name is given, not a Source instance.
SAML2 attribute representation in assertions
--------------------------------------------
SAML2 attribute profile (saml-profiles-2.0-os - Section 8) defines two kind of
attribute element syntax in the attribute statement of assertions, also
called *name format*:
- BASIC::
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
- URI::
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
*URI should be used when attributes have "universally" known unique names
like OID.*
Example::
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
Name="FirstName">
<saml:AttributeValue xsi:type="xs:string">By-Tor</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute
xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
Name="urn:oid:2.5.4.42" FriendlyName="givenName">
<saml:AttributeValue xsi:type="xs:string"
x500:Encoding="LDAP">Steven</saml:AttributeValue>
</saml:Attribute>
BASIC
_____
Two <Attribute> elements refer to the same SAML attribute if and only if the
values of their Name XML attributes are equal in the sense of Section 3.3.6 of
[Schema2].
No additional XML attributes are defined for use with the <Attribute> element.
The schema type of the contents of the <AttributeValue> element MUST be drawn
from one of the types defined in Section 3.3 of [Schema2]. The xsi:type
attribute MUST be present and be given the appropriate value.
X.500/LDAP Attribute Profile (URI)
__________________________________
**Extracted from the SAML2 core specifications**
Two <Attribute> elements refer to the same SAML attribute if and only if their
Name XML attribute values are equal in the sense of [RFC3061]. The
FriendlyName attribute plays no role in the comparison.
Directory attribute type definitions for use in native X.500 directories
specify the syntax of the attribute using ASN.1 [ASN.1]. For use in LDAP,
directory attribute definitions additionally include an LDAP syntax which
specifies how attribute or assertion values conforming to the syntax are to be
represented when transferred in the LDAP protocol (known as an LDAP-specific
encoding). The LDAP-specific encoding commonly produces Unicode characters in
UTF-8 form. This SAML attribute profile specifies the form of SAML attribute
values only for those directory attributes which have LDAP syntaxes. Future
extensions to this profile may define attribute value formats for directory
attributes whose syntaxes specify other encodings.
To represent the encoding rules in use for a particular attribute value, the
<AttributeValue> element MUST contain an XML attribute named Encoding defined
in the XML namespace urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500.
For any directory attribute with a syntax whose LDAP-specific encoding
exclusively produces UTF-8 character strings as values, the SAML attribute
value is encoded as simply the UTF-8 string itself, as the content of the
<AttributeValue> element, with no additional whitespace.
In such cases, the xsi:type XML attribute MUST be set to xs:string.
The profile-specific Encoding XML attribute is provided, with a value of LDAP.
The AttributeData instances have a field expiration_data. It the profile
exists, obsolete data are removed at loading.
When authentic 2 deals with attributes and needs mapping?
---------------------------------------------------------
Authentic2 behaves as an attribute provider:
* At the SSO login
* When an attribute request is received
Authentic requests (e.g. by soap) are not yet supported.
When Authentic2 behaves as an attribute provider at SSO login
_____________________________________________________________
At a SSO request, just before responding to the service provider, the saml2
idp module sends the signal 'add_attributes_to_response' giving the SP entity
ID.
The signal is connected to the function 'provide_attributes_at_sso()' in
charge of providing the attributes at the SSO for this SP.
**Attributes sources are of two kinds. The first ones are the sources that can
be requested by the IdP with a syncrhonous binding without user intercations.
These sources are called pull sources. They are for now limited to LDAP
sources. The other ones are sources are asyncrhonous bindings, usually
requiring user interactions. These sources are called push sources. They are
now limited to the attributes provided at SSO requests when the IdP acts as a
SAML2 SP. There attributes are put/found in the Django session.**
Each source in the system is declared with an instance of the AttributeSource
model. We'll see later that to forward attributes of push sources it is not
necessary that a source is declared in some circumstances.
To manage these sources an attribute policy is attached to services providers.
Then the service provider model must be extended with a attribute
attributes_at_sso_policy. The service provider must send the signal
'add_attributes_to_response'.
The implementation is actually done for SAML2 providers.
**In such a policy attributes from pull and push sources are treated
differently.**
**For pull sources, a list of attributes is indicated. Either an attribute is
searched in all the pull sources and whatever attribute value found is
returned. Or each attribute is indicated with a source. With each attribute is
indicated the output format and namespace.**
**The policy may also indicate that all the attributes in the Django session
must be forwarded. Then, no AttributeSource instance is required. All the
attributes are then forwarded without treating input namespace considerations.
When an AttributeSource instance is found, the input namespace of this source
is considered. An option can then be set to tell that the output format and
namespace must be taken. A list of attribute can also be given.
This list can be use to filter attributes to forward without or without taking
care of the source. The output namespace and format can also be trated per
attribute.**
If the namespace is default, the attribute names will be taken from the
system namespace. In BASIC the name will be the definition name. In URI, the
Name will be the OID in urn format and the friendly name will be the
definition name. If a namespace is given, the first identifier of this
attribute is taken as Name in BASIC. In URI, the same and the first friendly
name is taken.
::
class LibertyServiceProvider(models.Model):
...
attribute_policy = models.ForeignKey(AttributePolicy,
verbose_name=_("Attribute policy"), null=True, blank=True)
class AttributePolicy(models.Model):
# List of attributes to provide from pull sources at SSO Login.
# If an attribute is indicate without a source, from any source.
# The output format and namespace is given by each attribute.
attribute_list_for_sso_from_pull_sources = \
models.ForeignKey(LibertyAttributeMap,
related_name = "attributes of pull sources",
blank = True, null = True)
# Set to true for proxying attributes from pull sources at SSO Login.
# Attributes are in session.
# All attributes are forwarded as is except if the parameter
# 'attribute_list_for_sso_from_push_sources' is initialized
forward_attributes_from_pull_sources = models.BooleanField(default=False)
# Map attributes in session
# forward_attributes_in_session must be true
# At False, all attributes are forwarded as is
# At true, look for the namespace of the source for input, If not found,
# system namespace. Look for the options attribute_name_format and
# output_namespace of the attribute policy for output.
map_attributes_from_pull_sources = models.BooleanField(default=False)
# ATTRIBUTE_VALUE_FORMATS[0] =>
# (lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC, 'SAMLv2 BASIC')
output_name_format = models.CharField(max_length = 100,
choices = ATTRIBUTE_VALUE_FORMATS,
default = ATTRIBUTE_VALUE_FORMATS[0])
#ATTRIBUTES_NS[0] => ('Default', 'Default')
output_namespace = models.CharField(max_length = 100,
choices = ATTRIBUTES_NS, default = ATTRIBUTES_NS[0])
# Filter attributes pushed from source.
source_filter_for_sso_from_push_sources = \
models.ManyToManyField(AttributeSource,
related_name = "attributes of pull sources",
blank = True, null = True)
# List of attributes to filter from pull sources at SSO Login.
attribute_filter_for_sso_from_push_sources = \
models.ForeignKey(LibertyAttributeMap,
related_name = "attributes of pull sources",
blank = True, null = True)
# The sources of attributes of the previous list are considered.
# May be used conjointly with 'source_filter_for_sso_from_push_sources'
filter_source_of_filtered_attributes = models.BooleanField(default=False)
# To map the attributes of forwarded attributes with the defaut output
# format and namespace, use 'map_attributes_from_pull_sources'
# Use the following option to use the output format and namespace
# indicated for each attribute.
map_attributes_of_filtered_attributes = models.BooleanField(default=False)
# Set to true to take in account missing required attributes
send_error_and_no_attrs_if_missing_required_attrs = \
models.BooleanField(default=False)
class Meta:
verbose_name = _('attribute options policy')
verbose_name_plural = _('attribute options policies')
class AttributeList(models.Model):
name = models.CharField(max_length = 40, unique = True)
attributes = models.ManyToManyField(AttributeItem,
related_name = "attributes of the list",
blank = True, null = True)
class AttributeItem(models.Model):
attribute_name = models.CharField(max_length = 100, choices = ATTRIBUTES,
default = ATTRIBUTES[0])
# ATTRIBUTE_VALUE_FORMATS[0] =>
# (lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC, 'SAMLv2 BASIC')
output_attribute_name_format = models.CharField(max_length = 100,
choices = ATTRIBUTE_VALUE_FORMATS,
default = ATTRIBUTE_VALUE_FORMATS[0])
#ATTRIBUTES_NS[0] => ('Default', 'Default')
output_namespace = models.CharField(max_length = 100,
choices = ATTRIBUTES_NS, default = ATTRIBUTES_NS[0])
required = models.BooleanField(default=False)
source = models.ForeignKey(AttributeSource, blank = True, null = True)
A list of attributes can also be taken from the service provider metadata and
added to 'attribute_list_for_sso_from_pull_sources'. The namespace may be
extracted from the metadata. This namespace is then used to look for the
corresponding definition and then to provide the attribute in the right
namespace. Read attributes from metadata is not yet supported.
For the attributes of pull sources, once the list of attributes is defined,
They are loaded in the user profile.
As explained before the attribute_aggregator loading function send signals to
grab dictionnary of attributes. Up to know, only the ldap loading function are
connected to these signals. The namespace of LDAP sources is assumed to be
the same as the system namespace. There is here then no mapping needed. Other
kind of sources than LDAP can be defined in attribute aggregator.
To grab attributes from a LDAP the user dn in the LDAP or at least a local
identifier in the LDAP is required. For this purpose, each user has alias
associated with LDAP source. These aliases must their DN in the LDAP. When
the authentication LDAP backend will be taken in account, the dn will be taken
direclty from the user Model instance.
Each LDAP sources are declared with the binding parameters. The LDAP namespace
is always 'Default'.
If an attribute to load is not found and is required the answer should report
an error (Not yet implemented).
Attributes in response can also be provided with other means than from an LDAP
source. Attributes can be put in the user Django session and then loaded in
the profile. An option of the service provier indicate if attributes in the
session must be provided to the service provider.
To have the attribute loaded from the session, they must be provided in the
session as follows:
request.session['attributes'][source_name] = list()
The source_name must be the name of an existing instance of an
'AttributeSource'. Such an instance contains a field namespace indicating the
namespace of attributes.
This is currently implemented only for the SAML2 service provider module of
authentic2. Authsaml2, the SP module, parse the assertion and put the
attributes in the session.
::
if not 'multisource_attributes' in request.session:
request.session['attributes'] = dict{}
request.session['multisource_attributes'] \
[login.assertion.issuer.content] = attributes
Then, Authentic2 can be used as a SAML2 proxy forwarding attributes in
assertion, eventually doing a namespace mapping. For this, the option
forward attributes in sesion must be set (by default False).

View File

@ -0,0 +1,438 @@
.. _attribute_management_explained:
Attribute management machinery explained (attribute_aggregator module)
======================================================================
Attribute aggegrator module
---------------------------
The core attribute management is based on the attribute aggregator module.
Intro
_____
Attribute aggregator provides a main Model class called UserAttributeProfile,
functions to load attributes and extract attributes.
The mapping between attribute namespaces is built-in and depends on a unique
file (mapping.py).
A main schema is defined and is based on LDAP/X500 for naming. The support
of http://schemas.xmlsoap.org/ws/2005/05/identity/claims is partly complete.
Source of attributes are connected with attribute loading functions using
signals.
FAQ
___
Why not use the Django User profile?
The django user profile needs to define attributes as class attributes and
then support form filling or mapping with LDAP.
That is useful and may be used, especially because the profile can be used as
a source of attribute to load in the attribute_aggregator profile.
The attribute_aggregator profile allow to load multivalued attributes from any
source supported (LDAP, Django profile and attributes in Django session for
now) from any namespace defined in mapping.py (LDAP/X500 and claims for now).
The profile can be loaded giving a source or a list of attribute, or can be
from any known source, or with a dictionnary.
Attributes can be extracted with many functions in any namespace supported.
Quick explanation
_________________
The schema is defined in mapping.py and is made of definitions like this::
"sn": {
"oid": "2.5.4.4",
"display_name": _("sn surname"),
"alias": ['surname'],
"profile_field_name": 'last_name',
"type": "http://www.w3.org/2001/XMLSchema#string",
"namespaces": {
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims": {
"identifiers":
[
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
],
"friendly_names":
[
"Last Name",
],
}
}
},
The profile store all the data in a text field taht contains a cPickle list of
instances of the class AttributeData.
The profile is attached to a user and then can be created or loaded with::
profile = load_or_create_user_profile(user=user)
User may be None to create a temporary profile for an anonymous user. But
that need a DB cleaning function not implemented.
The model *UserAttributeProfile*
________________________________
The model 'UserAttributeProfile' can be attached to a user and then persist
(as a Model).
When the profile is loaded, all data stored are removed expect if the
the data has an expiration date later.
The profile provide several methods to store and extract attributes.
All the methods to add attributes are based on a main one accepting a
dictionnary of attribute is parameters 'load_by_dic()'. The other methods
('load_listed_attributes()', 'load_greedy()') send a signal with a list of
attributes (listed_attributes_call) or not (any_attributes_call) to grab a
dictionnary. The list is given with the definition name, oid or friendly name
of the attribute in the system namespace.
Into the dictionnary, attributes are given with their name, oid or friendly
name in the default namespace or with their name in a namepsace. An expiration
date can also be given (ISO8601 format), if none, attribute will be deleted at
next profile loading. The dictionnary format is as follows::
attributes = dict()
data_from_source = list()
a1 = dict()
a1['oid'] = definition_name
Or
a1['definition'] = definition_name
definition may be the definition name like 'gn'
or an alias like 'givenName'
Or
a1['name'] = attribute_name_in_ns
a1['namespace'] = ns_name
a1['expiration_date'] = date
a1['values'] = list_of_values
data_from_source.append(a1)
...
data_from_source.append(a2)
attributes[source_name] = data_from_source
Getters are defined to extract data from a profile. Only AttributeData
instances are extracted that assume that any attribute namespace can be used.
* get_data_of_definition(definition)
Return a list of AttributeData instances corresponding to the definition
given.
* get_freshest_data_of_definition(definition)
Return the freshest AttributeData instance. If multiple with no or same exp
date, random. Should use the creation date soon.
* get_data_of_source
Return a list of AttributeData instances corresponding to the source given.
* get_data_of_source_by_name
Idem but source name is given, not a Source instance.
* get_data_of_definition_and_source
Return a list of AttributeData instances corresponding to the definition and
source given.
* get_data_of_definition_and_source_by_name
Idem but source name is given, not a Source instance.
SAML2 attribute representation in assertions
--------------------------------------------
SAML2 attribute profile (saml-profiles-2.0-os - Section 8) defines two kind of
attribute element syntax in the attribute statement of assertions, also
called *name format*:
- BASIC::
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
- URI::
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
*URI should be used when attributes have "universally" known unique names
like OID.*
Example::
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
Name="FirstName">
<saml:AttributeValue xsi:type="xs:string">By-Tor</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute
xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
Name="urn:oid:2.5.4.42" FriendlyName="givenName">
<saml:AttributeValue xsi:type="xs:string"
x500:Encoding="LDAP">Steven</saml:AttributeValue>
</saml:Attribute>
BASIC
_____
Two <Attribute> elements refer to the same SAML attribute if and only if the
values of their Name XML attributes are equal in the sense of Section 3.3.6 of
[Schema2].
No additional XML attributes are defined for use with the <Attribute> element.
The schema type of the contents of the <AttributeValue> element MUST be drawn
from one of the types defined in Section 3.3 of [Schema2]. The xsi:type
attribute MUST be present and be given the appropriate value.
X.500/LDAP Attribute Profile (URI)
__________________________________
**Extracted from the SAML2 core specifications**
Two <Attribute> elements refer to the same SAML attribute if and only if their
Name XML attribute values are equal in the sense of [RFC3061]. The
FriendlyName attribute plays no role in the comparison.
Directory attribute type definitions for use in native X.500 directories
specify the syntax of the attribute using ASN.1 [ASN.1]. For use in LDAP,
directory attribute definitions additionally include an LDAP syntax which
specifies how attribute or assertion values conforming to the syntax are to be
represented when transferred in the LDAP protocol (known as an LDAP-specific
encoding). The LDAP-specific encoding commonly produces Unicode characters in
UTF-8 form. This SAML attribute profile specifies the form of SAML attribute
values only for those directory attributes which have LDAP syntaxes. Future
extensions to this profile may define attribute value formats for directory
attributes whose syntaxes specify other encodings.
To represent the encoding rules in use for a particular attribute value, the
<AttributeValue> element MUST contain an XML attribute named Encoding defined
in the XML namespace urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500.
For any directory attribute with a syntax whose LDAP-specific encoding
exclusively produces UTF-8 character strings as values, the SAML attribute
value is encoded as simply the UTF-8 string itself, as the content of the
<AttributeValue> element, with no additional whitespace.
In such cases, the xsi:type XML attribute MUST be set to xs:string.
The profile-specific Encoding XML attribute is provided, with a value of LDAP.
The AttributeData instances have a field expiration_data. It the profile
exists, obsolete data are removed at loading.
When authentic 2 deals with attributes and needs mapping?
---------------------------------------------------------
Authentic2 behaves as an attribute provider:
* At the SSO login
* When an attribute request is received
Authentic requests (e.g. by soap) are not yet supported.
When Authentic2 behaves as an attribute provider at SSO login
_____________________________________________________________
At a SSO request, just before responding to the service provider, the saml2
idp module sends the signal 'add_attributes_to_response' giving the SP entity
ID.
The signal is connected to the function 'provide_attributes_at_sso()' in
charge of providing the attributes at the SSO for this SP.
**Attributes sources are of two kinds. The first ones are the sources that can
be requested by the IdP with a syncrhonous binding without user intercations.
These sources are called pull sources. They are for now limited to LDAP
sources. The other ones are sources are asyncrhonous bindings, usually
requiring user interactions. These sources are called push sources. They are
now limited to the attributes provided at SSO requests when the IdP acts as a
SAML2 SP. There attributes are put/found in the Django session.**
Each source in the system is declared with an instance of the AttributeSource
model. We'll see later that to forward attributes of push sources it is not
necessary that a source is declared in some circumstances.
To manage these sources an attribute policy is attached to services providers.
Then the service provider model must be extended with a attribute
attributes_at_sso_policy. The service provider must send the signal
'add_attributes_to_response'.
The implementation is actually done for SAML2 providers.
**In such a policy attributes from pull and push sources are treated
differently.**
**For pull sources, a list of attributes is indicated. Either an attribute is
searched in all the pull sources and whatever attribute value found is
returned. Or each attribute is indicated with a source. With each attribute is
indicated the output format and namespace.**
**The policy may also indicate that all the attributes in the Django session
must be forwarded. Then, no AttributeSource instance is required. All the
attributes are then forwarded without treating input namespace considerations.
When an AttributeSource instance is found, the input namespace of this source
is considered. An option can then be set to tell that the output format and
namespace must be taken. A list of attribute can also be given.
This list can be use to filter attributes to forward without or without taking
care of the source. The output namespace and format can also be trated per
attribute.**
If the namespace is default, the attribute names will be taken from the
system namespace. In BASIC the name will be the definition name. In URI, the
Name will be the OID in urn format and the friendly name will be the
definition name. If a namespace is given, the first identifier of this
attribute is taken as Name in BASIC. In URI, the same and the first friendly
name is taken.
::
class LibertyServiceProvider(models.Model):
...
attribute_policy = models.ForeignKey(AttributePolicy,
verbose_name=_("Attribute policy"), null=True, blank=True)
class AttributePolicy(models.Model):
# List of attributes to provide from pull sources at SSO Login.
# If an attribute is indicate without a source, from any source.
# The output format and namespace is given by each attribute.
attribute_list_for_sso_from_pull_sources = \
models.ForeignKey(LibertyAttributeMap,
related_name = "attributes of pull sources",
blank = True, null = True)
# Set to true for proxying attributes from pull sources at SSO Login.
# Attributes are in session.
# All attributes are forwarded as is except if the parameter
# 'attribute_list_for_sso_from_push_sources' is initialized
forward_attributes_from_pull_sources = models.BooleanField(default=False)
# Map attributes in session
# forward_attributes_in_session must be true
# At False, all attributes are forwarded as is
# At true, look for the namespace of the source for input, If not found,
# system namespace. Look for the options attribute_name_format and
# output_namespace of the attribute policy for output.
map_attributes_from_pull_sources = models.BooleanField(default=False)
# ATTRIBUTE_VALUE_FORMATS[0] =>
# (lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC, 'SAMLv2 BASIC')
output_name_format = models.CharField(max_length = 100,
choices = ATTRIBUTE_VALUE_FORMATS,
default = ATTRIBUTE_VALUE_FORMATS[0])
#ATTRIBUTES_NS[0] => ('Default', 'Default')
output_namespace = models.CharField(max_length = 100,
choices = ATTRIBUTES_NS, default = ATTRIBUTES_NS[0])
# Filter attributes pushed from source.
source_filter_for_sso_from_push_sources = \
models.ManyToManyField(AttributeSource,
related_name = "attributes of pull sources",
blank = True, null = True)
# List of attributes to filter from pull sources at SSO Login.
attribute_filter_for_sso_from_push_sources = \
models.ForeignKey(LibertyAttributeMap,
related_name = "attributes of pull sources",
blank = True, null = True)
# The sources of attributes of the previous list are considered.
# May be used conjointly with 'source_filter_for_sso_from_push_sources'
filter_source_of_filtered_attributes = models.BooleanField(default=False)
# To map the attributes of forwarded attributes with the defaut output
# format and namespace, use 'map_attributes_from_pull_sources'
# Use the following option to use the output format and namespace
# indicated for each attribute.
map_attributes_of_filtered_attributes = models.BooleanField(default=False)
# Set to true to take in account missing required attributes
send_error_and_no_attrs_if_missing_required_attrs = \
models.BooleanField(default=False)
class Meta:
verbose_name = _('attribute options policy')
verbose_name_plural = _('attribute options policies')
class AttributeList(models.Model):
name = models.CharField(max_length = 40, unique = True)
attributes = models.ManyToManyField(AttributeItem,
related_name = "attributes of the list",
blank = True, null = True)
class AttributeItem(models.Model):
attribute_name = models.CharField(max_length = 100, choices = ATTRIBUTES,
default = ATTRIBUTES[0])
# ATTRIBUTE_VALUE_FORMATS[0] =>
# (lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC, 'SAMLv2 BASIC')
output_attribute_name_format = models.CharField(max_length = 100,
choices = ATTRIBUTE_VALUE_FORMATS,
default = ATTRIBUTE_VALUE_FORMATS[0])
#ATTRIBUTES_NS[0] => ('Default', 'Default')
output_namespace = models.CharField(max_length = 100,
choices = ATTRIBUTES_NS, default = ATTRIBUTES_NS[0])
required = models.BooleanField(default=False)
source = models.ForeignKey(AttributeSource, blank = True, null = True)
A list of attributes can also be taken from the service provider metadata and
added to 'attribute_list_for_sso_from_pull_sources'. The namespace may be
extracted from the metadata. This namespace is then used to look for the
corresponding definition and then to provide the attribute in the right
namespace. Read attributes from metadata is not yet supported.
For the attributes of pull sources, once the list of attributes is defined,
They are loaded in the user profile.
As explained before the attribute_aggregator loading function send signals to
grab dictionnary of attributes. Up to know, only the ldap loading function are
connected to these signals. The namespace of LDAP sources is assumed to be
the same as the system namespace. There is here then no mapping needed. Other
kind of sources than LDAP can be defined in attribute aggregator.
To grab attributes from a LDAP the user dn in the LDAP or at least a local
identifier in the LDAP is required. For this purpose, each user has alias
associated with LDAP source. These aliases must their DN in the LDAP. When
the authentication LDAP backend will be taken in account, the dn will be taken
direclty from the user Model instance.
Each LDAP sources are declared with the binding parameters. The LDAP namespace
is always 'Default'.
If an attribute to load is not found and is required the answer should report
an error (Not yet implemented).
Attributes in response can also be provided with other means than from an LDAP
source. Attributes can be put in the user Django session and then loaded in
the profile. An option of the service provier indicate if attributes in the
session must be provided to the service provider.
To have the attribute loaded from the session, they must be provided in the
session as follows:
request.session['attributes'][source_name] = list()
The source_name must be the name of an existing instance of an
'AttributeSource'. Such an instance contains a field namespace indicating the
namespace of attributes.
This is currently implemented only for the SAML2 service provider module of
authentic2. Authsaml2, the SP module, parse the assertion and put the
attributes in the session.
Then, Authentic2 can be used as a SAML2 proxy forwarding attributes in
assertion, eventually doing a namespace mapping. For this, the option
forward attributes in sesion must be set (by default False).

View File

@ -0,0 +1,44 @@
.. _attributes_in_session:
==============================================================
Attributes in session pushed by third SAML2 identity providers
==============================================================
When an assertion is received, assertion data, including attributes, are
pushed in the Django session dictionnary.
It leads to the creation of the following dictionnary::
request.session['multisource_attributes']
The keys of the dictionnary are the source names, i.e. the entity Id for
SAML2 identity providers.
The values are list of data extracted from assertions. Indeed, this is done
to store multiple assertion received from a same source in a same Django
session::
request.session['multisource_attributes'] \
[source_name] = list()
The items of this list are dictionnaries with the keys 'certificate_type' and
'attributes'.
For a saml2 assertion, all the keys are::
a8n['certificate_type'] = 'SAML2_assertion'
a8n['nameid'] = ...
a8n['subject_confirmation_method'] = ...
a8n['not_before'] = ...
a8n['not_on_or_after'] = ...
a8n['authn_context'] = ...
a8n['authn_instant'] = ...
a8n['attributes'] = attrs
a8n['attributes'] has the following structure::
attributes = {}
attributes[name] = (value1, value2, )
attributes[(name, format)] = (value1, value2, )
attributes[(name, format, nickname)] = (value1, value2, )
a8n['attributes'] = attributes

View File

@ -55,6 +55,10 @@ Documentation content
attribute_management
attribute_management_explained
attributes_in_session
Copyright
=========

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB