diff --git a/LICENSE b/LICENSE index 712c458..7b6eea7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2014 Joey Hess and contributors. +Copyright 2014 Joey Hess and contributors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/config-joey.hs b/config-joey.hs index 583c3bd..ee0c54a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -23,6 +23,7 @@ import qualified Propellor.Property.Apache as Apache import qualified Propellor.Property.Postfix as Postfix import qualified Propellor.Property.Grub as Grub import qualified Propellor.Property.Obnam as Obnam +import qualified Propellor.Property.Gpg as Gpg import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost import qualified Propellor.Property.HostingProvider.Linode as Linode @@ -122,7 +123,7 @@ kite = standardSystemUnhardened "kite.kitenet.net" Unstable "amd64" , "--exclude=/home/joey/lib" , "--exclude=.*/tmp/" , "--one-file-system" - ] Obnam.OnlyClient "98147487" + ] Obnam.OnlyClient (Gpg.GpgKeyId "98147487") `requires` Ssh.keyImported SshRsa "root" (Context "kite.kitenet.net") `requires` Ssh.knownHost hosts "eubackup.kitenet.net" "root" diff --git a/debian/changelog b/debian/changelog index 3fef340..3858ac2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,9 @@ propellor (0.9.3) UNRELEASED; urgency=medium * Can be used to configure tor hidden services. Thanks, Félix Sipma. * When multiple gpg keys are added, ensure that the privdata file can be decrypted by all of them. + * Convert GpgKeyId to newtype. + * DigitalOcean.distroKernel property now reboots into the distribution + kernel when necessary. -- Joey Hess Mon, 10 Nov 2014 11:15:27 -0400 diff --git a/debian/copyright b/debian/copyright index 3bdd010..1d333cc 100644 --- a/debian/copyright +++ b/debian/copyright @@ -2,7 +2,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Source: native package Files: * -Copyright: © 2010-2014 Joey Hess +Copyright: © 2010-2014 Joey Hess License: BSD-2-clause License: BSD-2-clause diff --git a/propellor.cabal b/propellor.cabal index 4da1419..8e552f2 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -1,5 +1,5 @@ Name: propellor -Version: 0.9.2 +Version: 0.9.3 Cabal-Version: >= 1.6 License: BSD3 Maintainer: Joey Hess diff --git a/src/Propellor/Property/Git.hs b/src/Propellor/Property/Git.hs index e5df7e4..8d49cbd 100644 --- a/src/Propellor/Property/Git.hs +++ b/src/Propellor/Property/Git.hs @@ -91,3 +91,6 @@ cloned owner url dir mbranch = check originurl (property desc checkout) -- installed here. , Just "git update-server-info" ] + +isGitDir :: FilePath -> IO Bool +isGitDir dir = isNothing <$> catchMaybeIO (readProcess "git" ["rev-parse", "--resolve-git-dir", dir]) diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index b469866..5819ea7 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -9,7 +9,8 @@ import System.PosixCompat installed :: Property installed = Apt.installed ["gnupg"] -type GpgKeyId = String +-- A numeric id, or a description of the key, in a form understood by gpg. +newtype GpgKeyId = GpgKeyId { getGpgKeyId :: String } -- | Sets up a user with a gpg key from the privdata. -- @@ -19,11 +20,8 @@ type GpgKeyId = String -- -- Recommend only using this for low-value dedicated role keys. -- No attempt has been made to scrub the key out of memory once it's used. --- --- The GpgKeyId does not have to be a numeric id; it can just as easily --- be a description of the key. keyImported :: GpgKeyId -> UserName -> Property -keyImported keyid user = flagFile' prop genflag +keyImported (GpgKeyId keyid) user = flagFile' prop genflag `requires` installed where desc = user ++ " has gpg key " ++ show keyid diff --git a/src/Propellor/Property/HostingProvider/DigitalOcean.hs b/src/Propellor/Property/HostingProvider/DigitalOcean.hs index 4565935..32165d4 100644 --- a/src/Propellor/Property/HostingProvider/DigitalOcean.hs +++ b/src/Propellor/Property/HostingProvider/DigitalOcean.hs @@ -1,21 +1,50 @@ -module Propellor.Property.HostingProvider.DigitalOcean where +module Propellor.Property.HostingProvider.DigitalOcean ( + distroKernel +) where import Propellor import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File +import Data.List + -- Digital Ocean does not provide any way to boot -- the kernel provided by the distribution, except using kexec. -- Without this, some old, and perhaps insecure kernel will be used. -- --- Note that this only causes the new kernel to be loaded on reboot. --- If the power is cycled, the old kernel still boots up. --- TODO: detect this and reboot immediately? +-- This property causes the distro kernel to be loaded on reboot, using kexec. +-- +-- If the power is cycled, the non-distro kernel still boots up. +-- So, this property also checks if the running kernel is present in /boot, +-- and if not, reboots immediately into a distro kernel. distroKernel :: Property distroKernel = propertyList "digital ocean distro kernel hack" - [ Apt.installed ["grub-pc", "kexec-tools"] + [ Apt.installed ["grub-pc", "kexec-tools", "file"] , "/etc/default/kexec" `File.containsLines` [ "LOAD_KEXEC=true" , "USE_GRUB_CONFIG=true" ] `describe` "kexec configured" + , check (not <$> runningInstalledKernel) + (cmdProperty "reboot" []) + `describe` "running installed kernel" ] + +runningInstalledKernel :: IO Bool +runningInstalledKernel = do + kernelver <- takeWhile (/= '\n') <$> readProcess "uname" ["-r"] + when (null kernelver) $ + error "failed to read uname -r" + kernelimages <- concat <$> mapM kernelsIn ["/", "/boot/"] + when (null kernelimages) $ + error "failed to find any installed kernel images" + findVersion kernelver <$> + readProcess "file" ("-L" : kernelimages) + +-- File output looks something like this, we want to unambiguously +-- match the running kernel version: +-- Linux kernel x86 boot executable bzImage, version 3.16-3-amd64 (debian-kernel@lists.debian.org) #1 SMP Debian 3.1, RO-rootFS, swap_dev 0x2, Normal VGA +findVersion :: String -> String -> Bool +findVersion ver s = (" version " ++ ver ++ " ") `isInfixOf` s + +kernelsIn :: FilePath -> IO [FilePath] +kernelsIn d = filter ("vmlinu" `isInfixOf`) <$> dirContents d diff --git a/src/Propellor/Property/Obnam.hs b/src/Propellor/Property/Obnam.hs index e18ca3f..4dc895e 100644 --- a/src/Propellor/Property/Obnam.hs +++ b/src/Propellor/Property/Obnam.hs @@ -48,8 +48,10 @@ backup dir crontimes params numclients = -- into root's keyring using Propellor.Property.Gpg.keyImported backupEncrypted :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Gpg.GpgKeyId -> Property backupEncrypted dir crontimes params numclients keyid = - backup dir crontimes (("--encrypt-with=" ++ keyid):params) numclients + backup dir crontimes params' numclients `requires` Gpg.keyImported keyid "root" + where + params' = ("--encrypt-with=" ++ Gpg.getGpgKeyId keyid) : params -- | Does a backup, but does not automatically restore. backup' :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Property diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs index 7b8216f..4a95067 100644 --- a/src/Propellor/Property/SiteSpecific/JoeySites.hs +++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs @@ -144,9 +144,8 @@ gitServer hosts = propertyList "git.kitenet.net setup" [ Obnam.latestVersion , Obnam.backupEncrypted "/srv/git" "33 3 * * *" [ "--repository=sftp://2318@usw-s002.rsync.net/~/git.kitenet.net" - , "--encrypt-with=1B169BE1" , "--client-name=wren" -- historical - ] Obnam.OnlyClient "1B169BE1" + ] Obnam.OnlyClient (Gpg.GpgKeyId "1B169BE1") `requires` Ssh.keyImported SshRsa "root" (Context "git.kitenet.net") `requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root" `requires` Ssh.authorizedKeys "family" (Context "git.kitenet.net") @@ -283,7 +282,7 @@ gitAnnexDistributor = combineProperties "git-annex distributor, including rsync , endpoint "/srv/web/downloads.kitenet.net/git-annex/autobuild" , endpoint "/srv/web/downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mavericks" -- git-annex distribution signing key - , Gpg.keyImported "89C809CB" "joey" + , Gpg.keyImported (Gpg.GpgKeyId "89C809CB") "joey" ] where endpoint d = combineProperties ("endpoint " ++ d)