From e030dd833d57e2023f387a73b9d64fce4aa6145f Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Sun, 13 Dec 2015 23:08:56 +0100 Subject: Gpg: add hasPrivKey and hasPubKey (cherry picked from commit 7196b884e35ba907891c00d6e2840a36dce2214c) --- src/Propellor/Property/Gpg.hs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index a16df11d..59448bca 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -41,3 +41,17 @@ dotDir :: User -> IO FilePath dotDir (User u) = do home <- homeDirectory <$> getUserEntryForName u return $ home ".gnupg" + +hasPrivKey :: GpgKeyId -> User -> IO Bool +hasPrivKey (GpgKeyId keyid) (User u) = do + value <- catchMaybeIO $ readProcess "su" ["-c", "gpg --list-secret-keys " ++ keyid, u] + return $ case value of + Just _ -> True + _ -> False + +hasPubKey :: GpgKeyId -> User -> IO Bool +hasPubKey (GpgKeyId keyid) (User u) = do + value <- catchMaybeIO $ readProcess "su" ["-c", "gpg --list-public-keys " ++ keyid, u] + return $ case value of + Just _ -> True + _ -> False -- cgit v1.2.3 From f77badde96531d3723c633084dd82597214d0f38 Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Mon, 14 Dec 2015 09:24:12 +0100 Subject: Gpg: use isJust (cherry picked from commit 1bb2377598e447e81e20a0e1de1a5d466851d655) --- src/Propellor/Property/Gpg.hs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index 59448bca..34c077bb 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -45,13 +45,9 @@ dotDir (User u) = do hasPrivKey :: GpgKeyId -> User -> IO Bool hasPrivKey (GpgKeyId keyid) (User u) = do value <- catchMaybeIO $ readProcess "su" ["-c", "gpg --list-secret-keys " ++ keyid, u] - return $ case value of - Just _ -> True - _ -> False + return $ isJust value hasPubKey :: GpgKeyId -> User -> IO Bool hasPubKey (GpgKeyId keyid) (User u) = do value <- catchMaybeIO $ readProcess "su" ["-c", "gpg --list-public-keys " ++ keyid, u] - return $ case value of - Just _ -> True - _ -> False + return $ isJust value -- cgit v1.2.3 From 50da0a84568d12f7c072e2bea0cb3546e37af226 Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Mon, 14 Dec 2015 09:28:32 +0100 Subject: Gpg.keyImported: check if a pubKey is imported instead of using a flagfile (cherry picked from commit 9712d125a2c3e3c609b68d9958207c251ba005ac) --- src/Propellor/Property/Gpg.hs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index 34c077bb..0423806c 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -21,19 +21,16 @@ newtype GpgKeyId = GpgKeyId { getGpgKeyId :: 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. keyImported :: GpgKeyId -> User -> Property HasInfo -keyImported (GpgKeyId keyid) user@(User u) = flagFile' prop genflag +keyImported key@(GpgKeyId keyid) user@(User u) = check (not <$> hasPubKey key user) prop `requires` installed where desc = u ++ " has gpg key " ++ show keyid - genflag = do - d <- dotDir user - return $ d ".propellor-imported-keyid-" ++ keyid prop = withPrivData src (Context keyid) $ \getkey -> - property desc $ getkey $ \key -> makeChange $ + property desc $ getkey $ \key' -> makeChange $ withHandle StdinHandle createProcessSuccess (proc "su" ["-c", "gpg --import", u]) $ \h -> do fileEncoding h - hPutStr h (unlines (privDataLines key)) + hPutStr h (unlines (privDataLines key')) 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" -- cgit v1.2.3 From f3c5e20fa5b21f3317f63bbcc2d43d708d2ae736 Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Wed, 16 Dec 2015 15:18:19 +0100 Subject: Gpg: parse GpgKeyType in keyImported (cherry picked from commit cdd1e093118b5eeab7743be7e2ec959980716145) --- src/Propellor/Property/Gpg.hs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index 0423806c..dae6e5d7 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -12,6 +12,8 @@ installed = Apt.installed ["gnupg"] -- A numeric id, or a description of the key, in a form understood by gpg. newtype GpgKeyId = GpgKeyId { getGpgKeyId :: String } +data GpgKeyType = GpgPubKey | GpgPrivKey + -- | Sets up a user with a gpg key from the privdata. -- -- Note that if a secret key is exported using gpg -a --export-secret-key, @@ -21,19 +23,31 @@ newtype GpgKeyId = GpgKeyId { getGpgKeyId :: 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. keyImported :: GpgKeyId -> User -> Property HasInfo -keyImported key@(GpgKeyId keyid) user@(User u) = check (not <$> hasPubKey key user) prop +keyImported key@(GpgKeyId keyid) user@(User u) = prop `requires` installed where desc = u ++ " has gpg key " ++ show keyid prop = withPrivData src (Context keyid) $ \getkey -> - property desc $ getkey $ \key' -> makeChange $ - withHandle StdinHandle createProcessSuccess - (proc "su" ["-c", "gpg --import", u]) $ \h -> do - fileEncoding h - hPutStr h (unlines (privDataLines key')) - hClose h + property desc $ getkey $ \key' -> do + let keylines = privDataLines key' + ifM (liftIO $ hasGpgKey (parse keylines)) + (return NoChange + , makeChange $ withHandle StdinHandle createProcessSuccess + (proc "su" ["-c", "gpg --import", u]) $ \h -> do + fileEncoding h + 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 + dotDir :: User -> IO FilePath dotDir (User u) = do home <- homeDirectory <$> getUserEntryForName u -- cgit v1.2.3 From 05dafa48efaad859665902c11e179a7cbdd8f433 Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Wed, 16 Dec 2015 19:10:56 +0100 Subject: Gpg: use processTranscript in hasPrivKey and hasPubKey (cherry picked from commit 21ffe59d0368f5cfe45316b31d661077e372d512) --- src/Propellor/Property/Gpg.hs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index dae6e5d7..fe339297 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -54,11 +54,9 @@ dotDir (User u) = do return $ home ".gnupg" hasPrivKey :: GpgKeyId -> User -> IO Bool -hasPrivKey (GpgKeyId keyid) (User u) = do - value <- catchMaybeIO $ readProcess "su" ["-c", "gpg --list-secret-keys " ++ keyid, u] - return $ isJust value +hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $ + snd <$> processTranscript "su" ["-c", "gpg --list-secret-keys", keyid, u] Nothing hasPubKey :: GpgKeyId -> User -> IO Bool -hasPubKey (GpgKeyId keyid) (User u) = do - value <- catchMaybeIO $ readProcess "su" ["-c", "gpg --list-public-keys " ++ keyid, u] - return $ isJust value +hasPubKey (GpgKeyId keyid) (User u) = catchBoolIO $ + snd <$> processTranscript "su" ["-c", "gpg --list-public-keys", keyid, u] Nothing -- cgit v1.2.3 From 9b9bf6028275e54da2df24b7413a585d5c84b254 Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Wed, 16 Dec 2015 19:11:54 +0100 Subject: hlint (cherry picked from commit e2d86f812bd37de9cda7d4ecc0e5b84821f359c1) --- src/Propellor/Gpg.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Propellor/Gpg.hs b/src/Propellor/Gpg.hs index 960c70d3..949eb5b5 100644 --- a/src/Propellor/Gpg.hs +++ b/src/Propellor/Gpg.hs @@ -79,12 +79,12 @@ rmKey keyid = exitBool =<< allM (uncurry actionMessage) ] where rmkeyring = boolSystem "gpg" $ - (map Param useKeyringOpts) ++ + (map Param useKeyringOpts) ++ [ Param "--batch" , Param "--yes" , Param "--delete-key", Param keyid ] - + gitconfig = ifM ((==) (keyid++"\n", True) <$> processTranscript "git" ["config", "user.signingkey"] Nothing) ( boolSystem "git" [ Param "config" @@ -92,7 +92,7 @@ rmKey keyid = exitBool =<< allM (uncurry actionMessage) , Param "user.signingkey" ] , return True - ) + ) reencryptPrivData :: IO Bool reencryptPrivData = ifM (doesFileExist privDataFile) @@ -101,7 +101,7 @@ reencryptPrivData = ifM (doesFileExist privDataFile) gitAdd privDataFile , return True ) - + gitAdd :: FilePath -> IO Bool gitAdd f = boolSystem "git" [ Param "add" @@ -125,7 +125,7 @@ gpgSignParams ps = ifM (doesFileExist keyring) -- Automatically sign the commit if there'a a keyring. gitCommit :: Maybe String -> [CommandParam] -> IO Bool gitCommit msg ps = do - let ps' = Param "commit" : ps ++ + let ps' = Param "commit" : ps ++ maybe [] (\m -> [Param "-m", Param m]) msg ps'' <- gpgSignParams ps' if isNothing msg -- cgit v1.2.3 From 1bc9d8200b8fa97d97a79a002eb60339790fa259 Mon Sep 17 00:00:00 2001 From: Félix Sipma Date: Thu, 17 Dec 2015 10:18:53 +0100 Subject: Gpg: fix gpg parameters in hasPrivKey and hasPubKey (cherry picked from commit 04464ae17a7396d0cafffefc2880e68f40fc42ad) --- src/Propellor/Property/Gpg.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index fe339297..0f1c70ea 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -55,8 +55,8 @@ dotDir (User u) = do hasPrivKey :: GpgKeyId -> User -> IO Bool hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $ - snd <$> processTranscript "su" ["-c", "gpg --list-secret-keys", keyid, u] Nothing + snd <$> processTranscript "su" ["-c", "gpg --list-secret-keys " ++ shellEscape keyid, u] Nothing hasPubKey :: GpgKeyId -> User -> IO Bool hasPubKey (GpgKeyId keyid) (User u) = catchBoolIO $ - snd <$> processTranscript "su" ["-c", "gpg --list-public-keys", keyid, u] Nothing + snd <$> processTranscript "su" ["-c", "gpg --list-public-keys " ++ shellEscape keyid, u] Nothing -- cgit v1.2.3 From 4e4c7bb914779ded627bc28de116acd8b0867986 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 17 Dec 2015 13:29:54 -0400 Subject: minor tweak --- src/Propellor/Property/Gpg.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs index 0f1c70ea..bd710ca7 100644 --- a/src/Propellor/Property/Gpg.hs +++ b/src/Propellor/Property/Gpg.hs @@ -31,7 +31,7 @@ keyImported key@(GpgKeyId keyid) user@(User u) = prop property desc $ getkey $ \key' -> do let keylines = privDataLines key' ifM (liftIO $ hasGpgKey (parse keylines)) - (return NoChange + ( return NoChange , makeChange $ withHandle StdinHandle createProcessSuccess (proc "su" ["-c", "gpg --import", u]) $ \h -> do fileEncoding h @@ -48,11 +48,6 @@ keyImported key@(GpgKeyId keyid) user@(User u) = prop hasGpgKey (Just GpgPubKey) = hasPubKey key user hasGpgKey (Just GpgPrivKey) = hasPrivKey key user -dotDir :: User -> IO FilePath -dotDir (User u) = do - home <- homeDirectory <$> getUserEntryForName u - return $ home ".gnupg" - hasPrivKey :: GpgKeyId -> User -> IO Bool hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $ snd <$> processTranscript "su" ["-c", "gpg --list-secret-keys " ++ shellEscape keyid, u] Nothing @@ -60,3 +55,8 @@ hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $ hasPubKey :: GpgKeyId -> User -> IO Bool hasPubKey (GpgKeyId keyid) (User u) = catchBoolIO $ snd <$> processTranscript "su" ["-c", "gpg --list-public-keys " ++ shellEscape keyid, u] Nothing + +dotDir :: User -> IO FilePath +dotDir (User u) = do + home <- homeDirectory <$> getUserEntryForName u + return $ home ".gnupg" -- cgit v1.2.3