Skip to content

Commit

Permalink
S3 - Using Profile with role_arn from config over credential file (#190)
Browse files Browse the repository at this point in the history
* Moving S3 reference from credentials to config file
* Referring to ConfigFile instead of CredentialsFile
* Cleaning code naming
* Support `[profile {profile_name}]` on config file instead of `[{profile_name}]` which is for credentials file only
  • Loading branch information
popei69 authored and tmspzz committed Jun 4, 2019
1 parent 12bef6c commit ba9372c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ To use configurations other than the `default` profile set the `$AWS_PROFILE`
environment variable to your desired profile.

Since version `0.21.0.58` Rome also supports privilege escalation via [Amazon STS](https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html)
by specifying `role_arn` and `source_profile` in `~/.aws/credentials`
by specifying `role_arn` and `source_profile` in `~/.aws/config`

### Selecting the AWS Region

Expand Down
26 changes: 14 additions & 12 deletions src/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,17 @@ s3EndpointOverride (URL (Absolute h) _ _) =
s3EndpointOverride _ = S3.s3

-- | Tries to get authentication details and region to perform
-- | requests to AWS.
-- | requests to AWS.
-- | The `AWS_PROFILE` is read from the environment
-- | or falls back to `default`.
-- | or falls back to `default`.
-- | The `AWS_REGION` is first read from the environment, if not found
-- | it is read from `~/.aws/config` based on the profile discovered in the previous step.
-- | The `AWS_ACCESS_KEY_ID` & `AWS_SECRET_ACCESS_KEY` are first
-- | read from the environment. If not found, then the `~/.aws/crendetilas`
-- | read from the environment. If not found, then the `~/.aws/credentials`
-- | file is read. If `source_profile` key is present the reading of the
-- | authentication details happens from this profile rather then the `AWS_PROFILE`.
-- | Finally, if `role_arn` is specified, the crendials gathered up to now are used
-- | to obtain new credentials with STS esclated to `role_arn`.
-- | Finally, if `role_arn` is specified, the credentials gathered up to now are used
-- | to obtain new credentials with STS escalated to `role_arn`.
getAWSEnv :: (MonadIO m, MonadCatch m) => ExceptT String m AWS.Env
getAWSEnv = do
region <- discoverRegion
Expand All @@ -94,13 +94,15 @@ getAWSEnv = do
(lookupEnv (T.unpack "AWS_PROFILE"))
credentials <-
runExceptT $ (AWS.credentialsFromFile =<< getAWSCredentialsFilePath) `catch` \(e :: IOError) -> ExceptT . return . Left . show $ e
config <-
runExceptT $ (AWS.configFromFile =<< getAWSConfigFilePath) `catch` \(e :: IOError) -> ExceptT . return . Left . show $ e
(auth, _) <-
AWS.catching AWS._MissingEnvError AWS.fromEnv $ \envError -> either
throwError
(\cred -> do
let finalProfile = fromMaybe
profile
(eitherToMaybe $ AWS.sourceProfileOf profile =<< credentials)
(eitherToMaybe $ AWS.sourceProfileOf profile =<< config)
let
authAndRegion =
(,)
Expand All @@ -109,7 +111,7 @@ getAWSEnv = do
T.unpack envError
++ ". "
++ e
++ " in file ~/.aws/credentilas"
++ " in file ~/.aws/credentials"
)
(AWS.authFromCredentilas finalProfile =<< credentials)
<*> pure (pure region)
Expand All @@ -118,7 +120,7 @@ getAWSEnv = do
credentials
manager <- liftIO (Conduit.newManager Conduit.tlsManagerSettings)
ref <- liftIO (newIORef Nothing)
let roleARN = eitherToMaybe $ AWS.roleARNOf profile =<< credentials
let roleARN = eitherToMaybe $ AWS.roleARNOf profile =<< config
let curerntEnv = AWS.Env region
(\_ _ -> pure ())
(AWS.retryConnectionFailure 3)
Expand Down Expand Up @@ -195,7 +197,7 @@ runUtilsCommand command absoluteRomefilePath _ _ =
lift $ encodeFile absoluteRomefilePath romeFileEntries
_ -> throwError "Error: Programming Error. Only Utils command supported."

-- | Runs a command containing a `UDCPayload`
-- | Runs a command containing a `UDCPayload`
runUDCCommand :: RomeCommand -> FilePath -> Bool -> RomeVersion -> RomeMonad ()
runUDCCommand command absoluteRomefilePath verbose romeVersion = do
cartfileEntries <- getCartfileEntries
Expand Down Expand Up @@ -618,7 +620,7 @@ downloadArtifacts mS3BucketName mlCacheDir mEnginePath reverseRepositoryMap fram
)
readerEnv
-- Use engine
(Nothing, lCacheDir, Just ePath) -> do
(Nothing, lCacheDir, Just ePath) -> do
let engineEnv = (cachePrefix, skipLocalCacheFlag, concurrentlyFlag, verbose)
let action1 = runReaderT
(downloadFrameworksAndArtifactsWithEngine ePath
Expand Down Expand Up @@ -713,7 +715,7 @@ uploadArtifacts mS3BucketName mlCacheDir mEnginePath reverseRepositoryMap framew
>> runReaderT
(saveVersionFilesToLocalCache lCacheDir gitRepoNamesAndVersions)
readerEnv
-- Engine, maybe Cache
-- Engine, maybe Cache
(Nothing, lCacheDir, Just enginePath) -> do
let engineEnv =
( cachePrefix
Expand Down Expand Up @@ -1538,7 +1540,7 @@ downloadFrameworkAndArtifactsWithEngine enginePath (Just lCacheDir) reverseRomeM
readerEnv
let sayFunc :: MonadIO m => String -> m ()
sayFunc = if verbose then sayLnWithTime else sayLn

case eitherFrameworkSuccess of
Right _ -> return ()
Left e -> liftIO $ do
Expand Down
46 changes: 37 additions & 9 deletions src/Network/AWS/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module Network.AWS.Utils
( ConfigFile
, credentialsFromFile
, configFromFile
, authFromCredentilas
, parseConfigFile
, regionOf
Expand All @@ -22,7 +23,7 @@ import Control.Monad ((<=<))
import Data.Either.Utils (maybeToEither)
import Data.Either.Extra (mapLeft)
import Data.Ini (Ini, lookupValue, parseIni)
import qualified Data.Text as T (Text, null, unpack)
import qualified Data.Text as T (Text, null, pack, unpack)
import qualified Data.Text.Encoding as T (encodeUtf8)
import qualified Data.Text.IO as T (readFile)
import qualified Network.AWS as AWS
Expand Down Expand Up @@ -54,6 +55,16 @@ credentialsFromFile filePath = do
withExceptT (("Could not parse " <> filePath <> ": ") <>) (action file)
where action a = ExceptT . return $ parseCredentialsFile a

-- | Reads `ConfigFile` from a file at a given path
configFromFile
:: MonadIO m
=> FilePath -- ^ The path to the file containing the config. Usually `~/.aws/config`
-> ExceptT String m ConfigFile
configFromFile filePath = do
file <- liftIO (T.readFile filePath)
withExceptT (("Could not parse " <> filePath <> ": ") <>) (action file)
where action a = ExceptT . return $ parseConfigFile a

authFromCredentilas :: T.Text -> CredentialsFile -> Either String AWS.Auth
authFromCredentilas profile credentials = AWS.Auth <$> authEnv
where
Expand Down Expand Up @@ -90,16 +101,33 @@ getPropertyFromCredentials
getPropertyFromCredentials profile property =
lookupValue profile property . asIni

sourceProfileOf :: T.Text -> CredentialsFile -> Either String T.Text
sourceProfileOf profile credFile =
getPropertyFromCredentials profile "source_profile" credFile
`withError` const (missingKeyError key profile)
where key = "source_profile"
getPropertyFromConfig
:: T.Text -> T.Text -> ConfigFile -> Either String T.Text
getPropertyFromConfig profile property =
lookupValue profile property . asIni

roleARNOf :: T.Text -> CredentialsFile -> Either String T.Text
roleARNOf profile credFile = getPropertyFromCredentials profile key credFile
sourceProfileOf :: T.Text -> ConfigFile -> Either String T.Text
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

roleARNOf :: T.Text -> ConfigFile -> Either String T.Text
roleARNOf profile configFile = getPropertyFromConfig finalProfile key configFile
`withError` const (missingKeyError key profile)
where key = "role_arn"
where
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 =
Expand Down

0 comments on commit ba9372c

Please sign in to comment.