diff options
author | Jon Robertson <jonrober@stanford.edu> | 2015-04-17 13:41:52 -0700 |
---|---|---|
committer | Jon Robertson <jonrober@stanford.edu> | 2015-06-08 15:24:34 -0700 |
commit | feacbd7d685b1790579f949b3e72a48412835d92 (patch) | |
tree | 10a123e9919cc85ebc3170ff2cd13011a189dfe4 /perl/lib/Wallet/Object/Duo.pm | |
parent | 0f943b75d34623b6825a0acf34ee2cd965bc6799 (diff) |
Merged all Duo objects into one module
To handle local proliferation of Duo integration type requests, all Duo
types have been merged into one module that will pick up and decide
integration specifics off of the object type.
If you are using the Duo types locally already, you'll want to load
perl/sql/wallet-1.3-update-duo.sql to your database to update the old
object types to all use the Duo module.
All existing Duo integrations have been added to the module for
handling, but nothing new has been added to the wallet object types.
Since there are a lot of Duo integrations, sites should only manually
add the ones they're interested in to the wallet types table.
Change-Id: If9c9a0a3e77923354f31d8f9c98a519c93df200b
Diffstat (limited to 'perl/lib/Wallet/Object/Duo.pm')
-rw-r--r-- | perl/lib/Wallet/Object/Duo.pm | 121 |
1 files changed, 113 insertions, 8 deletions
diff --git a/perl/lib/Wallet/Object/Duo.pm b/perl/lib/Wallet/Object/Duo.pm index d08294b..d0901de 100644 --- a/perl/lib/Wallet/Object/Duo.pm +++ b/perl/lib/Wallet/Object/Duo.pm @@ -29,7 +29,100 @@ use Wallet::Object::Base; # This version should be increased on any code change to this module. Always # use two digits for the minor version with a leading zero if necessary so # that it will sort properly. -$VERSION = '0.02'; +$VERSION = '0.03'; + +# Mappings from our types into what Duo calls the integration types. +our %DUO_TYPES = ( + 'duo' => { + integration => 'unix', + output => \&_output_generic, + }, + 'duo-ldap' => { + integration => 'ldapproxy', + output => \&_output_ldap, + }, + 'duo-pam' => { + integration => 'unix', + output => \&_output_pam, + }, + 'duo-radius' => { + integration => 'radius', + output => \&_output_radius, + }, + ); + +# Extra types to add. These are all just named as the Duo integration name +# with duo- before it and go to the generic output. Put them here to prevent +# pages of settings. These are also not all actually set as types in the +# types table to prevent overpopulation. You should manually create the +# entries in that table for any Duo integrations you want to add. +our @EXTRA_TYPES = ('accountsapi', 'adfs', 'adminapi', 'array', 'barracuda', + 'cisco', 'citrixcag', 'citrixns', 'confluence', 'drupal', + 'f5bigip', 'f5firepass', 'fortinet', 'jira', 'juniper', + 'juniperuac', 'lastpass', 'okta', 'onelogin', 'openvpn', + 'openvpnas', 'owa', 'paloalto', 'rdgateway', 'rdp', + 'rdweb', 'rest', 'rras', 'shibboleth', 'sonicwallsra', + 'splunk', 'tmg', 'uag', 'verify', 'vmwareview', 'websdk', + 'wordpress'); +for my $type (@EXTRA_TYPES) { + my $wallet_type = 'duo-'.$type; + $DUO_TYPES{$wallet_type}{integration} = $type; + $DUO_TYPES{$wallet_type}{output} = \&_output_generic; +}; + +############################################################################## +# Get output methods +############################################################################## + +# Output for any miscellaneous Duo integration, usually those that use a GUI +# to set information and so don't need a custom configuration file. +sub _output_generic { + my ($key, $secret, $hostname) = @_; + + my $output; + $output .= "Integration key: $key\n"; + $output .= "Secret key: $secret\n"; + $output .= "Host: $hostname\n"; + + return $output; +} + +# Output for the Duo unix integration, which hooks into the PAM stack. +sub _output_pam { + my ($key, $secret, $hostname) = @_; + + my $output = "[duo]\n"; + $output .= "ikey = $key\n"; + $output .= "skey = $secret\n"; + $output .= "host = $hostname\n"; + + return $output; +} + +# Output for the radius proxy, which can be plugged into the proxy config. +sub _output_radius { + my ($key, $secret, $hostname) = @_; + + my $output = "[radius_server_challenge]\n"; + $output .= "ikey = $key\n"; + $output .= "skey = $secret\n"; + $output .= "api_host = $hostname\n"; + $output .= "client = radius_client\n"; + + return $output; +} + +# Output for the LDAP proxy, which can be plugged into the proxy config. +sub _output_ldap { + my ($key, $secret, $hostname) = @_; + + my $output = "[ldap_server_challenge]\n"; + $output .= "ikey = $key\n"; + $output .= "skey = $secret\n"; + $output .= "api_host = $hostname\n"; + + return $output; +} ############################################################################## # Core methods @@ -86,7 +179,7 @@ sub new { # great here since we don't have a way to communicate the error back to the # caller. sub create { - my ($class, $type, $name, $schema, $creator, $host, $time, $duo_type) = @_; + my ($class, $type, $name, $schema, $creator, $host, $time) = @_; # We have to have a Duo integration key file set. if (not $Wallet::Config::DUO_KEY_FILE) { @@ -95,6 +188,12 @@ sub create { my $key_file = $Wallet::Config::DUO_KEY_FILE; my $agent = $Wallet::Config::DUO_AGENT; + # Make sure this is actually a type we know about, since this handler + # can handle many types. + if (!exists $DUO_TYPES{$type}) { + die "$type is not a valid duo integration\n"; + } + # Construct the Net::Duo::Admin object. require Net::Duo::Admin; my $duo = Net::Duo::Admin->new ( @@ -106,7 +205,7 @@ sub create { # Create the object in Duo. require Net::Duo::Admin::Integration; - $duo_type ||= $Wallet::Config::DUO_TYPE; + my $duo_type = $DUO_TYPES{$type}{integration}; my %data = ( name => "$name ($duo_type)", notes => 'Managed by wallet', @@ -201,11 +300,17 @@ sub get { my $json = JSON->new->utf8 (1)->relaxed (1); my $config = $json->decode (scalar slurp $Wallet::Config::DUO_KEY_FILE); - # Construct the returned file. - my $output; - $output .= "Integration key: $key\n"; - $output .= 'Secret key: ' . $integration->secret_key . "\n"; - $output .= "Host: $config->{api_hostname}\n"; + # Construct the returned file. Assume the generic handler in case there + # is no valid handler, though that shouldn't happen. + my $output_sub; + my $type = $self->{type}; + if (exists $DUO_TYPES{$type}{output}) { + $output_sub = $DUO_TYPES{$type}{output}; + } else { + $output_sub = \&_output_generic; + } + my $output = $output_sub->($key, $integration->secret_key, + $config->{api_hostname}); # Log the action and return. $self->log_action ('get', $user, $host, $time); |