Skip to content

Commit

Permalink
Add support for AssumeRole STS API (minio#188)
Browse files Browse the repository at this point in the history
This change adds support for requesting temporary object storage
credentials using the STS API. Some breaking changes are introduced to
enable this support:

- `Credentials` type has been removed. Use the `CredentialValue` type
instead. Corresponding to this the type signature for `setCreds` has
changed, though the functionality is the same.
- The type alias `Provider` has been renamed to `CredentialLoader` to
avoid naming confusion.
  • Loading branch information
donatello authored May 4, 2023
1 parent 7ae8a81 commit fa62ed5
Show file tree
Hide file tree
Showing 21 changed files with 781 additions and 490 deletions.
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ Changelog

## Version 1.7.0 -- Unreleased

* Fix data type `EventMessage` to not export partial fields
* Bump up min bound on time dep and fix deprecation warnings.
* Fix data type `EventMessage` to not export partial fields (#179)
* Bump up min bound on time dep and fix deprecation warnings (#181)
* Add `dev` flag to cabal for building with warnings as errors (#182)
* Fix AWS region map (#185)
* Fix XML generator tests (#187)
* Add support for STS Assume Role API (#188)

### Breaking changes in 1.7.0

* `Credentials` type has been removed. Use `CredentialValue` instead.
* `Provider` type has been replaced with `CredentialLoader`.
* `EventMessage` data type is updated.

## Version 1.6.0

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# MinIO Haskell Client SDK for Amazon S3 Compatible Cloud Storage [![Build Status](https://travis-ci.org/minio/minio-hs.svg?branch=master)](https://travis-ci.org/minio/minio-hs)[![Hackage](https://img.shields.io/hackage/v/minio-hs.svg)](https://hackage.haskell.org/package/minio-hs)[![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io)
# MinIO Haskell Client SDK for Amazon S3 Compatible Cloud Storage [![CI](https://github.com/minio/minio-hs/actions/workflows/ci.yml/badge.svg)](https://github.com/minio/minio-hs/actions/workflows/ci.yml)[![Hackage](https://img.shields.io/hackage/v/minio-hs.svg)](https://hackage.haskell.org/package/minio-hs)[![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io)

The MinIO Haskell Client SDK provides simple APIs to access [MinIO](https://min.io) and any Amazon S3 compatible object storage.

Expand Down
38 changes: 26 additions & 12 deletions examples/AssumeRole.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--
-- MinIO Haskell SDK, (C) 2022 MinIO, Inc.
-- MinIO Haskell SDK, (C) 2023 MinIO, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
Expand All @@ -15,19 +15,33 @@
--
{-# LANGUAGE OverloadedStrings #-}

import Network.Minio.Credentials
import Control.Monad.IO.Class (liftIO)
import Network.Minio
import Prelude

main :: IO ()
main = do
res <-
retrieveCredentials
$ STSAssumeRole
"https://play.min.io"
( CredentialValue
"Q3AM3UQ867SPQQA43P2F"
"zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"
Nothing
)
$ defaultSTSAssumeRoleOptions {saroLocation = Just "us-east-1"}
-- Use play credentials for example.
let assumeRole =
STSAssumeRole
( CredentialValue
"Q3AM3UQ867SPQQA43P2F"
"zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"
Nothing
)
$ defaultSTSAssumeRoleOptions
{ saroLocation = Just "us-east-1",
saroEndpoint = Just "https://play.min.io:9000"
}

-- Retrieve temporary credentials and print them.
cv <- requestSTSCredential assumeRole
print $ "Temporary credentials" ++ show (credentialValueText $ fst cv)
print $ "Expiry" ++ show (snd cv)

-- Configure 'ConnectInfo' to request temporary credentials on demand.
ci <- setSTSCredential assumeRole "https://play.min.io"
res <- runMinio ci $ do
buckets <- listBuckets
liftIO $ print $ "Top 5 buckets: " ++ show (take 5 buckets)
print res
9 changes: 6 additions & 3 deletions minio-hs.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ common base-settings
, RankNTypes
, ScopedTypeVariables
, TupleSections
, TypeFamilies


other-modules: Lib.Prelude
, Network.Minio.API
Expand All @@ -97,7 +95,11 @@ common base-settings
, Network.Minio.Utils
, Network.Minio.XmlGenerator
, Network.Minio.XmlParser
, Network.Minio.XmlCommon
, Network.Minio.JsonParser
, Network.Minio.Credentials.Types
, Network.Minio.Credentials.AssumeRole
, Network.Minio.Credentials

mixins: base hiding (Prelude)
, relude (Relude as Prelude)
Expand Down Expand Up @@ -142,7 +144,6 @@ library
exposed-modules: Network.Minio
, Network.Minio.AdminAPI
, Network.Minio.S3API
, Network.Minio.Credentials

Flag live-test
Description: Build the test suite that runs against a live MinIO server
Expand All @@ -164,6 +165,7 @@ test-suite minio-hs-live-server-test
, Network.Minio.Utils.Test
, Network.Minio.XmlGenerator.Test
, Network.Minio.XmlParser.Test
, Network.Minio.Credentials
build-depends: minio-hs
, raw-strings-qq
, tasty
Expand Down Expand Up @@ -197,6 +199,7 @@ test-suite minio-hs-test
, Network.Minio.Utils.Test
, Network.Minio.XmlGenerator.Test
, Network.Minio.XmlParser.Test
, Network.Minio.Credentials

Flag examples
Description: Build the examples
Expand Down
28 changes: 21 additions & 7 deletions src/Network/Minio.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--
-- MinIO Haskell SDK, (C) 2017-2019 MinIO, Inc.
-- MinIO Haskell SDK, (C) 2017-2023 MinIO, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
Expand All @@ -16,21 +16,25 @@

-- |
-- Module: Network.Minio
-- Copyright: (c) 2017-2019 MinIO Dev Team
-- Copyright: (c) 2017-2023 MinIO Dev Team
-- License: Apache 2.0
-- Maintainer: MinIO Dev Team <[email protected]>
--
-- Types and functions to conveniently access S3 compatible object
-- storage servers like MinIO.
module Network.Minio
( -- * Credentials
Credentials (..),
CredentialValue (..),
credentialValueText,
AccessKey (..),
SecretKey (..),
SessionToken (..),

-- ** Credential providers
-- ** Credential Loaders

-- | Run actions that retrieve 'Credentials' from the environment or
-- | Run actions that retrieve 'CredentialValue's from the environment or
-- files or other custom sources.
Provider,
CredentialLoader,
fromAWSConfigFile,
fromAWSEnv,
fromMinioEnv,
Expand All @@ -54,6 +58,15 @@ module Network.Minio
awsCI,
gcsCI,

-- ** STS Credential types
STSAssumeRole (..),
STSAssumeRoleOptions (..),
defaultSTSAssumeRoleOptions,
requestSTSCredential,
setSTSCredential,
ExpiryTime (..),
STSCredentialProvider,

-- * Minio Monad

----------------
Expand Down Expand Up @@ -225,14 +238,15 @@ This module exports the high-level MinIO API for object storage.
import qualified Data.Conduit as C
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.Combinators as CC
import Network.Minio.API
import Network.Minio.CopyObject
import Network.Minio.Credentials
import Network.Minio.Data
import Network.Minio.Errors
import Network.Minio.ListOps
import Network.Minio.PutObject
import Network.Minio.S3API
import Network.Minio.SelectAPI
import Network.Minio.Utils

-- | Lists buckets.
listBuckets :: Minio [BucketInfo]
Expand Down
28 changes: 24 additions & 4 deletions src/Network/Minio/API.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--
-- MinIO Haskell SDK, (C) 2017, 2018 MinIO, Inc.
-- MinIO Haskell SDK, (C) 2017-2023 MinIO, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
Expand All @@ -26,6 +26,7 @@ module Network.Minio.API
checkBucketNameValidity,
isValidObjectName,
checkObjectNameValidity,
requestSTSCredential,
)
where

Expand All @@ -34,21 +35,22 @@ import Control.Retry
limitRetriesByCumulativeDelay,
retrying,
)
import qualified Data.ByteArray as BA
import qualified Data.ByteString as B
import qualified Data.Char as C
import qualified Data.Conduit as C
import qualified Data.HashMap.Strict as H
import qualified Data.Text as T
import qualified Data.Time.Clock as Time
import Lib.Prelude
import Network.HTTP.Client (defaultManagerSettings)
import qualified Network.HTTP.Client as NClient
import Network.HTTP.Conduit (Response)
import qualified Network.HTTP.Conduit as NC
import Network.HTTP.Types (simpleQueryToQuery)
import qualified Network.HTTP.Types as HT
import Network.HTTP.Types.Header (hHost)
import Network.Minio.APICommon
import Network.Minio.Credentials
import Network.Minio.Data
import Network.Minio.Errors
import Network.Minio.Sign.V4
Expand Down Expand Up @@ -145,6 +147,20 @@ getHostPathRegion ri = do
else return pathStyle
)

-- | requestSTSCredential requests temporary credentials using the Security Token
-- Service API. The returned credential will include a populated 'SessionToken'
-- and an 'ExpiryTime'.
requestSTSCredential :: STSCredentialProvider p => p -> IO (CredentialValue, ExpiryTime)
requestSTSCredential p = do
endpoint <- maybe (throwIO $ MErrValidation MErrVSTSEndpointNotFound) return $ getSTSEndpoint p
let endPt = NC.parseRequest_ $ toString endpoint
settings
| NC.secure endPt = NC.tlsManagerSettings
| otherwise = defaultManagerSettings

mgr <- NC.newManager settings
liftIO $ retrieveSTSCredentials p ("", 0, False) mgr

buildRequest :: S3ReqInfo -> Minio NC.Request
buildRequest ri = do
maybe (return ()) checkBucketNameValidity $ riBucket ri
Expand Down Expand Up @@ -175,10 +191,14 @@ buildRequest ri = do

timeStamp <- liftIO Time.getCurrentTime

mgr <- asks mcConnManager
cv <- liftIO $ getCredential (connectCreds ci') (getEndpoint ci') mgr

let sp =
SignParams
(connectAccessKey ci')
(BA.convert (encodeUtf8 $ connectSecretKey ci' :: ByteString))
(coerce $ cvAccessKey cv)
(coerce $ cvSecretKey cv)
(coerce $ cvSessionToken cv)
ServiceS3
timeStamp
(riRegion ri')
Expand Down
12 changes: 8 additions & 4 deletions src/Network/Minio/AdminAPI.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--
-- MinIO Haskell SDK, (C) 2018 MinIO, Inc.
-- MinIO Haskell SDK, (C) 2018-2023 MinIO, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -70,7 +70,6 @@ import Data.Aeson
)
import qualified Data.Aeson as A
import Data.Aeson.Types (typeMismatch)
import qualified Data.ByteArray as BA
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text as T
Expand All @@ -81,6 +80,7 @@ import qualified Network.HTTP.Conduit as NC
import qualified Network.HTTP.Types as HT
import Network.HTTP.Types.Header (hHost)
import Network.Minio.APICommon
import Network.Minio.Credentials
import Network.Minio.Data
import Network.Minio.Errors
import Network.Minio.Sign.V4
Expand Down Expand Up @@ -666,6 +666,9 @@ buildAdminRequest areq = do

timeStamp <- liftIO getCurrentTime

mgr <- asks mcConnManager
cv <- liftIO $ getCredential (connectCreds ci) (getEndpoint ci) mgr

let hostHeader = (hHost, getHostAddr ci)
newAreq =
areq
Expand All @@ -678,8 +681,9 @@ buildAdminRequest areq = do
signReq = toRequest ci newAreq
sp =
SignParams
(connectAccessKey ci)
(BA.convert (encodeUtf8 $ connectSecretKey ci :: ByteString))
(coerce $ cvAccessKey cv)
(coerce $ cvSecretKey cv)
(coerce $ cvSessionToken cv)
ServiceS3
timeStamp
Nothing
Expand Down
Loading

0 comments on commit fa62ed5

Please sign in to comment.