#!/usr/bin/perl use strict; use warnings; use Mojo::File qw(curfile); use lib curfile()->dirname()->sibling('lib')->to_string; use Config::Tiny; use English qw(-no_match_vars); use File::Temp; use Getopt::Long qw(:config auto_help); use List::MoreUtils qw(uniq); use LWP::UserAgent; use Pod::Usage; use AccountManager::DB; use AccountManager::Metadata; use AccountManager::Entity; my %options; GetOptions( \%options, 'configuration=s', 'verbose', ) or pod2usage( -message => "unknown option, aborting\n", -verbose => 0 ); my $configuration_file = $ENV{MOJO_CONFIG} || 'conf/manager.conf'; my $configuration = Config::Tiny->read($configuration_file); if (!$configuration) { die Config::Tiny->errstr() . "\n"; } die "no database defined in configuration, aborting\n" if !$configuration->{database}; die "no federation defined in configuration, aborting\n" if !$configuration->{federations}; AccountManager::DB->register_db( driver => $configuration->{database}->{type}, database => $configuration->{database}->{name}, host => $configuration->{database}->{host}, password => $configuration->{database}->{password}, username => $configuration->{database}->{username}, options => [ split(/, */, $configuration->{database}->{options}) ] ); my $db = AccountManager::DB->new(); my $ua = LWP::UserAgent->new(); $db->begin_work(); AccountManager::Entity->delete_entities(all => 1); $db->dbh()->do('ALTER TABLE entities AUTO_INCREMENT = 1'); my %seen; foreach my $id (keys %{$configuration->{federations}}) { print "processing federation $id\n" if $options{verbose}; my $file = File::Temp->new(); my $url = $configuration->{federations}->{$id}; print "downloading metadata from url $url\n" if $options{verbose}; my $response = $ua->get($url, ':content_file' => $file->filename()); if (!$response->is_success()) { $db->rollback(); die "failed to download federation metadata: " . $response->status_line(); } my $metadata; eval { $metadata = AccountManager::Metadata->new( file => $file ); }; if ($EVAL_ERROR) { $db->rollback(); die "failed to load federation metadata: $EVAL_ERROR"; } print "parsing metadata from file $file\n" if $options{verbose}; my $entities; eval { $entities = $metadata->parse(); }; if ($EVAL_ERROR) { $db->rollback(); die "failed to parse federation metadata: $EVAL_ERROR"; } foreach my $entry (@$entities) { # skip entities different from SP or IdP next if !$entry->{type}; my $entity; if ($seen{$entry->{entityid}}++) { $entity = AccountManager::Entity->new( db => $db, entityid => $entry->{entityid}, ); $entity->load(); $entity->federations( $entity->federations(), $id ); $entity->update(); } else { eval { $entity = AccountManager::Entity->new( db => $db, type => $entry->{type}, entityid => $entry->{entityid}, display_name => $entry->{display_name}, information_url => $entry->{information_url}, organization_url => $entry->{organization_url}, ); if ($entry->{contacts}) { my @contacts = uniq grep { $_ } map { $_->{EmailAddress} } @{$entry->{contacts}}; $entity->contacts(@contacts); } $entity->federations($id); $entity->save(); }; if ($EVAL_ERROR) { warn "error while processing entity $entry->{entityid}: $EVAL_ERROR"; } } } } $db->commit(); __END__ =head1 NAME update-metadata - Out-of-band metadata processing =head1 SYNOPSIS update-metadata [options] Options: --configuration <file> --verbose