From d117dc39c7063a782fc587c8d97657a752826f4a Mon Sep 17 00:00:00 2001
From: Andreas Granig <agranig@sipwise.com>
Date: Mon, 20 Mar 2017 22:02:30 +0100
Subject: [PATCH] TT#13301 Use cached API cert for API test speed-up

If no locally cached API cert is available, download one and use it
throughout all of the tests. Speed-up factor is ~3x.

Change-Id: I083985f4e4ec7d8f7f4e0beec3a604be80a4bb59
---
 sandbox/keys.zip                          | Bin 0 -> 7811 bytes
 sandbox/unzip_keys.pl                     |  32 +++++++++++++++
 t/api-rest/api-all-links.t                |  13 ++----
 t/api-rest/api-balanceintervals.t         |  13 +-----
 t/api-rest/api-billingnetworks.t          |  14 ++-----
 t/api-rest/api-billingprofiles.t          |  14 ++-----
 t/api-rest/api-contracts.t                |  12 +-----
 t/api-rest/api-customercontacts.t         |  14 ++-----
 t/api-rest/api-customerfraudpreferences.t |  13 +-----
 t/api-rest/api-customers.t                |  17 +-------
 t/api-rest/api-events.t                   |  12 +-----
 t/api-rest/api-journals.t                 |  14 ++-----
 t/api-rest/api-lnp.t                      |  14 ++-----
 t/api-rest/api-method-override.t          |  14 ++-----
 t/api-rest/api-profilepackages.t          |  12 +-----
 t/api-rest/api-resellers.t                |  14 ++-----
 t/api-rest/api-rewriterulesets.t          |  14 ++-----
 t/api-rest/api-root.t                     |  12 +-----
 t/api-rest/api-rtc-full.t                 |  14 ++-----
 t/api-rest/api-subscribers-groups.t       |  14 ++-----
 t/api-rest/api-systemcontacts.t           |  14 ++-----
 t/api-rest/api-topuplogs.t                |  14 ++-----
 t/api-rest/api-valid-patch.t              |  14 ++-----
 t/lib/Test/Collection.pm                  |  47 ++++++++++++++++++++++
 24 files changed, 135 insertions(+), 230 deletions(-)
 create mode 100644 sandbox/keys.zip
 create mode 100755 sandbox/unzip_keys.pl

