Skip to content

Commit

Permalink
Read aws_session_token and aws_expiration (#211)
Browse files Browse the repository at this point in the history
* Read aws_session_token and aws_expiration from AWS credentials file
* Bump version number
  • Loading branch information
tmspzz authored Jan 27, 2020
1 parent 496f0cc commit 1c5b392
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 42 deletions.
2 changes: 1 addition & 1 deletion Rome.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Rome
version: 0.23.2.62
version: 0.23.2.63
synopsis: A cache for Carthage
description: Please see README.md
homepage: https://github.com/blender/Rome
Expand Down
2 changes: 1 addition & 1 deletion Rome.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Rome'
s.version = '0.23.2.62'
s.version = '0.23.2.63'
s.summary = 'A cache tool for Carthage'
s.homepage = 'https://github.com/blender/Rome'
s.source = { :http => "#{s.homepage}/releases/download/v#{s.version}/rome.zip" }
Expand Down
2 changes: 1 addition & 1 deletion app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import System.Exit


romeVersion :: RomeVersion
romeVersion = (0, 23, 2, 62)
romeVersion = (0, 23, 2, 63)



Expand Down
115 changes: 76 additions & 39 deletions src/Network/AWS/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ module Network.AWS.Utils
, sourceProfileOf
, accessKeyIdOf
, secretAccessKeyOf
, sessionTokenOf
, expirationOf
, roleARNOf
)
where
Expand All @@ -20,34 +22,37 @@ where
-- `Data.Romefile` and `Data.Carthage` and avoids dealing with the raw INI
-- file representation (String-keyed hashmaps) in the main logic.

import Control.Monad ( (<=<) )
import Data.Either.Utils ( maybeToEither )
import Data.Either.Extra ( mapLeft )
import Data.Ini ( Ini
, lookupValue
, parseIni
)
import Control.Applicative ( (<|>) )
import Control.Monad ( (<=<) )
import Control.Monad.IO.Class ( MonadIO
, liftIO
)
import Control.Monad.Except ( ExceptT(..)
, withExceptT
)
import Data.Either.Utils ( maybeToEither )
import Data.Either.Extra ( mapLeft )
import Data.Ini ( Ini
, lookupValue
, parseIni
)
import qualified Data.Text as T
( Text
, null
, pack
, unpack
)
( Text
, null
, pack
, unpack
)
import qualified Data.Text.Encoding as T
( encodeUtf8 )
( encodeUtf8 )
import qualified Data.Text.IO as T
( readFile )
( readFile )
import qualified Network.AWS as AWS
import qualified Network.AWS.Data as AWS
import qualified Network.AWS.Data.Sensitive as AWS
( Sensitive(..) )
( Sensitive(..) )
import Network.URL
import Control.Monad.IO.Class ( MonadIO
, liftIO
)
import Control.Monad.Except ( ExceptT(..)
, withExceptT
)
import qualified Text.Read as T
( readEither )

newtype ConfigFile = ConfigFile { _awsConfigIni :: Ini } deriving Show
newtype CredentialsFile = CredentialsFile { _awsCredentialsIni :: Ini } deriving Show
Expand Down Expand Up @@ -86,12 +91,16 @@ authFromCredentilas profile credentials = AWS.Auth <$> authEnv
where
accessKeyId = T.encodeUtf8 <$> accessKeyIdOf profile credentials
secretAccessKey = T.encodeUtf8 <$> secretAccessKeyOf profile credentials
sessionToken = T.encodeUtf8 <$> sessionTokenOf profile credentials
expirationDate = expirationOf profile credentials
authEnv =
AWS.AuthEnv
<$> (AWS.AccessKey <$> accessKeyId)
<*> (AWS.Sensitive . AWS.SecretKey <$> secretAccessKey)
<*> pure Nothing
<*> pure Nothing
<*> ( (Just . AWS.Sensitive . AWS.SessionToken <$> sessionToken)
<|> pure Nothing
)
<*> ((T.readEither =<< T.unpack <$> expirationDate) <|> pure Nothing)

