packages feed

hercules-ci-cli 0.2.4 → 0.2.5

raw patch · 5 files changed

+60/−6 lines, 5 files

Files

CHANGELOG.md view
@@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 0.2.5 - 2022-03-07++### Added++ - `hci secret echo`: write secret data on stdout. A side-effect free version of `hci secret add`.++ - `hci secret echo/add --password`: another safe way of inputting a secret field+ ## 0.2.4 - 2021-11-17  ### Added
hercules-ci-cli.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12  name:           hercules-ci-cli-version:        0.2.4+version:        0.2.5 synopsis:       The hci command for working with Hercules CI homepage:       https://docs.hercules-ci.com bug-reports:    https://github.com/hercules-ci/hercules-ci-agent/issues
src/Hercules/CLI/JSON.hs view
@@ -17,6 +17,7 @@ import Protolude import System.AtomicWrite.Writer.ByteString (atomicWriteFile) import System.Environment (getEnvironment, lookupEnv)+import System.IO (hGetEcho, hSetEcho)  mergePaths :: [([Text], Value)] -> Either Text Value mergePaths = mergeLeafPaths [] . toLeafPaths@@ -48,7 +49,7 @@         toLeafPaths [(path ++ [subpath], subitem)]     _ -> [(path, item)] -options :: Optparse.Parser (IO Value)+options :: Optparse.Parser (Maybe Text -> IO Value) options = do   strings <-     many@@ -61,6 +62,15 @@               <> Optparse.metavar2 "STRING"           )       )+  stringPasswords <-+    many+      ( Optparse.option+          Optparse.str+          ( Optparse.long "password"+              <> Optparse.help "Define a string at dot-separated PATH in the secret data using password input on stdin"+              <> Optparse.metavar "PATH"+          )+      )   jsons <-     many       ( Optparse.biOption@@ -120,7 +130,7 @@               <> Optparse.completer2 envCompleter           )       )-  pure do+  pure \maybeSecretName -> do     fileStrings <- for stringFiles readFileWithKey     fileJsons <- for jsonFiles readJsonFileWithKey     envStrings <- for stringEnvs readEnvWithKey@@ -133,11 +143,13 @@               Left e -> throwIO $ UserException $ "Value for key " <> key <> " is not valid JSON: " <> show e               Right r -> pure (key, r :: Value)         )+    passwordStrings <- for stringPasswords (askPasswordWithKey maybeSecretName)     let items =           map (first split) $             (fmap String <$> strings)               <> (fmap String <$> envStrings)               <> (fmap String <$> fileStrings)+              <> (fmap String <$> passwordStrings)               <> validJsons               <> envJsons               <> fileJsons@@ -194,6 +206,9 @@ writeJsonFile filePath v =   atomicWriteFile filePath $ BL.toStrict $ encodePretty' prettyConf v +printJson :: ToJSON a => a -> IO ()+printJson = BS.putStr . BL.toStrict . (<> "\n") . encodePretty' prettyConf+ prettyConf :: Data.Aeson.Encode.Pretty.Config prettyConf =   defConfig@@ -202,3 +217,19 @@       -- UNIX convention       confTrailingNewline = True     }++askPasswordWithKey :: Maybe Text -> Text -> IO (Text, Text)+askPasswordWithKey secretNameMaybe key = do+  case secretNameMaybe of+    Nothing -> putErrText $ "Enter value for " <> key <> ":"+    Just secretName -> putErrText $ "Enter value for " <> key <> " in secret " <> secretName <> ":"+  s <- T.strip <$> withEcho False getLine+  putErrText ""+  case s of+    "" -> throwIO $ UserException $ "Value must not be empty for " <> show key+    _ -> pure (key, s)++withEcho :: Bool -> IO a -> IO a+withEcho echo action = do+  old <- hGetEcho stdin+  bracket_ (hSetEcho stdin echo) (hSetEcho stdin old) action
src/Hercules/CLI/Login.hs view
@@ -34,7 +34,7 @@           }     putErrText "Please confirm your login at "     putErrText $ "  " <> CLIAuthorizationRequestCreateResponse.browserURL r-    putErrText "Waiting for confirmation..."+    putErrText "Waiting for you to confirm using the link..."     let tmpTok = CLIAuthorizationRequestCreateResponse.temporaryCLIToken r         -- TODO do something pretty with 404         pollLoop = do
src/Hercules/CLI/Secret.hs view
@@ -4,6 +4,7 @@ module Hercules.CLI.Secret where  import qualified Data.Aeson as A+import qualified Data.Aeson.Types as A import qualified Data.Map as M import qualified Data.Text as T import Hercules.CLI.Common (exitMsg, runAuthenticated)@@ -15,7 +16,7 @@ import System.FilePath (takeDirectory, (</>)) import UnliftIO.Directory (XdgDirectory (XdgConfig), createDirectoryIfMissing, doesFileExist, getXdgDirectory) -commandParser, initLocal, add :: Optparse.Parser (IO ())+commandParser, initLocal, add, echo :: Optparse.Parser (IO ()) commandParser =   subparser     ( mkCommand@@ -26,6 +27,10 @@           "add"           (Optparse.progDesc "Insert a secret into the local secrets file")           add+        <> mkCommand+          "echo"+          (Optparse.progDesc "Assemble a secret for stdout")+          echo     ) initLocal = do   projectOptionMaybe <- optional projectOption@@ -44,7 +49,7 @@   mkJson <- JSON.options   projectOptionMaybe <- optional projectOption   pure $ runAuthenticated do-    secretData <- liftIO mkJson+    secretData <- liftIO (mkJson (Just secretName))     projectPath <- getProjectPath projectOptionMaybe     secretsFilePath <- liftIO $ getSecretsFilePath projectPath     liftIO $@@ -60,6 +65,16 @@     liftIO $ writeJsonFile secretsFilePath secrets'     putErrText $ "hci: successfully wrote " <> secretName <> " to " <> toS secretsFilePath     putErrText "NOTE: Remember to synchronize this file with your agents!"+echo = do+  mkJson <- JSON.options+  pure do+    secretDataValue <- liftIO (mkJson Nothing)+    secretData <- case A.parse A.parseJSON secretDataValue of+      A.Error e -> exitMsg $ "The secret data must be an object. " <> toS e+      A.Success a -> pure a+    let secret =+          A.object ["kind" A..= A.String "Secret", "data" A..= (secretData :: Map Text A.Value)]+    liftIO $ JSON.printJson secret  getSecretsFilePath :: ProjectPath -> IO FilePath getSecretsFilePath projectPath = do