cache credentials for p2phttp in memory

This commit is contained in:
Joey Hess 2024-07-23 18:45:02 -04:00
parent 75771772ec
commit 48657405c6
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 40 additions and 24 deletions

View file

@ -42,7 +42,7 @@ getBasicAuthFromCredential r ccv u = do
Just c -> go (const noop) c
Nothing -> do
let storeincache = \c -> atomically $ do
(CredentialCache cc') <- takeTMVar ccv
CredentialCache cc' <- takeTMVar ccv
putTMVar ccv (CredentialCache (M.insert bu c cc'))
go storeincache =<< getUrlCredential u r
Nothing -> go (const noop) =<< getUrlCredential u r
@ -113,7 +113,9 @@ data CredentialCache = CredentialCache (M.Map CredentialBaseURL Credential)
-- when credential.useHttpPath is false, one Credential is cached
-- for each git repo accessed, and there are a reasonably small number of
-- those, so the cache will not grow too large.
data CredentialBaseURL = CredentialBaseURL URI
data CredentialBaseURL
= CredentialBaseURI URI
| CredentialBaseURL String
deriving (Show, Eq, Ord)
mkCredentialBaseURL :: Repo -> URLString -> Maybe CredentialBaseURL
@ -123,4 +125,4 @@ mkCredentialBaseURL r s = do
Config.get (ConfigKey "credential.useHttpPath") (ConfigValue "") r
if usehttppath
then Nothing
else Just $ CredentialBaseURL $ u { uriPath = "" }
else Just $ CredentialBaseURI $ u { uriPath = "" }

View file

@ -17,6 +17,7 @@ import Types
import Annex.Url
#ifdef WITH_SERVANT
import qualified Annex
import Annex.UUID
import Types.Remote
import P2P.Http
@ -35,6 +36,7 @@ import Network.HTTP.Client
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Internal as LI
import qualified Data.Map as M
import Control.Concurrent.STM
import Control.Concurrent.Async
import Control.Concurrent
@ -64,9 +66,14 @@ p2pHttpClient rmt fallback clientaction =
Just baseurl -> do
mgr <- httpManager <$> getUrlOptions
let clientenv = mkClientEnv mgr baseurl
go clientenv Nothing Nothing allProtocolVersions
ccv <- Annex.getRead Annex.gitcredentialcache
Git.CredentialCache cc <- liftIO $ atomically $
readTMVar ccv
case M.lookup (Git.CredentialBaseURL credentialbaseurl) cc of
Nothing -> go clientenv Nothing False Nothing allProtocolVersions
Just cred -> go clientenv (Just cred) True (credauth cred) allProtocolVersions
where
go clientenv mcred mauth (v:vs) = do
go clientenv mcred credcached mauth (v:vs) = do
myuuid <- getUUID
res <- clientaction clientenv v
(B64UUID (uuid rmt))
@ -75,11 +82,11 @@ p2pHttpClient rmt fallback clientaction =
mauth
case res of
Right resp -> do
maybe noop (\cred -> inRepo $ Git.approveUrlCredential cred) mcred
unless credcached $ cachecred mcred
return resp
Left (FailureResponse _ resp)
| statusCode (responseStatusCode resp) == 404 && not (null vs) ->
go clientenv mcred mauth vs
go clientenv mcred credcached mauth vs
| statusCode (responseStatusCode resp) == 401 ->
case mcred of
Nothing -> authrequired clientenv (v:vs)
@ -93,28 +100,37 @@ p2pHttpClient rmt fallback clientaction =
_ -> fallback (show ex)
Left clienterror -> fallback $
"git-annex HTTP API server returned an unexpected response: " ++ show clienterror
go _ _ _ [] = error "internal"
go _ _ _ _ [] = error "internal"
authrequired clientenv vs =
case p2pHttpUrlString <$> remoteAnnexP2PHttpUrl (gitconfig rmt) of
Nothing -> error "internal"
Just url -> do
cred <- prompt $
inRepo $ Git.getUrlCredential $
p2pHttpUrlWithoutUUID url
let mauth = do
ba <- Git.credentialBasicAuth cred
return $ Auth
(encodeBS (basicAuthUser ba))
(encodeBS (basicAuthPassword ba))
let mcred = if isJust mauth then Just cred else Nothing
go clientenv mcred mauth vs
authrequired clientenv vs = do
cred <- prompt $
inRepo $ Git.getUrlCredential credentialbaseurl
go clientenv (Just cred) False (credauth cred) vs
showstatuscode resp =
show (statusCode (responseStatusCode resp))
++ " " ++
decodeBS (statusMessage (responseStatusCode resp))
credentialbaseurl = case p2pHttpUrlString <$> remoteAnnexP2PHttpUrl (gitconfig rmt) of
Nothing -> error "internal"
Just url -> p2pHttpUrlWithoutUUID url
credauth cred = do
ba <- Git.credentialBasicAuth cred
return $ Auth
(encodeBS (basicAuthUser ba))
(encodeBS (basicAuthPassword ba))
cachecred mcred = case mcred of
Just cred -> do
inRepo $ Git.approveUrlCredential cred
ccv <- Annex.getRead Annex.gitcredentialcache
liftIO $ atomically $ do
Git.CredentialCache cc <- takeTMVar ccv
putTMVar ccv $ Git.CredentialCache $
M.insert (Git.CredentialBaseURL credentialbaseurl) cred cc
Nothing -> noop
#else
runP2PHttpClient rmt fallback = fallback "This remote uses an annex+http url, but this version of git-annex is not build with support for that."
#endif

View file

@ -28,8 +28,6 @@ Planned schedule of work:
## work notes
* cache git credential auth
* Rest of Remote.Git needs implementing.
* git-annex p2phttp serving .well-known for ACME.