regionOf :: T.Text -> ConfigFile -> Either String AWS.Region
regionOf profile = parseRegion <=< lookupValue profile "region" . asIni
Expand All @@ -106,44 +115,72 @@ endPointOf profile = parseURL <=< lookupValue profile "endpoint" . asIni
where
parseURL s = if T.null s
then Left "Failed reading: Failure parsing Endpoint from empty string"
else maybeToEither "Failed reading: Endpoint is not a valid URL" $ importURL . T.unpack $ s
else
maybeToEither "Failed reading: Endpoint is not a valid URL"
$ importURL
. T.unpack
$ s

getPropertyFromCredentials :: T.Text -> T.Text -> CredentialsFile -> Either String T.Text
getPropertyFromCredentials profile property = lookupValue profile property . asIni
getPropertyFromCredentials
:: T.Text -> T.Text -> CredentialsFile -> Either String T.Text
getPropertyFromCredentials profile property =
lookupValue profile property . asIni

getPropertyFromConfig :: T.Text -> T.Text -> ConfigFile -> Either String T.Text
getPropertyFromConfig profile property = lookupValue profile property . asIni

sourceProfileOf :: T.Text -> ConfigFile -> Either String T.Text
sourceProfileOf profile configFile = getPropertyFromConfig finalProfile key configFile
`withError` const (missingKeyError key profile)
sourceProfileOf profile configFile =
getPropertyFromConfig finalProfile key configFile
`withError` const (missingKeyError key profile)
where
key = "source_profile"
finalProfile = if profile == "default" then profile else T.pack "profile " <> profile
key = "source_profile"
finalProfile =
if profile == "default" then profile else T.pack "profile " <> profile

roleARNOf :: T.Text -> ConfigFile -> Either String T.Text
roleARNOf profile configFile = getPropertyFromConfig finalProfile key configFile
`withError` const (missingKeyError key profile)
roleARNOf profile configFile =
getPropertyFromConfig finalProfile key configFile
`withError` const (missingKeyError key profile)
where
key = "role_arn"
finalProfile = if profile == "default" then profile else T.pack "profile " <> profile
key = "role_arn"
finalProfile =
if profile == "default" then profile else T.pack "profile " <> profile

accessKeyIdOf :: T.Text -> CredentialsFile -> Either String T.Text
accessKeyIdOf profile credFile = getPropertyFromCredentials profile key credFile
`withError` const (missingKeyError key profile)
accessKeyIdOf profile credFile =
getPropertyFromCredentials profile key credFile
`withError` const (missingKeyError key profile)
where key = "aws_access_key_id"

missingKeyError :: T.Text -> T.Text -> String
missingKeyError key profile = "Could not find key `" ++ T.unpack key ++ "` for profile `" ++ T.unpack profile ++ "`"
missingKeyError key profile =
"Could not find key `"
++ T.unpack key
++ "` for profile `"
++ T.unpack profile
++ "`"

withError :: Either a b -> (a -> c) -> Either c b
withError = flip mapLeft

secretAccessKeyOf :: T.Text -> CredentialsFile -> Either String T.Text
secretAccessKeyOf profile credFile = getPropertyFromCredentials profile key credFile
`withError` const (missingKeyError key profile)
secretAccessKeyOf profile credFile =
getPropertyFromCredentials profile key credFile
`withError` const (missingKeyError key profile)
where key = "aws_secret_access_key"

sessionTokenOf :: T.Text -> CredentialsFile -> Either String T.Text
sessionTokenOf profile credFile =
getPropertyFromCredentials profile key credFile
`withError` const (missingKeyError key profile)
where key = "aws_session_token"

expirationOf :: T.Text -> CredentialsFile -> Either String T.Text
expirationOf profile credFile = getPropertyFromCredentials profile key credFile
`withError` const (missingKeyError key profile)
where key = "aws_expiration"

parseConfigFile :: T.Text -> Either String ConfigFile
parseConfigFile = fmap ConfigFile . parseIni

Expand Down

0 comments on commit 1c5b392

Please sign in to comment.