#!/usr/bin/perl #=============================================================================== # # FILE: migrate_keyshare_sqlite3.pl # # USAGE: ./migrate_keyshare_sqlite3.pl -d # # DESCRIPTION: # # OPTIONS: --- # REQUIREMENTS: --- # BUGS: --- # NOTES: --- # AUTHOR: Sion, # COMPANY: # VERSION: 1.0 # CREATED: 09/08/10 08:31:13 # REVISION: --- #=============================================================================== use strict; use warnings; use DBI; use DBD::SQLite; use Getopt::Std qw(getopts); use File::Copy; use File::Compare; use vars ( q!$opt_d!, # Database file fo convert q!$opt_f!, # Force commit if view has changed ); getopts('d:f') or die "Please supply a database file to work on with the -d flag"; if (!$opt_d) { print STDERR "Please supply a database file to work on with the -d flag\n"; exit 1; } ### # First Create a backup of the existing file copy($opt_d, $opt_d.".PRE_KEY_SHARE") or die "Backup failed: $!"; ### # Make sure that we can connect to this database my $dbh = DBI->connect("dbi:SQLite:dbname=$opt_d","","") or die "Couldn't connect: $!"; ### # Save copy of keydataview my $keydata_sql = "select * from keydata_view"; my $keydata_sth = $dbh->prepare($keydata_sql) or die "Couldn't prepare keydata_sql: $!"; $keydata_sth->execute(); open my $VIEW_FILE, '>', $opt_d.".KEYDATA_BEFORE" or die "$0 : failed to open output file '$opt_d.KEYDATA_BEFORE' : $!\n"; no warnings 'uninitialized'; while (my @view_row = $keydata_sth->fetchrow_array) { my $temp = join('|', @view_row); print $VIEW_FILE $temp; print $VIEW_FILE "\n"; } use warnings; close $VIEW_FILE or warn "$0 : failed to close output file '$opt_d.KEYDATA_BEFORE' : $!\n"; ### # Create new columns $dbh->do("alter table dnsseckeys add column state tinyint") or die "Couldn't add column state: $!"; $dbh->do("alter table dnsseckeys add column publish varchar(64) null default null") or die "Couldn't add column publish: $!"; $dbh->do("alter table dnsseckeys add column ready varchar(64) null default null") or die "Couldn't add column ready: $!"; $dbh->do("alter table dnsseckeys add column active varchar(64) null default null") or die "Couldn't add column active: $!"; $dbh->do("alter table dnsseckeys add column retire varchar(64) null default null") or die "Couldn't add column retire: $!"; $dbh->do("alter table dnsseckeys add column dead varchar(64) null default null") or die "Couldn't add column dead: $!"; ### # Migrate existing data my $keypairs_sth = $dbh->prepare("select id, state, publish, ready, active, retire, dead from keypairs") or die "Couldn't prepare keypairs_sql: $!"; my $update_sql = "update dnsseckeys set state = ?, publish = ?, ready = ?, active = ?, retire = ?, dead = ? where keypair_id = ?"; my $update_sth = $dbh->prepare($update_sql) or die "Couldn't prepare update_sql: $!"; $keypairs_sth->execute(); while (my @key_row = $keypairs_sth->fetchrow_array) { $update_sth->execute($key_row[1], $key_row[2], $key_row[3], $key_row[4], $key_row[5], $key_row[6], $key_row[0]) or die "Couldn't execute update command: $!"; } ### # Remove old columns # Arrgghhhh sqlite can't drop columns... Do it the long way $dbh->do("alter table keypairs rename to keypairs_temp") or die "Couldn't rename keypairs: $!"; $dbh->do("create table keypairs( id integer primary key autoincrement, HSMkey_id varchar(255) not null, algorithm tinyint not null, -- algorithm code size smallint, securitymodule_id tinyint, -- where the key is stored generate varchar(64) null default null, -- time key inserted into database policy_id mediumint, compromisedflag tinyint, publickey varchar(1024), -- public key data pre_backup varchar(64) null default null, -- time when backup was started backup varchar(64) null default null, -- time when backup was finished fixedDate tinyint default 0, -- Set to 1 to stop dates from being set according to the policy timings foreign key (securitymodule_id) references securitymodules (id), foreign key (policy_id) references policies (id) )") or die "Couldn't recreate keypairs: $!"; $dbh->do("insert into keypairs select id, HSMkey_id, algorithm, size, securitymodule_id, generate, policy_id, compromisedflag, publickey, NULL as pre_backup, backup, fixedDate from keypairs_temp") or die "Couldn't repopulate keypairs: $!"; ### # Fix old views (add new view) $dbh->do("drop view if exists KEYDATA_VIEW") or die "Couldn't drop view KEYDATA_VIEW"; $dbh->do("create view KEYDATA_VIEW as select k.id as id, d.state as state, k.generate as generate, d.publish as publish, d.ready as ready, d.active as active, d.retire as retire, d.dead as dead, d.keytype as keytype, k.algorithm as algorithm, k.HSMkey_id as location, d.zone_id as zone_id, k.policy_id as policy_id, k.securitymodule_id as securitymodule_id, k.size as size, k.compromisedflag as compromisedflag, k.fixedDate as fixedDate from keypairs k left outer join dnsseckeys d on k.id = d.keypair_id") or die "Couldn't recreate view KEYDATA_VIEW"; $dbh->do("create view KEYALLOC_VIEW as select v.id as id, location, algorithm, policy_id, securitymodule_id, size, compromisedflag, d.zone_id as zone_id from (select k.id as id, k.HSMkey_id as location, z.id as zone_id, k.algorithm as algorithm, k.policy_id as policy_id, k.securitymodule_id as securitymodule_id, k.size as size, k.compromisedflag as compromisedflag from keypairs k left join zones z where k.policy_id = z.policy_id ) v left outer join dnsseckeys d on d.zone_id = v.zone_id and d.keypair_id = v.id") or die "Couldn't recreate view KEYALLOC_VIEW"; ### # Compare keydataview with saved copy $keydata_sth->execute(); open my $NEW_VIEW_FILE, '>', $opt_d.".KEYDATA_AFTER" or die "$0 : failed to open output file '$opt_d.KEYDATA_AFTER' : $!\n"; no warnings 'uninitialized'; while (my @view_row = $keydata_sth->fetchrow_array) { my $temp = join('|', @view_row); print $NEW_VIEW_FILE $temp; print $NEW_VIEW_FILE "\n"; } use warnings; close $NEW_VIEW_FILE or warn "$0 : failed to close output file '$opt_d.KEYDATA_AFTER' : $!\n"; if (compare("$opt_d.KEYDATA_BEFORE","$opt_d.KEYDATA_AFTER") != 0) { print "keydata_view changed, this is probably bad.\n"; if ($opt_f) { print "Forcing commit due to -f flag\n"; } else { print "Compare the files $opt_d.KEYDATA_BEFORE and $opt_d.KEYDATA_AFTER; if you are happy that the changes are not important then run again with the -f flag to force a commit.\n"; $dbh->rollback; # This is slightly bad... this will not rollback and DDL $dbh->disconnect; move($opt_d.".PRE_KEY_SHARE", $opt_d) or die "Move of backup failed: $!"; exit 1; } } ### # Add new columns to zones table $dbh->do("alter table zones add column signconf varchar(4096)") or die "Couldn't add column signconf: $!"; $dbh->do("alter table zones add column input varchar(4096)") or die "Couldn't add column input: $!"; $dbh->do("alter table zones add column output varchar(4096)") or die "Couldn't add column output: $!"; ### # Update DB version number $dbh->do("update dbadmin set version = 2") or die "Couldn't update dbadmin: $!"; $dbh->commit; ### # Clean up the temp table $dbh->do("drop table keypairs_temp") or die "Couldn't drop keypairs_temp: $!"; $dbh->disconnect;