From b50f33395edc55317d95c53e34c4d810a5e49041 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 1 Jan 2015 13:57:13 -0400 Subject: update docs --- src/Propellor/Info.hs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/Propellor/Info.hs') diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs index a91f69c8..0437f8ec 100644 --- a/src/Propellor/Info.hs +++ b/src/Propellor/Info.hs @@ -26,8 +26,13 @@ getOS = askInfo _os -- | Indidate that a host has an A record in the DNS. -- --- TODO check at run time if the host really has this address. --- (Can't change the host's address, but as a sanity check.) +-- When propellor is used to deploy a DNS server for a domain, +-- the hosts in the domain are found by looking for these +-- and similar properites. +-- +-- When propellor --spin is used to deploy a host, it checks +-- if the host's IP Property matches the DNS. If the DNS is missing or +-- out of date, the host will instead be contacted directly by IP address. ipv4 :: String -> Property ipv4 = addDNS . Address . IPv4 -- cgit v1.3-2-g0d8e From 8172f243d73f0c7f7231d03c3561c3da5a7ad0d4 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 4 Jan 2015 12:44:05 -0400 Subject: DNS WIP --- src/Propellor/Info.hs | 1 + src/Propellor/PrivData/Paths.hs | 2 +- src/Propellor/Property.hs | 3 +- src/Propellor/Property/Dns.hs | 50 +++++++++++++++++++++++------ src/Propellor/Property/DnsSec.hs | 69 +++++++++++++++++++++++++++++++++++++--- src/Propellor/Types/Dns.hs | 1 + 6 files changed, 109 insertions(+), 17 deletions(-) (limited to 'src/Propellor/Info.hs') diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs index 0437f8ec..3af3fc15 100644 --- a/src/Propellor/Info.hs +++ b/src/Propellor/Info.hs @@ -64,6 +64,7 @@ addDNS r = pureInfoProperty (rdesc r) $ mempty { _dns = S.singleton r } rdesc (NS d) = unwords ["NS", ddesc d] rdesc (TXT s) = unwords ["TXT", s] rdesc (SRV x y z d) = unwords ["SRV", show x, show y, show z, ddesc d] + rdesc (INCLUDE f) = unwords ["$INCLUDE", f] ddesc (AbsDomain domain) = domain ddesc (RelDomain domain) = domain diff --git a/src/Propellor/PrivData/Paths.hs b/src/Propellor/PrivData/Paths.hs index 9f791b76..3d0d8a58 100644 --- a/src/Propellor/PrivData/Paths.hs +++ b/src/Propellor/PrivData/Paths.hs @@ -3,7 +3,7 @@ module Propellor.PrivData.Paths where import System.FilePath privDataDir :: FilePath -privDataDir = "privdata.joey" +privDataDir = "privdata" privDataFile :: FilePath privDataFile = privDataDir "privdata.gpg" diff --git a/src/Propellor/Property.hs b/src/Propellor/Property.hs index 37fd90d6..c0878fb6 100644 --- a/src/Propellor/Property.hs +++ b/src/Propellor/Property.hs @@ -26,8 +26,7 @@ propertyList :: Desc -> [Property] -> Property propertyList desc ps = Property desc (ensureProperties ps) (combineInfos ps) -- | Combines a list of properties, resulting in one property that --- ensures each in turn. Does not stop on failure; does propigate --- overall success/failure. +-- ensures each in turn. Stops if a property fails. combineProperties :: Desc -> [Property] -> Property combineProperties desc ps = Property desc (go ps NoChange) (combineInfos ps) where diff --git a/src/Propellor/Property/Dns.hs b/src/Propellor/Property/Dns.hs index 20530f26..89180963 100644 --- a/src/Propellor/Property/Dns.hs +++ b/src/Propellor/Property/Dns.hs @@ -56,18 +56,18 @@ import Data.List primary :: [Host] -> Domain -> SOA -> [(BindDomain, Record)] -> RevertableProperty primary hosts domain soa rs = RevertableProperty setup cleanup where - setup = withwarnings (check needupdate baseprop) - `requires` servingZones + setup = setupPrimary hosts domain soa rs + `onChange` Service.reloaded "bind9" + cleanup = cleanupPrimary domain `onChange` Service.reloaded "bind9" - cleanup = check (doesFileExist zonefile) $ - property ("removed dns primary for " ++ domain) - (makeChange $ removeZoneFile zonefile) - `requires` namedConfWritten - `onChange` Service.reloaded "bind9" +setupPrimary :: [Host] -> Domain -> SOA -> [(BindDomain, Record)] -> Property +setupPrimary hosts domain soa rs = withwarnings (check needupdate baseprop) + `requires` servingZones + where (partialzone, zonewarnings) = genZone hosts domain soa zone = partialzone { zHosts = zHosts partialzone ++ rs } - zonefile = "/etc/bind/propellor/db." ++ domain + zonefile = zoneFile domain baseprop = Property ("dns primary for " ++ domain) (makeChange $ writeZoneFile zone zonefile) (addNamedConf conf) @@ -100,6 +100,18 @@ primary hosts domain soa rs = RevertableProperty setup cleanup z = zone { zSOA = (zSOA zone) { sSerial = oldserial } } in z /= oldzone || oldserial < sSerial (zSOA zone) + +cleanupPrimary :: Domain -> Property +cleanupPrimary domain = check (doesFileExist zonefile) $ + property ("removed dns primary for " ++ domain) + (makeChange $ removeZoneFile zonefile) + `requires` namedConfWritten + where + zonefile = zoneFile domain + +zoneFile :: Domain -> FilePath +zoneFile domain = "/etc/bind/propellor/db." ++ domain + -- | Primary dns server for a domain, secured with DNSSEC. -- -- This is like `primary`, except the resulting zone @@ -121,8 +133,24 @@ primary hosts domain soa rs = RevertableProperty setup cleanup signedPrimary :: Recurrance -> [Host] -> Domain -> SOA -> [(BindDomain, Record)] -> RevertableProperty signedPrimary recurrance hosts domain soa rs = RevertableProperty setup cleanup where - setup = undefined - cleanup = undefined + -- TODO put signed zone file in named.conf. + -- TODO enable dnssec options. + -- dnssec-enable yes; dnssec-validation yes; dnssec-lookaside auto; + -- TODO if keys change, resign zone file. + -- TODO write to entirely different files than does primary, + -- so that primary can be reverted and signedPrimary enabled, + -- or vice-versa, without conflicts. + setup = setupPrimary hosts domain soa rs' + `onChange` toProp (zoneSigned domain (zoneFile domain)) + `onChange` Service.reloaded "bind9" + + cleanup = cleanupPrimary domain + `onChange` toProp (revert (zoneSigned domain (zoneFile domain))) + `onChange` Service.reloaded "bind9" + + -- Include the public keys into the zone file. + rs' = include PubKSK : include PubZSK : rs + include k = (RootDomain, INCLUDE (keyFn domain k)) -- | Secondary dns server for a domain. -- @@ -243,6 +271,7 @@ rField (MX _ _) = "MX" rField (NS _) = "NS" rField (TXT _) = "TXT" rField (SRV _ _ _ _) = "SRV" +rField (INCLUDE _) = "$INCLUDE" rValue :: Record -> String rValue (Address (IPv4 addr)) = addr @@ -256,6 +285,7 @@ rValue (SRV priority weight port target) = unwords , show port , dValue target ] +rValue (INCLUDE f) = f rValue (TXT s) = [q] ++ filter (/= q) s ++ [q] where q = '"' diff --git a/src/Propellor/Property/DnsSec.hs b/src/Propellor/Property/DnsSec.hs index 55a447a1..201cc003 100644 --- a/src/Propellor/Property/DnsSec.hs +++ b/src/Propellor/Property/DnsSec.hs @@ -1,7 +1,7 @@ module Propellor.Property.DnsSec where import Propellor -import Propellor.Property.File +import qualified Propellor.Property.File as File -- | Puts the DNSSEC key files in place from PrivData. -- @@ -14,10 +14,13 @@ keysInstalled domain = RevertableProperty setup cleanup map installkey keys cleanup = propertyList "DNSSEC keys removed" $ - map (notPresent . keyFn domain) keys + map (File.notPresent . keyFn domain) keys - installkey k = (if isPublic k then hasPrivContentExposedFrom else hasPrivContentFrom) - (keysrc k) (keyFn domain k) (Context domain) + installkey k = writer (keysrc k) (keyFn domain k) (Context domain) + where + writer + | isPublic k = File.hasPrivContentExposedFrom + | otherwise = File.hasPrivContentFrom keys = [ PubZSK, PrivZSK, PubKSK, PrivKSK ] @@ -30,6 +33,64 @@ keysInstalled domain = RevertableProperty setup cleanup else "dnssec-keygen -f KSK -a RSASHA256 -b 4096 -n ZONE " ++ domain ] +-- | Uses dnssec-signzone to sign a domain's zone file. +-- +-- signedPrimary uses this, so this property does not normally need to be +-- used directly. +zoneSigned :: Domain -> FilePath -> RevertableProperty +zoneSigned domain zonefile = RevertableProperty setup cleanup + where + setup = check needupdate (forceZoneSigned domain zonefile) + `requires` toProp (keysInstalled domain) + + cleanup = combineProperties ("removed signed zone for " ++ domain) + [ File.notPresent signedzonefile + , File.notPresent dssetfile + , toProp (revert (keysInstalled domain)) + ] + + signedzonefile = dir domain ++ ".signed" + dssetfile = dir "-" ++ domain ++ "." + dir = takeDirectory zonefile + + -- Need to update the signed zone if the zone file + -- has a newer timestamp. + needupdate = do + v <- catchMaybeIO $ getModificationTime signedzonefile + case v of + Nothing -> return True + Just t1 -> do + t2 <- getModificationTime zonefile + return (t2 >= t1) + +forceZoneSigned :: Domain -> FilePath -> Property +forceZoneSigned domain zonefile = property ("zone signed for " ++ domain) $ liftIO $ do + salt <- take 16 <$> saltSha1 + let p = proc "dnssec-signzone" + [ "-A" + , "-3", salt + , "-N", "keep" + , "-o", domain + , zonefile + -- the ordering of these key files does not matter + , keyFn domain PubZSK + , keyFn domain PubKSK + ] + -- Run in the same directory as the zonefile, so it will + -- write the dsset file there. + (_, _, _, h) <- createProcess $ + p { cwd = Just (takeDirectory zonefile) } + ifM (checkSuccessProcess h) + ( return MadeChange + , return FailedChange + ) + +saltSha1 :: IO String +saltSha1 = readProcess "sh" + [ "-c" + , "head -c 1024 /dev/urandom | sha1sum | cut -d ' ' -f 1" + ] + -- | The file used for a given key. keyFn :: Domain -> DnsSecKey -> FilePath keyFn domain k = "/etc/bind/propellor" diff --git a/src/Propellor/Types/Dns.hs b/src/Propellor/Types/Dns.hs index 5e9666d8..2fbf51e5 100644 --- a/src/Propellor/Types/Dns.hs +++ b/src/Propellor/Types/Dns.hs @@ -62,6 +62,7 @@ data Record | NS BindDomain | TXT String | SRV Word16 Word16 Word16 BindDomain + | INCLUDE FilePath deriving (Read, Show, Eq, Ord) getIPAddr :: Record -> Maybe IPAddr -- cgit v1.3-2-g0d8e From f36443755e9c151d7d93b172fb2260b007ec483f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 4 Jan 2015 14:05:42 -0400 Subject: propellor spin --- src/Propellor/Info.hs | 1 - src/Propellor/Property/Dns.hs | 8 +------- src/Propellor/Property/DnsSec.hs | 14 ++++++++++++-- src/Propellor/Types/Dns.hs | 1 - 4 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src/Propellor/Info.hs') diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs index 3af3fc15..0437f8ec 100644 --- a/src/Propellor/Info.hs +++ b/src/Propellor/Info.hs @@ -64,7 +64,6 @@ addDNS r = pureInfoProperty (rdesc r) $ mempty { _dns = S.singleton r } rdesc (NS d) = unwords ["NS", ddesc d] rdesc (TXT s) = unwords ["TXT", s] rdesc (SRV x y z d) = unwords ["SRV", show x, show y, show z, ddesc d] - rdesc (INCLUDE f) = unwords ["$INCLUDE", f] ddesc (AbsDomain domain) = domain ddesc (RelDomain domain) = domain diff --git a/src/Propellor/Property/Dns.hs b/src/Propellor/Property/Dns.hs index 27f81f62..c5a4efa9 100644 --- a/src/Propellor/Property/Dns.hs +++ b/src/Propellor/Property/Dns.hs @@ -133,7 +133,7 @@ signedPrimary recurrance hosts domain soa rs = RevertableProperty setup cleanup -- TODO enable dnssec options. -- dnssec-enable yes; dnssec-validation yes; dnssec-lookaside auto; setup = combineProperties ("dns primary for " ++ domain ++ " (signed)") - [ setupPrimary zonefile signedZoneFile hosts domain soa rs' + [ setupPrimary zonefile signedZoneFile hosts domain soa rs , toProp (zoneSigned domain zonefile) ] `onChange` Service.reloaded "bind9" @@ -142,10 +142,6 @@ signedPrimary recurrance hosts domain soa rs = RevertableProperty setup cleanup `onChange` toProp (revert (zoneSigned domain zonefile)) `onChange` Service.reloaded "bind9" - -- Include the public keys into the zone file. - rs' = include PubKSK : include PubZSK : rs - include k = (RootDomain, INCLUDE (keyFn domain k)) - -- Put DNSSEC zone files in a different directory than is used for -- the regular ones. This allows 'primary' to be reverted and -- 'signedPrimary' enabled, without the reverted property stomping @@ -271,7 +267,6 @@ rField (MX _ _) = "MX" rField (NS _) = "NS" rField (TXT _) = "TXT" rField (SRV _ _ _ _) = "SRV" -rField (INCLUDE _) = "$INCLUDE" rValue :: Record -> String rValue (Address (IPv4 addr)) = addr @@ -285,7 +280,6 @@ rValue (SRV priority weight port target) = unwords , show port , dValue target ] -rValue (INCLUDE f) = f rValue (TXT s) = [q] ++ filter (/= q) s ++ [q] where q = '"' diff --git a/src/Propellor/Property/DnsSec.hs b/src/Propellor/Property/DnsSec.hs index e4a8cad9..f39fcb25 100644 --- a/src/Propellor/Property/DnsSec.hs +++ b/src/Propellor/Property/DnsSec.hs @@ -41,6 +41,7 @@ zoneSigned :: Domain -> FilePath -> RevertableProperty zoneSigned domain zonefile = RevertableProperty setup cleanup where setup = check needupdate (forceZoneSigned domain zonefile) + `requires` includePubKeys domain zonefile `requires` toProp (keysInstalled domain) cleanup = combineProperties ("removed signed zone for " ++ domain) @@ -65,6 +66,12 @@ zoneSigned domain zonefile = RevertableProperty setup cleanup t2 <- getModificationTime f return (t2 >= t1) +includePubKeys :: Domain -> FilePath -> Property +includePubKeys domain zonefile = File.containsLines zonefile $ + map mkinclude [PubKSK, PubZSK] + where + mkinclude k = "$INCLUDE " ++ keyFn domain k + forceZoneSigned :: Domain -> FilePath -> Property forceZoneSigned domain zonefile = property ("zone signed for " ++ domain) $ liftIO $ do salt <- take 16 <$> saltSha1 @@ -95,8 +102,11 @@ saltSha1 = readProcess "sh" -- | The file used for a given key. keyFn :: Domain -> DnsSecKey -> FilePath -keyFn domain k = "/etc/bind/propellor/dnssec" - "K" ++ domain ++ "." ++ show k ++ keyExt k +keyFn domain k = "/etc/bind/propellor/dnssec" concat + [ "K" ++ domain ++ "." + , if isZoneSigningKey k then "ZSK" else "KSK" + , keyExt k + ] -- | These are the extensions that dnssec-keygen looks for. keyExt :: DnsSecKey -> String diff --git a/src/Propellor/Types/Dns.hs b/src/Propellor/Types/Dns.hs index 2fbf51e5..5e9666d8 100644 --- a/src/Propellor/Types/Dns.hs +++ b/src/Propellor/Types/Dns.hs @@ -62,7 +62,6 @@ data Record | NS BindDomain | TXT String | SRV Word16 Word16 Word16 BindDomain - | INCLUDE FilePath deriving (Read, Show, Eq, Ord) getIPAddr :: Record -> Maybe IPAddr -- cgit v1.3-2-g0d8e From bb7b8e789104a77b12030df5fe508afbe0eac2a5 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 4 Jan 2015 14:20:22 -0400 Subject: add $INCLUDE of pubkeys before zone file is written, to avoid pogoing --- src/Propellor/Info.hs | 1 + src/Propellor/Property/Dns.hs | 22 ++++++++++++++++------ src/Propellor/Property/DnsSec.hs | 7 ------- src/Propellor/Types/Dns.hs | 1 + 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'src/Propellor/Info.hs') diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs index 0437f8ec..3af3fc15 100644 --- a/src/Propellor/Info.hs +++ b/src/Propellor/Info.hs @@ -64,6 +64,7 @@ addDNS r = pureInfoProperty (rdesc r) $ mempty { _dns = S.singleton r } rdesc (NS d) = unwords ["NS", ddesc d] rdesc (TXT s) = unwords ["TXT", s] rdesc (SRV x y z d) = unwords ["SRV", show x, show y, show z, ddesc d] + rdesc (INCLUDE f) = unwords ["$INCLUDE", f] ddesc (AbsDomain domain) = domain ddesc (RelDomain domain) = domain diff --git a/src/Propellor/Property/Dns.hs b/src/Propellor/Property/Dns.hs index c5a4efa9..e9c7c769 100644 --- a/src/Propellor/Property/Dns.hs +++ b/src/Propellor/Property/Dns.hs @@ -133,7 +133,7 @@ signedPrimary recurrance hosts domain soa rs = RevertableProperty setup cleanup -- TODO enable dnssec options. -- dnssec-enable yes; dnssec-validation yes; dnssec-lookaside auto; setup = combineProperties ("dns primary for " ++ domain ++ " (signed)") - [ setupPrimary zonefile signedZoneFile hosts domain soa rs + [ setupPrimary zonefile signedZoneFile hosts domain soa rs' , toProp (zoneSigned domain zonefile) ] `onChange` Service.reloaded "bind9" @@ -142,6 +142,10 @@ signedPrimary recurrance hosts domain soa rs = RevertableProperty setup cleanup `onChange` toProp (revert (zoneSigned domain zonefile)) `onChange` Service.reloaded "bind9" + -- Include the public keys into the zone file. + rs' = include PubKSK : include PubZSK : rs + include k = (RootDomain, INCLUDE (keyFn domain k)) + -- Put DNSSEC zone files in a different directory than is used for -- the regular ones. This allows 'primary' to be reverted and -- 'signedPrimary' enabled, without the reverted property stomping @@ -267,6 +271,7 @@ rField (MX _ _) = "MX" rField (NS _) = "NS" rField (TXT _) = "TXT" rField (SRV _ _ _ _) = "SRV" +rField (INCLUDE _) = "$INCLUDE" rValue :: Record -> String rValue (Address (IPv4 addr)) = addr @@ -280,6 +285,7 @@ rValue (SRV priority weight port target) = unwords , show port , dValue target ] +rValue (INCLUDE f) = f rValue (TXT s) = [q] ++ filter (/= q) s ++ [q] where q = '"' @@ -345,12 +351,16 @@ genZoneFile (Zone zdomain soa rs) = unlines $ header = com $ "BIND zone file for " ++ zdomain ++ ". Generated by propellor, do not edit." genRecord :: Domain -> (BindDomain, Record) -> String +genRecord _ (_, record@(INCLUDE _)) = intercalate "\t" + [ rField record + , rValue record + ] genRecord zdomain (domain, record) = intercalate "\t" - [ domainHost zdomain domain - , "IN" - , rField record - , rValue record - ] + [ domainHost zdomain domain + , "IN" + , rField record + , rValue record + ] genSOA :: SOA -> [String] genSOA soa = diff --git a/src/Propellor/Property/DnsSec.hs b/src/Propellor/Property/DnsSec.hs index 37eea09c..b7557006 100644 --- a/src/Propellor/Property/DnsSec.hs +++ b/src/Propellor/Property/DnsSec.hs @@ -41,7 +41,6 @@ zoneSigned :: Domain -> FilePath -> RevertableProperty zoneSigned domain zonefile = RevertableProperty setup cleanup where setup = check needupdate (forceZoneSigned domain zonefile) - `requires` includePubKeys domain zonefile `requires` toProp (keysInstalled domain) cleanup = combineProperties ("removed signed zone for " ++ domain) @@ -66,12 +65,6 @@ zoneSigned domain zonefile = RevertableProperty setup cleanup t2 <- getModificationTime f return (t2 >= t1) -includePubKeys :: Domain -> FilePath -> Property -includePubKeys domain zonefile = File.containsLines zonefile $ - map mkinclude [PubKSK, PubZSK] - where - mkinclude k = "$INCLUDE " ++ keyFn domain k - forceZoneSigned :: Domain -> FilePath -> Property forceZoneSigned domain zonefile = property ("zone signed for " ++ domain) $ liftIO $ do salt <- take 16 <$> saltSha1 diff --git a/src/Propellor/Types/Dns.hs b/src/Propellor/Types/Dns.hs index 5e9666d8..2fbf51e5 100644 --- a/src/Propellor/Types/Dns.hs +++ b/src/Propellor/Types/Dns.hs @@ -62,6 +62,7 @@ data Record | NS BindDomain | TXT String | SRV Word16 Word16 Word16 BindDomain + | INCLUDE FilePath deriving (Read, Show, Eq, Ord) getIPAddr :: Record -> Maybe IPAddr -- cgit v1.3-2-g0d8e From 52664e622084b2986bc123f9725a0243a6794ace Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 4 Jan 2015 15:36:10 -0400 Subject: sshPubKey is renamed to Ssh.pubKey --- config-joey.hs | 8 ++++---- debian/changelog | 3 ++- propellor.cabal | 2 +- src/Propellor/Engine.hs | 2 +- src/Propellor/Info.hs | 7 ------- src/Propellor/Property/Ssh.hs | 19 +++++++++++++++---- 6 files changed, 23 insertions(+), 18 deletions(-) (limited to 'src/Propellor/Info.hs') diff --git a/config-joey.hs b/config-joey.hs index 8cfb9250..dbf3196b 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -278,7 +278,7 @@ elephant = standardSystem "elephant.kitenet.net" Unstable "amd64" & Systemd.installed & Systemd.persistentJournal & Ssh.hostKeys hostContext - & sshPubKey "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAJkoPRhUGT8EId6m37uBdYEtq42VNwslKnc9mmO+89ody066q6seHKeFY6ImfwjcyIjM30RTzEwftuVNQnbEB0=" + & Ssh.pubKey "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAJkoPRhUGT8EId6m37uBdYEtq42VNwslKnc9mmO+89ody066q6seHKeFY6ImfwjcyIjM30RTzEwftuVNQnbEB0=" & Ssh.keyImported SshRsa "joey" hostContext & Apt.serviceInstalledRunning "swapspace" @@ -459,9 +459,9 @@ myDnsPrimary dnssec domain extras = (if dnssec then Dns.signedPrimary (Weekly No monsters :: [Host] -- Systems I don't manage with propellor, monsters = -- but do want to track their public keys etc. [ host "usw-s002.rsync.net" - & sshPubKey "ssh-dss AAAAB3NzaC1kc3MAAAEBAI6ZsoW8a+Zl6NqUf9a4xXSMcV1akJHDEKKBzlI2YZo9gb9YoCf5p9oby8THUSgfh4kse7LJeY7Nb64NR6Y/X7I2/QzbE1HGGl5mMwB6LeUcJ74T3TQAlNEZkGt/MOIVLolJHk049hC09zLpkUDtX8K0t1yaCirC9SxDGLTCLEhvU9+vVdVrdQlKZ9wpLUNbdAzvbra+O/IVvExxDZ9WCHrnfNA8ddVZIGEWMqsoNgiuCxiXpi8qL+noghsSQNFTXwo7W2Vp9zj1JkCt3GtSz5IzEpARQaXEAWNEM0n1nJ686YUOhou64iRM8bPC1lp3QXvvZNgj3m+QHhIempx+de8AAAAVAKB5vUDaZOg14gRn7Bp81ja/ik+RAAABACPH/bPbW912x1NxNiikzGR6clLh+bLpIp8Qie3J7DwOr8oC1QOKjNDK+UgQ7mDQEgr4nGjNKSvpDi4c1QCw4sbLqQgx1y2VhT0SmUPHf5NQFldRQyR/jcevSSwOBxszz3aq9AwHiv9OWaO3XY18suXPouiuPTpIcZwc2BLDNHFnDURQeGEtmgqj6gZLIkTY0iw7q9Tj5FOyl4AkvEJC5B4CSzaWgey93Wqn1Imt7KI8+H9lApMKziVL1q+K7xAuNkGmx5YOSNlE6rKAPtsIPHZGxR7dch0GURv2jhh0NQYvBRn3ukCjuIO5gx56HLgilq59/o50zZ4NcT7iASF76TcAAAEAC6YxX7rrs8pp13W4YGiJHwFvIO1yXLGOdqu66JM0plO4J1ItV1AQcazOXLiliny3p2/W+wXZZKd5HIRt52YafCA8YNyMk/sF7JcTR4d4z9CfKaAxh0UpzKiAk+0j/Wu3iPoTOsyt7N0j1+dIyrFodY2sKKuBMT4TQ0yqQpbC+IDQv2i1IlZAPneYGfd5MIGygs2QMfaMQ1jWAKJvEO0vstZ7GB6nDAcg4in3ZiBHtomx3PL5w+zg48S4Ed69BiFXLZ1f6MnjpUOP75pD4MP6toS0rgK9b93xCrEQLgm4oD/7TCHHBo2xR7wwcsN2OddtwWsEM2QgOkt/jdCAoVCqwQ==" + & Ssh.pubKey "ssh-dss AAAAB3NzaC1kc3MAAAEBAI6ZsoW8a+Zl6NqUf9a4xXSMcV1akJHDEKKBzlI2YZo9gb9YoCf5p9oby8THUSgfh4kse7LJeY7Nb64NR6Y/X7I2/QzbE1HGGl5mMwB6LeUcJ74T3TQAlNEZkGt/MOIVLolJHk049hC09zLpkUDtX8K0t1yaCirC9SxDGLTCLEhvU9+vVdVrdQlKZ9wpLUNbdAzvbra+O/IVvExxDZ9WCHrnfNA8ddVZIGEWMqsoNgiuCxiXpi8qL+noghsSQNFTXwo7W2Vp9zj1JkCt3GtSz5IzEpARQaXEAWNEM0n1nJ686YUOhou64iRM8bPC1lp3QXvvZNgj3m+QHhIempx+de8AAAAVAKB5vUDaZOg14gRn7Bp81ja/ik+RAAABACPH/bPbW912x1NxNiikzGR6clLh+bLpIp8Qie3J7DwOr8oC1QOKjNDK+UgQ7mDQEgr4nGjNKSvpDi4c1QCw4sbLqQgx1y2VhT0SmUPHf5NQFldRQyR/jcevSSwOBxszz3aq9AwHiv9OWaO3XY18suXPouiuPTpIcZwc2BLDNHFnDURQeGEtmgqj6gZLIkTY0iw7q9Tj5FOyl4AkvEJC5B4CSzaWgey93Wqn1Imt7KI8+H9lApMKziVL1q+K7xAuNkGmx5YOSNlE6rKAPtsIPHZGxR7dch0GURv2jhh0NQYvBRn3ukCjuIO5gx56HLgilq59/o50zZ4NcT7iASF76TcAAAEAC6YxX7rrs8pp13W4YGiJHwFvIO1yXLGOdqu66JM0plO4J1ItV1AQcazOXLiliny3p2/W+wXZZKd5HIRt52YafCA8YNyMk/sF7JcTR4d4z9CfKaAxh0UpzKiAk+0j/Wu3iPoTOsyt7N0j1+dIyrFodY2sKKuBMT4TQ0yqQpbC+IDQv2i1IlZAPneYGfd5MIGygs2QMfaMQ1jWAKJvEO0vstZ7GB6nDAcg4in3ZiBHtomx3PL5w+zg48S4Ed69BiFXLZ1f6MnjpUOP75pD4MP6toS0rgK9b93xCrEQLgm4oD/7TCHHBo2xR7wwcsN2OddtwWsEM2QgOkt/jdCAoVCqwQ==" , host "github.com" - & sshPubKey "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" + & Ssh.pubKey "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" , host "ns6.gandi.net" & ipv4 "217.70.177.40" , host "turtle.kitenet.net" @@ -469,7 +469,7 @@ monsters = -- but do want to track their public keys etc. & ipv6 "2001:4978:f:2d9::2" & alias "backup.kitenet.net" & alias "usbackup.kitenet.net" - & sshPubKey "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAokMXQiX/NZjA1UbhMdgAscnS5dsmy+Q7bWrQ6tsTZ/o+6N/T5cbjoBHOdpypXJI3y/PiJTDJaQtXIhLa8gFg/EvxMnMz/KG9skADW1361JmfCc4BxicQIO2IOOe6eilPr+YsnOwiHwL0vpUnuty39cppuMWVD25GzxXlS6KQsLCvXLzxLLuNnGC43UAM0q4UwQxDtAZEK1dH2o3HMWhgMP2qEQupc24dbhpO3ecxh2C9678a3oGDuDuNf7mLp3s7ptj5qF3onitpJ82U5o7VajaHoygMaSRFeWxP2c13eM57j3bLdLwxVXFhePcKXARu1iuFTLS5uUf3hN6MkQcOGw==" + & Ssh.pubKey "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAokMXQiX/NZjA1UbhMdgAscnS5dsmy+Q7bWrQ6tsTZ/o+6N/T5cbjoBHOdpypXJI3y/PiJTDJaQtXIhLa8gFg/EvxMnMz/KG9skADW1361JmfCc4BxicQIO2IOOe6eilPr+YsnOwiHwL0vpUnuty39cppuMWVD25GzxXlS6KQsLCvXLzxLLuNnGC43UAM0q4UwQxDtAZEK1dH2o3HMWhgMP2qEQupc24dbhpO3ecxh2C9678a3oGDuDuNf7mLp3s7ptj5qF3onitpJ82U5o7VajaHoygMaSRFeWxP2c13eM57j3bLdLwxVXFhePcKXARu1iuFTLS5uUf3hN6MkQcOGw==" , host "old.kitenet.net" & ipv4 "80.68.85.49" , host "mouse.kitenet.net" diff --git a/debian/changelog b/debian/changelog index 79109a18..dee084ec 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -propellor (1.2.3) UNRELEASED; urgency=medium +propellor (1.3.0) UNRELEASED; urgency=medium * --spin checks if the DNS matches any configured IP address property of the host, and if not, sshes to the host by IP address. @@ -6,6 +6,7 @@ propellor (1.2.3) UNRELEASED; urgency=medium that docker exec doesn't enter a chroot. * Update intermediary propellor in --spin --via * Added support for DNSSEC. + * sshPubKey is renamed to Ssh.pubKey * Fix build with process 1.2.1.0. -- Joey Hess Thu, 01 Jan 2015 13:27:23 -0400 diff --git a/propellor.cabal b/propellor.cabal index 09cb19cf..a239bf4a 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -1,5 +1,5 @@ Name: propellor -Version: 1.2.2 +Version: 1.3.0 Cabal-Version: >= 1.6 License: BSD3 Maintainer: Joey Hess diff --git a/src/Propellor/Engine.hs b/src/Propellor/Engine.hs index f29ce1a9..667f6bfb 100644 --- a/src/Propellor/Engine.hs +++ b/src/Propellor/Engine.hs @@ -77,7 +77,7 @@ ensureProperties ps = ensure ps NoChange -- | Lifts an action into a different host. -- --- For example, `fromHost hosts "otherhost" getSshPubKey` +-- For example, `fromHost hosts "otherhost" getPubKey` fromHost :: [Host] -> HostName -> Propellor a -> Propellor (Maybe a) fromHost l hn getter = case findHost l hn of Nothing -> return Nothing diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs index 3af3fc15..b7ca81b5 100644 --- a/src/Propellor/Info.hs +++ b/src/Propellor/Info.hs @@ -70,13 +70,6 @@ addDNS r = pureInfoProperty (rdesc r) $ mempty { _dns = S.singleton r } ddesc (RelDomain domain) = domain ddesc RootDomain = "@" -sshPubKey :: String -> Property -sshPubKey k = pureInfoProperty ("ssh pubkey known") $ - mempty { _sshPubKey = Val k } - -getSshPubKey :: Propellor (Maybe String) -getSshPubKey = askInfo _sshPubKey - hostMap :: [Host] -> M.Map HostName Host hostMap l = M.fromList $ zip (map hostName l) l diff --git a/src/Propellor/Property/Ssh.hs b/src/Propellor/Property/Ssh.hs index 695b67cb..8b03d8a9 100644 --- a/src/Propellor/Property/Ssh.hs +++ b/src/Propellor/Property/Ssh.hs @@ -6,6 +6,7 @@ module Propellor.Property.Ssh ( authorizedKey, restarted, randomHostKeys, + pubKey, hostKeys, hostKey, keyImported, @@ -79,7 +80,16 @@ randomHostKeys = flagFile prop "/etc/ssh/.unique_host_keys" ensureProperty $ scriptProperty [ "DPKG_MAINTSCRIPT_NAME=postinst DPKG_MAINTSCRIPT_PACKAGE=openssh-server /var/lib/dpkg/info/openssh-server.postinst configure" ] --- | Sets all types of ssh host keys from the privdata. +-- | When a host has a well-known public key, this can be used to indicate +-- what the key is. It does not cause the key to be installed. +pubKey :: String -> Property +pubKey k = pureInfoProperty ("ssh pubkey known") $ + mempty { _sshPubKey = Val k } + +getPubKey :: Propellor (Maybe String) +getPubKey = askInfo _sshPubKey + +-- | Installs all commonly used types of ssh host keys from the privdata. hostKeys :: IsContext c => c -> Property hostKeys ctx = propertyList "known ssh host keys" [ hostKey SshDsa ctx @@ -87,7 +97,7 @@ hostKeys ctx = propertyList "known ssh host keys" , hostKey SshEcdsa ctx ] --- | Sets a single ssh host key from the privdata. +-- | Installs a single ssh host key from the privdata. hostKey :: IsContext c => SshKeyType -> c -> Property hostKey keytype context = combineProperties desc [ installkey (keysrc ".pub" (SshPubKey keytype "")) (install writeFile ".pub") @@ -140,10 +150,11 @@ fromKeyType SshDsa = "dsa" fromKeyType SshEcdsa = "ecdsa" fromKeyType SshEd25519 = "ed25519" --- | Puts some host's ssh public key into the known_hosts file for a user. +-- | Puts some host's ssh public key, as set using 'pubKey', +-- into the known_hosts file for a user. knownHost :: [Host] -> HostName -> UserName -> Property knownHost hosts hn user = property desc $ - go =<< fromHost hosts hn getSshPubKey + go =<< fromHost hosts hn getPubKey where desc = user ++ " knows ssh key for " ++ hn go (Just (Just k)) = do -- cgit v1.3-2-g0d8e