File Coverage

blib/lib/Connector/Role/SSLUserAgent.pm
Criterion Covered Total %
statement 26 59 44.0
branch 10 42 23.8
condition 0 3 0.0
subroutine 4 5 80.0
pod n/a
total 40 109 36.7


line stmt bran cond sub pod time code
1             use Moose::Role;
2 1     1   1111 use Data::Dumper;
  1         4504  
  1         4  
3 1     1   4637 use LWP::UserAgent;
  1         2  
  1         53  
4 1     1   612  
  1         40204  
  1         603  
5             has timeout => (
6             is => 'rw',
7             isa => 'Int',
8             required => 0,
9             default => 10,
10             );
11              
12             has proxy => (
13             is => 'rw',
14             isa => 'Str',
15             required => 0,
16             );
17              
18             has agent => (
19             is => 'rw',
20             isa => 'Object',
21             lazy => 1,
22             builder => '_init_agent',
23             );
24            
25             has use_net_ssl => (
26             is => 'rw',
27             isa => 'Bool',
28             default => 0,
29             );
30              
31             has ssl_ignore_hostname => (
32             is => 'rw',
33             isa => 'Bool',
34             default => 0,
35             );
36              
37             has ssl_ignore_mode => (
38             is => 'rw',
39             isa => 'Bool',
40             default => 0,
41             );
42              
43             has certificate_file => (
44             is => 'rw',
45             isa => 'Str',
46             );
47              
48             has certificate_key_file => (
49             is => 'rw',
50             isa => 'Str',
51             );
52              
53             has certificate_p12_file => (
54             is => 'rw',
55             isa => 'Str',
56             );
57              
58             has certificate_key_password => (
59             is => 'rw',
60             isa => 'Str',
61             );
62              
63             has ca_certificate_path => (
64             is => 'rw',
65             isa => 'Str',
66             );
67              
68             has ca_certificate_file => (
69             is => 'rw',
70             isa => 'Str',
71             );
72              
73              
74             my $self = shift;
75              
76 1     1   2 my %ENV_BACKUP = %ENV;
77              
78 1         28 my $ua = LWP::UserAgent->new;
79             $ua->timeout( $self->timeout() );
80 1         16 if ($self->proxy()) {
81 1         2567 $ua->proxy(['http', 'https'], $self->proxy());
82 1 50       45 }
83 0         0  
84             # Force usage of net::ssl
85             if ($self->use_net_ssl()) {
86             require Net::SSL;
87 1 50       26 $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "Net::SSL";
    50          
88 0         0  
89 0         0 if ($self->certificate_p12_file) {
90             $ENV{HTTPS_PKCS12_FILE} = $self->certificate_p12_file;
91 0 0       0  
92 0         0 if ($self->certificate_key_file || $self->certificate_file) {
93             die "Options certificate_file/certificate_key_file and certificate_p12_file are mutually exclusive";
94 0 0 0     0 }
95 0         0  
96             if ($self->certificate_key_password) {
97             $ENV{HTTPS_PKCS12_PASSWORD} = $self->certificate_key_password;
98 0 0       0 }
99 0         0 }
100              
101             if ($self->certificate_key_file) {
102             if ($self->certificate_key_password) {
103 0 0       0 die "Net::SSL does not support password protected keys - use certificate_p12_file instead";
    0          
104 0 0       0 }
105 0         0  
106             if (!$self->certificate_file) {
107             die "You need to pass certificate AND key file, use certificate_p12_file to pass a PKCS12";
108 0 0       0 }
109 0         0  
110             $ENV{HTTPS_KEY_FILE} = $self->certificate_key_file;
111             $ENV{HTTPS_CERT_FILE} = $self->certificate_file;
112 0         0  
113 0         0 } elsif ($self->certificate_file) {
114             die "You need to pass certificate AND key file, use certificate_p12_file to pass a PKCS12";
115             }
116 0         0  
117             if ($self->ca_certificate_path) {
118             $ENV{HTTPS_CA_DIR} = $self->ca_certificate_path;
119 0 0       0 }
120 0         0  
121             if ($self->ca_certificate_file) {
122             $ENV{HTTPS_CA_FILE} = $self->ca_certificate_file;
123 0 0       0 }
124 0         0  
125             $self->log()->trace('Using Net::SSL, EVN is' . Dumper $ENV);
126              
127 0         0 } # end of Net:SSL, IO::Socket::SSL
128             elsif( $self->LOCATION() =~ /^https:/i ) {
129              
130             require IO::Socket::SSL;
131             $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "IO::Socket::SSL";
132 1         695  
133 1         56957 my $ssl_opts = {
134             verify_hostname => ($self->ssl_ignore_hostname ? 0 : 1),
135 1 50       38 SSL_verify_mode => ($self->ssl_ignore_mode ? 0 : 1)
    50          
136             };
137             if ($self->certificate_p12_file) {
138             die "Using pkcs12 containers is not supported by IO::Socket::SSL"
139 1 50       103 }
140 0         0  
141             if ($self->certificate_key_file) {
142             if (!$self->certificate_file) {
143 1 50       27 die "You need to pass certificate AND key file";
    50          
144 0 0       0 }
145 0         0 $ssl_opts->{SSL_key_file} = $self->certificate_key_file;
146             $ssl_opts->{SSL_cert_file} = $self->certificate_file;
147 0         0  
148 0         0 if ( $self->certificate_key_password ) {
149             $ssl_opts->{SSL_passwd_cb} = sub { return $self->certificate_key_password; };
150 0 0       0 }
151 0     0   0  
  0         0  
152             } elsif ($self->certificate_file) {
153             die "You need to pass certificate AND key file";
154             }
155 0         0  
156             if ($self->ca_certificate_path) {
157             $ssl_opts->{SSL_ca_path} = $self->ca_certificate_path;
158 1 50       28 }
159 0         0  
160             if ($self->ca_certificate_file) {
161             $ssl_opts->{SSL_ca_file} = $self->ca_certificate_file;
162 1 50       26 }
163 0         0  
164             $ua->ssl_opts( %{$ssl_opts} );
165              
166 1         2 $self->log()->trace('Using IO::Socket::SSL with options ' . Dumper $ssl_opts);
  1         51  
167             } else {
168 1         63 # No ssl
169             }
170              
171             return $ua;
172             }
173 1         146  
174             1;
175              
176              
177             =head1 Connector::Role::SSLUserAgent
178              
179             Setup the HTTP UserAgent object with connection and SSL parameters.
180              
181             =head2 LWP options
182              
183             =over
184              
185             =item timeout
186              
187             Timeout for the connection in seconds, default is 10.
188              
189             =item proxy
190              
191             URL of a proxy to use, must include protocol and port,
192             e.g. https://proxy.intranet.company.com:8080/
193              
194             =back
195              
196             =head2 SSL support
197              
198             This connector supports client authentication using certificates.
199              
200             =over
201              
202             =item use_net_ssl
203              
204             Set this to a true value to use Net::SSL as backend library (otherwise
205             IO::Socket::SSL is used). Be aware the Net::SSL does not check the hostname
206             of the server certificate so Man-in-the-Middle-Attacks might be possible.
207             You should use this only with a really good reason or if you need support
208             for PKCS12 containers.
209              
210             =item ssl_ignore_hostname
211              
212             Do not validate the hostname of the server certificate (only useful with
213             IO::Socket::SSL as Net::SSL does not check the hostname at all).
214              
215             =item certificate_file
216              
217             Path to a PEM encoded certificate file.
218              
219             =item certificate_key_file
220              
221             Path to a PEM encoded key file.
222              
223             =item certificate_p12_file
224              
225             Path to a PKCS12 container file. This is only supported by Net:SSL and can
226             not be used together with certificate_file/certificate_key_file.
227              
228             =item certificate_key_password
229              
230             The plain password of your encrypted key or PKCS12 container. Note that
231             Net::SSL does not support password protected keys. You need to use a PKCS12
232             container instead! Leave this empty if your key is not protected by a password.
233              
234             =item ca_certificate_path
235              
236             Path to a directory with trusted certificates (with openssl hashed names).
237             Also used to validate the server certificate even if no client authentication
238             is used.
239              
240             =item ca_certificate_file
241              
242             Same as ca_certificate_path pointing to a single file.
243              
244             =item ssl_ignore_mode
245              
246             Boolean, turn of validation of ssl peer certificate (IO::Socket only).
247              
248             =back