Changeset 1461

Show
Ignore:
Timestamp:
04/04/08 22:21:25 (3 months ago)
Author:
kindlund
Message:

Still working on finalizing new-Agent support inside Clone.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • honeyclient/branches/exp/kindlund-simpler_agent/etc/honeyclient.xml

    r1452 r1461  
    328328                /var/log/messages 
    329329            </dhcp_log> 
     330            <!-- HoneyClient::Manager::VM::Clone Options --> 
     331            <Clone> 
     332                <archive_upon_suspend description="If set to 1, then everytime a cloned VM is suspended, a copy of the VM will be archived in the 'snapshot_path' directory.  Set this option to 0, if you discover errors during cloning operations, where the hard disk on the host system is overworked on slow systems." default="1"> 
     333                    1 
     334                </archive_upon_suspend> 
     335            </Clone> 
    330336            <!-- HoneyClient::Manager::VM::Test Options --> 
    331337            <Test> 
  • honeyclient/branches/exp/kindlund-simpler_agent/lib/HoneyClient/Manager/VM/Clone.pm

    r1460 r1461  
    7171  my $name = $clone->{'name'}; 
    7272 
    73   # Archive the cloned VM to the snapshot_path directory. 
    74   $clone->archive(); 
     73  # Suspend and archive the cloned VM to the snapshot_path directory. 
     74  $clone->suspend(perform_archive => 1); 
    7575 
    7676  # If you want the cloned VM to be suspended and no longer used, 
     
    315315use DateTime::HiRes; 
    316316 
     317# Make sure IO::File loads. 
     318BEGIN { use_ok('IO::File') or diag("Can't load IO::File package.  Check to make sure the package library is correctly listed within the path."); } 
     319require_ok('IO::File'); 
     320use IO::File; 
     321 
    317322=end testing 
    318323 
     
    371376# Include Base64 Libraries 
    372377use MIME::Base64 qw(encode_base64 decode_base64); 
     378 
     379# Include IO::File Libraries 
     380use IO::File; 
    373381 
    374382=pod 
     
    776784# VM Clone object. 
    777785# 
     786# Input: hashref 
     787# 
    778788# Output: The updated Clone $object, reflecting the status change 
    779789# of the clone VM.  Will croak if this operation fails. 
     
    821831                HoneyClient::Manager::Database::set_client_suspended($self->{'database_id'}); 
    822832            } elsif (/suspicious/) { 
     833                if (!$argsExist ||  
     834                    !exists($args{'fingerprint'}) || 
     835                    !defined($args{'fingerprint'})) { 
     836 
     837                    # Croak if no valid argument is supplied. 
     838                    $LOG->error("Error: No fingerprint argument supplied."); 
     839                    Carp::croak "Error: No fingerprint argument supplied."; 
     840                } 
     841 
    823842                # TODO: Need to implement this properly. 
     843                $LOG->info("(" . $self->{'name'} . ") - Inserting Fingerprint Into Database."); 
     844                # Make sure the fingerprint contains a client_id. 
     845                $args{'fingerprint'}->{'client_id'} = $self->{'database_id'}; 
     846                my $fingerprint_id = undef; 
     847                eval { 
     848                    $fingerprint_id = HoneyClient::Manager::Database::insert_fingerprint($args{'fingerprint'}); 
     849                }; 
     850                if ($@ || ($fingerprint_id == 0) || !defined($fingerprint_id)) { 
     851                    $LOG->warn("(" . $self->{'name'} . ") - Failure Inserting Fingerprint: " . $@); 
     852                } else { 
     853                    $LOG->info("(" . $self->{'name'} . ") - Database Insert Successful."); 
     854                } 
    824855            } elsif (/compromised/) { 
    825856                HoneyClient::Manager::Database::set_client_compromised($self->{'database_id'}); 
     
    838869sub _dumpFingerprint { 
    839870 
     871    # Get the supplied fingerprint. 
     872    my ($self, $fingerprint) = @_; 
     873 
    840874    # Dump the fingerprint to a file, if needed. 
    841875    my $COMPROMISE_FILE = getVar(name => "fingerprint_dump"); 
     
    848882        $Data::Dumper::Terse = 0; 
    849883        $Data::Dumper::Indent = 2; 
    850         print $dump_file "\$vmName = \"" . $vmName . "\";\n"; 
     884        print $dump_file "\$vmName = \"" . $self->{'name'} . "\";\n"; 
    851885        print $dump_file Dumper($fingerprint); 
    852886        $dump_file->close(); 
     
    10911125=pod 
    10921126 
    1093 =head2 $object->archive(snapshot_file => $snapshotFile)  
     1127=head2 $object->suspend(perform_archive => $boolean, snapshot_file => $snapshotFile)  
    10941128 
    10951129=over 4 
    10961130 
    1097 Archives an existing Clone object, by suspending the VM and saving 
    1098 a tar.gz archive file containing the VM to the B<$SNAPSHOT_PATH> 
     1131Suspends and optionally archives an existing Clone object, 
     1132by suspending the VM and saving a tar.gz archive file 
     1133containing the VM to the B<$SNAPSHOT_PATH> 
    10991134directory, as specified in the <HoneyClient/><Manager/><VM/> 
    11001135section of the etc/honeyclient.xml file. 
    11011136 
    11021137I<Inputs>: 
     1138 B<$boolean> is an optional argument, indicating that the 
     1139Clone object should be archived upon suspend. 
    11031140 B<$snapshotFile> is an optional argument, indicating the 
    11041141full, absolute path and filename of where the snapshot 
    11051142file should be stored. 
    11061143  
    1107 I<Output>: The archived Clone B<$object>. 
     1144I<Output>: The suspended/archived Clone B<$object>. 
    11081145 
    11091146I<Notes>: 
     
    11161153using ISO8601 date format variables. 
    11171154 
    1118 This operation destroys the Clone B<$object>.  Do not 
     1155This operation alters the Clone B<$object>.  Do not 
    11191156expect to perform any additional operations with  
    1120 this object once this call is finished. 
     1157this object once this call is finished, since the 
     1158underlying VM has been suspended. 
    11211159 
    11221160=back 
     
    11441182    my $question; 
    11451183    $question = prompt("#\n" . 
    1146                        "# Note: Testing real archive operations will *ONLY* work\n" . 
     1184                       "# Note: Testing real suspend/archive operations will *ONLY* work\n" . 
    11471185                       "# with a fully functional master VM that has the HoneyClient code\n" . 
    11481186                       "# loaded upon boot-up.\n" . 
     
    11581196 
    11591197        # Archive the clone. 
    1160         $clone->archive(snapshot_file => $snapshot); 
    1161  
    1162         # Wait for the archive to complete. 
     1198        $clone->suspend(perform_archive => 1, snapshot_file => $snapshot); 
     1199 
     1200        # Wait for the suspend/archive to complete. 
    11631201        sleep (45); 
    11641202     
    1165         # Test if the archive worked. 
    1166         is(-f $snapshot, 1, "archive(snapshot_file => '$snapshot')") or diag("The archive() call failed."); 
     1203        # Test if the operations worked. 
     1204        is(-f $snapshot, 1, "suspend(perform_archive => 1, snapshot_file => '$snapshot')") or diag("The suspend() call failed."); 
    11671205    
    11681206        unlink $snapshot; 
     
    11891227=cut 
    11901228 
    1191 sub archive
     1229sub suspend
    11921230 
    11931231    # Extract arguments. 
     
    12121250    # Sanity checks; check if any args were specified. 
    12131251    my $argsExist = scalar(%args); 
     1252    if (!$argsExist ||  
     1253        !exists($args{'perform_archive'}) || 
     1254        !defined($args{'perform_archive'})) { 
     1255        $args{'perform_archive'} = getVar(name => "archive_upon_suspend"); 
     1256    } 
    12141257 
    12151258    # Extract the VM configuration file. 
     
    12201263    $self->{'config'} = undef; 
    12211264     
    1222     $LOG->debug("Archiving clone VM (" . $vmConfig . ")."); 
     1265    $LOG->debug("Suspending clone VM (" . $vmConfig . ")."); 
    12231266    my $som = $self->{'_vm_handle'}->suspendVM(config => $vmConfig); 
    1224     if ($argsExist && 
    1225         exists($args{'snapshot_file'}) && 
    1226         defined($args{'snapshot_file'})) { 
    1227         $som = $self->{'_vm_handle'}->snapshotVM(config        => $vmConfig, 
    1228                                                  snapshot_file => $args{'snapshot_file'}); 
     1267 
     1268    if (!defined($som)) { 
     1269        $LOG->error("Unable to suspend VM (" . $self->{'config'} . ")."); 
     1270        $self->_changeStatus(status => "error"); 
    12291271    } else { 
    1230         $som = $self->{'_vm_handle'}->snapshotVM(config => $vmConfig); 
    1231     } 
    1232     if (!defined($som)) { 
    1233         $LOG->error("Unable to archive VM (" . $vmConfig . ")."); 
     1272        $self->_changeStatus(status => "suspended"); 
     1273    } 
     1274 
     1275    if ($args{'perform_archive'}) { 
     1276        if ($argsExist && 
     1277            exists($args{'snapshot_file'}) && 
     1278            defined($args{'snapshot_file'})) { 
     1279            $som = $self->{'_vm_handle'}->snapshotVM(config        => $vmConfig, 
     1280                                                     snapshot_file => $args{'snapshot_file'}); 
     1281        } else { 
     1282            $som = $self->{'_vm_handle'}->snapshotVM(config => $vmConfig); 
     1283        } 
     1284        if (!defined($som)) { 
     1285            $LOG->error("Unable to archive VM (" . $vmConfig . ")."); 
     1286        } 
    12341287    } 
    12351288 
     
    13021355 
    13031356# TODO: Fix this. 
    1304  
    1305         # Archive the clone. 
    1306         #$clone->archive(snapshot_file => $snapshot); 
    1307  
    1308         # Wait for the archive to complete. 
    1309         #sleep (45); 
    1310      
    1311         # Test if the archive worked. 
    1312         #is(-f $snapshot, 1, "archive(snapshot_file => '$snapshot')") or diag("The archive() call failed."); 
    1313     
    1314         #unlink $snapshot; 
    1315         #$clone = undef; 
    1316      
     1357        $clone = $clone->drive(work => { 'http://www.google.com/' => 1 }); 
     1358        isa_ok($clone, 'HoneyClient::Manager::VM::Clone', "drive(work => { 'http://www.google.com/' => 1})") or diag("The drive() call failed."); 
     1359        $clone = undef; 
     1360 
    13171361        # Connect to daemon as a client. 
    13181362        $stub = getClientHandle(namespace => "HoneyClient::Manager::VM"); 
     
    13721416    my $currentWork; 
    13731417    my $finishedWork = { 
    1374         'client_id'     => $self->{'database_id'}, 
     1418        'client_id'     => {}, 
    13751419        'links_visited' => {},  
    13761420        'links_timed_out' => {}, 
     
    13801424 
    13811425    while (scalar(%{$args{'work'}})) { 
     1426        # Make sure the database_id is set to the client_id. 
     1427        $finishedWork->{'client_id'} = $self->{'database_id'}; 
    13821428 
    13831429        # Extract the highest priority work. 
     
    13961442            $LOG->warn("(" . $self->{'name'} . ") - " . $self->{'driver_name'} . " - Integrity Check: FAILED"); 
    13971443            # XXX: Test this. 
    1398             _dumpFingerprint($result->{'fingerprint'}); 
     1444 
     1445            # Dump the fingerprint to a file, if need be. 
     1446            $self->_dumpFingerprint($result->{'fingerprint'}); 
     1447 
     1448            # Suspend and archive the cloned VM. 
     1449            $self->suspend(); 
     1450 
     1451            # If possibile, insert work history. 
     1452            $finishedWork->{'links_visited'}->{$currentWork} = $result->{'time_at'}; 
     1453            if (defined($self->{'database_id'})) { 
     1454                $numWorkInserted = HoneyClient::Manager::Database::insert_history_urls($finishedWork); 
     1455                $LOG->info($numWorkInserted . " URL(s) Inserted."); 
     1456            } 
     1457 
     1458            # Mark the VM as suspicious and insert the fingerprint, if possible. 
     1459            $self->_changeStatus(status => "suspicious", fingerprint => $result->{'fingerprint'}); 
     1460 
    13991461        } else { 
    14001462            $LOG->info("(" . $self->{'name'} . ") - " . $self->{'driver_name'} . " - Integrity Check: PASSED"); 
     1463            # If possibile, insert work history. 
     1464            $finishedWork->{'links_visited'}->{$currentWork} = $result->{'time_at'}; 
     1465            if (defined($self->{'database_id'})) { 
     1466                $numWorkInserted = HoneyClient::Manager::Database::insert_history_urls($finishedWork); 
     1467                $LOG->info($numWorkInserted . " URL(s) Inserted."); 
     1468            } 
    14011469        } 
    1402  
    1403         $finishedWork->{'links_visited'}->{$currentWork} = $result->{'time_at'}; 
    1404  
    1405         $numWorkInserted = HoneyClient::Manager::Database::insert_history_urls($finishedWork); 
    1406         $LOG->info($numWorkInserted . " URL(s) Inserted."); 
    14071470 
    14081471        # Flush the work history, after committing to the database. 
    14091472        $finishedWork->{'links_visited'} = {}; 
    14101473 
    1411     } 
     1474        # Create a new clone, if a compromise was found and we still have work to do. 
     1475        if (scalar(@{$result->{'fingerprint'}->{os_processes}}) && 
     1476            scalar(%{$args{'work'}})) { 
     1477            # Be sure to carry over any customizations into the newly created 
     1478            # clones. 
     1479            $self = HoneyClient::Manager::VM::Clone->new( 
     1480                        master_vm_config => $self->{'master_vm_config'}, 
     1481                        driver_name      => $self->{'driver_name'}, 
     1482                    ); 
     1483        } 
     1484    } 
     1485 
     1486    return $self; 
    14121487} 
    14131488 
  • honeyclient/branches/exp/kindlund-simpler_agent/t/honeyclient_manager_vm_clone.t

    r1451 r1461  
    8686 
    8787# Make sure Storable loads. 
    88 BEGIN { use_ok('Storable', qw(dclone)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
     88BEGIN { use_ok('Storable', qw(dclone thaw)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
    8989require_ok('Storable'); 
    9090can_ok('Storable', 'dclone'); 
    91 use Storable qw(dclone); 
     91can_ok('Storable', 'thaw'); 
     92use Storable qw(dclone thaw); 
     93 
     94# Make sure MIME::Base64 loads. 
     95BEGIN { use_ok('MIME::Base64', qw(encode_base64 decode_base64)) or diag("Can't load MIME::Base64 package.  Check to make sure the package library is correctly listed within the path."); } 
     96require_ok('MIME::Base64'); 
     97can_ok('MIME::Base64', 'encode_base64'); 
     98can_ok('MIME::Base64', 'decode_base64'); 
     99use MIME::Base64 qw(encode_base64 decode_base64); 
    92100 
    93101# Make sure Data::Dumper loads 
     
    128136require_ok('DateTime::HiRes'); 
    129137use DateTime::HiRes; 
     138 
     139# Make sure IO::File loads. 
     140BEGIN { use_ok('IO::File') or diag("Can't load IO::File package.  Check to make sure the package library is correctly listed within the path."); } 
     141require_ok('IO::File'); 
     142use IO::File; 
    130143} 
    131144 
     
    183196    # Now, kill the VM daemon. 
    184197    HoneyClient::Manager::VM->destroy(); 
    185     # XXX: See if this is still needed. 
    186     #sleep (10); 
    187198 
    188199    # Create a generic empty clone, with test state data. 
     
    218229# Kill the child daemon, if it still exists. 
    219230HoneyClient::Manager::VM->destroy(); 
    220 # XXX: See if this is still needed. 
    221 #sleep (1); 
    222231 
    223232# Report any failure found. 
     
    251260    my $question; 
    252261    $question = prompt("#\n" . 
    253                        "# Note: Testing real archive operations will *ONLY* work\n" . 
     262                       "# Note: Testing real suspend/archive operations will *ONLY* work\n" . 
    254263                       "# with a fully functional master VM that has the HoneyClient code\n" . 
    255264                       "# loaded upon boot-up.\n" . 
     
    257266                       "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" . 
    258267                       "#\n" . 
    259                        "# Do you want to test cloning this master VM?", "no"); 
     268                       "# Do you want to test cloning and archiving this master VM?", "no"); 
    260269    if ($question =~ /^y.*/i) { 
    261270 
     
    265274 
    266275        # Archive the clone. 
    267         $clone->archive(snapshot_file => $snapshot); 
    268  
    269         # Wait for the archive to complete. 
     276        $clone->suspend(perform_archive => 1, snapshot_file => $snapshot); 
     277 
     278        # Wait for the suspend/archive to complete. 
    270279        sleep (45); 
    271280     
    272         # Test if the archive worked. 
    273         is(-f $snapshot, 1, "archive(snapshot_file => '$snapshot')") or diag("The archive() call failed."); 
     281        # Test if the operations worked. 
     282        is(-f $snapshot, 1, "suspend(perform_archive => 1, snapshot_file => '$snapshot')") or diag("The suspend() call failed."); 
    274283    
    275284        unlink $snapshot; 
     
    286295# Kill the child daemon, if it still exists. 
    287296HoneyClient::Manager::VM->destroy(); 
    288 # XXX: See if this is still needed. 
    289 #sleep (1); 
    290297 
    291298# Report any failure found. 
     
    297304 
    298305 
     306# =begin testing 
     307{ 
     308# Shared test variables. 
     309my ($stub, $som, $URL); 
     310my $testVM = $ENV{PWD} . "/" . getVar(name      => "test_vm_config", 
     311                                      namespace => "HoneyClient::Manager::VM::Test"); 
     312 
     313# Catch all errors, in order to make sure child processes are 
     314# properly killed. 
     315eval { 
     316 
     317    # Pretend as though no other Clone objects have been created prior 
     318    # to this point. 
     319    $HoneyClient::Manager::VM::Clone::OBJECT_COUNT = -1; 
     320     
     321    my $question; 
     322    $question = prompt("#\n" . 
     323                       "# Note: Testing real drive operations will *ONLY* work\n" . 
     324                       "# with a fully functional master VM that has the HoneyClient code\n" . 
     325                       "# loaded upon boot-up.\n" . 
     326                       "#\n" . 
     327                       "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" . 
     328                       "#\n" . 
     329                       "# Do you want to test cloning and driving this master VM?", "no"); 
     330    if ($question =~ /^y.*/i) { 
     331 
     332        # Create a generic empty clone, with test state data. 
     333        my $clone = HoneyClient::Manager::VM::Clone->new(); 
     334        my $cloneConfig = $clone->{config}; 
     335 
     336# TODO: Fix this. 
     337        $clone = $clone->drive(work => { 'http://www.google.com/' => 1 }); 
     338        isa_ok($clone, 'HoneyClient::Manager::VM::Clone', "drive(work => { 'http://www.google.com/' => 1})") or diag("The drive() call failed."); 
     339        $clone = undef; 
     340 
     341        # Connect to daemon as a client. 
     342        $stub = getClientHandle(namespace => "HoneyClient::Manager::VM"); 
     343     
     344        # Destroy the clone VM. 
     345        $som = $stub->destroyVM(config => $cloneConfig); 
     346    } 
     347}; 
     348 
     349# Kill the child daemon, if it still exists. 
     350HoneyClient::Manager::VM->destroy(); 
     351 
     352# Report any failure found. 
     353if ($@) { 
     354    fail($@); 
     355} 
     356} 
     357 
     358 
     359 
    299360 
    3003611;