complete support for S3 signature=anonymous
aws-0.23 has been released. When built with an older aws, initremote will error out when run with signature=anonymous. And when a remote has been initialized with that by a version of git-annex that does support it, older versions will fail when the remote is accessed, with a useful error message. Sponsored-by: Dartmouth College's DANDI project
This commit is contained in:
parent
f3fbdddb8a
commit
e100993935
4 changed files with 55 additions and 37 deletions
|
@ -1,6 +1,11 @@
|
||||||
|
git-annex (10.20221104) upstream; urgency=medium
|
||||||
|
|
||||||
* S3: Support signature=anonymous to access a S3 bucket anonymously.
|
* S3: Support signature=anonymous to access a S3 bucket anonymously.
|
||||||
This can be used, for example, with importtree=yes to import from
|
This can be used, for example, with importtree=yes to import from
|
||||||
a public bucket.
|
a public bucket.
|
||||||
|
This feature needs git-annex to be built with aws-0.23.
|
||||||
|
|
||||||
|
-- Joey Hess <id@joeyh.name> Thu, 03 Nov 2022 14:07:31 -0400
|
||||||
|
|
||||||
git-annex (10.20221103) upstream; urgency=medium
|
git-annex (10.20221103) upstream; urgency=medium
|
||||||
|
|
||||||
|
|
83
Remote/S3.hs
83
Remote/S3.hs
|
@ -415,19 +415,20 @@ storeHelper info h magic f object p = liftIO $ case partSize info of
|
||||||
- that is difficult. -}
|
- that is difficult. -}
|
||||||
retrieve :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> Retriever
|
retrieve :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> Retriever
|
||||||
retrieve hv r rs c info = fileRetriever' $ \f k p iv -> withS3Handle hv $ \case
|
retrieve hv r rs c info = fileRetriever' $ \f k p iv -> withS3Handle hv $ \case
|
||||||
(Just h) ->
|
Right h ->
|
||||||
eitherS3VersionID info rs c k (T.pack $ bucketObject info k) >>= \case
|
eitherS3VersionID info rs c k (T.pack $ bucketObject info k) >>= \case
|
||||||
Left failreason -> do
|
Left failreason -> do
|
||||||
warning failreason
|
warning failreason
|
||||||
giveup "cannot download content"
|
giveup "cannot download content"
|
||||||
Right loc -> retrieveHelper info h loc (fromRawFilePath f) p iv
|
Right loc -> retrieveHelper info h loc (fromRawFilePath f) p iv
|
||||||
Nothing ->
|
Left S3HandleNeedCreds ->
|
||||||
getPublicWebUrls' (uuid r) rs info c k >>= \case
|
getPublicWebUrls' (uuid r) rs info c k >>= \case
|
||||||
Left failreason -> do
|
Left failreason -> do
|
||||||
warning failreason
|
warning failreason
|
||||||
giveup "cannot download content"
|
giveup "cannot download content"
|
||||||
Right us -> unlessM (withUrlOptions $ downloadUrl False k p iv us (fromRawFilePath f)) $
|
Right us -> unlessM (withUrlOptions $ downloadUrl False k p iv us (fromRawFilePath f)) $
|
||||||
giveup "failed to download content"
|
giveup "failed to download content"
|
||||||
|
Left S3HandleAnonymousOldAws -> giveupS3HandleProblem S3HandleAnonymousOldAws (uuid r)
|
||||||
|
|
||||||
retrieveHelper :: S3Info -> S3Handle -> (Either S3.Object S3VersionID) -> FilePath -> MeterUpdate -> Maybe IncrementalVerifier -> Annex ()
|
retrieveHelper :: S3Info -> S3Handle -> (Either S3.Object S3VersionID) -> FilePath -> MeterUpdate -> Maybe IncrementalVerifier -> Annex ()
|
||||||
retrieveHelper info h loc f p iv = retrieveHelper' h f p iv $
|
retrieveHelper info h loc f p iv = retrieveHelper' h f p iv $
|
||||||
|
@ -462,12 +463,12 @@ lockContentS3 hv r rs c info
|
||||||
|
|
||||||
checkKey :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> CheckPresent
|
checkKey :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> CheckPresent
|
||||||
checkKey hv r rs c info k = withS3Handle hv $ \case
|
checkKey hv r rs c info k = withS3Handle hv $ \case
|
||||||
Just h -> eitherS3VersionID info rs c k (T.pack $ bucketObject info k) >>= \case
|
Right h -> eitherS3VersionID info rs c k (T.pack $ bucketObject info k) >>= \case
|
||||||
Left failreason -> do
|
Left failreason -> do
|
||||||
warning failreason
|
warning failreason
|
||||||
giveup "cannot check content"
|
giveup "cannot check content"
|
||||||
Right loc -> checkKeyHelper info h loc
|
Right loc -> checkKeyHelper info h loc
|
||||||
Nothing ->
|
Left S3HandleNeedCreds ->
|
||||||
getPublicWebUrls' (uuid r) rs info c k >>= \case
|
getPublicWebUrls' (uuid r) rs info c k >>= \case
|
||||||
Left failreason -> do
|
Left failreason -> do
|
||||||
warning failreason
|
warning failreason
|
||||||
|
@ -476,6 +477,7 @@ checkKey hv r rs c info k = withS3Handle hv $ \case
|
||||||
let check u = withUrlOptions $
|
let check u = withUrlOptions $
|
||||||
Url.checkBoth u (fromKey keySize k)
|
Url.checkBoth u (fromKey keySize k)
|
||||||
anyM check us
|
anyM check us
|
||||||
|
Left S3HandleAnonymousOldAws -> giveupS3HandleProblem S3HandleAnonymousOldAws (uuid r)
|
||||||
|
|
||||||
checkKeyHelper :: S3Info -> S3Handle -> (Either S3.Object S3VersionID) -> Annex Bool
|
checkKeyHelper :: S3Info -> S3Handle -> (Either S3.Object S3VersionID) -> Annex Bool
|
||||||
checkKeyHelper info h loc = checkKeyHelper' info h o limit
|
checkKeyHelper info h loc = checkKeyHelper' info h o limit
|
||||||
|
@ -498,8 +500,8 @@ storeExportS3 hv r rs info magic f k loc p = void $ storeExportS3' hv r rs info
|
||||||
|
|
||||||
storeExportS3' :: S3HandleVar -> Remote -> RemoteStateHandle -> S3Info -> Maybe Magic -> FilePath -> Key -> ExportLocation -> MeterUpdate -> Annex (Maybe S3Etag, Maybe S3VersionID)
|
storeExportS3' :: S3HandleVar -> Remote -> RemoteStateHandle -> S3Info -> Maybe Magic -> FilePath -> Key -> ExportLocation -> MeterUpdate -> Annex (Maybe S3Etag, Maybe S3VersionID)
|
||||||
storeExportS3' hv r rs info magic f k loc p = withS3Handle hv $ \case
|
storeExportS3' hv r rs info magic f k loc p = withS3Handle hv $ \case
|
||||||
Just h -> go h
|
Right h -> go h
|
||||||
Nothing -> giveup $ needS3Creds (uuid r)
|
Left pr -> giveupS3HandleProblem pr (uuid r)
|
||||||
where
|
where
|
||||||
go h = do
|
go h = do
|
||||||
let o = T.pack $ bucketExportLocation info loc
|
let o = T.pack $ bucketExportLocation info loc
|
||||||
|
@ -510,45 +512,45 @@ storeExportS3' hv r rs info magic f k loc p = withS3Handle hv $ \case
|
||||||
retrieveExportS3 :: S3HandleVar -> Remote -> S3Info -> Key -> ExportLocation -> FilePath -> MeterUpdate -> Annex Verification
|
retrieveExportS3 :: S3HandleVar -> Remote -> S3Info -> Key -> ExportLocation -> FilePath -> MeterUpdate -> Annex Verification
|
||||||
retrieveExportS3 hv r info k loc f p = verifyKeyContentIncrementally AlwaysVerify k $ \iv ->
|
retrieveExportS3 hv r info k loc f p = verifyKeyContentIncrementally AlwaysVerify k $ \iv ->
|
||||||
withS3Handle hv $ \case
|
withS3Handle hv $ \case
|
||||||
Just h -> retrieveHelper info h (Left (T.pack exportloc)) f p iv
|
Right h -> retrieveHelper info h (Left (T.pack exportloc)) f p iv
|
||||||
Nothing -> case getPublicUrlMaker info of
|
Left S3HandleNeedCreds -> case getPublicUrlMaker info of
|
||||||
Just geturl -> either giveup return =<<
|
Just geturl -> either giveup return =<<
|
||||||
Url.withUrlOptions
|
Url.withUrlOptions
|
||||||
(Url.download' p iv (geturl exportloc) f)
|
(Url.download' p iv (geturl exportloc) f)
|
||||||
Nothing -> giveup $ needS3Creds (uuid r)
|
Nothing -> giveup $ needS3Creds (uuid r)
|
||||||
|
Left S3HandleAnonymousOldAws -> giveupS3HandleProblem S3HandleAnonymousOldAws (uuid r)
|
||||||
where
|
where
|
||||||
exportloc = bucketExportLocation info loc
|
exportloc = bucketExportLocation info loc
|
||||||
|
|
||||||
removeExportS3 :: S3HandleVar -> Remote -> RemoteStateHandle -> S3Info -> Key -> ExportLocation -> Annex ()
|
removeExportS3 :: S3HandleVar -> Remote -> RemoteStateHandle -> S3Info -> Key -> ExportLocation -> Annex ()
|
||||||
removeExportS3 hv r rs info k loc = withS3Handle hv $ \case
|
removeExportS3 hv r rs info k loc = withS3Handle hv $ \case
|
||||||
Just h -> do
|
Right h -> do
|
||||||
checkVersioning info rs k
|
checkVersioning info rs k
|
||||||
liftIO $ runResourceT $ do
|
liftIO $ runResourceT $ do
|
||||||
S3.DeleteObjectResponse <- sendS3Handle h $
|
S3.DeleteObjectResponse <- sendS3Handle h $
|
||||||
S3.DeleteObject (T.pack $ bucketExportLocation info loc) (bucket info)
|
S3.DeleteObject (T.pack $ bucketExportLocation info loc) (bucket info)
|
||||||
return ()
|
return ()
|
||||||
Nothing -> giveup $ needS3Creds (uuid r)
|
Left p -> giveupS3HandleProblem p (uuid r)
|
||||||
where
|
where
|
||||||
|
|
||||||
checkPresentExportS3 :: S3HandleVar -> Remote -> S3Info -> Key -> ExportLocation -> Annex Bool
|
checkPresentExportS3 :: S3HandleVar -> Remote -> S3Info -> Key -> ExportLocation -> Annex Bool
|
||||||
checkPresentExportS3 hv r info k loc = withS3Handle hv $ \case
|
checkPresentExportS3 hv r info k loc = withS3Handle hv $ \case
|
||||||
Just h -> checkKeyHelper info h (Left (T.pack $ bucketExportLocation info loc))
|
Right h -> checkKeyHelper info h (Left (T.pack $ bucketExportLocation info loc))
|
||||||
Nothing -> case getPublicUrlMaker info of
|
Left S3HandleNeedCreds -> case getPublicUrlMaker info of
|
||||||
Just geturl -> withUrlOptions $
|
Just geturl -> withUrlOptions $
|
||||||
Url.checkBoth (geturl $ bucketExportLocation info loc) (fromKey keySize k)
|
Url.checkBoth (geturl $ bucketExportLocation info loc) (fromKey keySize k)
|
||||||
Nothing -> do
|
Nothing -> giveupS3HandleProblem S3HandleNeedCreds (uuid r)
|
||||||
warning $ needS3Creds (uuid r)
|
Left S3HandleAnonymousOldAws -> giveupS3HandleProblem S3HandleAnonymousOldAws (uuid r)
|
||||||
giveup "No S3 credentials configured"
|
|
||||||
|
|
||||||
-- S3 has no move primitive; copy and delete.
|
-- S3 has no move primitive; copy and delete.
|
||||||
renameExportS3 :: S3HandleVar -> Remote -> RemoteStateHandle -> S3Info -> Key -> ExportLocation -> ExportLocation -> Annex (Maybe ())
|
renameExportS3 :: S3HandleVar -> Remote -> RemoteStateHandle -> S3Info -> Key -> ExportLocation -> ExportLocation -> Annex (Maybe ())
|
||||||
renameExportS3 hv r rs info k src dest = Just <$> go
|
renameExportS3 hv r rs info k src dest = Just <$> go
|
||||||
where
|
where
|
||||||
go = withS3Handle hv $ \case
|
go = withS3Handle hv $ \case
|
||||||
Just h -> do
|
Right h -> do
|
||||||
checkVersioning info rs k
|
checkVersioning info rs k
|
||||||
go' h
|
go' h
|
||||||
Nothing -> giveup $ needS3Creds (uuid r)
|
Left p -> giveupS3HandleProblem p (uuid r)
|
||||||
|
|
||||||
go' h = liftIO $ runResourceT $ do
|
go' h = liftIO $ runResourceT $ do
|
||||||
let co = S3.copyObject (bucket info) dstobject
|
let co = S3.copyObject (bucket info) dstobject
|
||||||
|
@ -564,8 +566,8 @@ renameExportS3 hv r rs info k src dest = Just <$> go
|
||||||
listImportableContentsS3 :: S3HandleVar -> Remote -> S3Info -> ParsedRemoteConfig -> Annex (Maybe (ImportableContentsChunkable Annex (ContentIdentifier, ByteSize)))
|
listImportableContentsS3 :: S3HandleVar -> Remote -> S3Info -> ParsedRemoteConfig -> Annex (Maybe (ImportableContentsChunkable Annex (ContentIdentifier, ByteSize)))
|
||||||
listImportableContentsS3 hv r info c =
|
listImportableContentsS3 hv r info c =
|
||||||
withS3Handle hv $ \case
|
withS3Handle hv $ \case
|
||||||
Nothing -> giveup $ needS3Creds (uuid r)
|
Right h -> Just <$> go h
|
||||||
Just h -> Just <$> go h
|
Left p -> giveupS3HandleProblem p (uuid r)
|
||||||
where
|
where
|
||||||
go h = do
|
go h = do
|
||||||
ic <- liftIO $ runResourceT $ extractFromResourceT =<< startlist h
|
ic <- liftIO $ runResourceT $ extractFromResourceT =<< startlist h
|
||||||
|
@ -678,7 +680,7 @@ retrieveExportWithContentIdentifierS3 hv r rs info loc (cid:_) dest gk p =
|
||||||
return (k, v)
|
return (k, v)
|
||||||
where
|
where
|
||||||
go iv = withS3Handle hv $ \case
|
go iv = withS3Handle hv $ \case
|
||||||
Just h -> do
|
Right h -> do
|
||||||
rewritePreconditionException $ retrieveHelper' h dest p iv $
|
rewritePreconditionException $ retrieveHelper' h dest p iv $
|
||||||
limitGetToContentIdentifier cid $
|
limitGetToContentIdentifier cid $
|
||||||
S3.getObject (bucket info) o
|
S3.getObject (bucket info) o
|
||||||
|
@ -690,7 +692,7 @@ retrieveExportWithContentIdentifierS3 hv r rs info loc (cid:_) dest gk p =
|
||||||
setS3VersionID info rs k vid
|
setS3VersionID info rs k vid
|
||||||
Left _ -> noop
|
Left _ -> noop
|
||||||
return k
|
return k
|
||||||
Nothing -> giveup $ needS3Creds (uuid r)
|
Left p -> giveupS3HandleProblem p (uuid r)
|
||||||
o = T.pack $ bucketExportLocation info loc
|
o = T.pack $ bucketExportLocation info loc
|
||||||
retrieveExportWithContentIdentifierS3 _ _ _ _ _ [] _ _ _ = giveup "missing content identifier"
|
retrieveExportWithContentIdentifierS3 _ _ _ _ _ [] _ _ _ = giveup "missing content identifier"
|
||||||
|
|
||||||
|
@ -739,12 +741,9 @@ removeExportWithContentIdentifierS3 hv r rs info k loc _removeablecids =
|
||||||
|
|
||||||
checkPresentExportWithContentIdentifierS3 :: S3HandleVar -> Remote -> S3Info -> Key -> ExportLocation -> [ContentIdentifier] -> Annex Bool
|
checkPresentExportWithContentIdentifierS3 :: S3HandleVar -> Remote -> S3Info -> Key -> ExportLocation -> [ContentIdentifier] -> Annex Bool
|
||||||
checkPresentExportWithContentIdentifierS3 hv r info _k loc knowncids =
|
checkPresentExportWithContentIdentifierS3 hv r info _k loc knowncids =
|
||||||
withS3Handle hv $ \case
|
withS3HandleOrFail (uuid r) hv $ \h ->
|
||||||
Just h -> flip anyM knowncids $
|
flip anyM knowncids $
|
||||||
checkKeyHelper' info h o . limitHeadToContentIdentifier
|
checkKeyHelper' info h o . limitHeadToContentIdentifier
|
||||||
Nothing -> do
|
|
||||||
warning $ needS3Creds (uuid r)
|
|
||||||
giveup "No S3 credentials configured"
|
|
||||||
where
|
where
|
||||||
o = T.pack $ bucketExportLocation info loc
|
o = T.pack $ bucketExportLocation info loc
|
||||||
|
|
||||||
|
@ -854,27 +853,43 @@ sendS3Handle
|
||||||
-> ResourceT IO a
|
-> ResourceT IO a
|
||||||
sendS3Handle h r = AWS.pureAws (hawscfg h) (hs3cfg h) (hmanager h) r
|
sendS3Handle h r = AWS.pureAws (hawscfg h) (hs3cfg h) (hmanager h) r
|
||||||
|
|
||||||
type S3HandleVar = TVar (Either (Annex (Maybe S3Handle)) (Maybe S3Handle))
|
type S3HandleVar = TVar (Either (Annex (Either S3HandleProblem S3Handle)) (Either S3HandleProblem S3Handle))
|
||||||
|
|
||||||
|
data S3HandleProblem
|
||||||
|
= S3HandleNeedCreds
|
||||||
|
| S3HandleAnonymousOldAws
|
||||||
|
|
||||||
|
giveupS3HandleProblem :: S3HandleProblem -> UUID -> Annex a
|
||||||
|
giveupS3HandleProblem S3HandleNeedCreds u = do
|
||||||
|
warning $ needS3Creds u
|
||||||
|
giveup "No S3 credentials configured"
|
||||||
|
giveupS3HandleProblem S3HandleAnonymousOldAws _ =
|
||||||
|
giveup "This S3 special remote is configured with signature=anonymous, but git-annex is buit with too old a version of the aws library to support that."
|
||||||
|
|
||||||
{- Prepares a S3Handle for later use. Does not connect to S3 or do anything
|
{- Prepares a S3Handle for later use. Does not connect to S3 or do anything
|
||||||
- else expensive. -}
|
- else expensive. -}
|
||||||
mkS3HandleVar :: ParsedRemoteConfig -> RemoteGitConfig -> UUID -> Annex S3HandleVar
|
mkS3HandleVar :: ParsedRemoteConfig -> RemoteGitConfig -> UUID -> Annex S3HandleVar
|
||||||
mkS3HandleVar c gc u = liftIO $ newTVarIO $ Left $
|
mkS3HandleVar c gc u = liftIO $ newTVarIO $ Left $
|
||||||
if isAnonymous c
|
if isAnonymous c
|
||||||
then go =<< liftIO AWS.anonymousCredentials
|
then
|
||||||
|
#if MIN_VERSION_aws(0,23,0)
|
||||||
|
go =<< liftIO AWS.anonymousCredentials
|
||||||
|
#else
|
||||||
|
return (Left S3HandleAnonymousOldAws)
|
||||||
|
#endif
|
||||||
else do
|
else do
|
||||||
mcreds <- getRemoteCredPair c gc (AWS.creds u)
|
mcreds <- getRemoteCredPair c gc (AWS.creds u)
|
||||||
case mcreds of
|
case mcreds of
|
||||||
Just creds -> go =<< liftIO (genCredentials creds)
|
Just creds -> go =<< liftIO (genCredentials creds)
|
||||||
Nothing -> return Nothing
|
Nothing -> return (Left S3HandleNeedCreds)
|
||||||
where
|
where
|
||||||
s3cfg = s3Configuration c
|
s3cfg = s3Configuration c
|
||||||
go awscreds = do
|
go awscreds = do
|
||||||
let awscfg = AWS.Configuration AWS.Timestamp awscreds debugMapper Nothing
|
let awscfg = AWS.Configuration AWS.Timestamp awscreds debugMapper Nothing
|
||||||
ou <- getUrlOptions
|
ou <- getUrlOptions
|
||||||
return $ Just $ S3Handle (httpManager ou) awscfg s3cfg
|
return $ Right $ S3Handle (httpManager ou) awscfg s3cfg
|
||||||
|
|
||||||
withS3Handle :: S3HandleVar -> (Maybe S3Handle -> Annex a) -> Annex a
|
withS3Handle :: S3HandleVar -> (Either S3HandleProblem S3Handle -> Annex a) -> Annex a
|
||||||
withS3Handle hv a = liftIO (readTVarIO hv) >>= \case
|
withS3Handle hv a = liftIO (readTVarIO hv) >>= \case
|
||||||
Right hdl -> a hdl
|
Right hdl -> a hdl
|
||||||
Left mkhdl -> do
|
Left mkhdl -> do
|
||||||
|
@ -884,10 +899,8 @@ withS3Handle hv a = liftIO (readTVarIO hv) >>= \case
|
||||||
|
|
||||||
withS3HandleOrFail :: UUID -> S3HandleVar -> (S3Handle -> Annex a) -> Annex a
|
withS3HandleOrFail :: UUID -> S3HandleVar -> (S3Handle -> Annex a) -> Annex a
|
||||||
withS3HandleOrFail u hv a = withS3Handle hv $ \case
|
withS3HandleOrFail u hv a = withS3Handle hv $ \case
|
||||||
Just hdl -> a hdl
|
Right hdl -> a hdl
|
||||||
Nothing -> do
|
Left p -> giveupS3HandleProblem p u
|
||||||
warning $ needS3Creds u
|
|
||||||
giveup "No S3 credentials configured"
|
|
||||||
|
|
||||||
needS3Creds :: UUID -> String
|
needS3Creds :: UUID -> String
|
||||||
needS3Creds u = missingCredPairFor "S3" (AWS.creds u)
|
needS3Creds u = missingCredPairFor "S3" (AWS.creds u)
|
||||||
|
|
|
@ -14,7 +14,7 @@ packages:
|
||||||
resolver: lts-18.13
|
resolver: lts-18.13
|
||||||
extra-deps:
|
extra-deps:
|
||||||
- IfElse-0.85
|
- IfElse-0.85
|
||||||
- aws-0.22
|
- aws-0.23
|
||||||
- bloomfilter-2.0.1.0
|
- bloomfilter-2.0.1.0
|
||||||
- git-lfs-1.2.0
|
- git-lfs-1.2.0
|
||||||
- http-client-restricted-0.0.4
|
- http-client-restricted-0.0.4
|
||||||
|
|
|
@ -13,7 +13,7 @@ packages:
|
||||||
- '.'
|
- '.'
|
||||||
extra-deps:
|
extra-deps:
|
||||||
- IfElse-0.85
|
- IfElse-0.85
|
||||||
- aws-0.22
|
- aws-0.23
|
||||||
- bloomfilter-2.0.1.0
|
- bloomfilter-2.0.1.0
|
||||||
- tasty-1.2
|
- tasty-1.2
|
||||||
- tasty-rerun-1.1.14
|
- tasty-rerun-1.1.14
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue