module Amazonka.Auth.InstanceProfile where
import Amazonka.Auth.Background
import Amazonka.Auth.Exception
import Amazonka.Data
import Amazonka.EC2.Metadata hiding (region)
import qualified Amazonka.EC2.Metadata as IdentityDocument (IdentityDocument (..))
import Amazonka.Env (Env, Env' (..))
import Amazonka.Prelude
import qualified Control.Exception as Exception
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy.Char8 as LBS8
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
fromDefaultInstanceProfile ::
MonadIO m =>
Env' withAuth ->
m Env
fromDefaultInstanceProfile :: forall (m :: * -> *) (withAuth :: * -> *).
MonadIO m =>
Env' withAuth -> m Env
fromDefaultInstanceProfile Env' withAuth
env =
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
Either HttpException ByteString
ls <-
forall e a. Exception e => IO a -> IO (Either e a)
Exception.try forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
MonadIO m =>
Manager -> Metadata -> m ByteString
metadata (forall (withAuth :: * -> *). Env' withAuth -> Manager
manager Env' withAuth
env) (IAM -> Metadata
IAM (Maybe Text -> IAM
SecurityCredentials forall a. Maybe a
Nothing))
case ByteString -> [ByteString]
BS8.lines forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either HttpException ByteString
ls of
Right (ByteString
x : [ByteString]
_) -> forall (m :: * -> *) (withAuth :: * -> *).
MonadIO m =>
Text -> Env' withAuth -> m Env
fromNamedInstanceProfile (ByteString -> Text
Text.decodeUtf8 ByteString
x) Env' withAuth
env
Left HttpException
e -> forall e a. Exception e => e -> IO a
Exception.throwIO (HttpException -> AuthError
RetrievalError HttpException
e)
Either HttpException [ByteString]
_ ->
forall e a. Exception e => e -> IO a
Exception.throwIO forall a b. (a -> b) -> a -> b
$
Text -> AuthError
InvalidIAMError Text
"Unable to get default IAM Profile from EC2 metadata"
fromNamedInstanceProfile ::
MonadIO m =>
Text ->
Env' withAuth ->
m Env
fromNamedInstanceProfile :: forall (m :: * -> *) (withAuth :: * -> *).
MonadIO m =>
Text -> Env' withAuth -> m Env
fromNamedInstanceProfile Text
name env :: Env' withAuth
env@Env {Manager
manager :: Manager
$sel:manager:Env :: forall (withAuth :: * -> *). Env' withAuth -> Manager
manager} =
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
Auth
keys <- IO AuthEnv -> IO Auth
fetchAuthInBackground IO AuthEnv
getCredentials
Region
region <- IO Region
getRegionFromIdentity
forall (f :: * -> *) a. Applicative f => a -> f a
pure Env' withAuth
env {$sel:auth:Env :: Identity Auth
auth = forall a. a -> Identity a
Identity Auth
keys, Region
$sel:region:Env :: Region
region :: Region
region}
where
getCredentials :: IO AuthEnv
getCredentials =
forall e a. Exception e => IO a -> IO (Either e a)
Exception.try (forall (m :: * -> *).
MonadIO m =>
Manager -> Metadata -> m ByteString
metadata Manager
manager (IAM -> Metadata
IAM forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> IAM
SecurityCredentials forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Text
name))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall {b} {t} {a} {a}.
Exception b =>
(t -> Either a a) -> (a -> b) -> Either HttpException t -> IO a
handleErr (forall a. FromJSON a => ByteString -> Either String a
eitherDecode' forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LBS8.fromStrict) String -> AuthError
invalidIAMErr
getRegionFromIdentity :: IO Region
getRegionFromIdentity =
forall e a. Exception e => IO a -> IO (Either e a)
Exception.try (forall (m :: * -> *).
MonadIO m =>
Manager -> m (Either String IdentityDocument)
identity Manager
manager)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall {b} {t} {a} {a}.
Exception b =>
(t -> Either a a) -> (a -> b) -> Either HttpException t -> IO a
handleErr (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IdentityDocument -> Region
IdentityDocument.region) String -> AuthError
invalidIdentityErr
handleErr :: (t -> Either a a) -> (a -> b) -> Either HttpException t -> IO a
handleErr t -> Either a a
f a -> b
g = \case
Left HttpException
e -> forall e a. Exception e => e -> IO a
Exception.throwIO (HttpException -> AuthError
RetrievalError HttpException
e)
Right t
x -> forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall e a. Exception e => e -> IO a
Exception.throwIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
g) forall (f :: * -> *) a. Applicative f => a -> f a
pure (t -> Either a a
f t
x)
invalidIAMErr :: String -> AuthError
invalidIAMErr String
e =
Text -> AuthError
InvalidIAMError forall a b. (a -> b) -> a -> b
$
forall a. Monoid a => [a] -> a
mconcat [Text
"Error parsing IAM profile '", Text
name, Text
"' ", String -> Text
Text.pack String
e]
invalidIdentityErr :: String -> AuthError
invalidIdentityErr String
e =
Text -> AuthError
InvalidIAMError forall a b. (a -> b) -> a -> b
$
forall a. Monoid a => [a] -> a
mconcat [Text
"Error parsing Instance Identity Document ", String -> Text
Text.pack String
e]