File Coverage

blib/lib/App/TenableSC.pm
Criterion Covered Total %
statement 30 78 38.4
branch 0 34 0.0
condition 0 15 0.0
subroutine 10 18 55.5
pod 7 7 100.0
total 47 152 30.9


line stmt bran cond sub pod time code
1             package App::TenableSC;
2              
3 1     1   833 use strict;
  1         2  
  1         28  
4 1     1   5 use warnings;
  1         2  
  1         27  
5              
6 1     1   720 use Getopt::Long qw( :config gnu_compat );
  1         10284  
  1         4  
7 1     1   666 use Pod::Usage;
  1         52303  
  1         131  
8 1     1   588 use Term::ReadKey;
  1         2225  
  1         72  
9 1     1   13 use Carp;
  1         2  
  1         61  
10 1     1   7 use File::Basename;
  1         4  
  1         66  
11              
12 1     1   548 use App::TenableSC::Utils qw(:all);
  1         2  
  1         150  
13 1     1   424 use App::TenableSC::Logger;
  1         2  
  1         28  
14              
15 1     1   6 use Net::SecurityCenter;
  1         2  
  1         916  
16              
17             our $VERSION = '0.311';
18              
19             my @global_options = (
20             'help|h',
21             'man',
22             'version|v',
23             'verbose',
24              
25             'hostname=s',
26              
27             'username=s',
28             'password=s',
29              
30             'ssl_cert_file=s',
31             'ssl_key_file=s',
32             'ssl_password=s',
33              
34             'access_key=s',
35             'secret_key=s',
36              
37             'config=s'
38             );
39              
40             $SIG{'__DIE__'} = sub {
41             cli_error(@_);
42             };
43              
44             our @command_options = ();
45              
46             sub run {
47              
48 0     0 1   my ( $class, %args ) = @_;
49              
50 0           my $options = {};
51 0           my $config = {};
52 0           my $logger = App::TenableSC::Logger->new;
53 0           my @config_params = qw(hostname username password access_key secret_key
54             verbose scheme timeout ssl_cert_file ssl_key_file ssl_password);
55              
56 0 0         GetOptions( $options, ( @global_options, @command_options ) ) or pod2usage( -verbose => 0 );
57              
58 0 0         pod2usage(1) if ( $options->{'help'} );
59 0 0         cli_version if ( $options->{'version'} );
60              
61 0 0         if ( $options->{'config'} ) {
62              
63 0           $config = config_parser( file_slurp( $options->{'config'} ) );
64              
65 0 0 0       if ( $config && defined( $config->{'SecurityCenter'} ) ) {
66              
67 0           foreach my $param (@config_params) {
68 0 0         if ( defined( $config->{'SecurityCenter'}->{$param} ) ) {
69 0           $options->{$param} = $config->{'SecurityCenter'}->{$param};
70             }
71             }
72              
73             } else {
74 0           cli_error('Failed to parse config file');
75             }
76              
77             }
78              
79 0 0         pod2usage( -exitstatus => 0, -verbose => 2 ) if ( $options->{'man'} );
80 0 0 0       pod2usage( -exitstatus => 0, -verbose => 0 ) if ( !$options->{'hostname'} || !$options->{'username'} );
81              
82 0 0 0       if ( $options->{'username'} && !$options->{'password'} ) {
83 0           $options->{'password'} = cli_readkey("Enter $options->{username} password: ");
84             }
85              
86 0           my $self = {
87             config => $config,
88             options => $options,
89             logger => $logger,
90             sc => undef,
91             };
92              
93 0           bless $self, $class;
94              
95 0           $self->startup;
96              
97 0           return $self;
98              
99             }
100              
101             sub startup {
102 0     0 1   my ($self) = @_;
103             }
104              
105             sub logger {
106 0     0 1   return shift->{'logger'};
107             }
108              
109             sub options {
110 0     0 1   return shift->{'options'};
111             }
112              
113             sub config {
114 0     0 1   return shift->{'config'};
115             }
116              
117             sub sc {
118 0     0 1   return shift->{'sc'};
119             }
120              
121             sub connect {
122              
123 0     0 1   my ($self) = @_;
124              
125 0           my $sc_options = {};
126              
127 0 0         $sc_options->{'logger'} = $self->logger if ( $self->options->{'verbose'} );
128 0 0         $sc_options->{'scheme'} = $self->options->{'scheme'} if ( $self->options->{'scheme'} );
129              
130             # Set SSL options for IO::Socket::SSL
131 0 0         if ( defined $self->options->{'ssl_cert_file'} ) {
132              
133 0           $sc_options->{'ssl_options'}->{'SSL_cert_file'} = $self->options->{'ssl_cert_file'};
134              
135 0 0         if ( defined $self->options->{'ssl_key_file'} ) {
136 0           $sc_options->{'ssl_options'}->{'SSL_key_file'} = $self->options->{'ssl_key_file'};
137             }
138              
139 0 0         if ( defined $self->options->{'ssl_password'} ) {
140             $sc_options->{'ssl_options'}->{'SSL_passwd_cb'} = sub {
141 0     0     $self->options->{'ssl_password'};
142             }
143 0           }
144              
145             }
146              
147 0           my $sc = Net::SecurityCenter->new( $self->options->{'hostname'}, $sc_options );
148              
149 0           my %auth = ();
150              
151             # Username and password authentication
152 0 0 0       if ( $self->options->{'username'} && $self->options->{'password'} ) {
153             %auth = (
154             username => $self->options->{'username'},
155 0           password => $self->options->{'password'},
156             );
157             }
158              
159             # API Key authentication
160 0 0 0       if ( $self->options->{'secret_key'} && $self->options->{'access_key'} ) {
161             %auth = (
162             secret_key => $self->options->{'secret_key'},
163 0           access_key => $self->options->{'access_key'},
164             );
165             }
166              
167 0 0         $sc->login(%auth) or cli_error $sc->error;
168              
169 0           $self->{'sc'} = $sc;
170 0           return $sc;
171              
172             }
173              
174             1;
175              
176             =pod
177              
178             =encoding UTF-8
179              
180              
181             =head1 NAME
182              
183             App::TenableSC - Base class for Tenable.sc (SecurityCenter) applications
184              
185              
186             =head1 SYNOPSIS
187              
188             use App::TenableSC;
189              
190             # Add additional command line options
191             @App::TenableSC::command_options = ( 'opt1=s', 'opt2=s', 'flag' );
192              
193             App::TenableSC->run;
194              
195              
196             =head1 DESCRIPTION
197              
198             This module provides Perl scripts easy way to write Tenable.sc (SecurityCenter)
199             application using L.
200              
201              
202             =head1 METHODS
203              
204             =head2 run
205              
206             Run the application.
207              
208             use App::TenableSC::MyApp;
209              
210             # Add additional command line options
211             @App::TenableSC::command_options = ( 'opt1=s', 'opt2=s', 'flag' );
212              
213             App::TenableSC::MyApp->run;
214              
215              
216             =head1 HELPER METHODS
217              
218             =head2 config
219              
220             Return config object
221              
222             =head2 connect
223              
224             Connect to Tenable.sc instance with provided credentials and return L object.
225              
226             =head2 logger
227              
228             Return L object.
229              
230             =head2 options
231              
232             Return command line argument options.
233              
234             =head2 sc
235              
236             Return L object.
237              
238             =head2 startup
239              
240             This is your main hook into the application, it will be called at application startup.
241             Meant to be overloaded in a subclass.
242              
243             sub startup {
244             my ($self) = @_;
245              
246             my $sc = $self->connect;
247              
248             $sc->plugin->download(id => $self->option->{'id'}, file => $self->option->{'file'});
249              
250             exit 0;
251             }
252              
253              
254             =head1 DEFAULT COMMAND LINE ARGUMENTS
255              
256             =over 4
257              
258             =item * C : Tenable.sc host/IP address
259              
260             =item * C : Username
261              
262             =item * C : Password
263              
264             =item * C : Access Key
265              
266             =item * C : Secret Key
267              
268             =item * C : Configuration file
269              
270             =item * C : Brief help message
271              
272             =item * C : Full documentation
273              
274             =item * C : Command version
275              
276             =item * C : Full documentation
277              
278             =back
279              
280              
281             =head1 SUPPORT
282              
283             =head2 Bugs / Feature Requests
284              
285             Please report any bugs or feature requests through the issue tracker
286             at L.
287             You will be notified automatically of any progress on your issue.
288              
289             =head2 Source Code
290              
291             This is open source software. The code repository is available for
292             public review and contribution under the terms of the license.
293              
294             L
295              
296             git clone https://github.com/giterlizzi/perl-Net-SecurityCenter.git
297              
298              
299             =head1 AUTHOR
300              
301             =over 4
302              
303             =item * Giuseppe Di Terlizzi
304              
305             =back
306              
307              
308             =head1 LICENSE AND COPYRIGHT
309              
310             This software is copyright (c) 2018-2023 by Giuseppe Di Terlizzi.
311              
312             This is free software; you can redistribute it and/or modify it under
313             the same terms as the Perl 5 programming language system itself.
314              
315             =cut