git.iko.soy/typeable/minio-hs
on master help sign in
17 files changed+348−258
since splitsnapshots
unifiedsplit
.github/workflows/ci.yml+208−170 minio-hs.cabal+8−7 src/Lib/Prelude.hs+1−1 src/Network/Minio/API.hs+3−3 src/Network/Minio/Credentials.hs+1−1 src/Network/Minio/Credentials/AssumeRole.hs+3−1 src/Network/Minio/Credentials/Types.hs+7−2 src/Network/Minio/Data.hs+12−11 src/Network/Minio/Data/Crypto.hs+8−8 src/Network/Minio/SelectAPI.hs+7−7 src/Network/Minio/Sign/V4.hs+1−1 src/Network/Minio/Utils.hs+2−2 src/Network/Minio/XmlCommon.hs+1−1 src/Network/Minio/XmlParser.hs+1−1 stack.yaml+4−4 stack.yaml.lock+12−5 test/LiveServer.hs+69−33
.github/workflows/ci.yml+208−170
@@ -18,30 +18,31 @@ env:
1818 MINIO_ACCESS_KEY: minio
1919 MINIO_SECRET_KEY: minio123
2020 MINIO_LOCAL: 1
21− MINIO_SECURE: 1
2221
2322jobs:
2423 ormolu:
2524 runs-on: ubuntu-latest
2625 steps:
27− - uses: actions/checkout@v3
28− - uses: mrkkrp/ormolu-action@v8
26+ - uses: actions/checkout@v4
27+ - uses: haskell-actions/run-ormolu@v15
28+ with:
29+ version: "0.5.0.1"
2930
3031 hlint:
3132 runs-on: ubuntu-latest
3233 steps:
33− - uses: actions/checkout@v3
34+ - uses: actions/checkout@v4
3435
35− - name: 'Set up HLint'
36− uses: haskell/actions/hlint-setup@v2
37− with:
38− version: '3.5'
36+ - name: "Set up HLint"
37+ uses: haskell-actions/hlint-setup@v2
38+ with:
39+ version: "3.5"
3940
40− - name: 'Run HLint'
41− uses: haskell/actions/hlint-run@v2
42− with:
43− path: '["src/", "test/", "examples"]'
44− fail-on: warning
41+ - name: "Run HLint"
42+ uses: haskell-actions/hlint-run@v2
43+ with:
44+ path: '["src/", "test/", "examples"]'
45+ fail-on: warning
4546
4647 cabal:
4748 name: ${{ matrix.os }} / ghc-${{ matrix.ghc }} / cabal-${{ matrix.cabal }}
@@ -49,180 +50,217 @@ jobs:
4950 needs: ormolu
5051 strategy:
5152 matrix:
52− os: [ubuntu-latest, windows-latest] # Removed macos-latest due to cert issues.
53− cabal: ["3.6", "3.8", "latest"]
53+ os: [ubuntu-latest, windows-latest, macos-latest]
54+ cabal: ["3.8", "latest"]
5455 ghc:
56+ - "9.8"
57+ - "9.6"
5558 - "9.4"
5659 - "9.2"
5760 - "9.0"
5861 - "8.10"
59− - "8.8"
60− - "8.6"
6162 exclude:
62− - os: windows-latest
63− ghc: "9.4"
64− cabal: "3.6"
63+ # macos llvm issue for versions less than 9.2
64+ - os: macos-latest
65+ ghc: "8.10"
66+ - os: macos-latest
67+ ghc: "9.0"
68+ # Cabal 3.8 supports GHC < 9.6
69+ - cabal: "3.8"
70+ ghc: "9.6"
71+ - cabal: "3.8"
72+ ghc: "9.8"
6573
6674 steps:
67− - uses: actions/checkout@v3
68− if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
69−
70− - uses: haskell/actions/setup@v2
71− id: setup-haskell-cabal
72− name: Setup Haskell
73− with:
74− ghc-version: ${{ matrix.ghc }}
75− cabal-version: ${{ matrix.cabal }}
76−
77− - name: Configure
78− run: |
79− cabal configure --enable-tests --enable-benchmarks --test-show-details=direct -fexamples -fdev -flive-test
80−
81− - name: Freeze
82− run: |
83− cabal freeze
84−
85− - uses: actions/cache@v3
86− name: Cache ~/.cabal/packages, ~/.cabal/store and dist-newstyle
87− with:
88− path: |
89− ~/.cabal/packages
90− ~/.cabal/store
91− dist-newstyle
92− key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('**/*.cabal', '**/cabal.project', '**/cabal.project.freeze') }}
93− restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
94−
95− - name: Install dependencies
96− run: |
97− cabal build --only-dependencies
98−
99− - name: Build
100− run: |
101− cabal build
102−
103− - name: Setup MinIO for testing (Linux)
104− if: matrix.os == 'ubuntu-latest'
105− run: |
106− mkdir -p /tmp/minio /tmp/minio-config/certs
107− cp test/cert/* /tmp/minio-config/certs/
108− (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/linux-amd64/minio; chmod +x ./minio)
109− sudo cp /tmp/minio-config/certs/public.crt /usr/local/share/ca-certificates/
110− sudo update-ca-certificates
111−
112− - name: Setup MinIO for testing (MacOS)
113− if: matrix.os == 'macos-latest'
114− run: |
115− mkdir -p /tmp/minio /tmp/minio-config/certs
116− cp test/cert/* /tmp/minio-config/certs/
117− (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/darwin-amd64/minio; chmod +x ./minio)
118− sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /tmp/minio-config/certs/public.crt
119−
120− - name: Setup MinIO for testing (Windows)
121− if: matrix.os == 'windows-latest'
122− run: |
123− New-Item -ItemType Directory -Path "$env:temp/minio-config/certs/"
124− Copy-Item -Path test\cert\* -Destination "$env:temp/minio-config/certs/"
125− Invoke-WebRequest -Uri https://dl.minio.io/server/minio/release/windows-amd64/minio.exe -OutFile $HOME/minio.exe
126− Import-Certificate -FilePath "$env:temp/minio-config/certs/public.crt" -CertStoreLocation Cert:\LocalMachine\Root
127−
128− - name: Test (Non-Windows)
129− if: matrix.os != 'windows-latest'
130− run: |
131− /tmp/minio/minio server --quiet --certs-dir /tmp/minio-config/certs data1 data2 data3 data4 2>&1 > minio.log &
132− ghc --version
133− cabal --version
134− cabal test
135−
136− - name: Test (Windows)
137− if: matrix.os == 'windows-latest'
138− run: |
139− Start-Process -NoNewWindow -FilePath "$HOME/minio.exe" -ArgumentList "--certs-dir", "$env:temp/minio-config/certs", "server", "$env:temp/data1", "$env:temp/data2", "$env:temp/data3", "$env:temp/data4"
140− ghc --version
141− cabal --version
142− cabal test
75+ - uses: actions/checkout@v4
76+ if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
77+
78+ - uses: haskell-actions/setup@v2
79+ id: setup
80+ name: Setup Haskell
81+ with:
82+ ghc-version: ${{ matrix.ghc }}
83+ cabal-version: ${{ matrix.cabal }}
84+ cabal-update: true
85+
86+ - name: Configure
87+ run: |
88+ cabal configure --enable-tests --enable-benchmarks --test-show-details=direct -fexamples -fdev -flive-test
89+ cabal build all --dry-run
90+ # The last step generates dist-newstyle/cache/plan.json for the cache key.
91+
92+ - name: Restore cached dependencies
93+ uses: actions/cache/restore@v4
94+ id: cache
95+ env:
96+ key: ${{ runner.os }}-ghc-${{ steps.setup.outputs.ghc-version }}-cabal-${{ steps.setup.outputs.cabal-version }}
97+ with:
98+ path: ${{ steps.setup.outputs.cabal-store }}
99+ key: ${{ env.key }}-plan-${{ hashFiles('**/plan.json') }}
100+ restore-keys: ${{ env.key }}-
101+
102+ - name: Install dependencies
103+ # If we had an exact cache hit, the dependencies will be up to date.
104+ if: steps.cache.outputs.cache-hit != 'true'
105+ run: cabal build all --only-dependencies
106+
107+ # Cache dependencies already here, so that we do not have to rebuild them should the subsequent steps fail.
108+ - name: Save cached dependencies
109+ uses: actions/cache/save@v4
110+ # If we had an exact cache hit, trying to save the cache would error because of key clash.
111+ if: steps.cache.outputs.cache-hit != 'true'
112+ with:
113+ path: ${{ steps.setup.outputs.cabal-store }}
114+ key: ${{ steps.cache.outputs.cache-primary-key }}
115+
116+ - name: Build
117+ run: |
118+ cabal build all
119+
120+ - name: Setup TLS certs for MinIO for testing (Linux)
121+ if: matrix.os == 'ubuntu-latest'
122+ run: |
123+ mkdir -p /tmp/minio /tmp/minio-config/certs
124+ cp test/cert/* /tmp/minio-config/certs/
125+ (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/linux-amd64/minio; chmod +x ./minio)
126+ sudo cp /tmp/minio-config/certs/public.crt /usr/local/share/ca-certificates/
127+ sudo update-ca-certificates
128+
129+ ## Currently disable TLS setup for MacOS due to issues in trusting it on MacOS.
130+ - name: Setup TLS certs for MinIO for testing (MacOS)
131+ if: matrix.os == 'macos-latest'
132+ run: |
133+ mkdir -p /tmp/minio /tmp/minio-config/certs
134+ cp test/cert/* /tmp/minio-config/certs/
135+ (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/darwin-amd64/minio; chmod +x ./minio)
136+ # sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /tmp/minio-config/certs/public.crt
137+
138+ - name: Setup MinIO for testing (Windows)
139+ if: matrix.os == 'windows-latest'
140+ run: |
141+ New-Item -ItemType Directory -Path "$env:temp/minio-config/certs/"
142+ Copy-Item -Path test\cert\* -Destination "$env:temp/minio-config/certs/"
143+ Invoke-WebRequest -Uri https://dl.minio.io/server/minio/release/windows-amd64/minio.exe -OutFile $HOME/minio.exe
144+ Import-Certificate -FilePath "$env:temp/minio-config/certs/public.crt" -CertStoreLocation Cert:\LocalMachine\Root
145+
146+ - name: Test (Linux)
147+ if: matrix.os == 'ubuntu-latest'
148+ env:
149+ MINIO_SECURE: 1
150+ run: |
151+ /tmp/minio/minio server --quiet --certs-dir /tmp/minio-config/certs data1 data2 data3 data4 2>&1 > minio.log &
152+ ghc --version
153+ cabal --version
154+ cabal test all
155+
156+ - name: Test (MacOS)
157+ if: matrix.os == 'macos-latest'
158+ # # Leave MINIO_SECURE unset to disable TLS in tests.
159+ # env:
160+ # MINIO_SECURE: 1
161+ run: |
162+ /tmp/minio/minio server --quiet data1 data2 data3 data4 2>&1 > minio.log &
163+ ghc --version
164+ cabal --version
165+ cabal test all
166+
167+ - name: Test (Windows)
168+ if: matrix.os == 'windows-latest'
169+ env:
170+ MINIO_SECURE: 1
171+ run: |
172+ Start-Process -NoNewWindow -FilePath "$HOME/minio.exe" -ArgumentList "--certs-dir", "$env:temp/minio-config/certs", "server", "$env:temp/data1", "$env:temp/data2", "$env:temp/data3", "$env:temp/data4"
173+ ghc --version
174+ cabal --version
175+ cabal test all
143176
144177 stack:
145178 name: stack / ghc ${{ matrix.ghc }}
146179 runs-on: ${{ matrix.os }}
180+ env:
181+ MINIO_SECURE: 1
147182 strategy:
148183 matrix:
149184 ghc:
150185 - "8.10.7"
151186 - "9.0.2"
152− - "9.2.4"
187+ - "9.2.8"
188+ - "9.4.8"
189+ - "9.6.5"
190+ - "9.8.2"
153191 os: [ubuntu-latest]
154192
155193 steps:
156− - uses: actions/checkout@v3
157− if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
158−
159− - uses: haskell/actions/setup@v2
160− name: Setup Haskell Stack
161− with:
162− enable-stack: true
163− ghc-version: ${{ matrix.ghc }}
164− stack-version: 'latest'
165−
166− - uses: actions/cache@v3
167− name: Cache ~/.stack
168− with:
169− path: ~/.stack
170− key: ${{ runner.os }}-stack-global-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }}
171− restore-keys: |
172− ${{ runner.os }}-stack-global-
173− - uses: actions/cache@v3
174− name: Cache .stack-work
175− with:
176− path: .stack-work
177− key: ${{ runner.os }}-stack-work-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }}-${{ hashFiles('**/*.hs') }}
178− restore-keys: |
179− ${{ runner.os }}-stack-work-
180−
181− - name: Install dependencies
182− run: |
183− stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --only-dependencies
184−
185− - name: Build
186− run: |
187− stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --flag minio-hs:examples --flag minio-hs:live-test --flag minio-hs:dev
188−
189− - name: Setup MinIO for testing (Linux)
190− if: matrix.os == 'ubuntu-latest'
191− run: |
192− mkdir -p /tmp/minio /tmp/minio-config/certs
193− cp test/cert/* /tmp/minio-config/certs/
194− (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/linux-amd64/minio; chmod +x ./minio)
195− sudo cp /tmp/minio-config/certs/public.crt /usr/local/share/ca-certificates/
196− sudo update-ca-certificates
197−
198− - name: Setup MinIO for testing (MacOS)
199− if: matrix.os == 'macos-latest'
200− run: |
201− mkdir -p /tmp/minio /tmp/minio-config/certs
202− cp test/cert/* /tmp/minio-config/certs/
203− (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/darwin-amd64/minio; chmod +x ./minio)
204− sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /tmp/minio-config/certs/public.crt
205−
206− - name: Setup MinIO for testing (Windows)
207− if: matrix.os == 'windows-latest'
208− run: |
209− New-Item -ItemType Directory -Path "$env:temp/minio-config/certs/"
210− Copy-Item -Path test\cert\* -Destination "$env:temp/minio-config/certs/"
211− Invoke-WebRequest -Uri https://dl.minio.io/server/minio/release/windows-amd64/minio.exe -OutFile $HOME/minio.exe
212− Import-Certificate -FilePath "$env:temp/minio-config/certs/public.crt" -CertStoreLocation Cert:\LocalMachine\Root
213−
214− - name: Test (Non-Windows)
215− if: matrix.os != 'windows-latest'
216− run: |
217− /tmp/minio/minio server --quiet --certs-dir /tmp/minio-config/certs data1 data2 data3 data4 2>&1 > minio.log &
218− ghc --version
219− stack --version
220− stack test --system-ghc --flag minio-hs:live-test --flag minio-hs:dev
221−
222− - name: Test (Windows)
223− if: matrix.os == 'windows-latest'
224− run: |
225− Start-Process -NoNewWindow -FilePath "$HOME/minio.exe" -ArgumentList "--certs-dir", "$env:temp/minio-config/certs", "server", "$env:temp/data1", "$env:temp/data2", "$env:temp/data3", "$env:temp/data4"
226− ghc --version
227− cabal --version
228− stack test --system-ghc --flag minio-hs:live-test --flag minio-hs:dev
194+ - uses: actions/checkout@v4
195+ if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
196+
197+ - uses: haskell-actions/setup@v2
198+ with:
199+ ghc-version: ${{ matrix.ghc }}
200+ enable-stack: true
201+ stack-version: "latest"
202+
203+ - uses: actions/cache@v4
204+ name: Cache ~/.stack
205+ with:
206+ path: ~/.stack
207+ key: ${{ runner.os }}-stack-global-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }}
208+ restore-keys: |
209+ ${{ runner.os }}-stack-global-
210+ - uses: actions/cache@v4
211+ name: Cache .stack-work
212+ with:
213+ path: .stack-work
214+ key: ${{ runner.os }}-stack-work-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }}-${{ hashFiles('**/*.hs') }}
215+ restore-keys: |
216+ ${{ runner.os }}-stack-work-
217+
218+ - name: Install dependencies
219+ run: |
220+ stack --version
221+ stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --only-dependencies
222+
223+ - name: Build
224+ run: |
225+ stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --flag minio-hs:examples --flag minio-hs:live-test --flag minio-hs:dev
226+
227+ - name: Setup MinIO for testing (Linux)
228+ if: matrix.os == 'ubuntu-latest'
229+ run: |
230+ mkdir -p /tmp/minio /tmp/minio-config/certs
231+ cp test/cert/* /tmp/minio-config/certs/
232+ (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/linux-amd64/minio; chmod +x ./minio)
233+ sudo cp /tmp/minio-config/certs/public.crt /usr/local/share/ca-certificates/
234+ sudo update-ca-certificates
235+
236+ - name: Setup MinIO for testing (MacOS)
237+ if: matrix.os == 'macos-latest'
238+ run: |
239+ mkdir -p /tmp/minio /tmp/minio-config/certs
240+ cp test/cert/* /tmp/minio-config/certs/
241+ (cd /tmp/minio; wget -q https://dl.min.io/server/minio/release/darwin-amd64/minio; chmod +x ./minio)
242+ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /tmp/minio-config/certs/public.crt
243+
244+ - name: Setup MinIO for testing (Windows)
245+ if: matrix.os == 'windows-latest'
246+ run: |
247+ New-Item -ItemType Directory -Path "$env:temp/minio-config/certs/"
248+ Copy-Item -Path test\cert\* -Destination "$env:temp/minio-config/certs/"
249+ Invoke-WebRequest -Uri https://dl.minio.io/server/minio/release/windows-amd64/minio.exe -OutFile $HOME/minio.exe
250+ Import-Certificate -FilePath "$env:temp/minio-config/certs/public.crt" -CertStoreLocation Cert:\LocalMachine\Root
251+
252+ - name: Test (Non-Windows)
253+ if: matrix.os != 'windows-latest'
254+ run: |
255+ /tmp/minio/minio server --quiet --certs-dir /tmp/minio-config/certs data1 data2 data3 data4 2>&1 > minio.log &
256+ ghc --version
257+ stack --version
258+ stack test --system-ghc --flag minio-hs:live-test --flag minio-hs:dev
259+
260+ - name: Test (Windows)
261+ if: matrix.os == 'windows-latest'
262+ run: |
263+ Start-Process -NoNewWindow -FilePath "$HOME/minio.exe" -ArgumentList "--certs-dir", "$env:temp/minio-config/certs", "server", "$env:temp/data1", "$env:temp/data2", "$env:temp/data3", "$env:temp/data4"
264+ ghc --version
265+ cabal --version
266+ stack test --system-ghc --flag minio-hs:live-test --flag minio-hs:dev
minio-hs.cabal+8−7
@@ -1,6 +1,6 @@
11cabal-version: 2.4
22name: minio-hs
3−version: 1.6.0
3+version: 1.7.0
44synopsis: A MinIO Haskell Library for Amazon S3 compatible cloud
55 storage.
66description: The MinIO Haskell client library provides simple APIs to
@@ -22,12 +22,12 @@ extra-doc-files:
2222extra-source-files:
2323 examples/*.hs
2424 stack.yaml
25−tested-with: GHC == 8.6.5
26− , GHC == 8.8.4
27− , GHC == 8.10.7
25+tested-with: GHC == 8.10.7
2826 , GHC == 9.0.2
29− , GHC == 9.2.7
30− , GHC == 9.4.5
27+ , GHC == 9.2.8
28+ , GHC == 9.4.8
29+ , GHC == 9.6.5
30+ , GHC == 9.8.2
3131
3232source-repository head
3333 type: git
@@ -114,9 +114,10 @@ common base-settings
114114 , case-insensitive >= 1.2
115115 , conduit >= 1.3
116116 , conduit-extra >= 1.3
117− , connection
117+ , crypton-connection
118118 , cryptonite >= 0.25
119119 , cryptonite-conduit >= 0.2
120+ , data-default-class
120121 , digest >= 0.0.1
121122 , directory
122123 , filepath >= 1.4
src/Lib/Prelude.hs+1−1
@@ -42,7 +42,7 @@ import UnliftIO as Exports
4242both :: (a -> b) -> (a, a) -> (b, b)
4343both f (a, b) = (f a, f b)
4444
45−showBS :: Show a => a -> ByteString
45+showBS :: (Show a) => a -> ByteString
4646showBS a = encodeUtf8 (show a :: Text)
4747
4848toStrictBS :: LByteString -> ByteString
src/Network/Minio/API.hs+3−3
@@ -150,7 +150,7 @@ getHostPathRegion ri = do
150150-- | requestSTSCredential requests temporary credentials using the Security Token
151151-- Service API. The returned credential will include a populated 'SessionToken'
152152-- and an 'ExpiryTime'.
153−requestSTSCredential :: STSCredentialProvider p => p -> IO (CredentialValue, ExpiryTime)
153+requestSTSCredential :: (STSCredentialProvider p) => p -> IO (CredentialValue, ExpiryTime)
154154requestSTSCredential p = do
155155 endpoint <- maybe (throwIO $ MErrValidation MErrVSTSEndpointNotFound) return $ getSTSEndpoint p
156156 let endPt = NC.parseRequest_ $ toString endpoint
@@ -337,7 +337,7 @@ isValidBucketName bucket =
337337 isIPCheck = and labelAsNums && length labelAsNums == 4
338338
339339-- Throws exception iff bucket name is invalid according to AWS rules.
340−checkBucketNameValidity :: MonadIO m => Bucket -> m ()
340+checkBucketNameValidity :: (MonadIO m) => Bucket -> m ()
341341checkBucketNameValidity bucket =
342342 unless (isValidBucketName bucket) $
343343 throwIO $
@@ -347,7 +347,7 @@ isValidObjectName :: Object -> Bool
347347isValidObjectName object =
348348 T.length object > 0 && B.length (encodeUtf8 object) <= 1024
349349
350−checkObjectNameValidity :: MonadIO m => Object -> m ()
350+checkObjectNameValidity :: (MonadIO m) => Object -> m ()
351351checkObjectNameValidity object =
352352 unless (isValidObjectName object) $
353353 throwIO $
src/Network/Minio/Credentials.hs+1−1
@@ -47,7 +47,7 @@ data STSCredentialStore = STSCredentialStore
4747 refreshAction :: Endpoint -> NC.Manager -> IO (CredentialValue, ExpiryTime)
4848 }
4949
50−initSTSCredential :: STSCredentialProvider p => p -> IO STSCredentialStore
50+initSTSCredential :: (STSCredentialProvider p) => p -> IO STSCredentialStore
5151initSTSCredential p = do
5252 let action = retrieveSTSCredentials p
5353 -- start with dummy credential, so that refresh happens for first request.
src/Network/Minio/Credentials/AssumeRole.hs+3−1
@@ -41,6 +41,8 @@ defaultDurationSeconds :: Second
4141defaultDurationSeconds = 3600
4242
4343-- | Assume Role API argument.
44+--
45+-- @since 1.7.0
4446data STSAssumeRole = STSAssumeRole
4547 { -- | Credentials to use in the AssumeRole STS API.
4648 sarCredentials :: CredentialValue,
@@ -119,7 +121,7 @@ data AssumeRoleResult = AssumeRoleResult
119121-- <RequestId>c6104cbe-af31-11e0-8154-cbc7ccf896c7</RequestId>
120122-- </ResponseMetadata>
121123-- </AssumeRoleResponse>
122−parseSTSAssumeRoleResult :: MonadIO m => ByteString -> Text -> m AssumeRoleResult
124+parseSTSAssumeRoleResult :: (MonadIO m) => ByteString -> Text -> m AssumeRoleResult
123125parseSTSAssumeRoleResult xmldata namespace = do
124126 r <- parseRoot $ LB.fromStrict xmldata
125127 let s3Elem' = s3Elem namespace
src/Network/Minio/Credentials/Types.hs+7−2
@@ -14,6 +14,7 @@
1414-- limitations under the License.
1515--
1616{-# LANGUAGE GeneralizedNewtypeDeriving #-}
17+{-# LANGUAGE StrictData #-}
1718
1819module Network.Minio.Credentials.Types where
1920
@@ -37,11 +38,13 @@ newtype SessionToken = SessionToken {unSessionToken :: BA.ScrubbedBytes}
3738 deriving newtype (Eq, IsString, Semigroup, Monoid)
3839
3940-- | Object storage credential data type. It has support for the optional
40−-- <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html
41−-- SessionToken> for using temporary credentials requested via STS.
41+-- [SessionToken](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)
42+-- for using temporary credentials requested via STS.
4243--
4344-- The show instance for this type does not print the value of secrets for
4445-- security.
46+--
47+-- @since 1.7.0
4548data CredentialValue = CredentialValue
4649 { cvAccessKey :: AccessKey,
4750 cvSecretKey :: SecretKey,
@@ -70,6 +73,8 @@ credentialValueText cv =
7073type Endpoint = (ByteString, Int, Bool)
7174
7275-- | Typeclass for STS credential providers.
76+--
77+-- @since 1.7.0
7378class STSCredentialProvider p where
7479 retrieveSTSCredentials ::
7580 p ->
src/Network/Minio/Data.hs+12−11
@@ -16,6 +16,7 @@
1616{-# LANGUAGE CPP #-}
1717{-# LANGUAGE GADTs #-}
1818{-# LANGUAGE GeneralizedNewtypeDeriving #-}
19+{-# LANGUAGE StrictData #-}
1920{-# LANGUAGE TypeFamilies #-}
2021
2122module Network.Minio.Data where
@@ -34,6 +35,7 @@ import qualified Data.Aeson as A
3435import qualified Data.ByteArray as BA
3536import qualified Data.ByteString as B
3637import qualified Data.ByteString.Lazy as LB
38+import Data.Default.Class (def)
3739import qualified Data.HashMap.Strict as H
3840import qualified Data.Ini as Ini
3941import qualified Data.List as List
@@ -156,15 +158,10 @@ instance IsString ConnectInfo where
156158 connectDisableTLSCertValidation = False
157159 }
158160
159−-- | Contains access key and secret key to access object storage.
160−data Credentials = Credentials
161− { cAccessKey :: Text,
162− cSecretKey :: Text
163− }
164− deriving stock (Eq, Show)
165−
166161-- | A 'CredentialLoader' is an action that may return a 'CredentialValue'.
167162-- Loaders may be chained together using 'findFirst'.
163+--
164+-- @since 1.7.0
168165type CredentialLoader = IO (Maybe CredentialValue)
169166
170167-- | Combines the given list of loaders, by calling each one in
@@ -232,7 +229,7 @@ setCreds cv connInfo =
232229-- | 'setSTSCredential' configures `ConnectInfo` to retrieve temporary
233230-- credentials via the STS API on demand. It is automatically refreshed on
234231-- expiry.
235−setSTSCredential :: STSCredentialProvider p => p -> ConnectInfo -> IO ConnectInfo
232+setSTSCredential :: (STSCredentialProvider p) => p -> ConnectInfo -> IO ConnectInfo
236233setSTSCredential p ci = do
237234 store <- initSTSCredential p
238235 return ci {connectCreds = CredsSTS store}
@@ -308,7 +305,7 @@ newtype SSECKey = SSECKey BA.ScrubbedBytes
308305
309306-- | Validates that the given ByteString is 32 bytes long and creates
310307-- an encryption key.
311−mkSSECKey :: MonadThrow m => ByteString -> m SSECKey
308+mkSSECKey :: (MonadThrow m) => ByteString -> m SSECKey
312309mkSSECKey keyBytes
313310 | B.length keyBytes /= 32 =
314311 throwM MErrVInvalidEncryptionKeyLength
@@ -325,7 +322,7 @@ data SSE where
325322 -- argument is the optional KMS context that must have a
326323 -- `A.ToJSON` instance - please refer to the AWS S3 documentation
327324 -- for detailed information.
328− SSEKMS :: A.ToJSON a => Maybe ByteString -> Maybe a -> SSE
325+ SSEKMS :: (A.ToJSON a) => Maybe ByteString -> Maybe a -> SSE
329326 -- | Specifies server-side encryption with customer provided
330327 -- key. The argument is the encryption key to be used.
331328 SSEC :: SSECKey -> SSE
@@ -1119,7 +1116,11 @@ connect :: ConnectInfo -> IO MinioConn
11191116connect ci = do
11201117 let settings
11211118 | connectIsSecure ci && connectDisableTLSCertValidation ci =
1122− let badTlsSettings = Conn.TLSSettingsSimple True False False
1119+ let badTlsSettings =
1120+ case def of
1121+ tlsSettings@Conn.TLSSettingsSimple {} ->
1122+ tlsSettings {Conn.settingDisableCertificateValidation = True}
1123+ _ -> def
11231124 in TLS.mkManagerSettings badTlsSettings Nothing
11241125 | connectIsSecure ci = NC.tlsManagerSettings
11251126 | otherwise = defaultManagerSettings
src/Network/Minio/Data/Crypto.hs+8−8
@@ -43,26 +43,26 @@ import qualified Data.Conduit as C
4343hashSHA256 :: ByteString -> ByteString
4444hashSHA256 = digestToBase16 . hashWith SHA256
4545
46−hashSHA256FromSource :: Monad m => C.ConduitM () ByteString m () -> m ByteString
46+hashSHA256FromSource :: (Monad m) => C.ConduitM () ByteString m () -> m ByteString
4747hashSHA256FromSource src = do
4848 digest <- C.connect src sinkSHA256Hash
4949 return $ digestToBase16 digest
5050 where
5151 -- To help with type inference
52− sinkSHA256Hash :: Monad m => C.ConduitM ByteString Void m (Digest SHA256)
52+ sinkSHA256Hash :: (Monad m) => C.ConduitM ByteString Void m (Digest SHA256)
5353 sinkSHA256Hash = sinkHash
5454
5555-- Returns MD5 hash hex encoded.
5656hashMD5 :: ByteString -> ByteString
5757hashMD5 = digestToBase16 . hashWith MD5
5858
59−hashMD5FromSource :: Monad m => C.ConduitM () ByteString m () -> m ByteString
59+hashMD5FromSource :: (Monad m) => C.ConduitM () ByteString m () -> m ByteString
6060hashMD5FromSource src = do
6161 digest <- C.connect src sinkMD5Hash
6262 return $ digestToBase16 digest
6363 where
6464 -- To help with type inference
65− sinkMD5Hash :: Monad m => C.ConduitM ByteString Void m (Digest MD5)
65+ sinkMD5Hash :: (Monad m) => C.ConduitM ByteString Void m (Digest MD5)
6666 sinkMD5Hash = sinkHash
6767
6868hmacSHA256 :: ByteString -> ByteString -> HMAC SHA256
@@ -71,15 +71,15 @@ hmacSHA256 message key = hmac key message
7171hmacSHA256RawBS :: ByteString -> ByteString -> ByteString
7272hmacSHA256RawBS message key = convert $ hmacSHA256 message key
7373
74−digestToBS :: ByteArrayAccess a => a -> ByteString
74+digestToBS :: (ByteArrayAccess a) => a -> ByteString
7575digestToBS = convert
7676
77−digestToBase16 :: ByteArrayAccess a => a -> ByteString
77+digestToBase16 :: (ByteArrayAccess a) => a -> ByteString
7878digestToBase16 = convertToBase Base16
7979
8080-- Returns MD5 hash base 64 encoded.
81−hashMD5ToBase64 :: ByteArrayAccess a => a -> ByteString
81+hashMD5ToBase64 :: (ByteArrayAccess a) => a -> ByteString
8282hashMD5ToBase64 = convertToBase Base64 . hashWith MD5
8383
84−encodeToBase64 :: ByteArrayAccess a => a -> ByteString
84+encodeToBase64 :: (ByteArrayAccess a) => a -> ByteString
8585encodeToBase64 = convertToBase Base64
src/Network/Minio/SelectAPI.hs+7−7
@@ -119,7 +119,7 @@ instance Exception EventStreamException
119119chunkSize :: Int
120120chunkSize = 32 * 1024
121121
122−parseBinary :: Bin.Binary a => ByteString -> IO a
122+parseBinary :: (Bin.Binary a) => ByteString -> IO a
123123parseBinary b = do
124124 case Bin.decodeOrFail $ LB.fromStrict b of
125125 Left (_, _, msg) -> throwIO $ ESEDecodeFail msg
@@ -135,7 +135,7 @@ bytesToHeaderName t = case t of
135135 _ -> throwIO ESEInvalidHeaderType
136136
137137parseHeaders ::
138− MonadUnliftIO m =>
138+ (MonadUnliftIO m) =>
139139 Word32 ->
140140 C.ConduitM ByteString a m [MessageHeader]
141141parseHeaders 0 = return []
@@ -163,7 +163,7 @@ parseHeaders hdrLen = do
163163
164164-- readNBytes returns N bytes read from the string and throws an
165165-- exception if N bytes are not present on the stream.
166−readNBytes :: MonadUnliftIO m => Int -> C.ConduitM ByteString a m ByteString
166+readNBytes :: (MonadUnliftIO m) => Int -> C.ConduitM ByteString a m ByteString
167167readNBytes n = do
168168 b <- LB.toStrict <$> (C.takeCE n .| C.sinkLazy)
169169 if B.length b /= n
@@ -171,7 +171,7 @@ readNBytes n = do
171171 else return b
172172
173173crcCheck ::
174− MonadUnliftIO m =>
174+ (MonadUnliftIO m) =>
175175 C.ConduitM ByteString ByteString m ()
176176crcCheck = do
177177 b <- readNBytes 12
@@ -208,7 +208,7 @@ crcCheck = do
208208 then accumulateYield n' c'
209209 else return c'
210210
211−handleMessage :: MonadUnliftIO m => C.ConduitT ByteString EventMessage m ()
211+handleMessage :: (MonadUnliftIO m) => C.ConduitT ByteString EventMessage m ()
212212handleMessage = do
213213 b1 <- readNBytes 4
214214 msgLen :: Word32 <- liftIO $ parseBinary b1
@@ -254,7 +254,7 @@ handleMessage = do
254254 passThrough $ n - B.length b
255255
256256selectProtoConduit ::
257− MonadUnliftIO m =>
257+ (MonadUnliftIO m) =>
258258 C.ConduitT ByteString EventMessage m ()
259259selectProtoConduit = crcCheck .| handleMessage
260260
@@ -281,7 +281,7 @@ selectObjectContent b o r = do
281281 return $ NC.responseBody resp .| selectProtoConduit
282282
283283-- | A helper conduit that returns only the record payload bytes.
284−getPayloadBytes :: MonadIO m => C.ConduitT EventMessage ByteString m ()
284+getPayloadBytes :: (MonadIO m) => C.ConduitT EventMessage ByteString m ()
285285getPayloadBytes = do
286286 evM <- C.await
287287 case evM of
src/Network/Minio/Sign/V4.hs+1−1
@@ -346,7 +346,7 @@ chunkSizeConstant = 64 * 1024
346346
347347-- base16Len computes the number of bytes required to represent @n (> 0)@ in
348348-- hexadecimal.
349−base16Len :: Integral a => a -> Int
349+base16Len :: (Integral a) => a -> Int
350350base16Len n
351351 | n == 0 = 0
352352 | otherwise = 1 + base16Len (n `div` 16)
src/Network/Minio/Utils.hs+2−2
@@ -175,7 +175,7 @@ isSuccessStatus sts =
175175 in (s >= 200 && s < 300)
176176
177177httpLbs ::
178− MonadIO m =>
178+ (MonadIO m) =>
179179 NC.Request ->
180180 NC.Manager ->
181181 m (NC.Response LByteString)
@@ -239,7 +239,7 @@ http req mgr = do
239239-- Similar to mapConcurrently but limits the number of threads that
240240-- can run using a quantity semaphore.
241241limitedMapConcurrently ::
242− MonadUnliftIO m =>
242+ (MonadUnliftIO m) =>
243243 Int ->
244244 (t -> m a) ->
245245 [t] ->
src/Network/Minio/XmlCommon.hs+1−1
@@ -35,7 +35,7 @@ uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g
3535uncurry6 f (a, b, c, d, e, g) = f a b c d e g
3636
3737-- | Parse time strings from XML
38−parseS3XMLTime :: MonadIO m => Text -> m UTCTime
38+parseS3XMLTime :: (MonadIO m) => Text -> m UTCTime
3939parseS3XMLTime t =
4040 maybe (throwIO $ MErrVXmlParse $ "timestamp parse failure: " <> t) return $
4141 iso8601ParseM $
src/Network/Minio/XmlParser.hs+1−1
@@ -218,7 +218,7 @@ parseNotification xmldata = do
218218 events
219219 (Filter $ FilterKey $ FilterRules rules)
220220
221−parseSelectProgress :: MonadIO m => ByteString -> m Progress
221+parseSelectProgress :: (MonadIO m) => ByteString -> m Progress
222222parseSelectProgress xmldata = do
223223 r <- parseRoot $ LB.fromStrict xmldata
224224 let bScanned = T.concat $ r $/ element "BytesScanned" &/ content
stack.yaml+4−4
@@ -15,7 +15,7 @@
1515# resolver:
1616# name: custom-snapshot
1717# location: "./custom-snapshot.yaml"
18−resolver: lts-19.7
18+resolver: lts-22.19
1919
2020# User packages to be built.
2121# Various formats can be used as shown in the example below.
@@ -36,17 +36,17 @@ resolver: lts-19.7
3636# non-dependency (i.e. a user package), and its test suites and benchmarks
3737# will not be run. This is useful for tweaking upstream packages.
3838packages:
39−- '.'
39+ - "."
4040# Dependency packages to be pulled from upstream that are not in the resolver
4141# (e.g., acme-missiles-0.3)
42−extra-deps: []
42+extra-deps:
43+ - crypton-connection-0.3.2
4344
4445# Override default flag values for local packages and extra-deps
4546flags: {}
4647
4748# Extra package databases containing global packages
4849extra-package-dbs: []
49−
5050# Control whether we use the GHC we find on the path
5151# system-ghc: true
5252#
stack.yaml.lock+12−5
@@ -3,10 +3,17 @@
33# For more information, please see the documentation at:
44# https://docs.haskellstack.org/en/stable/lock_files
55
6−packages: []
6+packages:
7+- completed:
8+ hackage: crypton-connection-0.3.2@sha256:c7937edc25ab022bcf167703f2ec5ab73b62908e545bb587d2aa42b33cd6f6cc,1581
9+ pantry-tree:
10+ sha256: f986ad29b008cbe5732606e9cde1897191c486a2f1f169a4cb75fd915bce397c
11+ size: 394
12+ original:
13+ hackage: crypton-connection-0.3.2
714snapshots:
815- completed:
9− size: 618884
10− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/7.yaml
11− sha256: 57d4ce67cc097fea2058446927987bc1f7408890e3a6df0da74e5e318f051c20
12− original: lts-19.7
16+ sha256: e5cac927cf7ccbd52aa41476baa68b88c564ee6ddc3bc573dbf4210069287fe7
17+ size: 713340
18+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/19.yaml
19+ original: lts-22.19
test/LiveServer.hs+69−33
@@ -49,8 +49,53 @@ main = defaultMain tests
4949tests :: TestTree
5050tests = testGroup "Tests" [liveServerUnitTests]
5151
52+lookupTestEnv :: IO (Maybe ConnectInfo, (AccessKey, SecretKey))
53+lookupTestEnv = do
54+ val <- Env.lookupEnv "MINIO_LOCAL"
55+ secure <- Env.lookupEnv "MINIO_SECURE"
56+ let localServerMaybe = case (val, secure) of
57+ (Just _, Just _) -> Just "https://localhost:9000"
58+ (Just _, Nothing) -> Just "http://localhost:9000"
59+ _ -> Nothing
60+ accessKeyE <- Env.lookupEnv "MINIO_ACCESS_KEY"
61+ let accessKey = maybe "minioadmin" fromString accessKeyE
62+ secretKeyE <- Env.lookupEnv "MINIO_SECRET_KEY"
63+ let secretKey = maybe "minioadmin" fromString secretKeyE
64+ return (localServerMaybe, (accessKey, secretKey))
65+
66+loadTestServerConnInfo :: IO ConnectInfo
67+loadTestServerConnInfo = do
68+ (localServerMaybe, (ak, sk)) <- lookupTestEnv
69+ return $ case localServerMaybe of
70+ Just localServer -> do
71+ setCreds (CredentialValue ak sk mempty) localServer
72+ _ -> minioPlayCI
73+
74+loadTestServerConnInfoSTS :: IO ConnectInfo
75+loadTestServerConnInfoSTS = do
76+ (localServerMaybe, (ak, sk)) <- lookupTestEnv
77+ case localServerMaybe of
78+ Just localServer -> do
79+ let creds = CredentialValue ak sk mempty
80+ assumeRole =
81+ STSAssumeRole
82+ { sarCredentials = creds,
83+ sarOptions = defaultSTSAssumeRoleOptions
84+ }
85+ setSTSCredential assumeRole localServer
86+ Nothing -> do
87+ let creds = case connectCreds minioPlayCI of
88+ CredsStatic c -> c
89+ _ -> error "unexpected play creds"
90+ assumeRole =
91+ STSAssumeRole
92+ { sarCredentials = creds,
93+ sarOptions = defaultSTSAssumeRoleOptions
94+ }
95+ setSTSCredential assumeRole minioPlayCI
96+
5297-- conduit that generates random binary stream of given length
53−randomDataSrc :: MonadIO m => Int64 -> C.ConduitM () ByteString m ()
98+randomDataSrc :: (MonadIO m) => Int64 -> C.ConduitM () ByteString m ()
5499randomDataSrc = genBS
55100 where
56101 concatIt bs n =
@@ -68,7 +113,7 @@ randomDataSrc = genBS
68113 yield $ concatIt byteArr64 oneMiB
69114 genBS (s - oneMiB)
70115
71−mkRandFile :: R.MonadResource m => Int64 -> m FilePath
116+mkRandFile :: (R.MonadResource m) => Int64 -> m FilePath
72117mkRandFile size = do
73118 dir <- liftIO getTemporaryDirectory
74119 C.runConduit $ randomDataSrc size C..| CB.sinkTempFile dir "miniohstest.random"
@@ -76,34 +121,24 @@ mkRandFile size = do
76121funTestBucketPrefix :: Text
77122funTestBucketPrefix = "miniohstest-"
78123
79−loadTestServerConnInfo :: IO ConnectInfo
80−loadTestServerConnInfo = do
81− val <- Env.lookupEnv "MINIO_LOCAL"
82− isSecure <- Env.lookupEnv "MINIO_SECURE"
83− return $ case (val, isSecure) of
84− (Just _, Just _) -> setCreds (CredentialValue "minio" "minio123" mempty) "https://localhost:9000"
85− (Just _, Nothing) -> setCreds (CredentialValue "minio" "minio123" mempty) "http://localhost:9000"
86− (Nothing, _) -> minioPlayCI
87−
88−loadTestServerConnInfoSTS :: IO ConnectInfo
89−loadTestServerConnInfoSTS = do
90− val <- Env.lookupEnv "MINIO_LOCAL"
91− isSecure <- Env.lookupEnv "MINIO_SECURE"
92− let cv = CredentialValue "minio" "minio123" mempty
93− assumeRole =
94− STSAssumeRole
95− { sarCredentials = cv,
96− sarOptions = defaultSTSAssumeRoleOptions
97− }
98− case (val, isSecure) of
99− (Just _, Just _) -> setSTSCredential assumeRole "https://localhost:9000"
100− (Just _, Nothing) -> setSTSCredential assumeRole "http://localhost:9000"
101− (Nothing, _) -> do
102− cv' <- case connectCreds minioPlayCI of
103− CredsStatic c -> return c
104− _ -> error "unexpected play creds"
105− let assumeRole' = assumeRole {sarCredentials = cv'}
106− setSTSCredential assumeRole' minioPlayCI
124+funTestWithBucketNoSTS ::
125+ TestName ->
126+ (([Char] -> Minio ()) -> Bucket -> Minio ()) ->
127+ TestTree
128+funTestWithBucketNoSTS t minioTest = testCaseSteps t $ \step -> do
129+ -- generate a random name for the bucket
130+ bktSuffix <- liftIO $ generate $ Q.vectorOf 10 (Q.choose ('a', 'z'))
131+ let b = T.concat [funTestBucketPrefix, T.pack bktSuffix]
132+ liftStep = liftIO . step
133+ connInfo <- loadTestServerConnInfo
134+ ret <- runMinio connInfo $ do
135+ liftStep $ "Creating bucket for test - " ++ t
136+ foundBucket <- bucketExists b
137+ liftIO $ foundBucket @?= False
138+ makeBucket b Nothing
139+ minioTest liftStep b
140+ deleteBucket b
141+ isRight ret @? ("Functional test " ++ t ++ " failed => " ++ show ret)
107142
108143funTestWithBucket ::
109144 TestName ->
@@ -603,7 +638,7 @@ presignedUrlFunTest = funTestWithBucket "presigned Url tests" $
603638 []
604639 []
605640
606− print putUrl
641+ -- print putUrl
607642 let size1 = 1000 :: Int64
608643 inputFile <- mkRandFile size1
609644
@@ -692,7 +727,7 @@ presignedUrlFunTest = funTestWithBucket "presigned Url tests" $
692727 NC.httpLbs req mgr
693728
694729presignedPostPolicyFunTest :: TestTree
695−presignedPostPolicyFunTest = funTestWithBucket "Presigned Post Policy tests" $
730+presignedPostPolicyFunTest = funTestWithBucketNoSTS "Presigned Post Policy tests" $
696731 \step bucket -> do
697732 step "presignedPostPolicy basic test"
698733 now <- liftIO Time.getCurrentTime
@@ -1222,9 +1257,10 @@ getNPutSSECTest =
12221257assumeRoleRequestTest :: TestTree
12231258assumeRoleRequestTest = testCaseSteps "Assume Role STS API" $ \step -> do
12241259 step "Load credentials"
1260+ (_, (ak, sk)) <- lookupTestEnv
12251261 val <- Env.lookupEnv "MINIO_LOCAL"
12261262 isSecure <- Env.lookupEnv "MINIO_SECURE"
1227− let localMinioCred = Just $ CredentialValue "minio" "minio123" mempty
1263+ let localMinioCred = Just $ CredentialValue ak sk mempty
12281264 playCreds =
12291265 case connectCreds minioPlayCI of
12301266 CredsStatic c -> Just c