Changeset 3483

Show
Ignore:
Timestamp:
04/13/10 02:00:09 (2 years ago)
Author:
bldewolf
Message:

Fix TLS, resolving several bugs.

#878 * Corrected function name passed to constructor.
#879 * Change logging function passed by master to use Log4perl to allow
logging in both master and node.
#599 * Added directive "tls_match", which is a regex for matching against the
dumped certificate of the client.
* Add documentation for TLS to munin-node.conf.pod.
* Clean up logging in TLS.pm to reduce noise during normal operations.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/common/lib/Munin/Common/Config.pm

    r3413 r3483  
    3232        "service_order", "category_order", "version", 
    3333        "tls_certificate", "tls_private_key", "tls_pem", 
    34         "tls_verify_certificate", "tls_verify_depth", 
     34        "tls_verify_certificate", "tls_verify_depth", "tls_match", 
    3535        "tls_ca_certificate", "graph_data_size", "colour", 
    3636        "graph_printf", "ok", "unknown", "palette", "realservname", 
  • trunk/common/lib/Munin/Common/TLS.pm

    r2431 r3483  
    3333        tls_vdepth         => $args->{tls_vdepth} || 0, 
    3434        tls_verify         => $args->{tls_verify} || 0, 
     35        tls_match          => $args->{tls_match} || '', 
    3536    }; 
    3637 
     
    210211    my $err = &Net::SSLeay::print_errs(""); 
    211212    if (defined $err and length $err) { 
    212        $self->{logger}("[WARNING] in set_verify_depth: $err"); 
     213        $self->{logger}("[WARNING] in set_verify_depth: $err"); 
    213214    } 
    214215    Net::SSLeay::CTX_set_verify ($self->{tls_context},  
     
    217218    $err = &Net::SSLeay::print_errs(""); 
    218219    if (defined $err and length $err) { 
    219        $self->{logger}("[WARNING] in set_verify: $err"); 
     220        $self->{logger}("[WARNING] in set_verify: $err"); 
    220221    } 
    221222     
     
    230231        my ($ok, $subj_cert, $issuer_cert, $depth,  
    231232            $errorcode, $arg, $chain) = @_; 
    232         #    $self->{logger}("ok is ${ok}"); 
    233233 
    234234        $tls_verified->{"level"}++; 
     
    271271    } while $p; 
    272272    $cipher_list .= '\n'; 
    273     $self->{logger}("[TLS] Available cipher list: $cipher_list.")
     273    $self->{logger}("[TLS] Available cipher list: $cipher_list.") if $self->{DEBUG}
    274274} 
    275275 
     
    281281    my $err = &Net::SSLeay::print_errs(""); 
    282282    if (defined $err and length $err) { 
    283         $self->{logger}("TLS Warning in set_rfd: $err"); 
     283        $self->{logger}("[TLS] Warning in set_rfd: $err"); 
    284284    } 
    285285    Net::SSLeay::set_wfd($self->{tls_session}, $self->{write_fd}); 
    286286    $err = &Net::SSLeay::print_errs(""); 
    287287    if (defined $err and length $err) { 
    288         $self->{logger}("TLS Warning in set_wfd: $err"); 
     288        $self->{logger}("[TLS] Warning in set_wfd: $err"); 
    289289    } 
    290290} 
     
    294294    my ($self, $tls_verified) = @_; 
    295295 
    296     $self->{logger}("Accept/Connect: $self->{private_key_loaded}, " . $self->_use_key_if_present()) if $self->{DEBUG}; 
     296    $self->{logger}("[TLS] Accept/Connect: $self->{private_key_loaded}, " . $self->_use_key_if_present()) if $self->{DEBUG}; 
    297297    my $res; 
    298298    if ($self->_use_key_if_present()) { 
     
    302302        $res = Net::SSLeay::connect($self->{tls_session}); 
    303303    } 
    304     $self->{logger}("Done Accept/Connect") if $self->{DEBUG}; 
     304    $self->{logger}("[TLS] Done Accept/Connect") if $self->{DEBUG}; 
    305305 
    306306    my $err = &Net::SSLeay::print_errs(""); 
     
    320320        $self->{tls_session} = undef; 
    321321    } 
     322    elsif ($self->{"tls_match"} and 
     323        Net::SSLeay::dump_peer_certificate($self->{tls_session}) !~ /$self->{tls_match}/) 
     324    {  
     325        $self->{logger}("[ERROR] Could not match pattern \"" . $self->{tls_match} . 
     326                "\" in dump of certificate."); 
     327        $self->_on_unmatched_cert(); 
     328        Net::SSLeay::free ($self->{tls_session}); 
     329        Net::SSLeay::CTX_free ($self->{tls_context}); 
     330        $self->{tls_session} = undef; 
     331    } 
    322332    else 
    323333    { 
    324         $self->{logger}("[TLS] TLS enabled.")
    325         $self->{logger}("[TLS] Cipher `" . Net::SSLeay::get_cipher($self->{tls_session}) . "'.")
    326         $self->{logger}("[TLS] client cert: " . Net::SSLeay::dump_peer_certificate($self->{tls_session}))
     334        $self->{logger}("[TLS] TLS enabled.") if $self->{DEBUG}
     335        $self->{logger}("[TLS] Cipher `" . Net::SSLeay::get_cipher($self->{tls_session}) . "'.") if $self->{DEBUG}
     336        $self->{logger}("[TLS] client cert: " . Net::SSLeay::dump_peer_certificate($self->{tls_session})) if $self->{DEBUG}
    327337    } 
    328338} 
     
    350360sub _on_unverified_cert {} 
    351361 
     362# Redefine in sub class if needed 
     363sub _on_unmatched_cert {} 
    352364 
    353365sub read { 
     
    362374    my $err = &Net::SSLeay::print_errs(""); 
    363375    if (defined $err and length $err) { 
    364         $self->{logger}("TLS Warning in read: $err"); 
     376        $self->{logger}("[TLS] Warning in read: $err"); 
    365377        return; 
    366378    } 
     379    $self->{logger}("DEBUG: < $_") if $self->{DEBUG}; 
     380 
    367381    if($_ eq '') { undef $_; } #returning '' signals EOF 
    368382 
    369     $self->{logger}("DEBUG: < $_") if $self->{DEBUG}; 
    370383 
    371384    return $_; 
     
    384397    my $err = &Net::SSLeay::print_errs(""); 
    385398    if (defined $err and length $err) { 
    386         $self->{logger}("TLS Warning in write: $err"); 
     399        $self->{logger}("[TLS] Warning in write: $err"); 
    387400        return 0; 
    388401    } 
  • trunk/master/doc/munin.conf.pod.in

    r3394 r3483  
    174174willing to go to reach a known, trusted CA when verifying a 
    175175certificate.  Default is C<5>.  Affects: munin-update. 
     176 
     177=item B<tls_match> <value> 
     178 
     179This directive, if defined, searches a dump of the certificate provided by the 
     180remote host for the given regex.  The dump of the certificate is two lines of 
     181the form: 
     182 
     183        Subject Name: /C=c/ST=st/L=l/O=o/OU=ou/CN=cn/emailAddress=email 
     184        Issuer  Name: /C=c/ST=st/O=o/OU=ou/CN=cn/emailAddress=email 
     185 
     186So, for example, one could match the subject distinguished name by the directive: 
     187 
     188        tls_match Subject Name: /C=c/ST=st/L=l/O=o/OU=ou/CN=cn/emailAddress=email 
     189 
     190Note that the fields are dumped in the order they appear in the certificate. 
     191It's best to view the dump of the certificate by running munin-update in debug 
     192mode and reviewing the logs. 
     193 
     194Unfortunately, due to the limited functionality of the SSL module in use, it is 
     195not possible to provide finer-grained filtering.  By default this value is not 
     196defined.  Affects: munin-update. 
    176197 
    177198=item FIXME: This section MAY be complete, it may be missing a directive or two. 
  • trunk/master/lib/Munin/Master/Node.pm

    r3480 r3483  
    122122    # value is therefore "disabled" (and not "auto" as before). 
    123123    my $tls_requirement = $config->{tls}; 
    124     INFO "TLS set to \"$tls_requirement\"."; 
     124    DEBUG "TLS set to \"$tls_requirement\"."; 
    125125    return if $tls_requirement eq 'disabled'; 
     126    my $logger = Log::Log4perl->get_logger("Munin::Master"); 
    126127    $self->{tls} = Munin::Common::TLSClient->new({ 
    127128        DEBUG        => $config->{debug}, 
    128         logger       => \&logger
     129        logger       => sub { $logger->warn(@_) }
    129130        read_fd      => fileno($self->{reader}), 
    130131        read_func    => sub { _node_read_single($self) }, 
     
    135136        tls_vdepth   => $config->{tls_verify_depth}, 
    136137        tls_verify   => $config->{tls_verify_certificate}, 
     138        tls_match    => $config->{tls_match}, 
    137139        write_fd     => fileno($self->{writer}), 
    138         write_func   => sub { _write_socket_single($self, @_) }, 
     140        write_func   => sub { _node_write_single($self, @_) }, 
    139141    }); 
    140142 
  • trunk/node/doc/munin-node.conf.pod

    r2492 r3483  
    6161directories will be overlooked. 
    6262 
     63=item B<tls> <value> 
     64 
     65Can have four values. C<paranoid>, C<enabled>, C<auto>, and 
     66C<disabled>.  C<Paranoid> and C<enabled> require a TLS connection, 
     67while C<disabled> will not attempt one at all. 
     68 
     69The current default is C<disabled> because C<auto> is broken.  C<Auto> 
     70causes bad interaction between munin-update and munin-node if the node 
     71is unprepared to go to TLS. 
     72 
     73If you see data dropouts (gaps in graphs) please try to disable TLS. 
     74 
     75=item B<tls_verify_certificate> <value> 
     76 
     77This directive can be C<yes> or C<no>.  It determines if the remote 
     78certificate needs to be signed by a CA that is known locally.  Default 
     79is C<no>. 
     80 
     81=item B<tls_private_key> <value> 
     82 
     83This directive sets the location of the private key to be used for 
     84TLS.  Default is @@CONFDIR@@/munin-node.pem.  The private key and 
     85certificate can be stored in the same file. 
     86 
     87=item B<tls_certificate> <value> 
     88 
     89This directive sets the location of the TLS certificate to be used for 
     90TLS.  Default is @@CONFDIR@@/munin-node.pem.  The private key and 
     91certificate can be stored in the same file. 
     92 
     93=item B<tls_ca_certificate> <value> 
     94 
     95This directive sets the CA certificate to be used to verify the node's 
     96certificate, if tls_verify_certificate is set to C<yes>.  Default is 
     97@@CONFDIR@@/cacert.pem. 
     98 
     99=item B<tls_verify_depth> <value> 
     100 
     101This directive sets how many signings up a chain of signatures TLS is 
     102willing to go to reach a known, trusted CA when verifying a 
     103certificate.  Default is C<5>. 
     104 
     105=item B<tls_match> <value> 
     106 
     107This directive, if defined, searches a dump of the certificate provided by the 
     108remote host for the given regex.  The dump of the certificate is two lines of 
     109the form: 
     110 
     111        Subject Name: /C=c/ST=st/L=l/O=o/OU=ou/CN=cn/emailAddress=email 
     112        Issuer  Name: /C=c/ST=st/O=o/OU=ou/CN=cn/emailAddress=email 
     113 
     114So, for example, one could match the subject distinguished name by the directive: 
     115 
     116        tls_match Subject Name: /C=c/ST=st/L=l/O=o/OU=ou/CN=cn/emailAddress=email 
     117 
     118Note that the fields are dumped in the order they appear in the certificate. 
     119It's best to view the dump of the certificate by running munin-update in debug 
     120mode and reviewing the logs. 
     121 
     122Unfortunately, due to the limited functionality of the SSL module in use, it is 
     123not possible to provide finer-grained filtering.  By default this value is not 
     124defined. 
     125 
    63126=back 
    64127 
  • trunk/node/lib/Munin/Node/Config.pm

    r3298 r3483  
    8888        tls_verify_certificate 
    8989        tls_verify_depth 
     90        tls_match 
    9091    ); 
    9192 
  • trunk/node/lib/Munin/Node/Server.pm

    r3406 r3483  
    249249    my $tls_verify = $config->{tls_verify_certificate} 
    250250                  || 'no'; 
     251    my $tls_match  = $config->{tls_match}; 
    251252 
    252253    my $depth = $config->{tls_verify_depth}; 
     
    264265        tls_vdepth   => $depth, 
    265266        tls_verify   => $tls_verify, 
     267        tls_match    => $tls_match, 
    266268        write_fd     => fileno(STDOUT), 
    267269        write_func   => sub { print @_ },