initsite.in 21.5 KB
Newer Older
Leigh B. Stoller's avatar
Leigh B. Stoller committed
1
2
#!/usr/bin/perl -w
#
3
# GENIPUBLIC-COPYRIGHT
4
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# All rights reserved.
#
use strict;
use English;
use Getopt::Std;

#
# Initialize an emulab to act as a protogeni emulab. Add optional -c
# option if this is a clearinghouse.
# 
sub usage()
{
    print "Usage: initpgenisite [-c]\n";
    exit(1);
}
my $optlist = "c";
my $asch    = 0;
my $cflag   = "";

#
# Configure variables
#
my $TB		  = "@prefix@";
my $TBOPS         = "@TBOPSEMAIL@";
my $TBLOGS        = "@TBLOGSEMAIL@";
30
my $OURDOMAIN     = "@OURDOMAIN@";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
31
32
my $PGENIDOMAIN   = "@PROTOGENI_DOMAIN@";
my $PGENISUPPORT  = @PROTOGENI_SUPPORT@;
33
my $PROTOGENI_RPCNAME = "@PROTOGENI_RPCNAME@";
34
my $PROTOGENI_RPCPORT = "@PROTOGENI_RPCPORT@";
35
my $PROTOGENI_URL = "@PROTOGENI_URL@";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
36
37
38
39
40
41
42
43
44
my $geniuserid    = "geniuser";
my $geniprojid    = "GeniSlices";
my $PROTOUSER	  = "elabman";
my $NEWUSER	  = "$TB/sbin/newuser";
my $NEWPROJ	  = "$TB/sbin/newproj";
my $MKPROJ	  = "$TB/sbin/mkproj";
my $TBACCT	  = "$TB/sbin/tbacct";
my $ADDAUTHORITY  = "$TB/sbin/protogeni/addauthority";
my $GETCACERTS    = "$TB/sbin/protogeni/getcacerts";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
45
my $POSTCRL       = "$TB/sbin/protogeni/postcrl";
46
my $GENCRL        = "$TB/sbin/protogeni/gencrl";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
47
my $GENCRLBUNDLE  = "$TB/sbin/protogeni/gencrlbundle";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
48
my $MKSYSCERT	  = "$TB/sbin/mksyscert";
49
my $MKUSERCERT	  = "$TB/sbin/mkusercert";
50
my $BATCHEXP      = "$TB/bin/batchexp";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
51
my $WAP           = "$TB/sbin/withadminprivs";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
52
53
54
my $SACERT	  = "$TB/etc/genisa.pem";
my $CMCERT	  = "$TB/etc/genicm.pem";
my $CHCERT	  = "$TB/etc/genich.pem";
55
my $SESCERT	  = "$TB/etc/genises.pem";
56
my $RPCCERT	  = "$TB/etc/genirpc.pem";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
57
58
59
60
61
my $SUDO	  = "/usr/local/bin/sudo";
my $MYSQL         = "/usr/local/bin/mysql";
my $MYSQLADMIN    = "/usr/local/bin/mysqladmin";
my $MYSQLSHOW     = "/usr/local/bin/mysqlshow";
my $MYSQLDUMP     = "/usr/local/bin/mysqldump";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
62
63
my $PKG_INFO      = "/usr/sbin/pkg_info";
my $FETCH	  = "/usr/bin/fetch";
64
my $OPENSSL       = "/usr/bin/openssl";
65
66
67
my $APACHE_START  = "@APACHE_START_COMMAND@";
my $APACHE_CONF   = "@INSTALL_APACHE_CONFIG@/httpd.conf";
my $APACHE_FLAGS  = ("@APACHE_VERSION@" == "22" ?
68
		     "apache22_flags" : "apache_flags");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
69
70
71
72
73
74
75

# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/site/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

# Protos
sub fatal($);
76
sub UpdateCert($$$$);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
77
78
79
80
81
82
83
84

#
# Turn off line buffering on output
#
$| = 1; 

