Skip to content
Snippets Groups Projects
account-manager-client.pl 12.9 KiB
Newer Older
#!/usr/bin/perl

## Copyright (c) GEANT
## This software was developed by RENATER. The research leading to these results has received funding
## from the European Community¹s Seventh Framework Programme (FP7/2007-2013) under grant agreement nº 238875 (GÉANT).

## 18/07/2014, Olivier Salaün
## Command-line client for the Test IdP Account Manager

use strict;
use utf8;
use lib qw(lib conf);
use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use IdPAccountManager::TestAccount;
use IdPAccountManager::ServiceProvider;
use IdPAccountManager::AuthenticationToken;
use IdPAccountManager::Logger;

my %options;
GetOptions(
    \%options,
    'account_profile=s',
    'contacts=s',
    'delete',
    'displayname=s',
    'email_address=s',
    'filter_expired',
    'sp_entityid=s',
    'token=s',
) or pod2usage(
    -message => "unknown option, aborting\n",
    -verbose => 0
);

my $action = $ARGV[0];

pod2usage(
    -message => "no action given, aborting\n",
    -verbose => 0
) unless $action;


if ($action eq 'add_test_account') {
    pod2usage(
        -message => "missing account_profile option, aborting\n",
        -verbose => 0
    ) unless $options{'account_profile'};
    pod2usage(
        -message => "missing sp_entityid option, aborting\n",
        -verbose => 0
    ) unless $options{'sp_entityid'};
    my $test_account = IdPAccountManager::TestAccount->new(
        account_profile => $options{'account_profile'},
        sp_entityid     => $options{'sp_entityid'}
    );

    die "Failed to create test account\n"
        unless $test_account;

    die "Failed to save test account\n"
        unless $test_account->save(
            accounts_validity_period => $Conf::global{'accounts_validity_period'}
        );

    printf "Account created:\n\tuserid: user%d\n\tpassword: %s\n",
      $test_account->get('id'), $test_account->get('user_password');

} elsif ($action eq 'list_test_accounts') {
    my %args;
    if ($options{'sp_entityid'}) {
        push @{ $args{'query'} }, 'sp_entityid' => $options{'sp_entityid'};
    if ($options{'account_profile'}) {
        push @{ $args{'query'} },
          'account_profile' => $options{'account_profile'};
    if ($options{'filter_expired'}) {
        push @{ $args{'query'} }, 'expiration_date' => { lt => time };
    my $all = IdPAccountManager::TestAccount::list_test_accounts(%args);
        printf "No matching test account in DB\n";
    foreach my $test_account (@$all) {
        $test_account->print();
        next unless $options{'delete'};
        die "failed to delete test account\n"
            unless $test_account->delete();
        printf "%d accounts removed\n", $#{$all} + 1;
        die "failed to update simpleSAMLphp configuration file\n"
            unless IdPAccountManager::Tools::update_ssp_authsources(
                $Conf::global{'root_manager_dir'},
                \%Conf::global
            );
        printf "Update simpleSamlPhp configuration file...\n";
    }

} elsif ($action eq 'parse_federation_metadata') {
    my $federation_metadata = IdPAccountManager::SAMLMetadata->new();

    die "unable to load federation metadata\n"
        unless $federation_metadata->load(
            federation_metadata_file_path =>
              $Conf::global{'federation_metadata_file_path'}
    my %args;
    if ($options{'sp_entityid'}) {
        $args{'filter_entity_id'} = $options{'sp_entityid'};
    }

    die "unable to parse federation metadata\n"
        unless $federation_metadata->parse(%args);

    printf "Document %s parsed\n",
      $Conf::global{'federation_metadata_file_path'};

    ## List SAML entities
    printf "Hashref representing the metadata:\n";
    IdPAccountManager::Tools::dump_var(
        $federation_metadata->{'federation_metadata_as_hashref'},
        0, \*STDOUT);

} elsif ($action eq 'add_service_provider') {
    pod2usage(
        -message => "missing sp_entityid option, aborting\n",
        -verbose => 0
    ) unless $options{'sp_entityid'};
    pod2usage(
        -message => "missing contacts option, aborting\n",
        -verbose => 0
    ) unless $options{'contacts'};
    ## Check if entry already exists in DB first
    my $service_provider =
      IdPAccountManager::ServiceProvider->new(
        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 = IdPAccountManager::ServiceProvider->new(
            entityid    => $options{'sp_entityid'},
            contacts    => $options{'contacts'},
            displayname => $options{'displayname'}
        );
        die "failed to create service provider\n"
            unless $service_provider;
    die "failed to save service provider"
        unless $service_provider->save();
    printf "Service Provider created\n";
} elsif ($action eq 'list_service_providers') {
    my $all = IdPAccountManager::ServiceProvider::list_service_providers(%args);
    if ($#{$all} < 0) {
        printf "No service provider in DB\n";
    }
    foreach my $service_provider (@$all) {
        $service_provider->print();
    }
} elsif ($action eq 'list_authentication_tokens') {
    if ($options{'sp_entityid'}) {
        push @{ $args{'query'} }, 'sp_entityid' => $options{'sp_entityid'};
    }
    if ($options{'token'}) {
        push @{ $args{'query'} }, 'token' => $options{'token'};
    if ($options{'filter_expired'}) {
        push @{ $args{'query'} }, 'creation_date' =>
          { lt => time - ($Conf::global{'tokens_validity_period'} * 3600) };

    my $all =
      IdPAccountManager::AuthenticationToken::list_authentication_tokens(%args);

        printf "No corresponding token found in DB\n";
    foreach my $authentication_token (@$all) {
        $authentication_token->print();
        next unless options{'delete'};
        die "failed to delete authentication token\n"
            unless $authentication_token->delete();
    if ($options{'delete'}) {
        printf "%d tokens removed\n", $#{$all} + 1;

    }
} elsif ($action eq 'get_authentication_token') {
    if ($options{'token'}) {
        $args{'token'} = $options{'token'};
    }

    my $authentication_token =
      IdPAccountManager::AuthenticationToken->new(%args);
    die "No corresponding token found in DB\n"
        unless $authentication_token->load();
    if ($options{'sp_entityid'}) {
        die "Authentication token cannot be used for this SP\n"
            unless $authentication_token->get('sp_entityid')
                eq $options{'sp_entityid'};
} elsif ($action eq 'add_authentication_token') {
    pod2usage(
        -message => "missing email_address option, aborting\n",
        -verbose => 0
    ) unless $options{'email_address'};
    pod2usage(
        -message => "missing sp_entityid option, aborting\n",
        -verbose => 0
    ) unless $options{'sp_entityid'};
    my $authentication_token = IdPAccountManager::AuthenticationToken->new(
        'email_address' => $options{'email_address'},
        'sp_entityid'   => $options{'sp_entityid'}
    );

    die "failed to create authentication token\n"
        unless $authentication_token;

    ## First remove token if on exist for this email+SP
    if ($authentication_token->load()) {
        die "failed to delete authentication token\n"
            unless $authentication_token->delete();
        $authentication_token = IdPAccountManager::AuthenticationToken->new(
            'email_address' => $options{'email_address'},
            'sp_entityid'   => $options{'sp_entityid'}
        );
        die "failed to create authentication token\n"
            unless $authentication_token;
    die "failed to save authentication token\n"
        unless $authentication_token->save();
    $authentication_token->print();
} elsif ($action eq 'send_notice') {
    pod2usage(
        -message => "missing email_address option, aborting\n",
        -verbose => 0
    ) unless $options{'email_address'};

    my $logger = IdPAccountManager::Logger->new(
        file      => $Conf::global{'log_file'},
        verbosity => $Conf::global{'log_level'}
    );

    die "Failed to send mail notice to $options{'email_address'}\n"
        unless IdPAccountManager::Tools::mail_notice(
            'template'            => 'templates/mail/notification_generic_error.tt2.eml',
            'data'                => {},
            'to'                  => $options{'email_address'},
            'logger'              => $logger,
            'conf'                => \%Conf::global,
            'admin_email'         => $Conf::global{'admin_email'},
            'dev_no_mail_outside' => $Conf::global{'dev_no_mail_outside'},
            'dev_sp_contact'      => $Conf::global{'dev_sp_contact'},
            'notice_from'         => $Conf::global{'notice_from'}
    printf "Mail notice sent to $options{'email_address'}\n";
        -message => "invalid action '$action', aborting\n",
account-manager-client.pl - Command line client to the Test Account manager
B<account-manager-client.pl> B<add_test_account>
S<B<--account_profile> I<string>>
S<B<--sp_entityid> I<string>>

B<account-manager-client.pl> B<list_test_accounts>
S<[B<--account_profile> I<string>]>
S<[B<--sp_entityid> I<string>]>
[B<--filter_expired>]
[B<--delete>]

B<account-manager-client.pl> B<parse_federation_metadata>
S<[B<--sp_entityid> I<string>]>

B<account-manager-client.pl> B<add_service_provider>
S<B<--sp_entityid> I<string>>
S<B<--contact> I<string>>
S<[B<--displayname> I<string>]>

B<account-manager-client.pl> B<list_service_providers>
B<account-manager-client.pl> B<list_authentication_tokens>
S<B<--sp_entityid> I<string>>
S<[B<--token> I<string>]>
[B<--filter_expired>]
[B<--delete>]

B<account-manager-client.pl> B<get_authentication_token>
S<B<--sp_entityid> I<string>>
S<[B<--token> I<string>]>

B<account-manager-client.pl> B<add_authentication_token>
S<B<--sp_entityid> I<string>>
S<B<--email_address> I<string>>

B<account-manager-client.pl> B<send_notice>
S<B<--email_address> I<string>>
The Test Account manager instanciates test accounts associated to a SAML
Identity Provider.  This script provides a command-line interface for most
functions.
    $> account-manager-client.pl add_test_account \
Guillaume ROUSSE's avatar
Guillaume ROUSSE committed
    --sp_entityid https://test.federation.renater.fr/test/ressource \
    --account_profile student1

Adds a new test account.

    $> account-manager-client.pl list_test_accounts \
Guillaume ROUSSE's avatar
Guillaume ROUSSE committed
    --sp_entityid https://test.federation.renater.fr/test/ressource \
    --account_profile student1

List all test accounts. Criterias can be added to filter test accounts.

    $> account-manager-client.pl list_test_accounts --filter_expired
    $> account-manager-client.pl list_test_accounts --filter_expired \
    --delete

Remove all expired test accounts from DB.

    $> account-manager-client.pl parse_federation_metadata
Parses the SAML metadata file, as defined by the
C<federation_metadata_file_path> configuration parameter.
    $> account-manager-client.pl list_authentication_tokens \
Guillaume ROUSSE's avatar
Guillaume ROUSSE committed
    --sp_entityid https://test.federation.renater.fr/test/ressource \
    --token dhj67sjJ

List all authentication tokens. Criterias can be added to filter tokens.

    $> account-manager-client.pl list_authentication_tokens \
    --filter_expired

List all expired authentication tokens.

    $> account-manager-client.pl list_authentication_tokens \
    --filter_expired --delete

Remove all expired authentication tokens from DB.

    $> account-manager-client.pl get_authentication_token \
Guillaume ROUSSE's avatar
Guillaume ROUSSE committed
    --token dhj67sjJ

Get informations on a token.

    $> account-manager-client.pl add_authentication_token \
Guillaume ROUSSE's avatar
Guillaume ROUSSE committed
    --email_address john@my.fqdn \
    --sp_entityid https://test.federation.renater.fr/test/ressource

Adds a new test account.

    $> account-manager-client.pl send_notice --email_address=john@my.fqdn

Sends a mail notice to the specified email address.

    $> account-manager-client.pl add_service_provider \
Guillaume ROUSSE's avatar
Guillaume ROUSSE committed
    --sp_entityid https://test.federation.renater.fr/test/ressource \
    --displayname 'Test SP' --contacts email1@dom,email2@dom

Adds a new Service provider

Olivier Salaün (olivier.salaun@renater.fr)

=head1 LICENSE

Copyright (c) GEANT
This software was developed by RENATER. The research leading to these results has received funding
from the European Community¹s Seventh Framework Programme (FP7/2007-2013) under grant agreement nº 238875 (GÉANT).