Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read aws_session_token and aws_expiration #211

Merged
merged 4 commits into from
Jan 27, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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" }
2 changes: 1 addition & 1 deletion app/Main.hs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import System.Exit


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



115 changes: 76 additions & 39 deletions src/Network/AWS/Utils.hs
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@ module Network.AWS.Utils
, sourceProfileOf
, accessKeyIdOf
, secretAccessKeyOf
, sessionTokenOf
, expirationOf
, roleARNOf
)
where
@@ -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
@@ -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
@@ -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