diff --git a/sandbox/keys.zip b/sandbox/keys.zip
new file mode 100644
index 0000000000000000000000000000000000000000..c2eabbdb78f7183bf86897d3cb3869685608f7d1
GIT binary patch
literal 7811
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
MJpMa}lmD~&4@=|iG5`Po

literal 0
HcmV?d00001

diff --git a/sandbox/unzip_keys.pl b/sandbox/unzip_keys.pl
new file mode 100755
index 0000000000..520eca8229
--- /dev/null
+++ b/sandbox/unzip_keys.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -w
+use strict;
+use Data::Dumper;
+use File::Slurp qw/read_file/;
+use IO::Uncompress::Unzip qw/unzip/;
+
+my $zip = read_file("keys.zip");
+my $z = IO::Uncompress::Unzip->new(\$zip, MultiStream => 0, Append => 1);
+
+my $data;
+while(!$z->eof() && (my $hdr = $z->getHeaderInfo())) {
+    print "+++ found $$hdr{Name}\n";
+    unless($hdr->{Name} =~ /\.pem$/) {
+        # wrong file, just read stream, clear buffer and try next
+        while($z->read($data) > 0) {};
+        $data = undef;
+        $z->nextStream();
+        next;
+    }
+
+    # got our pem file
+    while($z->read($data) > 0) {}
+    last;
+}
+$z->close();
+unless($data) {
+    die "no PEM file found\n";
+}
+
+open my $fh, ">:raw", "/tmp/out.zip";
+print $fh $data;
+close $fh;
diff --git a/t/api-rest/api-all-links.t b/t/api-rest/api-all-links.t
index 43fdbfa541..edbfc3f4a4 100644
--- a/t/api-rest/api-all-links.t
+++ b/t/api-rest/api-all-links.t
@@ -2,7 +2,6 @@ use warnings;
 use strict;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
@@ -10,15 +9,9 @@ my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
 my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-balanceintervals.t b/t/api-rest/api-balanceintervals.t
index a21ebff33f..3b172c9551 100644
--- a/t/api-rest/api-balanceintervals.t
+++ b/t/api-rest/api-balanceintervals.t
@@ -5,7 +5,6 @@ use threads::shared qw();
 
 #use Sipwise::Base; #causes segfault when creating threads..
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use Time::HiRes; #prevent warning from Time::Warp
@@ -53,18 +52,10 @@ if ($is_local_env) {
 my %config = $catalyst_config->getall();
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 my $req_identifier;
 my $infinite_future;
diff --git a/t/api-rest/api-billingnetworks.t b/t/api-rest/api-billingnetworks.t
index 70ff59f776..36b023d540 100644
--- a/t/api-rest/api-billingnetworks.t
+++ b/t/api-rest/api-billingnetworks.t
@@ -1,6 +1,5 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use Storable qw();
@@ -17,18 +16,11 @@ use NGCP::Panel::Utils::BillingNetworks qw();
 my $is_local_env = 0;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 {
     my $blocks = [{ip=>'fdfe::5a55:caff:fefa:9089',mask=>128},
diff --git a/t/api-rest/api-billingprofiles.t b/t/api-rest/api-billingprofiles.t
index 28cb5329f0..99b61829e1 100644
--- a/t/api-rest/api-billingprofiles.t
+++ b/t/api-rest/api-billingprofiles.t
@@ -1,24 +1,16 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $is_local_env = 0;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-contracts.t b/t/api-rest/api-contracts.t
index e1dbbf3aa9..b427434232 100644
--- a/t/api-rest/api-contracts.t
+++ b/t/api-rest/api-contracts.t
@@ -2,7 +2,6 @@
 
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
@@ -11,18 +10,11 @@ use DateTime::Format::Strptime qw();
 use DateTime::Format::ISO8601 qw();
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
 
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-customercontacts.t b/t/api-rest/api-customercontacts.t
index 9082587090..7b2b5ccbc8 100644
--- a/t/api-rest/api-customercontacts.t
+++ b/t/api-rest/api-customercontacts.t
@@ -1,22 +1,14 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #goto SKIP;
 # OPTIONS tests
diff --git a/t/api-rest/api-customerfraudpreferences.t b/t/api-rest/api-customerfraudpreferences.t
index 917b40b742..f428278376 100644
--- a/t/api-rest/api-customerfraudpreferences.t
+++ b/t/api-rest/api-customerfraudpreferences.t
@@ -1,22 +1,13 @@
 #use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #$ua->add_handler("request_send",  sub {
 #    my ($request, $ua, $h) = @_;
diff --git a/t/api-rest/api-customers.t b/t/api-rest/api-customers.t
index bdb40fb750..f1ae1600a7 100644
--- a/t/api-rest/api-customers.t
+++ b/t/api-rest/api-customers.t
@@ -4,7 +4,6 @@ use strict;
 use warnings;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
@@ -12,23 +11,11 @@ use DateTime qw();
 use DateTime::Format::Strptime qw();
 use DateTime::Format::ISO8601 qw();
 
-BEGIN {
-    unshift(@INC,'../../lib');
-}
-
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
-
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
 
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-events.t b/t/api-rest/api-events.t
index 3c25221d55..84dde51db8 100644
--- a/t/api-rest/api-events.t
+++ b/t/api-rest/api-events.t
@@ -1,6 +1,5 @@
 #use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use Data::Dumper;
@@ -8,18 +7,11 @@ use Data::Dumper;
 my $is_local_env = 0;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
 
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #$ua->add_handler("request_send",  sub {
 #    my ($request, $ua, $h) = @_;
diff --git a/t/api-rest/api-journals.t b/t/api-rest/api-journals.t
index 06435c3b96..4005c4b6c4 100644
--- a/t/api-rest/api-journals.t
+++ b/t/api-rest/api-journals.t
@@ -1,6 +1,5 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use Storable qw();
@@ -39,18 +38,11 @@ if ($is_local_env) {
 my %config = $catalyst_config->getall();
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 my $t = time;
 my $default_reseller_id = 1;
diff --git a/t/api-rest/api-lnp.t b/t/api-rest/api-lnp.t
index 36e1dbbeeb..6ec661be5c 100644
--- a/t/api-rest/api-lnp.t
+++ b/t/api-rest/api-lnp.t
@@ -1,6 +1,5 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use DateTime::Format::ISO8601;
@@ -13,18 +12,11 @@ use warnings;
 my $is_local_env = 0;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #$ua->add_handler("request_send",  sub {
 #    my ($request, $ua, $h) = @_;
diff --git a/t/api-rest/api-method-override.t b/t/api-rest/api-method-override.t
index 6dba4cdea2..08d2d8f867 100644
--- a/t/api-rest/api-method-override.t
+++ b/t/api-rest/api-method-override.t
@@ -1,24 +1,16 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $is_local_env = 0;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #$ua->add_handler("request_send",  sub {
 #    my ($request, $ua, $h) = @_;
diff --git a/t/api-rest/api-profilepackages.t b/t/api-rest/api-profilepackages.t
index 514504d51e..ae17667e18 100644
--- a/t/api-rest/api-profilepackages.t
+++ b/t/api-rest/api-profilepackages.t
@@ -2,7 +2,6 @@ use warnings;
 use strict;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use Storable qw();
@@ -12,18 +11,11 @@ use JSON::PP;
 use LWP::Debug;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
 
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-resellers.t b/t/api-rest/api-resellers.t
index 9e93224927..bdd47e58e4 100644
--- a/t/api-rest/api-resellers.t
+++ b/t/api-rest/api-resellers.t
@@ -2,23 +2,15 @@ use warnings;
 use strict;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-rewriterulesets.t b/t/api-rest/api-rewriterulesets.t
index 5a2e2e1555..26f335d579 100644
--- a/t/api-rest/api-rewriterulesets.t
+++ b/t/api-rest/api-rewriterulesets.t
@@ -2,23 +2,15 @@ use warnings;
 use strict;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-root.t b/t/api-rest/api-root.t
index b6603da6d4..28bf6b32eb 100644
--- a/t/api-rest/api-root.t
+++ b/t/api-rest/api-root.t
@@ -2,23 +2,15 @@ use strict;
 use warnings;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
 
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 # OPTIONS tests
 {
diff --git a/t/api-rest/api-rtc-full.t b/t/api-rest/api-rtc-full.t
index 884df19d6a..70538254cd 100644
--- a/t/api-rest/api-rtc-full.t
+++ b/t/api-rest/api-rtc-full.t
@@ -2,7 +2,6 @@ use warnings;
 use strict;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use URI::Escape qw();
@@ -17,7 +16,6 @@ unless ($ENV{TEST_RTC}) {
 }
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my $domain_name = $ENV{TEST_RTC_DOMAIN};
 unless ($domain_name) {
@@ -25,15 +23,9 @@ unless ($domain_name) {
 }
 
 my ($ua, $req, $res, $data);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 my ($domain_id);
 {
diff --git a/t/api-rest/api-subscribers-groups.t b/t/api-rest/api-subscribers-groups.t
index 2fc0c7d7d6..c0908fb644 100644
--- a/t/api-rest/api-subscribers-groups.t
+++ b/t/api-rest/api-subscribers-groups.t
@@ -1,24 +1,16 @@
 use Sipwise::Base;
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $is_local_env = 0;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #$ua->add_handler("request_send",  sub {
 #    my ($request, $ua, $h) = @_;
diff --git a/t/api-rest/api-systemcontacts.t b/t/api-rest/api-systemcontacts.t
index f00394c0cd..6de4078019 100644
--- a/t/api-rest/api-systemcontacts.t
+++ b/t/api-rest/api-systemcontacts.t
@@ -2,23 +2,15 @@ use strict;
 use warnings;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 #goto SKIP;
 # OPTIONS tests
diff --git a/t/api-rest/api-topuplogs.t b/t/api-rest/api-topuplogs.t
index 61c2138aa6..f8e280bb45 100644
--- a/t/api-rest/api-topuplogs.t
+++ b/t/api-rest/api-topuplogs.t
@@ -5,7 +5,6 @@ use Scalar::Util qw(looks_like_number);
 
 #use Sipwise::Base; #causes segfault when creating threads..
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 use DateTime::Format::Strptime;
@@ -37,18 +36,11 @@ if ($is_local_env) {
 my %config = $catalyst_config->getall();
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 my $t = time;
 my $default_reseller_id = 1;
diff --git a/t/api-rest/api-valid-patch.t b/t/api-rest/api-valid-patch.t
index 8b6c16afd2..0cbe9a23a9 100644
--- a/t/api-rest/api-valid-patch.t
+++ b/t/api-rest/api-valid-patch.t
@@ -2,23 +2,15 @@ use strict;
 use warnings;
 
 use Net::Domain qw(hostfqdn);
-use LWP::UserAgent;
 use JSON qw();
 use Test::More;
 
 my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
-my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!);
 
 my ($ua, $req, $res);
-$ua = LWP::UserAgent->new;
-
-$ua->ssl_opts(
-        verify_hostname => 0,
-        SSL_verify_mode => 0,
-    );
-my $user = $ENV{API_USER} // 'administrator';
-my $pass = $ENV{API_PASS} // 'administrator';
-$ua->credentials($netloc, "api_admin_http", $user, $pass);
+
+use Test::Collection;
+$ua = Test::Collection->new()->ua();
 
 my $body;
 
diff --git a/t/lib/Test/Collection.pm b/t/lib/Test/Collection.pm
index 899dda50a6..fc281ec1dd 100644
--- a/t/lib/Test/Collection.pm
+++ b/t/lib/Test/Collection.pm
@@ -19,6 +19,14 @@ use Data::Dumper;
 use File::Slurp qw/write_file/;
 use Storable;
 use Carp qw(cluck longmess shortmess);
+use IO::Uncompress::Unzip;
+
+has 'crt_path' => (
+    is => 'ro',
+    isa => 'Str',
+    lazy => 1,
+    default => sub {'/tmp/apicert.pem';},
+);
 
 has 'data_cache_file' => (
     is => 'ro',
@@ -252,8 +260,47 @@ sub init_ua {
         verify_hostname => 0,
         SSL_verify_mode => 0,
     );
+    $self->init_ssl_cert($ua);
     return $ua;
 }
+sub init_ssl_cert {
+    my ($self, $ua) = @_;
+    unless(-f $self->crt_path) {
+        my $res = $ua->post(
+            $self->base_uri . '/api/admincerts/',
+            Content_Type => 'application/json',
+            Content => '{}'
+        );
+        unless($res->is_success) {
+            die "failed to fetch client certificate: " . $res->status_line . "\n";
+        }
+        my $zip = $res->decoded_content;
+        my $z = IO::Uncompress::Unzip->new(\$zip, MultiStream => 0, Append => 1);
+        my $data;
+        while(!$z->eof() && (my $hdr = $z->getHeaderInfo())) {
+            unless($hdr->{Name} =~ /\.pem$/) {
+                # wrong file, just read stream, clear buffer and try next
+                while($z->read($data) > 0) {}
+                $data = undef;
+                $z->nextStream();
+                next;
+            }
+            while($z->read($data) > 0) {}
+            last;
+        }
+        $z->close();
+        unless($data) {
+            die "failed to find PEM file in client certificate zip file\n";
+        }
+        open my $fh, ">:raw", $self->crt_path or die "failed to open " . $self->crt_path . ": $!\n";
+        print $fh $data;
+        close $fh;
+    }
+    $ua->ssl_opts(
+        SSL_cert_file => $self->crt_path,
+        SSL_key_file => $self->crt_path,
+    );
+}
 sub runas {
     my $self = shift;
     my($role_in,$uri) = @_;