# Load the Testbed support stuff.
use lib "@prefix@/lib";
85
use libtestbed;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
86
use libdb qw(TBSetSiteVar TBOPSPID DBQueryFatal);
Gary Wong's avatar
Gary Wong committed
87
use emutil qw(TBGetUniqueIndex);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
88
89
use User;
use Project;
90
use Experiment;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
91
use OSinfo;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

if ($UID != 0) {
    fatal("Must be root to run this script\n");
}

#
# Check args.
#
my %options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (defined($options{"c"})) {
    $asch  = 1;
    $cflag = "-c";
}

109
110
111
#
# People seem to miss this.
#
112
if ($PGENIDOMAIN =~ /^unknown/i) {
113
114
115
116
117
    print STDERR "Please define PROTOGENI_DOMAIN in your defs file!\n";
    print STDERR "Then reconfig,rebuild,reinstall, then try this again.\n";
    exit(1);
}

118
119
120
#
# Check for (and update) an old (pre-URN) root certificate.
#
121
122
123
124
125
126
system( "$OPENSSL x509 -text -noout < $TB/etc/emulab.pem | " .
	"grep -q -i URI:urn:publicid:IDN" );
if( $? == -1 ) {
    die( "could not inspect root certificate $TB/etc/emulab.pem" );
} elsif( $? & 0x7F ) {
    die( "unexpected signal while inspecting root certificate" );
Gary Wong's avatar
Gary Wong committed
127
} elsif( $? ) {
128
129
    # grep returned non-zero exit code (indicating no matches): this is
    # an old certificate, so regenerate it.
130
131
132
133
134
135
136
137
    my $extfile = "/tmp/$$"; # not worth trying to be secure
    open( EXTFILE, "> $extfile" ) or die "can't open $extfile";
    print EXTFILE "subjectAltName=URI:urn:publicid:IDN+${OURDOMAIN}+authority+root\n";
    print EXTFILE "issuerAltName=URI:urn:publicid:IDN+${OURDOMAIN}+authority+root\n";
    close EXTFILE;

    print "Adding URN to root certificate...\n";

138
139
140
141
    my $originalfile = "$TB/etc/emulab.pem.orig";
    -f $originalfile and
	die( "refusing to overwrite $originalfile" );
    rename( "$TB/etc/emulab.pem", "$originalfile" ) or
142
	die( "could not rename root certificate" );
143
144

    my $serial = TBGetUniqueIndex( "user_sslcerts" );
145
146
147
148
    # Save the new certificate to a temporary file: OpenSSL will reuse the
    # plain text from the old certificate instead of the current version,
    # so we regenerate the whole thing once we've finished to avoid
    # horrible confusion.
149
    system( "$OPENSSL x509 -days 2000 -text -extfile $extfile " .
150
151
152
	    "-set_serial $serial -signkey $TB/etc/emulab.key " .
	    "< $originalfile > $TB/etc/emulab.tmp" );

153
154
    # For some reason, OpenSSL can return non-zero even when the certificate
    # generation succeeded.  Check the output file instead.
155
156
    if( !( -s "$TB/etc/emulab.tmp" ) ) {
	rename( "$originalfile", "$TB/etc/emulab.pem" );
157
	die( "could not generate new root certificate" );	    
158
159
160
161
162
    }

    # Regenerate the certificate, so that the comments are up to date.
    system( "$OPENSSL x509 -text < $TB/etc/emulab.tmp > $TB/etc/emulab.pem" );
    unlink( "$TB/etc/emulab.tmp" );
163
164
165
166
167
168
169

    print "Root certificate updated.  You will need to send the new\n";
    print "certificate to the clearing house.\n";

    unlink( "$TB/etc/.federated" );
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
170
171
172
#
# Have you sent in your certificate to Utah?
#
173
if (!$asch && ! -e "$TB/etc/.federated") {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
    my $done = 0;
    my $federated = 0;

    while (!$done) {
	print "Have you sent in your root certificate to Utah? [y/n]: ";

	$_ = <STDIN>;
	if ($_ =~ /^(y|yes)$/i) {
	    $federated = 1;
	    $done = 1;
	}
	elsif ($_ =~ /^(n|no)$/i) {
	    $federated = 0;
	    $done = 1;
	}
    }
    if ($federated) {
	system("/usr/bin/touch $TB/etc/.federated");
    }
    else {
	print "Please email $TB/etc/emulab.pem to testbed-ops\@flux.utah.edu";
	print "\n";
	print "This is a public key, so no harm in sending it in email.\n";
	print "Once you hear back from Utah, please rerun this script.\n";
	exit(1);
    }
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
202
203
204
#
# Packages.
#
205
206
207
208
209
210
211
my %packlist =
    ("libxml2>=2.6.26"       => "/usr/ports/textproc/libxml2",
     "p5-Frontier-RPC"       => "/usr/ports/net/p5-Frontier-RPC",
     "p5-XML-LibXML>=1.70"   => "/usr/ports/textproc/p5-XML-LibXML",
     "xmlsec1"               => "/usr/ports/security/xmlsec1",
     "p5-Crypt-SSLeay>=0.57" => "/usr/ports/security/p5-Crypt-SSLeay",
     "p5-Crypt-OpenSSL-X509" => "/usr/ports/security/p5-Crypt-OpenSSL-X509",
212
     "p5-Crypt-X509"         => "/usr/ports/security/p5-Crypt-X509",
213
214
     "xerces-c2>=2.7.0"      => "/usr/ports/textproc/xerces-c2",
     "p5-XML-SemanticDiff"   => "/usr/ports/textproc/p5-XML-SemanticDiff",
215
     );
Leigh B. Stoller's avatar
Leigh B. Stoller committed
216
217
my $needpkgs = 0;

218
foreach my $pkgname (sort(keys(%packlist))) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
219
220
    my $pkgdir = $packlist{$pkgname};
    
221
222
    print STDERR "Checking for package $pkgname\n";

Leigh B. Stoller's avatar
Leigh B. Stoller committed
223
224
225
226
227
228
229
230
231
232
233
    next
	if (system("$PKG_INFO -E '${pkgname}*' >/dev/null") == 0);

    print STDERR "Please install $pkgdir\n";
    $needpkgs++;
}
if ($needpkgs) {
    print STDERR "Then return to this script and start again.\n";
    exit(1);
}

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#
# crossdomain.xml is needed to allow the flash client to talk to
# this host.
#

my $crosstext = <<'CROSSEND';
<?xml version="1.0"?>
<cross-domain-policy>
    <site-control permitted-cross-domain-policies="all"/>
</cross-domain-policy>
CROSSEND

open CROSS_OUT, ">$TB/www/crossdomain.xml"
    or fatal("Could not create $TB/www/crossdomain.xml");
print CROSS_OUT $crosstext;
close CROSS_OUT;

chmod(0644, "$TB/www/crossdomain.xml");

if (! -e "$TB/www/protogeni") {
    mkdir("$TB/www/protogeni", 0775)
	or fatal("Could not mkdir $TB/www/protogeni");
}

$crosstext = <<'CROSSEND';
<?xml version="1.0"?>
<cross-domain-policy>
261
    <allow-access-from domain="*.emulab.net" />
262
263
264
265
266
267
268
269
270
271
272
    <allow-access-from domain="*.protogeni.net" />
</cross-domain-policy>
CROSSEND

open CROSS_OUT, ">$TB/www/protogeni/crossdomain.xml"
    or fatal("Could not create $TB/www/protogeni/crossdomain.xml");
print CROSS_OUT $crosstext;
close CROSS_OUT;

chmod(0644, "$TB/www/protogeni/crossdomain.xml");

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
my $FLASH_LINE = "flashpolicy stream tcp  nowait          root    /bin/echo               /bin/echo '<cross-domain-policy> <site-control permitted-cross-domain-policies=\"master-only\"/> <allow-access-from domain=\"*\" to-ports=\"80,443,$PROTOGENI_RPCPORT\"/> </cross-domain-policy>'";

my $restartinetd = 0;

if (system("egrep -q -s 'flashpolicy' /etc/services")) {
    print "Please add 'flashpolicy     843/tcp' to /etc/services\n";
    $restartinetd++;
}
if (system("egrep -q -s 'flashpolicy' /etc/inetd.conf")) {
    print "Please add \n$FLASH_LINE\n to /etc/services\n";
    $restartinetd++;
}
if ($restartinetd) {
    print "Then restart inetd and rerun this script.\n";
    exit(1);
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
289
290
291
292
293
#
# The web server needs to do client authentication, for the geni xmlrpc
# interface. A bundle of CA certs from the trusted roots (emulabs) will
# be used. This bundle will periodically update as sites come online.
#
294
295
296
297
298
299
300
301
302
if (! -e "$TB/etc/genica.bundle") {
    system("/bin/cp $TB/etc/emulab.pem $TB/etc/genica.bundle") == 0
	or fatal("Could not initialize $TB/etc/genica.bundle");
}
if (! -e "$TB/etc/genicrl.bundle") {
    system("/usr/bin/touch $TB/etc/genicrl.bundle") == 0
	or fatal("Could not initialize $TB/etc/genicrl.bundle");
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
303
304
305
306
307
if ($asch) {
    if (! -e "$TB/www/genica.bundle") {
	system("/bin/cp $TB/etc/emulab.pem $TB/www/genica.bundle") == 0
	    or fatal("Could not initialize $TB/www/genica.bundle");
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
308
309
    chmod(0644, "$TB/www/genica.bundle");

Leigh B. Stoller's avatar
Leigh B. Stoller committed
310
311
312
313
314
315
316
    # CRL 
    if (! -e "$TB/www/genicrl.bundle") {
	system("/usr/bin/touch $TB/www/genicrl.bundle") == 0
	    or fatal("Could not initialize $TB/www/genicrl.bundle");
    }
    chmod(0644, "$TB/www/genicrl.bundle");

Leigh B. Stoller's avatar
Leigh B. Stoller committed
317
318
319
320
321
322
323
324
325
326
327
328
    #
    # This is a pain. xmlsec1 cannot deal with a bundle of certs and so we
    # need to split up the bundle into a directory of certs. I hope to deal
    # with this at some point.
    #
    if (! -e "$TB/etc/genicacerts") {
	mkdir("$TB/etc/genicacerts", 0755)
	    or fatal("Could not mkdir $TB/etc/genicacerts");
    }
    system("/bin/cp $TB/etc/emulab.pem $TB/etc/genicacerts") == 0
	or fatal("Could not initialize $TB/etc/genicacerts");
}
329
330
if (! -e "$TB/lib/ssl/syscert.cnf" ||
    system( "grep -q protogeni_oids \"$TB/lib/ssl/syscert.cnf\"" ) != 0 ) {
331
332
333
334
335
    print "Please go to the ssl subdir of your build tree and do:\n";
    print "    sudo gmake install-conf\n";
    print "Then rerun this script\n";
    exit(1);
}
336
337
338
339
340
341
342
343
#
# I do not understand where this file comes from.
#
if (! -e "$TB/ssl/index.txt.attr" ||
    system("egrep -q -s 'no' $TB/ssl/index.txt.attr")) {
    system("echo 'unique_subject = no' > $TB/ssl/index.txt.attr") == 0
	or fatal("Could not update $TB/ssl/index.txt.attr");
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
344

Leigh B. Stoller's avatar
Leigh B. Stoller committed
345
346
my $restartapache = 0;

347
if (system("egrep -q -s 'PGENI' $APACHE_CONF")) {
348
    print "Please go to the apache subdir of your build tree and do:\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
349
350
351
    print "    gmake\n";
    print "    sudo gmake install\n";
    $restartapache++;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
352
353
}
if (system("egrep -q -s 'DPGENI' /etc/rc.conf")) {
354
    print "Please add '$APACHE_FLAGS=\"-DSSL -DPGENI\"' to /etc/rc.conf\n";
355
356
    $restartapache++;
}
357
if ($restartapache) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
358
    print "Then restart apache:\n";
359
    print "    sudo $APACHE_START restart\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
360
    print "Then rerun this script\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
361
362
363
    exit(1);
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
364
365
366
367
368
369
370
#
# On the clients, we have to get the bundle from Utah website and
# then break it up for xmlsec (see above). We use a script for this
# since the clients need to do this everytime a new client is added.
# This script restarts apache.
#
if (!$asch) {
371
    system("$GETCACERTS -l -p") == 0
Leigh B. Stoller's avatar
Leigh B. Stoller committed
372
373
	or fatal("Could not get CA bundle from Utah");

Leigh B. Stoller's avatar
Leigh B. Stoller committed
374
    #
Leigh B. Stoller's avatar
Leigh B. Stoller committed
375
376
    # This cron entry will autoupdate the CA/CRL certs by getting them from
    # Utah.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
377
378
379
    #
    if (system("egrep -q -s '$GETCACERTS' /etc/crontab")) {
	print "Please add this line to /etc/crontab:\n\n";
380
	print "13  4  *  *	*  root  $GETCACERTS\n\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
381
382
383
384
385
386
	print "Then rerun this script\n";
	exit(1);
    }
}
else {
    #
Leigh B. Stoller's avatar
Leigh B. Stoller committed
387
388
    # But on the clearinghouse, we have to generate the CRL bundle for 
    # downloading by remote sites.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
389
390
391
    #
    if (system("egrep -q -s '$GENCRLBUNDLE' /etc/crontab")) {
	print "Please add this line to /etc/crontab:\n\n";
392
	print "10  4  *  *  *  root  $GENCRLBUNDLE\n\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
393
394
	print "Then rerun this script\n";
	exit(1);
Gary Wong's avatar
Gary Wong committed
395
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
396
397
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
398
399
400
#
# user/project that slices (experiments) belong to.
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
401
402
my $geniuser = User->Lookup($geniuserid);
if (!defined($geniuser)) {
403
    fatal("Need to do an install in the protogeni/etc directory.")
Leigh B. Stoller's avatar
Leigh B. Stoller committed
404
405
	if (! -e "$TB/etc/protogeni/geniuser.xml");

406
    print "Creating Geni pseudo user ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
    system("$SUDO -u $PROTOUSER $WAP $NEWUSER $TB/etc/protogeni/geniuser.xml");
    fatal("Could not create geni user")
	if ($?);

    system("$SUDO -u $PROTOUSER $WAP $TBACCT verify $geniuserid");
    fatal("Could not verify geni user")
	if ($?);

    $geniuser = User->Lookup($geniuserid);    
    fatal("Could not lookup $geniuserid")
	if (!defined($geniuser));
}
my $geniproj = Project->Lookup($geniprojid);
if (!defined($geniproj)) {
    fatal("Need to do an install")
	if (! -e "$TB/etc/protogeni/geniproj.xml");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
423

424
    print "Creating Geni slices project ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
425
426
427
428
429
430
431
432
433
434
435
    system("$SUDO -u $PROTOUSER $WAP $NEWPROJ $TB/etc/protogeni/geniproj.xml");
    fatal("Could not create geni project")
	if ($?);

    system("$SUDO -u $PROTOUSER $WAP $MKPROJ -s $geniprojid");
    fatal("Could not approve geni project")
	if ($?);

    $geniproj = Project->Lookup($geniprojid);
    fatal("Could not lookup $geniprojid")
	if (!defined($geniproj));
Leigh B. Stoller's avatar
Leigh B. Stoller committed
436
437
438
}
$geniuser->Refresh();
$geniproj->Refresh();
439

Leigh B. Stoller's avatar
Leigh B. Stoller committed
440
441
442
443
# Create an encrypted certificate for the test scripts.
my $sslcert;
$geniuser->SSLCert(1, \$sslcert);
if (!defined($sslcert)) {
444
445
446
447
    my $passwd = substr(TBGenSecretKey(), 0, 10);
    system("$SUDO -u $PROTOUSER $WAP $MKUSERCERT -p '$passwd' $geniuserid");
    fatal("Could not create encrypted certificate for geni user")
	if ($?);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
448
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
449
450

#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# Need this fake type for now.
#
my $osinfo = OSinfo->Lookup(TBOPSPID(), "RHL-STD");
if (!defined($osinfo)) {
    fatal("No RHL-STD OSID in the ops project!");
}
my $osid = $osinfo->osid();

DBQueryFatal("replace into node_types (type,class,isvirtnode,isdynamic) ".
	     "values ('pcfake','pcvm',1,1)");
DBQueryFatal("replace into node_type_attributes ".
	     "(type,attrkey,attrvalue,attrtype) values ".
	     "('pcfake','rebootable','1','boolean')");
DBQueryFatal("replace into node_type_attributes ".
	     "(type,attrkey,attrvalue,attrtype) values ".
	     "('pcfake','default_osid','$osid','integer')");

#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
469
470
# Databases.
#
471
print "Creating Databases ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
472
473
474
475
476
477
478
479
480
481
482
foreach my $dbname ("geni", "geni-ch", "geni-cm") {
    if (system("$MYSQLSHOW $dbname >/dev/null 2>/dev/null")) {
	system("$MYSQLADMIN create $dbname") == 0
	    or fatal("Could not create DB: $dbname");
    }
    if (system("$MYSQLDUMP -d $dbname geni_users >/dev/null 2>/dev/null")) {
	system("$MYSQL $dbname < $TB/etc/protogeni/protogeni.sql") == 0
	    or fatal("Could not initialize DB: $dbname");
    }
}

483
484
485
486
487
488
foreach my $dbname( "geni", "geni-ch", "geni-cm" ) {
    system( "$MYSQL -e \"UPDATE geni_authorities SET type='ses' WHERE " .
	    "hrn LIKE '%.ses' AND type='';\" $dbname" ) == 0
	    or fatal( "Could not update SES type: $dbname" );
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
489
490
491
492
493
#
# Now we can load the libraries.
#
require Genixmlrpc;
require GeniRegistry;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
494
495
496
497

#
# Generate the certs we need.
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
498
if (! -e $CMCERT) {
499
    print "Creating CM certificate ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
500
    system("$SUDO -u $PROTOUSER $MKSYSCERT -o $CMCERT ".
501
	   "  -u $PROTOGENI_URL/cm " .
502
503
	   "  -i urn:publicid:IDN+${OURDOMAIN}+authority+cm " .
	   "$PGENIDOMAIN.cm") == 0
Leigh B. Stoller's avatar
Leigh B. Stoller committed
504
505
506
	   or fatal("Could not generate $CMCERT");
}
if (! -e $SACERT) {
507
    print "Creating SA certificate ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
508
    system("$SUDO -u $PROTOUSER $MKSYSCERT -o $SACERT ".
509
	   "  -u $PROTOGENI_URL/sa " .
510
511
	   "  -i urn:publicid:IDN+${OURDOMAIN}+authority+sa " .
	   "$PGENIDOMAIN.sa") == 0
Leigh B. Stoller's avatar
Leigh B. Stoller committed
512
513
	   or fatal("Could not generate $SACERT");
}
514
515
516
if (! -e $SESCERT) {
    print "Creating SES certificate ...\n";
    system("$SUDO -u $PROTOUSER $MKSYSCERT -o $SESCERT ".
517
	   "  -u $PROTOGENI_URL/ses " .
518
519
	   "  -i urn:publicid:IDN+${OURDOMAIN}+authority+ses " .
	   "$PGENIDOMAIN.ses") == 0
520
521
	   or fatal("Could not generate $SESCERT");
}
522
523
524
525
526
527
if (! -e $RPCCERT) {
    print "Creating RPC server certificate ...\n";
    system("$SUDO -u $PROTOUSER $MKSYSCERT -o $RPCCERT ".
	   "'ProtoGENI RPC Server' $PROTOGENI_RPCNAME") == 0
	   or fatal("Could not generate $SESCERT");
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
528
529
if ($asch) {
    if (! -e $CHCERT) {
530
	print "Creating CH certificate ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
531
	system("$SUDO -u $PROTOUSER $MKSYSCERT -o $CHCERT ".
532
	       "  -u $PROTOGENI_URL/ch " .
533
534
	       "  -i urn:publicid:IDN+${OURDOMAIN}+authority+ch " .
	       "$PGENIDOMAIN.ch") == 0
Leigh B. Stoller's avatar
Leigh B. Stoller committed
535
536
	       or fatal("Could not generate $CHCERT");
    }
537
    UpdateCert( $CHCERT, "$PROTOGENI_URL/ch",
538
539
		"urn:publicid:IDN+${OURDOMAIN}+authority+ch",
		"$PGENIDOMAIN.ch" );
Leigh B. Stoller's avatar
Leigh B. Stoller committed
540
541
542
543
544
545
546
547
548
549
550
551
552
553
    #
    # Copy the CH certificate out to the web interface, but only the public
    # key of course. 
    #
    my $chcertificate = GeniCertificate->LoadFromFile($CHCERT);
    fatal("Could not load certificate from $CHCERT")
	if (!defined($chcertificate));
    
    my $certfile = $chcertificate->WriteToFile();
    if (system("$SUDO /bin/mv $certfile $TB/www/genich.pem")) {
	$chcertificate->Delete();
	unlink($certfile);
	fatal("Could not mv $certfile to $TB/www/genich.pem");
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
554
555
    chmod(0644, "$TB/www/genich.pem");

Leigh B. Stoller's avatar
Leigh B. Stoller committed
556
557
558
559
560
561
562
563
564
565
    #
    # Add the cert to the DB directly.
    #
    system("$ADDAUTHORITY -c $CHCERT ma") == 0
	or fatal("Could not add MA certificate");
}
else {
    #
    # Grab the CH certificate from Utah. Only one for now.
    #
566
    print "Fetching clearinghouse certificate from Utah ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
567
568
569
    system("$FETCH -q -o $CHCERT http://boss.emulab.net/genich.pem") == 0
	or fatal("Could not fetch clearinghouse certificate from Utah");
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
570

571
572
573
#
# Update obsolete (pre-URN) certificates.
#
574
UpdateCert( $CMCERT, "$PROTOGENI_URL/cm",
575
576
	    "urn:publicid:IDN+${OURDOMAIN}+authority+cm",
	    "$PGENIDOMAIN.cm" );
577
UpdateCert( $SACERT, "$PROTOGENI_URL/sa",
578
579
	    "urn:publicid:IDN+${OURDOMAIN}+authority+sa",
	    "$PGENIDOMAIN.sa" );
580
UpdateCert( $SESCERT, "$PROTOGENI_URL/ses",
581
582
583
	    "urn:publicid:IDN+${OURDOMAIN}+authority+ses",
	    "$PGENIDOMAIN.ses" );

Leigh B. Stoller's avatar
Leigh B. Stoller committed
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
#
# Load the SA cert to act as caller context.
#
my $certificate = GeniCertificate->LoadFromFile($SACERT);
if (!defined($certificate)) {
    fatal("Could not load certificate from $SACERT\n");
}
my $context = Genixmlrpc->Context($certificate);
if (!defined($context)) {
    fatal("Could not create context to talk to clearinghouse");
}

#
# Note that we had to send the clearinghouse $TB/etc/emulab.pem so they
# know about this new site. That is sent out of band (email).
#
600
print "Getting credential to talk to clearinghouse ...\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
601
602
603
604
605
606
607
608
609
610
611
my $credential = GeniRegistry::ClearingHouse->GetCredential($context);
if (!defined($credential)) {
    fatal("Could not get credential to talk to clearinghouse");
}
my $clearinghouse = GeniRegistry::ClearingHouse->Create($context,
							$credential);
if (!defined($clearinghouse)) {
    fatal("Could not create a clearinghouse client");
}

#
612
613
614
615
616
617
# Add certs to the local SA database.
#
system("$ADDAUTHORITY $SACERT sa") == 0
    or fatal("Could not add SA certificate");
system("$ADDAUTHORITY $CMCERT cm") == 0
    or fatal("Could not add CM certificate");
618
619
system("$ADDAUTHORITY $SESCERT ses") == 0
    or fatal("Could not add SES certificate");
620

621
622
623
624
625
626
627
628
#
# Add certs to the local CM database.
#
system("$ADDAUTHORITY -a $SACERT sa") == 0
    or fatal("Could not add SA certificate to CM DB");
system("$ADDAUTHORITY -a $CMCERT cm") == 0
    or fatal("Could not add CM certificate to CM DB");

629
630
#
# Register our certs at the clearinghouse.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
631
632
#
print "Registering SA cert at the clearinghouse.\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
633
if ($clearinghouse->Register("SA", $certificate->cert())) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
634
635
636
    fatal("Could not register SA cert at the clearinghouse");
}
my $cmcert = GeniCertificate->LoadFromFile($CMCERT);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
637
if (!defined($cmcert)) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
638
639
640
    fatal("Could not load certificate from $CMCERT\n");
}
print "Registering CM cert at the clearinghouse.\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
641
if ($clearinghouse->Register("CM", $cmcert->cert())) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
642
643
    fatal("Could not register CM cert at the clearinghouse");
}
644
645
646
647
my $sescert = GeniCertificate->LoadFromFile($SESCERT);
if (!defined($sescert)) {
    fatal("Could not load certificate from $SESCERT\n");
}
648
649
650
651
652
653
# Don't treat SES registration failure as a fatal error quite yet, until
# we're certain that server-side support exists everywhere.
print "Registering SES cert at the clearinghouse.\n";
if ($clearinghouse->Register("SES", $sescert->cert())) {
    print("Warning: could not register SES cert at the clearinghouse\n");
}
654
655
656
657
658
659

#
# Local SiteVars to hold the UUIDs.
#
TBSetSiteVar('protogeni/sa_uuid', $certificate->uuid());
TBSetSiteVar('protogeni/cm_uuid', $cmcert->uuid());
660
TBSetSiteVar('protogeni/ses_uuid', $sescert->uuid());
661

Leigh B. Stoller's avatar
Leigh B. Stoller committed
662
663
664
665
666
667
668
669
670
exit(0);

sub fatal($)
{
    my ($msg) = @_;

    die("*** $0:\n".
	"    $msg\n");
}
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700

# Add a URN to old certificates.  (This is horrible, mainly because
# we want to reuse the same private keys.)
sub UpdateCert($$$$)
{
    my ($cert, $url, $urn, $hrn) = @_;

    if( system( "$OPENSSL x509 -text -noout < $cert | " .
		"grep -q -i URI:urn:publicid:IDN" ) ) {
	my $extfile = "/tmp/$$.ext"; # not worth trying to be secure
	my $keyfile = "/tmp/$$.key";
	my $uuid = qx{$OPENSSL x509 -subject -noout < $cert};

	die "could not read subject from $cert"
	    unless defined( $uuid );
	die "no UUID found in subject"
	    unless $uuid =~ /CN=([-a-f0-9]+)/;
	$uuid = $1;

	open( OLDFILE, "< $cert" ) or die "can't open $cert";
	open( NEWFILE, "> $keyfile" ) or die "can't open $keyfile";
	while( <OLDFILE> ) {
	    print NEWFILE;
	    last if /-----END RSA PRIVATE KEY-----/;
	}
	close OLDFILE;
	close NEWFILE;

	print "Adding URN to $cert...\n";

701
702
703
704
	my $originalfile = "${cert}.orig";
	-f $originalfile and
	    die( "refusing to overwrite $originalfile" );
	rename( "$cert", "$originalfile" ) or
705
706
707
708
709
710
711
	    die( "could not rename $cert" );

	system("$SUDO -u $PROTOUSER $MKSYSCERT -o $cert ".
	       "  -u $url -i $urn -k $keyfile $hrn $uuid" ) == 0
	       or fatal("Could not generate $cert");
    }
}