Encrypting confidential files on the install server
Motivation
Usually the (read) access restrictions on the files and scripts on the FAI install server are rather weak. So it is a bit tricky to put passwords and other confidential stuff there. We therefore use encryption to store confidential information on the install server. After the installation the confidential files are secured by the login authentication and filesystem permissions, so they can be safely decrypted. As a drawback, someone has to manually login into the freshly installed system and provide the secret key for the encryption.
Overview
A. Generate a gpg key pair for this purpose.
B. Encrypt confidential files, add information about ownership and filesystem permission.
C. Adjust FAI configuration to install the encrypted files in /var/lib/fai/secrets/install/ and the decryption script /usr/local/sbin/fai-secrets-install on the target system and perform installation
D. Log into the freshly installed system (as root) and run fai-secrets-install.
A. Generate a gpg key pair
Well, you know how to do that. Choose a reasonable name for the user id (FAI Installation at ... or something like that), supply a passphrase and note the key id. You can store the public key on the install server (e.g. to encode a random root password at install time) but you don't want to deposit the secret key there.
B. Encrypt confidential files
Encrypt your confidential files and add information about file owner and permission. The syntax expected by the decryption script fai-secrets-install is straightforward and best documented by an example:
##FAI_secret v1.0 type: file location: /etc/ssh/ssh_host_dsa_key owner: root:root mode: 600 -----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.6 (GNU/Linux) hQIOA6/Tc/NaxvkSEAf/eZRBl/EqLFFKNHBGGOxAGO8PvHEJxDqQq4UVdU58Rfip HPvBfnNGSsPyskXM1DPfykEMqc/0GH2qGg/hcLJZ4adI2FT7bqfuPcNj33LDJgG1 ... 5KvfSE01vPfUcGKERLCHs2XL =8a9r -----END PGP MESSAGE-----
The first line (##FAI_secret v1.0) is just a magic cookie. The line "type: file" indicates that the encrypted data is a file content. We have not implemented any other type yet, but one could e.g. imagine a type line that includes a single line of encrypted information into a plain text file.
Here is a helper script /usr/local/sbin/fai-secrets-collect that we install on all our servers. Its purpose is to collect sensitive information of an already installed system which can be put on the install server afterwards. This helps us to preserve ssh host keys during reinstallation::
#!/usr/bin/perl #********************************************************************* # # fai-secrets-collect: collects sensitive system information, encrypts # and writes to /var/lib/fai/secrets/status # # authors: Thomas Gebhardt <gebhardt_at_hrz.uni-marburg.de>; # Andreas Gabriel <gabriel_at_hrz.uni-marburg.de> # licence: GPLv2 # version: 2007-03-06 # #********************************************************************* use strict; use warnings; #use Getopt::Std; #use vars qw($opt_d $opt_f $opt_g); use Env qw(GNUPGHOME HOSTNAME); use Crypt::GPG; $HOSTNAME = $HOSTNAME || `hostname`; #defaults: my $STATUS_DIR = "/var/lib/fai/secrets/status"; my $GPG_KEY_ID = "0x... here goes your gpg key id"; $GNUPGHOME = "/etc/fai/gnupg"; # no "my" here! (tied to ENV variable) my %SECRETS = ( "/etc/ssh/ssh_host_dsa_key" => "ssh_host_dsa_key", "/etc/ssh/ssh_host_dsa_key.pub" => "ssh_host_dsa_key.pub", "/etc/ssh/ssh_host_rsa_key" => "ssh_host_rsa_key", "/etc/ssh/ssh_host_rsa_key.pub" => "ssh_host_rsa_key.pub", "/etc/tsm/TSM.PWD" => "ITSM_password", "/etc/exim4/passwd.client" => "exim4_passwd.client", "/etc/libnss-ldap.secret" => "libnss-ldap.secret", "/etc/pam_ldap.secret" => "pam_ldap.secret", ... append files to suit your needs ... ); foreach my $file (keys %SECRETS) { next unless -r $file; my ($mode,$uid,$gid) = (stat $file)[2,4,5]; $mode &= 07777; # discard file type info $mode = sprintf("%4o",$mode); my $user = (getpwuid $uid)[0]; my $group = (getgrgid $gid)[0]; my $file_content; # slurp file: { local( $/, *SECRET ) ; open( SECRET, $file ) or die "oh, tested -r just before ???\n"; $file_content = <SECRET>; } my $gpg = new Crypt::GPG; my $encrypted = $gpg->encrypt ($file_content, $GPG_KEY_ID); my $file_dir = $STATUS_DIR . "/" . $SECRETS{$file}; mkdir($file_dir) unless( -d $file_dir ); my $file_status = $file_dir . "/" . $HOSTNAME ; print "encrypting $file as $file_status\n"; open (ENCRYPTED, "> $file_status") or die "can't open $file_status for writing: $?"; print ENCRYPTED "##FAI_secret v1.0\n"; # magic header print ENCRYPTED "\n"; print ENCRYPTED "type: file\n"; print ENCRYPTED "location: $file\n"; print ENCRYPTED "owner: $user\:$group\n"; print ENCRYPTED "mode: $mode\n"; print ENCRYPTED "\n"; print ENCRYPTED $encrypted; close ENCRYPTED; } print "**********************************************************\n"; print "To complete the collection copy all secrets to your fai's svn working directory with the following command:\n\n"; print "\> scp -r $STATUS_DIR/* \<username\@hostname\>:\<fai_svn_working_dir\>/files/var/lib/fai/secrets/install\n\n"; print "**********************************************************\n\n";
The scripts uses the perl module Crypt::GPG and expects the public gpg keyring in the directory /etc/fai/gnupg.
C. Adjust FAI configuration and perform installation
Configure FAI to install the encrypted data and the decryption script. You know how to do that. Most probably you will write a script like
#! /bin/sh fcopy -Bi -m root,root,700 /usr/local/sbin/fai-secrets-install fcopy -Bi -m root,root,700 /usr/local/sbin/fai-secrets-collect fcopy -Bi -m root,root,600 /var/lib/fai/secrets/install/ssh_host_dsa_key fcopy -Bi -m root,root,600 /var/lib/fai/secrets/install/ssh_host_dsa_key.pub ...