module Propellor.Property.Gpg where
import Propellor.Base
import qualified Propellor.Property.Apt as Apt
import System.PosixCompat
installed :: Property DebianLike
installed = Apt.installed ["gnupg"]
newtype GpgKeyId = GpgKeyId { getGpgKeyId :: String }
data GpgKeyType = GpgPubKey | GpgPrivKey
keyImported :: GpgKeyId -> User -> Property (HasInfo + DebianLike)
keyImported key@(GpgKeyId keyid) user@(User u) = prop
`requires` installed
where
desc = u ++ " has gpg key " ++ show keyid
prop :: Property (HasInfo + DebianLike)
prop = withPrivData src (Context keyid) $ \getkey ->
property desc $ getkey $ \key' -> do
let keylines = privDataLines key'
ifM (liftIO $ hasGpgKey (parse keylines))
( return NoChange
, makeChange $ withHandle StdinHandle createProcessSuccess
(proc "su" ["--login", "-c", "gpg --import", u]) $ \h -> do
hPutStr h (unlines keylines)
hClose h
)
src = PrivDataSource GpgKey "Either a gpg public key, exported with gpg --export -a, or a gpg private key, exported with gpg --export-secret-key -a"
parse ("-----BEGIN PGP PUBLIC KEY BLOCK-----":_) = Just GpgPubKey
parse ("-----BEGIN PGP PRIVATE KEY BLOCK-----":_) = Just GpgPrivKey
parse _ = Nothing
hasGpgKey Nothing = error $ "Failed to run gpg parser on armored key " ++ keyid
hasGpgKey (Just GpgPubKey) = hasPubKey key user
hasGpgKey (Just GpgPrivKey) = hasPrivKey key user
hasPrivKey :: GpgKeyId -> User -> IO Bool
hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $
snd <$> processTranscript "su" ["--login", "-c", "gpg --list-secret-keys " ++ shellEscape keyid, u] Nothing
hasPubKey :: GpgKeyId -> User -> IO Bool
hasPubKey (GpgKeyId keyid) (User u) = catchBoolIO $
snd <$> processTranscript "su" ["--login", "-c", "gpg --list-public-keys " ++ shellEscape keyid, u] Nothing
dotDir :: User -> IO FilePath
dotDir (User u) = do
home <- homeDirectory <$> getUserEntryForName u
return $ home </> ".gnupg"