Skip to content

Commit

Permalink
Merge pull request #951 from arianvp/fix-aws-sso
Browse files Browse the repository at this point in the history
Allow config files without credential files and allow overriding paths
  • Loading branch information
endgame committed Aug 7, 2023
2 parents 7353924 + 0c0614e commit 5461403
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 26 deletions.
11 changes: 11 additions & 0 deletions lib/amazonka/CHANGELOG.md
Expand Up @@ -2,9 +2,20 @@

## Unreleased

### Changed

- `amazonka`: Add support for `AWS_SHARED_CREDENTIALS_FILE` and `AWS_CONFIG_FILE` environment variables to override the
default paths `$HOME/.aws/credentials` and `$HOME/.aws/config` [\#951](https://github.com/brendanhay/amazonka/pull/951)

### Fixed

- `amazonka`: Allow reading the AWS config file when the credentials file is missing [\#951](https://github.com/brendanhay/amazonka/pull/951).
This is useful when you are using a role-based authentication method or AWS IAM Identity Center (formerly AWS SSO) which does not require a credentials file.
Before this fix you had to create an empty credentials file for these methods to work correctly.
- `amazonka`: During logging, do not print bytestrings that have unprintable characters
[\#952](https://github.com/brendanhay/amazonka/pull/952)


## [2.0.0](https://github.com/brendanhay/amazonka/tree/2.0.0)
Released: **28 July 2023**, Compare: [2.0.0-rc2](https://github.com/brendanhay/amazonka/compare/2.0.0-rc2...2.0.0)

Expand Down
110 changes: 84 additions & 26 deletions lib/amazonka/src/Amazonka/Auth/ConfigFile.hs
Expand Up @@ -36,7 +36,36 @@ import System.Info (os)
-- Amazonka currently understands them:
--
-- * AWS recommends credentials do not live in the config file, but
-- allows it.
-- allows it. You should instead define them in the credentials file.
--
-- * You can set @role_arn@ together with either @source_profile@,
-- @credential_source@ , or @web_identity_token_file@. Unlike the
-- standard SDK we only support @role_session_name@ for
-- @web_identity_token_file@ and not the other AssumeRole methods.
-- This might be fixed in the future.
--
-- * If you set @role_arn@ and @source_profile@, the source profile's
-- credentials will be used to assume the role.
--
-- * If you set @role_arn@ and @credential_source@, the credentials are
-- retrieved from the specified source. The source can be one of
-- @Environment@, @Ec2InstanceMetadata@, or @EcsContainer@.
--
-- * If you set @role_arn@ and @web_identity_token_file@, the OIDC token in
-- the file will be used to assume the role. You can also
-- set @role_session_name@ to specify the name of the session.
--
-- * You can finally also configure assuming a role using AWS Identity Center
-- (Formerly AWS SSO) by setting @sso_start_url@, @sso_region@,
-- @sso_account_id@, and @sso_role_name@ in your profile section.
-- Amazonka currently does not initiate the SSO login flow, so you will have
-- to do that yourself using the AWS CLI. Amazonka will then look in
-- @~\/.aws\/sso\/cache@ for a cached token.
--
-- * We currently only support 'Legacy' SSO profiles and do not support
-- setting common SSO settings in a @[sso-session <name>]@ section or
-- support token refresh. So use the following guide to set up your AWS CLI:
-- https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-legacy.html
--
-- * Sections in the config file start should either be named
-- @[default]@ or @[profile foo]@. Unprefixed @[foo]@ currently
Expand All @@ -60,7 +89,14 @@ fromFilePath ::
Env' withAuth ->
m Env
fromFilePath profile credentialsFile configFile env = liftIO $ do
credentialsIni <- loadIniFile credentialsFile
-- If we fail to read the credentials file, assume it's empty and
-- move on. It is valid to configure only a config file if you plan
-- to assume a role using any of the assume role methods.
credentialsIni <-
Exception.catchJust
(\(_ :: AuthError) -> Just mempty)
(loadIniFile credentialsFile)
pure
-- If we fail to read the config file, assume it's empty and move
-- on. It is valid to configure only a credentials file if you only
-- want to set keys, for example.
Expand Down Expand Up @@ -107,12 +143,18 @@ fromFilePath profile credentialsFile configFile env = liftIO $ do
config <- ask
case HashMap.lookup pName config of
Nothing ->
liftIO . Exception.throwIO . InvalidFileError $
"Missing profile: " <> Text.pack (show pName)
liftIO
. Exception.throwIO
. InvalidFileError
$ "Missing profile: "
<> Text.pack (show pName)
Just p -> case parseConfigProfile p of
Nothing ->
liftIO . Exception.throwIO . InvalidFileError $
"Parse error in profile: " <> Text.pack (show pName)
liftIO
. Exception.throwIO
. InvalidFileError
$ "Parse error in profile: "
<> Text.pack (show pName)
Just (cp, mRegion) -> do
env' <- case cp of
ExplicitKeys keys ->
Expand All @@ -126,7 +168,8 @@ fromFilePath profile credentialsFile configFile env = liftIO $ do
in liftIO
. Exception.throwIO
. InvalidFileError
$ "Infinite source_profile loop: " <> textTrace
$ "Infinite source_profile loop: "
<> textTrace
else do
lift . modify $ (sourceProfileName :)
sourceEnv <- evalConfig sourceProfileName
Expand All @@ -141,8 +184,9 @@ fromFilePath profile credentialsFile configFile env = liftIO $ do
fromWebIdentity tokenFile roleArn mRoleSessionName env
AssumeRoleViaSSO startUrl ssoRegion accountId roleName -> do
cachedTokenFile <-
liftIO $
configPathRelative =<< relativeCachedTokenFile startUrl
liftIO
$ configPathRelative
=<< relativeCachedTokenFile startUrl
fromSSO cachedTokenFile ssoRegion accountId roleName env

-- Once we have the env from the profile, apply the region
Expand Down Expand Up @@ -188,19 +232,24 @@ parseConfigProfile profile = parseProfile <&> (,parseRegion)
parseRegion = Region' <$> HashMap.lookup "region" profile

explicitKey =
fmap ExplicitKeys $
AuthEnv
<$> ( AccessKey . Text.encodeUtf8
<$> HashMap.lookup "aws_access_key_id" profile
)
<*> ( Sensitive . SecretKey . Text.encodeUtf8
<$> HashMap.lookup "aws_secret_access_key" profile
)
<*> Just
( Sensitive . SessionToken . Text.encodeUtf8
<$> HashMap.lookup "aws_session_token" profile
fmap ExplicitKeys
$ AuthEnv
<$> ( AccessKey
. Text.encodeUtf8
<$> HashMap.lookup "aws_access_key_id" profile
)
<*> Just Nothing -- No token expiry in config file
<*> ( Sensitive
. SecretKey
. Text.encodeUtf8
<$> HashMap.lookup "aws_secret_access_key" profile
)
<*> Just
( Sensitive
. SessionToken
. Text.encodeUtf8
<$> HashMap.lookup "aws_session_token" profile
)
<*> Just Nothing -- No token expiry in config file
assumeRoleFromProfile =
AssumeRoleFromProfile
<$> HashMap.lookup "role_arn" profile
Expand Down Expand Up @@ -254,6 +303,12 @@ data CredentialSource = Environment | Ec2InstanceMetadata | EcsContainer
-- Throws 'MissingFileError' if 'credFile' is missing, or 'InvalidFileError'
-- if an error occurs during parsing.
--
-- If @AWS_SHARED_CREDENTIALS_FILE@ is set, it will be used instead of looking
-- for @.aws\/credentials@ in the @HOME@ directory
-- If @AWS_CONFIG_FILE@ is set, it will be used instead of looking for
-- @.aws\/config@ in the @HOME@ directory.
-- If @AWS_PROFILE@ is set, it will be used instead of the default profile
--
-- This looks in in the @HOME@ directory as determined by the
-- <http://hackage.haskell.org/package/directory directory> library.
--
Expand All @@ -263,11 +318,14 @@ data CredentialSource = Environment | Ec2InstanceMetadata | EcsContainer
fromFileEnv ::
(MonadIO m, Foldable withAuth) => Env' withAuth -> m Env
fromFileEnv env = liftIO $ do
mProfile <- Environment.lookupEnv "AWS_PROFILE"
cred <- configPathRelative "/.aws/credentials"
conf <- configPathRelative "/.aws/config"

fromFilePath (maybe "default" Text.pack mProfile) cred conf env
profile <- Environment.lookupEnv "AWS_PROFILE" <&> maybe "default" Text.pack
conf <-
Environment.lookupEnv "AWS_CONFIG_File"
>>= maybe (configPathRelative "/.aws/config") pure
cred <-
Environment.lookupEnv "AWS_SHARED_CREDENTIALS_FILE"
>>= maybe (configPathRelative "/.aws/credentials") pure
fromFilePath profile cred conf env

configPathRelative :: String -> IO String
configPathRelative p = handling_ _IOException err dir
Expand Down

0 comments on commit 5461403

Please sign in to comment.