propellor spin

This commit is contained in:
Joey Hess 2014-11-11 12:58:53 -04:00
parent f559ccaf73
commit 84304821be
Failed to extract signature
6 changed files with 119 additions and 81 deletions

View File

@ -113,8 +113,9 @@ Library
Other-Modules: Other-Modules:
Propellor.Types.Info Propellor.Types.Info
Propellor.CmdLine Propellor.CmdLine
Propellor.Keyring Propellor.Gpg
Propellor.SimpleSh Propellor.SimpleSh
Propellor.PrivData.Paths
Propellor.Property.Docker.Shim Propellor.Property.Docker.Shim
Utility.Applicative Utility.Applicative
Utility.Data Utility.Data

View File

@ -13,7 +13,8 @@ import System.Posix.IO
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
import Propellor import Propellor
import Propellor.Keyring import Propellor.PrivData.Paths
import Propellor.Gpg
import qualified Propellor.Property.Docker as Docker import qualified Propellor.Property.Docker as Docker
import qualified Propellor.Property.Docker.Shim as DockerShim import qualified Propellor.Property.Docker.Shim as DockerShim
import Utility.FileMode import Utility.FileMode

101
src/Propellor/Gpg.hs Normal file
View File

@ -0,0 +1,101 @@
module Propellor.Gpg where
import Control.Applicative
import System.IO
import System.FilePath
import System.Directory
import Data.Maybe
import Data.List.Utils
import Propellor.PrivData.Paths
import Utility.SafeCommand
import Utility.Process
import Utility.Monad
import Utility.Misc
import Utility.Tmp
type KeyId = String
keyring :: FilePath
keyring = privDataDir </> "keyring.gpg"
listPubKeys :: IO [KeyId]
listPubKeys = parse . lines <$> readProcess "gpg" listopts
where
listopts = useKeyringOpts ++ ["--with-colons", "--list-public-keys"]
parse = mapMaybe (keyIdField . split ":")
keyIdField ("pub":_:_:_:f:_) = Just f
keyIdField _ = Nothing
useKeyringOpts :: [String]
useKeyringOpts =
[ "--options"
, "/dev/null"
, "--no-default-keyring"
, "--keyring", keyring
]
addKey :: KeyId -> IO ()
addKey keyid = exitBool =<< allM id
[ gpg, gitadd keyring, reencryptprivdata, gitconfig, gitcommit ]
where
gpg = do
createDirectoryIfMissing True privDataDir
boolSystem "sh"
[ Param "-c"
, Param $ "gpg --export " ++ keyid ++ " | gpg " ++
unwords (useKeyringOpts ++ ["--import"])
]
reencryptprivdata = ifM (doesFileExist privDataFile)
( do
gpgEncrypt privDataFile =<< gpgDecrypt privDataFile
gitadd privDataFile
, return True
)
gitadd f = boolSystem "git"
[ Param "add"
, File f
]
gitconfig = boolSystem "git"
[ Param "config"
, Param "user.signingkey"
, Param keyid
]
gitcommit = gitCommit
[ File keyring
, Param "-m"
, Param "propellor addkey"
]
{- Automatically sign the commit if there'a a keyring. -}
gitCommit :: [CommandParam] -> IO Bool
gitCommit ps = do
k <- doesFileExist keyring
boolSystem "git" $ catMaybes $
[ Just (Param "commit")
, if k then Just (Param "--gpg-sign") else Nothing
] ++ map Just ps
gpgDecrypt :: FilePath -> IO String
gpgDecrypt f = ifM (doesFileExist f)
( readProcess "gpg" ["--decrypt", f]
, return ""
)
gpgEncrypt :: FilePath -> String -> IO ()
gpgEncrypt f s = do
keyids <- listPubKeys
let opts =
[ "--default-recipient-self"
, "--armor"
, "--encrypt"
] ++ concatMap (\k -> ["--recipient", k]) keyids
encrypted <- writeReadProcessEnv "gpg" opts
Nothing
(Just $ flip hPutStr s)
Nothing
viaTmp writeFile f encrypted

View File

@ -1,50 +0,0 @@
module Propellor.Keyring where
import Propellor
import Utility.SafeCommand
keyring :: FilePath
keyring = privDataDir </> "keyring.gpg"
addKey :: String -> IO ()
addKey keyid = exitBool =<< allM id [ gpg, gitadd, gitconfig, gitcommit ]
where
gpg = do
createDirectoryIfMissing True privDataDir
boolSystem "sh"
[ Param "-c"
, Param $ "gpg --export " ++ keyid ++ " | gpg " ++
unwords (gpgopts ++ ["--import"])
]
gitadd = boolSystem "git"
[ Param "add"
, File keyring
]
gitconfig = boolSystem "git"
[ Param "config"
, Param "user.signingkey"
, Param keyid
]
gitcommit = gitCommit
[ File keyring
, Param "-m"
, Param "propellor addkey"
]
gpgopts =
[ "--options"
, "/dev/null"
, "--no-default-keyring"
, "--keyring", keyring
]
{- Automatically sign the commit if there'a a keyring. -}
gitCommit :: [CommandParam] -> IO Bool
gitCommit ps = do
k <- doesFileExist keyring
boolSystem "git" $ catMaybes $
[ Just (Param "commit")
, if k then Just (Param "--gpg-sign") else Nothing
] ++ map Just ps

View File

@ -3,7 +3,6 @@
module Propellor.PrivData where module Propellor.PrivData where
import Control.Applicative import Control.Applicative
import System.FilePath
import System.IO import System.IO
import System.Directory import System.Directory
import Data.Maybe import Data.Maybe
@ -19,10 +18,11 @@ import Propellor.Types
import Propellor.Types.Info import Propellor.Types.Info
import Propellor.Message import Propellor.Message
import Propellor.Info import Propellor.Info
import Propellor.Gpg
import Propellor.PrivData.Paths
import Utility.Monad import Utility.Monad
import Utility.PartialPrelude import Utility.PartialPrelude
import Utility.Exception import Utility.Exception
import Utility.Process
import Utility.Tmp import Utility.Tmp
import Utility.SafeCommand import Utility.SafeCommand
import Utility.Misc import Utility.Misc
@ -146,30 +146,3 @@ decryptPrivData = fromMaybe M.empty . readish <$> gpgDecrypt privDataFile
makePrivDataDir :: IO () makePrivDataDir :: IO ()
makePrivDataDir = createDirectoryIfMissing False privDataDir makePrivDataDir = createDirectoryIfMissing False privDataDir
privDataDir :: FilePath
privDataDir = "privdata"
privDataFile :: FilePath
privDataFile = privDataDir </> "privdata.gpg"
privDataLocal :: FilePath
privDataLocal = privDataDir </> "local"
gpgDecrypt :: FilePath -> IO String
gpgDecrypt f = ifM (doesFileExist f)
( readProcess "gpg" ["--decrypt", f]
, return ""
)
gpgEncrypt :: FilePath -> String -> IO ()
gpgEncrypt f s = do
encrypted <- writeReadProcessEnv "gpg"
[ "--default-recipient-self"
, "--armor"
, "--encrypt"
]
Nothing
(Just $ flip hPutStr s)
Nothing
viaTmp writeFile f encrypted

View File

@ -0,0 +1,12 @@
module Propellor.PrivData.Paths where
import System.FilePath
privDataDir :: FilePath
privDataDir = "privdata"
privDataFile :: FilePath
privDataFile = privDataDir </> "privdata.gpg"
privDataLocal :: FilePath
privDataLocal = privDataDir </> "local"