diff options
| author | Joey Hess <joey@kitenet.net> | 2014-04-14 02:24:55 -0400 |
|---|---|---|
| committer | Joey Hess <joey@kitenet.net> | 2014-04-14 02:24:55 -0400 |
| commit | 18d33cd39100981c5c6e5f3c1c0f88d336287f29 (patch) | |
| tree | 7863ddbdf7b3255d42b7354c0d8b21184f452241 /Propellor/Property/Ssh.hs | |
| parent | 9e9d0f1d410f806b546abed6055b25ac81f7042e (diff) | |
| parent | 3a45bfa1a2ae855cac0653e92f897c3d151f038d (diff) | |
Merge branch 'joeyconfig'
Diffstat (limited to 'Propellor/Property/Ssh.hs')
| -rw-r--r-- | Propellor/Property/Ssh.hs | 105 |
1 files changed, 97 insertions, 8 deletions
diff --git a/Propellor/Property/Ssh.hs b/Propellor/Property/Ssh.hs index 59845f8f..b13a12bf 100644 --- a/Propellor/Property/Ssh.hs +++ b/Propellor/Property/Ssh.hs @@ -4,13 +4,20 @@ module Propellor.Property.Ssh ( passwordAuthentication, hasAuthorizedKeys, restartSshd, - uniqueHostKeys + randomHostKeys, + hostKey, + keyImported, + knownHost, + authorizedKeys ) where import Propellor import qualified Propellor.Property.File as File import Propellor.Property.User import Utility.SafeCommand +import Utility.FileMode + +import System.PosixCompat sshBool :: Bool -> String sshBool True = "yes" @@ -35,12 +42,20 @@ permitRootLogin = setSshdConfig "PermitRootLogin" passwordAuthentication :: Bool -> Property passwordAuthentication = setSshdConfig "PasswordAuthentication" +dotDir :: UserName -> IO FilePath +dotDir user = do + h <- homedir user + return $ h </> ".ssh" + +dotFile :: FilePath -> UserName -> IO FilePath +dotFile f user = do + d <- dotDir user + return $ d </> f + hasAuthorizedKeys :: UserName -> IO Bool -hasAuthorizedKeys = go <=< homedir +hasAuthorizedKeys = go <=< dotFile "authorized_keys" where - go Nothing = return False - go (Just home) = not . null <$> catchDefaultIO "" - (readFile $ home </> ".ssh" </> "authorized_keys") + go f = not . null <$> catchDefaultIO "" (readFile f) restartSshd :: Property restartSshd = cmdProperty "service" ["ssh", "restart"] @@ -48,11 +63,11 @@ restartSshd = cmdProperty "service" ["ssh", "restart"] -- | Blows away existing host keys and make new ones. -- Useful for systems installed from an image that might reuse host keys. -- A flag file is used to only ever do this once. -uniqueHostKeys :: Property -uniqueHostKeys = flagFile prop "/etc/ssh/.unique_host_keys" +randomHostKeys :: Property +randomHostKeys = flagFile prop "/etc/ssh/.unique_host_keys" `onChange` restartSshd where - prop = Property "ssh unique host keys" $ do + prop = Property "ssh random host keys" $ do void $ liftIO $ boolSystem "sh" [ Param "-c" , Param "rm -f /etc/ssh/ssh_host_*" @@ -60,3 +75,77 @@ uniqueHostKeys = flagFile prop "/etc/ssh/.unique_host_keys" ensureProperty $ cmdProperty "/var/lib/dpkg/info/openssh-server.postinst" ["configure"] + +-- | Sets ssh host keys from the site's PrivData. +-- +-- (Uses a null username for host keys.) +hostKey :: SshKeyType -> Property +hostKey keytype = combineProperties desc + [ Property desc (install writeFile (SshPubKey keytype "") ".pub") + , Property desc (install writeFileProtected (SshPrivKey keytype "") "") + ] + `onChange` restartSshd + where + desc = "known ssh host key (" ++ fromKeyType keytype ++ ")" + install writer p ext = withPrivData p $ \key -> do + let f = "/etc/ssh/ssh_host_" ++ fromKeyType keytype ++ "_key" ++ ext + s <- liftIO $ readFileStrict f + if s == key + then noChange + else makeChange $ writer f key + +-- | Sets up a user with a ssh private key and public key pair +-- from the site's PrivData. +keyImported :: SshKeyType -> UserName -> Property +keyImported keytype user = combineProperties desc + [ Property desc (install writeFile (SshPubKey keytype user) ".pub") + , Property desc (install writeFileProtected (SshPrivKey keytype user) "") + ] + where + desc = user ++ " has ssh key (" ++ fromKeyType keytype ++ ")" + install writer p ext = do + f <- liftIO $ keyfile ext + ifM (liftIO $ doesFileExist f) + ( noChange + , ensureProperty $ combineProperties desc + [ Property desc $ + withPrivData p $ \key -> makeChange $ + writer f key + , File.ownerGroup f user user + ] + ) + keyfile ext = do + home <- homeDirectory <$> getUserEntryForName user + return $ home </> ".ssh" </> "id_" ++ fromKeyType keytype ++ ext + +fromKeyType :: SshKeyType -> String +fromKeyType SshRsa = "rsa" +fromKeyType SshDsa = "dsa" +fromKeyType SshEcdsa = "ecdsa" + +-- | Puts some host's ssh public key into the known_hosts file for a user. +knownHost :: [Host] -> HostName -> UserName -> Property +knownHost hosts hn user = Property desc $ + go =<< fromHost hosts hn getSshPubKey + where + desc = user ++ " knows ssh key for " ++ hn + go (Just (Just k)) = do + f <- liftIO $ dotFile "known_hosts" user + ensureProperty $ combineProperties desc + [ File.dirExists (takeDirectory f) + , f `File.containsLine` (hn ++ " " ++ k) + , File.ownerGroup f user user + ] + go _ = do + warningMessage $ "no configred sshPubKey for " ++ hn + return FailedChange + +-- | Makes a user have authorized_keys from the PrivData +authorizedKeys :: UserName -> Property +authorizedKeys user = Property (user ++ " has authorized_keys") $ + withPrivData (SshAuthorizedKeys user) $ \v -> do + f <- liftIO $ dotFile "authorized_keys" user + liftIO $ do + createDirectoryIfMissing True (takeDirectory f) + writeFileProtected f v + ensureProperty $ File.ownerGroup f user user |
