summaryrefslogtreecommitdiff
path: root/src/Propellor/Property/Gpg.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Propellor/Property/Gpg.hs')
-rw-r--r--src/Propellor/Property/Gpg.hs39
1 files changed, 29 insertions, 10 deletions
diff --git a/src/Propellor/Property/Gpg.hs b/src/Propellor/Property/Gpg.hs
index a16df11d..bd710ca7 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,22 +23,39 @@ 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) = 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 $
- 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
+
+hasPrivKey :: GpgKeyId -> User -> IO Bool
+hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $
+ 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 " ++ shellEscape keyid, u] Nothing
+
dotDir :: User -> IO FilePath
dotDir (User u) = do
home <- homeDirectory <$> getUserEntryForName u