From 34d83c2dd2a17af92e48d74ebfbbfce28c7e8525 Mon Sep 17 00:00:00 2001 From: Jon Robertson Date: Wed, 8 Oct 2014 20:33:56 -0700 Subject: Split Duo type out into multiple sub-types The existing functionality is now in the duo-pam object type. The old duo type now returns output in a generic config file, and new types for the Duo auth proxy in LDAP and Radius proxies are added. Change-Id: I1525d79b44dafcf3ef85368297baefafcb5dc179 --- perl/lib/Wallet/Object/Duo/LDAPProxy.pm | 202 ++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 perl/lib/Wallet/Object/Duo/LDAPProxy.pm (limited to 'perl/lib/Wallet/Object/Duo/LDAPProxy.pm') diff --git a/perl/lib/Wallet/Object/Duo/LDAPProxy.pm b/perl/lib/Wallet/Object/Duo/LDAPProxy.pm new file mode 100644 index 0000000..cd32523 --- /dev/null +++ b/perl/lib/Wallet/Object/Duo/LDAPProxy.pm @@ -0,0 +1,202 @@ +# Wallet::Object::Duo::LDAPProxy -- Duo auth proxy integration for LDAP +# +# Written by Jon Robertson +# Copyright 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# See LICENSE for licensing terms. + +############################################################################## +# Modules and declarations +############################################################################## + +package Wallet::Object::Duo::LDAPProxy; +require 5.006; + +use strict; +use warnings; +use vars qw(@ISA $VERSION); + +use JSON; +use Net::Duo::Admin; +use Net::Duo::Admin::Integration; +use Perl6::Slurp qw(slurp); +use Wallet::Config (); +use Wallet::Object::Duo; + +@ISA = qw(Wallet::Object::Duo); + +# 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.01'; + +############################################################################## +# Core methods +############################################################################## + +# Override create to provide the specific Duo integration type that will be +# used in the remote Duo record. +sub create { + my ($class, $type, $name, $schema, $creator, $host, $time) = @_; + + $time ||= time; + my $self = $class->SUPER::create ($type, $name, $schema, $creator, $host, + $time, 'ldap'); + return $self; +} + +# Override get to output the data in a specific format used for Duo LDAP +# integration +sub get { + my ($self, $user, $host, $time) = @_; + $time ||= time; + + # Check that the object isn't locked. + my $id = $self->{type} . ':' . $self->{name}; + if ($self->flag_check ('locked')) { + $self->error ("cannot get $id: object is locked"); + return; + } + + # Retrieve the integration from Duo. + my $key; + eval { + my %search = (du_name => $self->{name}); + my $row = $self->{schema}->resultset ('Duo')->find (\%search); + $key = $row->get_column ('du_key'); + }; + if ($@) { + $self->error ($@); + return; + } + my $integration = Net::Duo::Admin::Integration->new ($self->{duo}, $key); + + # We also need the admin server name, which we can get from the Duo object + # configuration with a bit of JSON decoding. + 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 = "[ldap_server_challenge]\n"; + $output .= "ikey = $key\n"; + $output .= 'skey = ' . $integration->secret_key . "\n"; + $output .= "api_host = $config->{api_hostname}\n"; + + # Log the action and return. + $self->log_action ('get', $user, $host, $time); + return $output; +} + +1; +__END__ + +############################################################################## +# Documentation +############################################################################## + +=for stopwords +Allbery Duo integration DBH keytab + +=head1 NAME + +Wallet::Object::Duo::LDAPProxy -- Duo auth proxy integration for LDAP + +=head1 SYNOPSIS + + my @name = qw(duo-ldap host.example.com); + my @trace = ($user, $host, time); + my $object = Wallet::Object::Duo::LDAPProxy->create (@name, $schema, @trace); + my $config = $object->get (@trace); + $object->destroy (@trace); + +=head1 DESCRIPTION + +Wallet::Object::Duo::LDAPProxy is a representation of Duo +integrations with the wallet, specifically to output Duo integrations +in a format that can easily be pulled into configuring the Duo +Authentication Proxy for LDAP. It implements the wallet object API +and provides the necessary glue to create a Duo integration, return a +configuration file containing the key and API information for that +integration, and delete the integration from Duo when the wallet object +is destroyed. + +The integration information is always returned in the configuration file +format expected by the Authentication Proxy for Duo in configuring it +for LDAP. + +This object can be retrieved repeatedly without changing the secret key, +matching Duo's native behavior with integrations. To change the keys of +the integration, delete it and recreate it. + +To use this object, at least one configuration parameter must be set. See +L for details on supported configuration parameters and +information about how to set wallet configuration. + +=head1 METHODS + +This object mostly inherits from Wallet::Object::Duo. See the +documentation for that class for all generic methods. Below are only +those methods that are overridden or behave specially for this +implementation. + +=over 4 + +=item create(TYPE, NAME, DBH, PRINCIPAL, HOSTNAME [, DATETIME]) + +This will override the Wallet::Object::Duo class with the information +needed to create a specific integration type in Duo. It creates a new +object with the given TYPE and NAME (TYPE is normally C and +must be for the rest of the wallet system to use the right class, but +this module doesn't check for ease of subclassing), using DBH as the +handle to the wallet metadata database. PRINCIPAL, HOSTNAME, and +DATETIME are stored as history information. PRINCIPAL should be the +user who is creating the object. If DATETIME isn't given, the current +time is used. + +When a new Duo integration object is created, a new integration will be +created in the configured Duo account and the integration key will be +stored in the wallet object. If the integration already exists, create() +will fail. + +If create() fails, it throws an exception. + +=item get(PRINCIPAL, HOSTNAME [, DATETIME]) + +Retrieves the configuration information for the Duo integration and +returns that information in the format expected by the configuration file +for the Duo UNIX integration. Returns undef on failure. The caller +should call error() to get the error message if get() returns undef. + +The returned configuration look look like: + + [ldap_server_challenge] + ikey = + skey = + api_host = + +The C parameter will be taken from the configuration file pointed +to by the DUO_KEY_FILE configuration variable. + +PRINCIPAL, HOSTNAME, and DATETIME are stored as history information. +PRINCIPAL should be the user who is downloading the keytab. If DATETIME +isn't given, the current time is used. + +=back + +=head1 LIMITATIONS + +Only one Duo account is supported for a given wallet implementation. + +=head1 SEE ALSO + +Net::Duo(3), Wallet::Config(3), Wallet::Object::Duo(3), wallet-backend(8) + +This module is part of the wallet system. The current version is +available from L. + +=head1 AUTHORS + +Jon Robertson + +=cut -- cgit v1.2.3 From 94cfb1c7969515a863d7b0e09f00b6ced5f4fc5c Mon Sep 17 00:00:00 2001 From: Jon Robertson Date: Thu, 9 Oct 2014 09:55:21 -0700 Subject: Created tests for new Duo object types Change-Id: I818be125f3195316b44e650ba6e05b8e0b831ea6 --- perl/lib/Wallet/Config.pm | 6 +- perl/lib/Wallet/Object/Duo/LDAPProxy.pm | 2 +- perl/t/data/duo/integration-ldap.json | 11 +++ perl/t/data/duo/integration-radius.json | 11 +++ perl/t/object/duo-ldap.t | 160 +++++++++++++++++++++++++++++++ perl/t/object/duo-pam.t | 159 ++++++++++++++++++++++++++++++ perl/t/object/duo-radius.t | 165 ++++++++++++++++++++++++++++++++ perl/t/object/duo.t | 7 +- 8 files changed, 513 insertions(+), 8 deletions(-) create mode 100644 perl/t/data/duo/integration-ldap.json create mode 100644 perl/t/data/duo/integration-radius.json create mode 100644 perl/t/object/duo-ldap.t create mode 100644 perl/t/object/duo-pam.t create mode 100644 perl/t/object/duo-radius.t (limited to 'perl/lib/Wallet/Object/Duo/LDAPProxy.pm') diff --git a/perl/lib/Wallet/Config.pm b/perl/lib/Wallet/Config.pm index 527658c..2eb57f9 100644 --- a/perl/lib/Wallet/Config.pm +++ b/perl/lib/Wallet/Config.pm @@ -217,9 +217,9 @@ our $DUO_KEY_FILE; =item DUO_TYPE -The type of integration to create. Currently, only one type of integration -can be created by one wallet configuration. This restriction may be relaxed -in the future. The default value is C to create UNIX integrations. +The type of integration to create. The default value is C to create +UNIX integrations, since this was the first integration created and users +may rely on it to still be the default. =cut diff --git a/perl/lib/Wallet/Object/Duo/LDAPProxy.pm b/perl/lib/Wallet/Object/Duo/LDAPProxy.pm index cd32523..757a61a 100644 --- a/perl/lib/Wallet/Object/Duo/LDAPProxy.pm +++ b/perl/lib/Wallet/Object/Duo/LDAPProxy.pm @@ -42,7 +42,7 @@ sub create { $time ||= time; my $self = $class->SUPER::create ($type, $name, $schema, $creator, $host, - $time, 'ldap'); + $time, 'ldapproxy'); return $self; } diff --git a/perl/t/data/duo/integration-ldap.json b/perl/t/data/duo/integration-ldap.json new file mode 100644 index 0000000..78a4c9f --- /dev/null +++ b/perl/t/data/duo/integration-ldap.json @@ -0,0 +1,11 @@ +{ + "enroll_policy": "enroll", + "greeting": "", + "groups_allowed": [], + "integration_key": "DIRWIH0ZZPV4G88B37VQ", + "name": "Integration for LDAP proxy", + "notes": "", + "secret_key": "QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o", + "type": "ldap", + "visual_style": "default" +} diff --git a/perl/t/data/duo/integration-radius.json b/perl/t/data/duo/integration-radius.json new file mode 100644 index 0000000..514a33e --- /dev/null +++ b/perl/t/data/duo/integration-radius.json @@ -0,0 +1,11 @@ +{ + "enroll_policy": "enroll", + "greeting": "", + "groups_allowed": [], + "integration_key": "DIRWIH0ZZPV4G88B37VQ", + "name": "Integration for Radius proxy", + "notes": "", + "secret_key": "QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o", + "type": "radius", + "visual_style": "default" +} diff --git a/perl/t/object/duo-ldap.t b/perl/t/object/duo-ldap.t new file mode 100644 index 0000000..3648eba --- /dev/null +++ b/perl/t/object/duo-ldap.t @@ -0,0 +1,160 @@ +#!/usr/bin/perl +# +# Tests for the Duo Auth proxy LDAP integration object implementation. +# +# Written by Russ Allbery +# Copyright 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# See LICENSE for licensing terms. + +use strict; +use warnings; + +use POSIX qw(strftime); +use Test::More; + +BEGIN { + eval 'use Net::Duo'; + plan skip_all => 'Net::Duo required for testing duo' + if $@; + eval 'use Net::Duo::Mock::Agent'; + plan skip_all => 'Net::Duo::Mock::Agent required for testing duo' + if $@; +} + +BEGIN { + use_ok('Wallet::Admin'); + use_ok('Wallet::Config'); + use_ok('Wallet::Object::Duo::LDAPProxy'); +} + +use lib 't/lib'; +use Util; + +# Some global defaults to use. +my $user = 'admin@EXAMPLE.COM'; +my $host = 'localhost'; +my @trace = ($user, $host, time); +my $date = strftime ('%Y-%m-%d %H:%M:%S', localtime $trace[2]); + +# Flush all output immediately. +$| = 1; + +# Use Wallet::Admin to set up the database. +db_setup; +my $admin = eval { Wallet::Admin->new }; +is ($@, '', 'Database connection succeeded'); +is ($admin->reinitialize ($user), 1, 'Database initialization succeeded'); +my $schema = $admin->schema; + +# Create a mock object to use for Duo calls. +my $mock = Net::Duo::Mock::Agent->new ({ key_file => 't/data/duo/keys.json' }); + +# Test error handling in the absence of configuration. +my $object = eval { + Wallet::Object::Duo::LDAPProxy->new ('duo-ldap', 'test', $schema); +}; +is ($object, undef, 'Wallet::Object::Duo::LDAPProxy new with no config failed'); +is ($@, "duo object implementation not configured\n", '...with correct error'); +$object = eval { + Wallet::Object::Duo::LDAPProxy->create ('duo-ldap', 'test', $schema, + @trace); +}; +is ($object, undef, 'Wallet::Object::Duo::LDAPProxy creation with no config failed'); +is ($@, "duo object implementation not configured\n", '...with correct error'); + +# Set up the Duo configuration. +$Wallet::Config::DUO_AGENT = $mock; +$Wallet::Config::DUO_KEY_FILE = 't/data/duo/keys.json'; + +# Test creating an integration. +note ('Test creating an integration'); +my $expected = { + name => 'test (ldapproxy)', + notes => 'Managed by wallet', + type => 'ldapproxy', +}; +$mock->expect ( + { + method => 'POST', + uri => '/admin/v1/integrations', + content => $expected, + response_file => 't/data/duo/integration.json', + } +); +$object = Wallet::Object::Duo::LDAPProxy->create ('duo-ldap', 'test', $schema, + @trace); +isa_ok ($object, 'Wallet::Object::Duo::LDAPProxy'); + +# Check the metadata about the new wallet object. +$expected = <<"EOO"; + Type: duo-ldap + Name: test + Duo key: DIRWIH0ZZPV4G88B37VQ + Created by: $user + Created from: $host + Created on: $date +EOO +is ($object->show, $expected, 'Show output is correct'); + +# Test retrieving the integration information. +note ('Test retrieving an integration'); +$mock->expect ( + { + method => 'GET', + uri => '/admin/v1/integrations/DIRWIH0ZZPV4G88B37VQ', + response_file => 't/data/duo/integration-ldap.json', + } +); +my $data = $object->get (@trace); +ok (defined ($data), 'Retrieval succeeds'); +$expected = <<'EOO'; +[ldap_server_challenge] +ikey = DIRWIH0ZZPV4G88B37VQ +skey = QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o +api_host = example-admin.duosecurity.com +EOO +is ($data, $expected, '...and integration data is correct'); + +# Ensure that we can't retrieve the object when locked. +is ($object->flag_set ('locked', @trace), 1, + 'Setting object to locked succeeds'); +is ($object->get, undef, '...and now get fails'); +is ($object->error, 'cannot get duo-ldap:test: object is locked', + '...with correct error'); +is ($object->flag_clear ('locked', @trace), 1, + '...and clearing locked flag works'); + +# Create a new object by wallet type and name. +$object = Wallet::Object::Duo::LDAPProxy->new ('duo-ldap', 'test', $schema); + +# Test deleting an integration. We can't test this entirely properly because +# currently Net::Duo::Mock::Agent doesn't support stacking multiple expected +# calls and delete makes two calls. +note ('Test deleting an integration'); +$mock->expect ( + { + method => 'GET', + uri => '/admin/v1/integrations/DIRWIH0ZZPV4G88B37VQ', + response_file => 't/data/duo/integration.json', + } +); +TODO: { + local $TODO = 'Net::Duo::Mock::Agent not yet capable'; + + is ($object->destroy (@trace), 1, 'Duo object deletion succeeded'); + $object = eval { Wallet::Object::Duo::LDAPProxy->new ('duo-ldap', 'test', + $schema) }; + is ($object, undef, '...and now object cannot be retrieved'); + is ($@, "cannot find duo:test\n", '...with correct error'); +} + +# Clean up. +$admin->destroy; +END { + unlink ('wallet-db'); +} + +# Done testing. +done_testing (); diff --git a/perl/t/object/duo-pam.t b/perl/t/object/duo-pam.t new file mode 100644 index 0000000..7b88787 --- /dev/null +++ b/perl/t/object/duo-pam.t @@ -0,0 +1,159 @@ +#!/usr/bin/perl +# +# Tests for the Duo PAM integration object implementation. +# +# Written by Russ Allbery +# Copyright 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# See LICENSE for licensing terms. + +use strict; +use warnings; + +use POSIX qw(strftime); +use Test::More; + +BEGIN { + eval 'use Net::Duo'; + plan skip_all => 'Net::Duo required for testing duo' + if $@; + eval 'use Net::Duo::Mock::Agent'; + plan skip_all => 'Net::Duo::Mock::Agent required for testing duo' + if $@; +} + +BEGIN { + use_ok('Wallet::Admin'); + use_ok('Wallet::Config'); + use_ok('Wallet::Object::Duo::PAM'); +} + +use lib 't/lib'; +use Util; + +# Some global defaults to use. +my $user = 'admin@EXAMPLE.COM'; +my $host = 'localhost'; +my @trace = ($user, $host, time); +my $date = strftime ('%Y-%m-%d %H:%M:%S', localtime $trace[2]); + +# Flush all output immediately. +$| = 1; + +# Use Wallet::Admin to set up the database. +db_setup; +my $admin = eval { Wallet::Admin->new }; +is ($@, '', 'Database connection succeeded'); +is ($admin->reinitialize ($user), 1, 'Database initialization succeeded'); +my $schema = $admin->schema; + +# Create a mock object to use for Duo calls. +my $mock = Net::Duo::Mock::Agent->new ({ key_file => 't/data/duo/keys.json' }); + +# Test error handling in the absence of configuration. +my $object = eval { + Wallet::Object::Duo::PAM->new ('duo-pam', 'test', $schema); +}; +is ($object, undef, 'Wallet::Object::Duo::PAM new with no config failed'); +is ($@, "duo object implementation not configured\n", '...with correct error'); +$object = eval { + Wallet::Object::Duo::PAM->create ('duo-pam', 'test', $schema, @trace); +}; +is ($object, undef, 'Wallet::Object::Duo::PAM creation with no config failed'); +is ($@, "duo object implementation not configured\n", '...with correct error'); + +# Set up the Duo configuration. +$Wallet::Config::DUO_AGENT = $mock; +$Wallet::Config::DUO_KEY_FILE = 't/data/duo/keys.json'; + +# Test creating an integration. +note ('Test creating an integration'); +my $expected = { + name => 'test (unix)', + notes => 'Managed by wallet', + type => 'unix', +}; +$mock->expect ( + { + method => 'POST', + uri => '/admin/v1/integrations', + content => $expected, + response_file => 't/data/duo/integration.json', + } +); +$object = Wallet::Object::Duo::PAM->create ('duo-pam', 'test', $schema, + @trace); +isa_ok ($object, 'Wallet::Object::Duo::PAM'); + +# Check the metadata about the new wallet object. +$expected = <<"EOO"; + Type: duo-pam + Name: test + Duo key: DIRWIH0ZZPV4G88B37VQ + Created by: $user + Created from: $host + Created on: $date +EOO +is ($object->show, $expected, 'Show output is correct'); + +# Test retrieving the integration information. +note ('Test retrieving an integration'); +$mock->expect ( + { + method => 'GET', + uri => '/admin/v1/integrations/DIRWIH0ZZPV4G88B37VQ', + response_file => 't/data/duo/integration.json', + } +); +my $data = $object->get (@trace); +ok (defined ($data), 'Retrieval succeeds'); +$expected = <<'EOO'; +[duo] +ikey = DIRWIH0ZZPV4G88B37VQ +skey = QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o +host = example-admin.duosecurity.com +EOO +is ($data, $expected, '...and integration data is correct'); + +# Ensure that we can't retrieve the object when locked. +is ($object->flag_set ('locked', @trace), 1, + 'Setting object to locked succeeds'); +is ($object->get, undef, '...and now get fails'); +is ($object->error, 'cannot get duo-pam:test: object is locked', + '...with correct error'); +is ($object->flag_clear ('locked', @trace), 1, + '...and clearing locked flag works'); + +# Create a new object by wallet type and name. +$object = Wallet::Object::Duo::PAM->new ('duo-pam', 'test', $schema); + +# Test deleting an integration. We can't test this entirely properly because +# currently Net::Duo::Mock::Agent doesn't support stacking multiple expected +# calls and delete makes two calls. +note ('Test deleting an integration'); +$mock->expect ( + { + method => 'GET', + uri => '/admin/v1/integrations/DIRWIH0ZZPV4G88B37VQ', + response_file => 't/data/duo/integration.json', + } +); +TODO: { + local $TODO = 'Net::Duo::Mock::Agent not yet capable'; + + is ($object->destroy (@trace), 1, 'Duo object deletion succeeded'); + $object = eval { Wallet::Object::Duo::PAM->new ('duo-pam', 'test', + $schema) }; + is ($object, undef, '...and now object cannot be retrieved'); + is ($@, "cannot find duo:test\n", '...with correct error'); +} + +# Clean up. +$admin->destroy; +END { + unlink ('wallet-db'); +} + +# Done testing. +done_testing (); diff --git a/perl/t/object/duo-radius.t b/perl/t/object/duo-radius.t new file mode 100644 index 0000000..f258518 --- /dev/null +++ b/perl/t/object/duo-radius.t @@ -0,0 +1,165 @@ +#!/usr/bin/perl +# +# Tests for the Duo Auth proxy Radius integration object implementation. +# +# Written by Russ Allbery +# Copyright 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# See LICENSE for licensing terms. + +use strict; +use warnings; + +use POSIX qw(strftime); +use Test::More; + +BEGIN { + eval 'use Net::Duo'; + plan skip_all => 'Net::Duo required for testing duo' + if $@; + eval 'use Net::Duo::Mock::Agent'; + plan skip_all => 'Net::Duo::Mock::Agent required for testing duo' + if $@; +} + +BEGIN { + use_ok('Wallet::Admin'); + use_ok('Wallet::Config'); + use_ok('Wallet::Object::Duo::RadiusProxy'); +} + +use lib 't/lib'; +use Util; + +# Some global defaults to use. +my $user = 'admin@EXAMPLE.COM'; +my $host = 'localhost'; +my @trace = ($user, $host, time); +my $date = strftime ('%Y-%m-%d %H:%M:%S', localtime $trace[2]); + +# Flush all output immediately. +$| = 1; + +# Use Wallet::Admin to set up the database. +db_setup; +my $admin = eval { Wallet::Admin->new }; +is ($@, '', 'Database connection succeeded'); +is ($admin->reinitialize ($user), 1, 'Database initialization succeeded'); +my $schema = $admin->schema; + +# Create a mock object to use for Duo calls. +my $mock = Net::Duo::Mock::Agent->new ({ key_file => 't/data/duo/keys.json' }); + +# Test error handling in the absence of configuration. +my $object = eval { + Wallet::Object::Duo::RadiusProxy->new ('duo-raduys', 'test', $schema); +}; +is ($object, undef, + 'Wallet::Object::Duo::RadiusProxy new with no config failed'); +is ($@, "duo object implementation not configured\n", '...with correct error'); +$object = eval { + Wallet::Object::Duo::RadiusProxy->create ('duo-radius', 'test', $schema, + @trace); +}; +is ($object, undef, + 'Wallet::Object::Duo::RadiusProxy creation with no config failed'); +is ($@, "duo object implementation not configured\n", '...with correct error'); + +# Set up the Duo configuration. +$Wallet::Config::DUO_AGENT = $mock; +$Wallet::Config::DUO_KEY_FILE = 't/data/duo/keys.json'; + +# Test creating an integration. +note ('Test creating an integration'); +my $expected = { + name => 'test (radius)', + notes => 'Managed by wallet', + type => 'radius', +}; +$mock->expect ( + { + method => 'POST', + uri => '/admin/v1/integrations', + content => $expected, + response_file => 't/data/duo/integration-radius.json', + } +); +$object = Wallet::Object::Duo::RadiusProxy->create ('duo-radius', 'test', + $schema, @trace); +isa_ok ($object, 'Wallet::Object::Duo::RadiusProxy'); + +# Check the metadata about the new wallet object. +$expected = <<"EOO"; + Type: duo-radius + Name: test + Duo key: DIRWIH0ZZPV4G88B37VQ + Created by: $user + Created from: $host + Created on: $date +EOO +is ($object->show, $expected, 'Show output is correct'); + +# Test retrieving the integration information. +note ('Test retrieving an integration'); +$mock->expect ( + { + method => 'GET', + uri => '/admin/v1/integrations/DIRWIH0ZZPV4G88B37VQ', + response_file => 't/data/duo/integration-radius.json', + } +); +my $data = $object->get (@trace); +ok (defined ($data), 'Retrieval succeeds'); +$expected = <<'EOO'; +[radius_server_challenge] +ikey = DIRWIH0ZZPV4G88B37VQ +skey = QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o +api_host = example-admin.duosecurity.com +client = radius_client +EOO +is ($data, $expected, '...and integration data is correct'); + +# Ensure that we can't retrieve the object when locked. +is ($object->flag_set ('locked', @trace), 1, + 'Setting object to locked succeeds'); +is ($object->get, undef, '...and now get fails'); +is ($object->error, 'cannot get duo-radius:test: object is locked', + '...with correct error'); +is ($object->flag_clear ('locked', @trace), 1, + '...and clearing locked flag works'); + +# Create a new object by wallet type and name. +$object = Wallet::Object::Duo::RadiusProxy->new ('duo-radius', 'test', + $schema); + +# Test deleting an integration. We can't test this entirely properly because +# currently Net::Duo::Mock::Agent doesn't support stacking multiple expected +# calls and delete makes two calls. +note ('Test deleting an integration'); +$mock->expect ( + { + method => 'GET', + uri => '/admin/v1/integrations/DIRWIH0ZZPV4G88B37VQ', + response_file => 't/data/duo/integration.json', + } +); +TODO: { + local $TODO = 'Net::Duo::Mock::Agent not yet capable'; + + is ($object->destroy (@trace), 1, 'Duo object deletion succeeded'); + $object = eval { + Wallet::Object::Duo::RadiusProxy->new ('duo-radius', 'test', $schema); + }; + is ($object, undef, '...and now object cannot be retrieved'); + is ($@, "cannot find duo:test\n", '...with correct error'); +} + +# Clean up. +$admin->destroy; +END { + unlink ('wallet-db'); +} + +# Done testing. +done_testing (); diff --git a/perl/t/object/duo.t b/perl/t/object/duo.t index f73fe7e..a975597 100755 --- a/perl/t/object/duo.t +++ b/perl/t/object/duo.t @@ -108,10 +108,9 @@ $mock->expect ( my $data = $object->get (@trace); ok (defined ($data), 'Retrieval succeeds'); $expected = <<'EOO'; -[duo] -ikey = DIRWIH0ZZPV4G88B37VQ -skey = QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o -host = example-admin.duosecurity.com +Integration key: DIRWIH0ZZPV4G88B37VQ +Secret key: QO4ZLqQVRIOZYkHfdPDORfcNf8LeXIbCWwHazY7o +Host: example-admin.duosecurity.com EOO is ($data, $expected, '...and integration data is correct'); -- cgit v1.2.3 From 88db4268a1bb9458e17872fe16d913f4f09c2fb6 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Mon, 8 Dec 2014 20:23:49 -0800 Subject: Add stopwords for new modules Change-Id: Ie1d2bcee19ace444f6f7083814133593b160d97d --- perl/lib/Wallet/Object/Duo/LDAPProxy.pm | 2 +- perl/lib/Wallet/Object/Duo/RDP.pm | 2 +- perl/lib/Wallet/Object/Duo/RadiusProxy.pm | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'perl/lib/Wallet/Object/Duo/LDAPProxy.pm') diff --git a/perl/lib/Wallet/Object/Duo/LDAPProxy.pm b/perl/lib/Wallet/Object/Duo/LDAPProxy.pm index 757a61a..74ff43c 100644 --- a/perl/lib/Wallet/Object/Duo/LDAPProxy.pm +++ b/perl/lib/Wallet/Object/Duo/LDAPProxy.pm @@ -96,7 +96,7 @@ __END__ ############################################################################## =for stopwords -Allbery Duo integration DBH keytab +Allbery Duo integration DBH keytab LDAP auth =head1 NAME diff --git a/perl/lib/Wallet/Object/Duo/RDP.pm b/perl/lib/Wallet/Object/Duo/RDP.pm index 4e7ff04..2e975fc 100644 --- a/perl/lib/Wallet/Object/Duo/RDP.pm +++ b/perl/lib/Wallet/Object/Duo/RDP.pm @@ -97,7 +97,7 @@ __END__ ############################################################################## =for stopwords -Allbery Duo integration DBH keytab +Allbery Duo integration DBH keytab RDP =head1 NAME diff --git a/perl/lib/Wallet/Object/Duo/RadiusProxy.pm b/perl/lib/Wallet/Object/Duo/RadiusProxy.pm index 2a29dec..faa0c2f 100644 --- a/perl/lib/Wallet/Object/Duo/RadiusProxy.pm +++ b/perl/lib/Wallet/Object/Duo/RadiusProxy.pm @@ -97,11 +97,11 @@ __END__ ############################################################################## =for stopwords -Allbery Duo integration DBH keytab +Allbery Duo integration DBH keytab auth =head1 NAME -Wallet::Object::Duo::RadiusProxy -- Duo auth proxy integration for radius +Wallet::Object::Duo::RadiusProxy -- Duo auth proxy integration for RADIUS =head1 SYNOPSIS -- cgit v1.2.3