diff --git a/bin/account-manager-client.pl b/bin/account-manager-client.pl index cca72296d76ad392af4a0b889fbcf56418888dc5..483e8d06174c254899c65e1478efb6647ac1dcd8 100755 --- a/bin/account-manager-client.pl +++ b/bin/account-manager-client.pl @@ -19,7 +19,7 @@ use IdPAccountManager::AuthenticationToken; my %options; unless (&GetOptions(\%options, 'help', 'add_test_account', 'account_profile=s', 'sp_entityid=s', 'list_test_accounts', 'parse_federation_metadata', 'list_service_providers','list_authentication_tokens', 'get_authentication_token', 'add_authentication_token','email_address=s', - 'token=s','send_notice','filter_expired','delete')) { + 'token=s','send_notice','filter_expired','delete','add_service_provider','contacts=s','displayname=s')) { die "Unknown options."; } @@ -107,7 +107,42 @@ if ($options{'add_test_account'}) { printf "Hashref representing the metadata:\n"; &IdPAccountManager::Tools::dump_var($federation_metadata->{'federation_metadata_as_hashref'}, 0, \*STDOUT); -}elsif ($options{'list_service_providers'}) { +}elsif ($options{'add_service_provider'}) { + + unless ($options{'sp_entityid'}) { + die "Missing sp_entityid option"; + } + + unless ($options{'contacts'}) { + die "Missing contacts option"; + } + + ## Check if entry already exists in DB first + my $service_provider = new IdPAccountManager::ServiceProvider(entityid => $options{'sp_entityid'}); + if ($service_provider->load(speculative => 1)) { + printf "Entry for %s already in DB; update it with new data\n", $options{'sp_entityid'}; + + $service_provider->contacts($options{'contacts'}); + $service_provider->displayname($options{'displayname'}) if ($options{'displayname'}); + }else { + + $service_provider = new IdPAccountManager::ServiceProvider(entityid => $options{'sp_entityid'}, + contacts => $options{'contacts'}, + displayname => $options{'displayname'}); + unless (defined $service_provider) { + IdPAccountManager::Tools::do_log('error',"Failed to create service provider"); + exit -1; + } + } + + unless ($service_provider->save()) { + IdPAccountManager::Tools::do_log('error',"Failed to create service provider"); + exit -1; + } + + printf "Service Provider created:\n"; + + }elsif ($options{'list_service_providers'}) { my %args; @@ -277,10 +312,14 @@ Get informations on a token. Adds a new test account. -=item C<account-manager-client.pl --send_notice ----email_address=john@my.fqdn> +=item C<account-manager-client.pl --send_notice --email_address=john@my.fqdn> Sends a mail notice to the specified email address. +=item C<account-manager-client.pl --add_service_provider --sp_entityid=='https://test.federation.renater.fr/test/ressource --displayname='Test SP' --contacts=email1@dom,email2@dom> + +Adds a new Service provider + =back =head1 AUTHOR diff --git a/bin/account-manager-web.pl b/bin/account-manager-web.pl index e3e0b16a72a997eb2a953ce284c2a8f297f51c74..1fe3951eeb8159ceaab52ccc80666c52b5758d9d 100755 --- a/bin/account-manager-web.pl +++ b/bin/account-manager-web.pl @@ -280,8 +280,62 @@ sub req_select_sp { &IdPAccountManager::Tools::do_log('error', "Failed to parse federation metadata : $!"); return undef; } + + ## Create a serviceprovider object to store major parameters for this SP in DB + my $service_provider = new IdPAccountManager::ServiceProvider(entityid => $self->{'param_in'}{'sp_entityid'}); + + ## Prepare data + #open TMP, ">/tmp/account_manager_metadata.dump"; &IdPAccountManager::Tools::dump_var($federation_metadata->{'federation_metadata_as_hashref'}[0], 0, \*TMP); close TMP; + my $sp_metadata_as_hashref = $federation_metadata->{'federation_metadata_as_hashref'}[0]; + my @contacts; + if (defined $sp_metadata_as_hashref->{'contacts'}) { + foreach my $contact (@{$sp_metadata_as_hashref->{'contacts'}}) { + my $email = $contact->{'EmailAddress'}; + $email =~ s/^(mailto:)//; ## Remove 'mailto:' prefixes if any + push @contacts, $email; + } + } + my $display_name; + if (defined $sp_metadata_as_hashref->{'display_name'}) { + ## Use English version of displayName if available + if ($sp_metadata_as_hashref->{'display_name'}{'en'}) { + $display_name = $sp_metadata_as_hashref->{'display_name'}{'en'}; + ## Else any language + }else { + foreach my $lang (keys %{$sp_metadata_as_hashref->{'display_name'}}) { + #&IdPAccountManager::Tools::do_log('TRACE', "Display name(%s): %s", $lang, $sp_metadata_as_hashref->{'display_name'}{$lang}); + $display_name = $sp_metadata_as_hashref->{'display_name'}{$lang}; + last; + } + } + } + + ## Try loading DB object first + if ($service_provider->load(speculative => 1)) { + $service_provider->contacts(join(',', @contacts)); + $service_provider->displayname($display_name); + + }else { + + $service_provider = new IdPAccountManager::ServiceProvider(entityid => $self->{'param_in'}{'sp_entityid'}, + contacts => join(',', @contacts), + displayname => $display_name); + unless (defined $service_provider) { + push @{$self->{'param_out'}{'errors'}}, "internal"; + &IdPAccountManager::Tools::do_log('error', "Failed to create serviceprovider object"); + return undef; + } + } + + unless ($service_provider->save()) { + push @{$self->{'param_out'}{'errors'}}, "internal"; + &IdPAccountManager::Tools::do_log('error', "Failed to save serviceprovider object"); + return undef; + } + $self->{'param_out'}{'sp_metadata_as_hashref'} = $federation_metadata->{'federation_metadata_as_hashref'}[0]; + $self->{'param_out'}{'serviceprovider'} = $service_provider; return 1; @@ -305,6 +359,22 @@ sub req_generate_token { return undef; } + ## Create a serviceprovider object to load parameters for this SP from DB + my $service_provider = new IdPAccountManager::ServiceProvider(entityid => $self->{'param_in'}{'sp_entityid'}); + # Try loading DB object first + unless ($service_provider->load(speculative => 1)) { + push @{$self->{'param_out'}{'errors'}}, "internal"; + &IdPAccountManager::Tools::do_log('error', "Failed to load SP with entityid '%s'", $self->{'param_in'}{'sp_entityid'}); + return undef; + } + + ## Check that email_address is a known contact for this SP + unless ($service_provider->is_contact($self->{'param_in'}{'email_address'})) { + push @{$self->{'param_out'}{'errors'}}, "internal"; + &IdPAccountManager::Tools::do_log('error', "Requested a token for %s for an unautorized address '%s'", $self->{'param_in'}{'sp_entityid'}, $self->{'param_in'}{'email_address'}); + return undef; + } + my $authentication_token = new IdPAccountManager::AuthenticationToken(); unless (defined $authentication_token) { push @{$self->{'param_out'}{'errors'}}, "internal"; diff --git a/conf/create-manager-db.sql b/conf/create-manager-db.sql index f6d69beacc2ae871b2a7c4ea8b85df0e35dd18e7..a93c0a884640b7f332b57e2a9d011c64117769c9 100644 --- a/conf/create-manager-db.sql +++ b/conf/create-manager-db.sql @@ -21,8 +21,10 @@ CREATE TABLE `serviceproviders` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `entityid` varchar(200) NOT NULL, `displayname` varchar(500) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; + `contacts` varchar(2000) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `entityid` (`entityid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; CREATE TABLE `testaccounts` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, diff --git a/lib/IdPAccountManager/ServiceProvider.pm b/lib/IdPAccountManager/ServiceProvider.pm index d7447464674e753c9612cfb2d40a9b31e17a5327..c038874410723ff8a31c37004b31bdedc8c21c1d 100644 --- a/lib/IdPAccountManager/ServiceProvider.pm +++ b/lib/IdPAccountManager/ServiceProvider.pm @@ -27,11 +27,40 @@ sub print { my $fd = shift || \*STDOUT; printf $fd "ServiceProvider ID=%s; entityid=%s; displayname=%s; contacts=%s\n", - $self->get('id'), $self->get('entityid'), $self->get('displayname'), $self->get('contacts'); + $self->id, $self->entityid, $self->displayname, $self->contacts; return 1. } +## list contacts for this SP, including those listed in conf.dev_sp_contact +sub list_contacts_as_array { + my $self = shift; + + my @contact_list; + + foreach my $contact_email (split /,/, $self->contacts()) { + push @contact_list, $contact_email; + } + + foreach my $contact_email (split /,/, $Conf::global{'dev_sp_contact'}) { + push @contact_list, $contact_email; + } + + return @contact_list; +} + +## Check if email address is a known contact (or conf.dev_sp_contact) +sub is_contact { + my $self = shift; + my $email = shift; + + foreach my $known_contact ($self->list_contacts_as_array()) { + return 1 if (lc($email) eq lc($known_contact)); + } + + return 0; +} + ## list all test accounts ## Class method sub list_service_providers { @@ -40,7 +69,8 @@ sub list_service_providers { my $persistent_accounts= IdPAccountManager::Data::Serviceprovider::Manager->get_serviceproviders(%args); my $service_providers; foreach my $persistent_sp (@{$persistent_accounts}) { - my $service_provider = new IdPAccountManager::ServiceProvider($persistent_sp); + my $service_provider = new IdPAccountManager::ServiceProvider(entityid => $persistent_sp->entityid()); + $service_provider->load(); push @$service_providers, $service_provider; } diff --git a/templates/web/select_sp.tt2.html b/templates/web/select_sp.tt2.html index 4631668982b3c2fe89bc6b02f030cb713d2b67d7..0d178032130e56ac4531824fe28664bd74683763 100644 --- a/templates/web/select_sp.tt2.html +++ b/templates/web/select_sp.tt2.html @@ -1,6 +1,6 @@ <h3>Send email challenge</h3> -[% IF sp_metadata_as_hashref.display_name && sp_metadata_as_hashref.display_name.en %] -[% SET sp_display_name = sp_metadata_as_hashref.display_name.en %] +[% IF serviceprovider.displayname %] +[% SET sp_display_name = serviceprovider.displayname %] [% ELSE %] [% SET sp_display_name = sp_metadata_as_hashref.entityid %] [% END %] @@ -8,24 +8,15 @@ Before you can create test accounts at this Identity Provider, we need to ensure you are a legitimate administrator of "[% sp_display_name %]". </div> -<fieldset> +<fieldset class="scrollable"> [% IF sp_metadata_as_hashref.contacts.defined %] <legend>Select your email address</legend> <label for="sp_entityid">The email addresses below have been extracted from your SP SAML metadata.<br/>Please select the email address where an email challenge can be sent to validate your identity</label> -[% FOREACH contact IN sp_metadata_as_hashref.contacts -%] - [% matches = contact.EmailAddress.match('^(mailto:)?(.*)$') %] - [% contacts.${matches.1} = 1 %] -[% END %] - -[% FOREACH email IN conf.dev_sp_contact.split(',') %] -[% contacts.${email} = 1 %] -[% END %] - <div class="radio_inline"> -[% FOREACH email IN contacts.keys.sort %] +[% FOREACH email IN serviceprovider.list_contacts_as_array.sort %] <input name="email_address" value="[% email %]" type="radio" class="required"/><label for="email_address">[% email %]</label><br/> <input type="hidden" name="sp_entityid" value="[% sp_metadata_as_hashref.entityid %]" id="sp_entityid"/> @@ -34,9 +25,8 @@ Before you can create test accounts at this Identity Provider, we need to ensure </div> [% ELSE %] -<div class="alert-box warning radius">No ContactPerson elements could be found in your SP SAML metadata. Therefore we are unable to provide test accounts for your SP. Please contact your local federation +No ContactPerson elements could be found in your SP SAML metadata. Therefore we are unable to provide test accounts for your SP. Please contact your local federation administrator to add ContactPerson information to the SAML metadata. -</div> [% END %] </fieldset> @@ -48,4 +38,4 @@ administrator to add ContactPerson information to the SAML metadata. input.val([input.attr('value')]); }); }); -</script> +</script> \ No newline at end of file