-
+
+
+
-
+
+
+
+
+
+
diff --git a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Downloader.pm b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Downloader.pm
index 5f08bd1bb..98b277e86 100644
--- a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Downloader.pm
+++ b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Downloader.pm
@@ -190,6 +190,7 @@ sub confNode {
elsif ( $target =~ s/^samlmetadata:// ) {
my $h = $self->keyToH( $target, $self->conf );
$h = $h->{samlIDPMetaDataXML} if ( $h->{samlIDPMetaDataXML} );
+ $h = $h->{samlSPMetaDataXML} if ( $h->{samlSPMetaDataXML} );
my $metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new();
$metadata->initializeFromConfHash($h);
my $text = $target;
@@ -204,7 +205,6 @@ sub confNode {
target => "samlmetadata",
) . "";
}
-
else {
$target =~ s/^(\w+)://;
my $type = $1 || 'text';
@@ -213,7 +213,17 @@ sub confNode {
$text =~ s/^.*\///;
my $h = $self->keyToH( $target, $self->conf );
+ # Try to get value from defaultConf
$h = $self->keyToH( $target, $self->defaultConf ) unless ( defined $h );
+
+ # If no value found, try to remove 2 first target components
+ # to manage complex hash like samlIDPMetaDataOptions
+ unless ( defined $h ) {
+ $target =~ /([^\/]*)$/;
+ $h = $self->keyToH( $1, $self->defaultConf );
+ }
+
+ # If still no value, set a default value depending on type
unless ( defined $h ) {
$self->lmLog( "$target does not exists in menu hash", "debug" );
$h = {
diff --git a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm
index b9a2c6cd7..31b92afc8 100644
--- a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm
+++ b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm
@@ -35,6 +35,7 @@ sub confUpload {
# Variables to store current vhost and IDP name
my $vhostname;
my $idpname;
+ my $spname;
# 1. ANALYSE DATAS
@@ -88,11 +89,20 @@ sub confUpload {
$idpname = $name;
}
+ # Get SAML SP name
+ if ( $id =~ /samlSPMetaDataExportedAttributes\/([^\/]*)?$/ ) {
+ $self->lmLog( "Entering SP $name", 'debug' );
+ $spname = $name;
+ }
+
# Manage new keys
if ($NK) {
# Special case: avoid bug with node created from parent node
- if ( $id =~ /^(virtualHosts|samlIDPMetaDataExportedAttributes)/ ) {
+ if ( $id =~
+/^(virtualHosts|samlIDPMetaDataExportedAttributes|samlSPMetaDataExportedAttributes)/
+ )
+ {
$self->lmLog( "Special trigger for $id (attribute $name)",
'debug' );
@@ -110,6 +120,11 @@ s/^virtualHosts\/([^\/]*)?\/header.*/exportedHeaders\/$1\/$name/;
# SAML IDP attribute
$id =~
s/^samlIDPMetaDataExportedAttributes\/([^\/]*)?.*/samlIDPMetaDataExportedAttributes\/$1\/$name/;
+
+ # SAML SP attribute
+ $id =~
+s/^samlSPMetaDataExportedAttributes\/([^\/]*)?.*/samlSPMetaDataExportedAttributes\/$1\/$name/;
+
}
# Normal case
@@ -126,11 +141,16 @@ s/^(exportedHeaders|locationRules)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$3/;
$id =~
s/^(samlIDPMetaDataXML|samlIDPMetaDataExportedAttributes|samlIDPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$idpname\/$3/;
+ # Set current SAML SP name
+ $id =~
+s/^(samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$spname\/$3/;
+
$self->lmLog( "id transformed into $id", 'debug' );
next
if ( $id =~
- /^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode)/ );
+/^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode)/
+ );
my ( $confKey, $test ) = $self->getConfTests($id);
my ( $res, $m );
@@ -467,7 +487,7 @@ sub findAllConfKeys {
sub formatValue {
my ( $self, $key, $value ) = @_;
my $newvalue = $value;
- if ( $key =~ /^samlIDPMetaDataXML/ ) {
+ if ( $key =~ /^(samlIDPMetaDataXML|samlSPMetaDataXML)/ ) {
my $metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new();
if ( ref($value) ) {
$metadata->initializeFromConfHash($value);
diff --git a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm
index 576eb9603..573570c94 100644
--- a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm
+++ b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm
@@ -83,6 +83,33 @@ sub cstruct {
}
);
}
+ elsif ( $k1 =~ /^samlSPMetaDataNode/i ) {
+ %$h = (
+ %$h,
+ samlSPMetaDataNode => {
+ $k2 => {
+ _nodes => [
+ qw(samlSPMetaDataXML samlSPMetaDataExportedAttributes samlSPMetaDataOptions)
+ ],
+ samlSPMetaDataExportedAttributes => {
+ _nodes => [
+ "hash:/samlSPMetaDataExportedAttributes/$k2"
+ . ":samlSPMetaDataExportedAttributes:samlAttribute"
+ ],
+ _js => 'samlAttributeRoot'
+ },
+ samlSPMetaDataXML => "samlmetadata:/samlSPMetaDataXML/$k2"
+ . ":samlSPMetaDataXML:filearea",
+ samlSPMetaDataOptions => {
+ _nodes =>
+ ['samlSPMetaDataOptionsRequestedAuthnContext'],
+ samlSPMetaDataOptionsRequestedAuthnContext =>
+"text:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsRequestedAuthnContext",
+ },
+ }
+ }
+ );
+ }
return $h;
}
@@ -93,7 +120,7 @@ sub struct {
my $self = shift;
return {
_nodes => [
- qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode)
+ qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode n:samlSPMetaDataNode)
],
_help => 'default',
@@ -503,13 +530,22 @@ sub struct {
# virtual keys should not begin like configuration keys.
samlIDPMetaDataNode => {
_nodes => [
-'nhash:/samlIDPMetaDataExportedAttributes:samlIDPMetaDataNode:samlMetaData'
+'nhash:/samlIDPMetaDataExportedAttributes:samlIDPMetaDataNode:samlIdpMetaData'
],
_upload => [ '/samlIDPMetaDataXML', '/samlIDPMetaDataOptions' ],
_help => 'default',
_js => 'samlIdpRoot',
},
+ samlSPMetaDataNode => {
+ _nodes => [
+'nhash:/samlSPMetaDataExportedAttributes:samlSPMetaDataNode:samlSpMetaData'
+ ],
+ _upload => [ '/samlSPMetaDataXML', '/samlSPMetaDataOptions' ],
+ _help => 'default',
+ _js => 'samlSpRoot',
+ },
+
samlServiceMetaData => {
_nodes => [
qw(samlEntityID
@@ -958,6 +994,31 @@ sub testStruct {
keyTest => sub { return 1; },
},
},
+ samlSPMetaDataExportedAttributes => {
+ keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
+ keyMsgFail => 'Bad metadata name',
+ '*' => {
+ keyTest => qr/^\w([\w\-]*\w)?$/,
+ keyMsgFail => 'Bad attribute name',
+ test => sub { return 1; },
+ },
+ },
+ samlSPMetaDataXML => {
+ keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
+ keyMsgFail => 'Bad metadata name',
+ '*' => {
+ test => sub { return 1; },
+ keyTest => sub { return 1; },
+ },
+ },
+ samlSPMetaDataOptions => {
+ keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
+ keyMsgFail => 'Bad metadata name',
+ '*' => {
+ test => sub { return 1; },
+ keyTest => sub { return 1; },
+ },
+ },
samlServicePrivateKey => $testNotDefined,
samlEntityID => $testNotDefined,
samlOrganizationDisplayName => $testNotDefined,
@@ -1096,26 +1157,20 @@ sub defaultConf {
########
# SAML #
########
- samlIDPMetaDataXML => { 'authentic' => {} },
- samlIDPMetaDataExportedAttributes =>
- { 'authentic' => { 'uid' => '0;uid;;' } },
- samlIDPMetaDataOptions => {
- 'authentic' => {
- 'samlIDPMetaDataOptionsNameIDFormat' => '',
- 'samlIDPMetaDataOptionsForceAuthn' => '0',
- 'samlIDPMetaDataOptionsAllowProxiedAuthn' => '1',
- 'samlIDPMetaDataOptionsSSOBinding' => '',
- 'samlIDPMetaDataOptionsSLOBinding' => '',
- 'samlIDPMetaDataOptionsResolutionRule' => '',
- 'samlIDPMetaDataOptionsAllowLoginFromIDP' => '1',
- 'samlIDPMetaDataOptionsAdaptSessionUtime' => '1',
- }
- },
samlServicePrivateKey => '',
samlEntityID => $portal . '/saml/metadata',
samlOrganizationDisplayName => 'Example',
samlOrganizationName => 'Example',
samlOrganizationURL => 'http://www.example.com',
+ samlIDPMetaDataOptionsNameIDFormat => '',
+ samlIDPMetaDataOptionsForceAuthn => '0',
+ samlIDPMetaDataOptionsAllowProxiedAuthn => '1',
+ samlIDPMetaDataOptionsSSOBinding => '',
+ samlIDPMetaDataOptionsSLOBinding => '',
+ samlIDPMetaDataOptionsResolutionRule => '',
+ samlIDPMetaDataOptionsAllowLoginFromIDP => '1',
+ samlIDPMetaDataOptionsAdaptSessionUtime => '1',
+ samlSPMetaDataOptionsRequestedAuthnContext => '',
samlSPSSODescriptorAuthnRequestsSigned => '0',
samlSPSSODescriptorKeyDescriptorSigning => '',
samlSPSSODescriptorSingleLogoutServiceHTTP =>
@@ -1191,18 +1246,8 @@ sub subDefaultConf {
'proxy' => 'https://remote/index.pl/sessions',
'ns' => 'https://remote/Lemonldap/NG/Common/CGI/SOAPService',
},
- samlIDPMetaDataXML => { {} },
samlIDPMetaDataExportedAttributes => { 'uid' => '0;uid;;' },
- samlIDPMetaDataOptions => {
- 'samlIDPMetaDataOptionsNameIDFormat' => '',
- 'samlIDPMetaDataOptionsForceAuthn' => '0',
- 'samlIDPMetaDataOptionsAllowProxiedAuthn' => '1',
- 'samlIDPMetaDataOptionsSSOBinding' => '',
- 'samlIDPMetaDataOptionsSLOBinding' => '',
- 'samlIDPMetaDataOptionsResolutionRule' => '',
- 'samlIDPMetaDataOptionsAllowLoginFromIDP' => '1',
- 'samlIDPMetaDataOptionsAdaptSessionUtime' => '1',
- },
+ samlSPMetaDataExportedAttributes => { 'uid' => '0;uid;;' },
};
}
diff --git a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
index 5cca4379b..9df911e53 100644
--- a/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
+++ b/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
@@ -198,8 +198,8 @@ sub en {
saml => 'SAML',
samlServicePrivateKey => 'Private Key',
- samlIDPMetaDataNode => 'Identity providers',
- samlIDPMetaDataXML => 'Metadata XML',
+ samlIDPMetaDataNode => 'SAML identity providers',
+ samlIDPMetaDataXML => 'Metadata',
samlIDPMetaDataExportedAttributes => 'Exported attributes',
samlIDPMetaDataOptions => 'Options',
samlIDPMetaDataOptionsNameIDFormat => 'NameID format',
@@ -211,6 +211,11 @@ sub en {
samlIDPMetaDataOptionsSSOBinding => 'SSO binding',
samlIDPMetaDataOptionsSLOBinding => 'SLO binding',
samlIDPMetaDataOptionsResolutionRule => 'Resolution rule',
+ samlSPMetaDataNode => 'SAML service providers',
+ samlSPMetaDataXML => 'Metadata',
+ samlSPMetaDataExportedAttributes => 'Exported attributes',
+ samlSPMetaDataOptions => 'Options',
+ samlSPMetaDataOptionsRequestedAuthnContext => 'Authentication context',
samlServiceMetaData => 'SAML 2 Service',
samlEntityID => 'Entity Identifier',
samlOrganization => 'Organization',
@@ -413,8 +418,8 @@ sub fr {
saml => 'SAML',
samlServicePrivateKey => 'Clé privée',
- samlIDPMetaDataNode => 'Fournisseurs d\'identités',
- samlIDPMetaDataXML => 'XML Metadata',
+ samlIDPMetaDataNode => 'Fournisseurs d\'identité SAML',
+ samlIDPMetaDataXML => 'Metadonnées',
samlIDPMetaDataExportedAttributes => 'Attributs exportés',
samlIDPMetaDataOptions => 'Options',
samlIDPMetaDataOptionsNameIDFormat => 'Format NameID',
@@ -428,6 +433,12 @@ sub fr {
samlIDPMetaDataOptionsSSOBinding => 'Méthode SSO',
samlIDPMetaDataOptionsSLOBinding => 'Méthode SLO',
samlIDPMetaDataOptionsResolutionRule => 'Règle de résolution',
+ samlSPMetaDataNode => 'Fournisseurs de service SAML',
+ samlSPMetaDataXML => 'Metadonnées',
+ samlSPMetaDataExportedAttributes => 'Attributs exportés',
+ samlSPMetaDataOptions => 'Options',
+ samlSPMetaDataOptionsRequestedAuthnContext =>
+ 'Contexte d\'authentification',
samlServiceMetaData => 'Service SAML 2',
samlEntityID => 'Identifiant d\'entité',
samlOrganization => 'Organisation',