p2phttp combining unauth and auth options

p2phttp: Support serving unauthenticated users while requesting
authentication for operations that need it. Eg, --unauth-readonly can be
combined with --authenv.

Drop locking currently needs authentication so it will prompt for that.
That still needs to be addressed somehow.
This commit is contained in:
Joey Hess 2024-10-17 11:10:28 -04:00
parent 4e59828f4c
commit 0629219617
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 67 additions and 15 deletions

View file

@ -1,3 +1,11 @@
git-annex (10.20240928) UNRELEASED; urgency=medium
* p2phttp: Support serving unauthenticated users while requesting
authentication for operations that need it. Eg, --unauth-readonly
can be combined with --authenv.
-- Joey Hess <id@joeyh.name> Thu, 17 Oct 2024 11:02:17 -0400
git-annex (10.20240927) upstream; urgency=medium git-annex (10.20240927) upstream; urgency=medium
* Detect when a preferred content expression contains "not present", * Detect when a preferred content expression contains "not present",

View file

@ -128,10 +128,15 @@ seek o = getAnnexWorkerPool $ \workerpool ->
mkGetServerMode :: M.Map Auth P2P.ServerMode -> Options -> GetServerMode mkGetServerMode :: M.Map Auth P2P.ServerMode -> Options -> GetServerMode
mkGetServerMode _ o _ Nothing mkGetServerMode _ o _ Nothing
| wideOpenOption o = Just P2P.ServeReadWrite | wideOpenOption o =
| unauthAppendOnlyOption o = Just P2P.ServeAppendOnly ServerMode P2P.ServeReadWrite False
| unauthReadOnlyOption o = Just P2P.ServeReadOnly | unauthAppendOnlyOption o =
| otherwise = Nothing ServerMode P2P.ServeAppendOnly canauth
| unauthReadOnlyOption o =
ServerMode P2P.ServeReadOnly canauth
| otherwise = CannotServeRequests
where
canauth = authEnvOption o || authEnvHttpOption o
mkGetServerMode authenv o issecure (Just auth) = mkGetServerMode authenv o issecure (Just auth) =
case (issecure, authEnvOption o, authEnvHttpOption o) of case (issecure, authEnvOption o, authEnvHttpOption o) of
(Secure, True, _) -> checkauth (Secure, True, _) -> checkauth
@ -139,9 +144,10 @@ mkGetServerMode authenv o issecure (Just auth) =
_ -> noauth _ -> noauth
where where
checkauth = case M.lookup auth authenv of checkauth = case M.lookup auth authenv of
Just servermode -> Just servermode Just servermode -> ServerMode servermode False
Nothing -> noauth Nothing -> noauth
noauth = mkGetServerMode authenv o issecure Nothing noauth = mkGetServerMode authenv noautho issecure Nothing
noautho = o { authEnvOption = False, authEnvHttpOption = False }
getAuthEnv :: IO (M.Map Auth P2P.ServerMode) getAuthEnv :: IO (M.Map Auth P2P.ServerMode)
getAuthEnv = do getAuthEnv = do

View file

@ -52,8 +52,14 @@ data P2PHttpServerState = P2PHttpServerState
type AnnexWorkerPool = TMVar (WorkerPool (Annex.AnnexState, Annex.AnnexRead)) type AnnexWorkerPool = TMVar (WorkerPool (Annex.AnnexState, Annex.AnnexRead))
-- Nothing when the server is not allowed to serve any requests. type GetServerMode = IsSecure -> Maybe Auth -> ServerMode
type GetServerMode = IsSecure -> Maybe Auth -> Maybe P2P.ServerMode
data ServerMode
= ServerMode
{ serverMode :: P2P.ServerMode
, authenticationAllowed :: Bool
}
| CannotServeRequests
mkP2PHttpServerState :: AcquireP2PConnection -> AnnexWorkerPool -> GetServerMode -> IO P2PHttpServerState mkP2PHttpServerState :: AcquireP2PConnection -> AnnexWorkerPool -> GetServerMode -> IO P2PHttpServerState
mkP2PHttpServerState acquireconn annexworkerpool getservermode = P2PHttpServerState mkP2PHttpServerState acquireconn annexworkerpool getservermode = P2PHttpServerState
@ -143,13 +149,23 @@ checkAuthActionClass
-> (P2P.ServerMode -> Handler a) -> (P2P.ServerMode -> Handler a)
-> Handler a -> Handler a
checkAuthActionClass st sec auth actionclass go = checkAuthActionClass st sec auth actionclass go =
case (getServerMode st sec auth, actionclass) of case (sm, actionclass) of
(Just P2P.ServeReadWrite, _) -> go P2P.ServeReadWrite (ServerMode { serverMode = P2P.ServeReadWrite }, _) ->
(Just P2P.ServeAppendOnly, RemoveAction) -> throwError err403 go P2P.ServeReadWrite
(Just P2P.ServeAppendOnly, _) -> go P2P.ServeAppendOnly (ServerMode { serverMode = P2P.ServeAppendOnly }, RemoveAction) ->
(Just P2P.ServeReadOnly, ReadAction) -> go P2P.ServeReadOnly throwError $ forbiddenWithoutAuth sm
(Just P2P.ServeReadOnly, _) -> throwError err403 (ServerMode { serverMode = P2P.ServeAppendOnly }, _) ->
(Nothing, _) -> throwError basicAuthRequired go P2P.ServeAppendOnly
(ServerMode { serverMode = P2P.ServeReadOnly }, ReadAction) ->
go P2P.ServeReadOnly
(ServerMode { serverMode = P2P.ServeReadOnly }, _) ->
throwError $ forbiddenWithoutAuth sm
(CannotServeRequests, _) -> throwError basicAuthRequired
where
sm = getServerMode st sec auth
forbiddenAction :: ServerError
forbiddenAction = err403
basicAuthRequired :: ServerError basicAuthRequired :: ServerError
basicAuthRequired = err401 { errHeaders = [(h, v)] } basicAuthRequired = err401 { errHeaders = [(h, v)] }
@ -157,6 +173,11 @@ basicAuthRequired = err401 { errHeaders = [(h, v)] }
h = "WWW-Authenticate" h = "WWW-Authenticate"
v = "Basic realm=\"git-annex\", charset=\"UTF-8\"" v = "Basic realm=\"git-annex\", charset=\"UTF-8\""
forbiddenWithoutAuth :: ServerMode -> ServerError
forbiddenWithoutAuth sm
| authenticationAllowed sm = basicAuthRequired
| otherwise = forbiddenAction
data ConnectionParams = ConnectionParams data ConnectionParams = ConnectionParams
{ connectionProtocolVersion :: P2P.ProtocolVersion { connectionProtocolVersion :: P2P.ProtocolVersion
, connectionServerUUID :: UUID , connectionServerUUID :: UUID

View file

@ -0,0 +1,11 @@
[[!comment format=mdwn
username="joey"
subject="""comment 6"""
date="2024-10-17T15:07:12Z"
content="""
I've implemented combining --unauth-readonly (or --unauth-appendonly) with
--authenv/--authenv-http.
Read-only drop locking in that configuration still needs to be addressed, it
does prompt for authentication currently.
"""]]

View file

@ -116,10 +116,16 @@ convenient way to download the content of any key, by using the path
Allows unauthenticated users to read the repository, but not make Allows unauthenticated users to read the repository, but not make
modifications to it. modifications to it.
This can be combined with `--authenv` or `--authenv-http` to allow
anonymous readonly access, and authenticated write access.
* `--unauth-appendonly` * `--unauth-appendonly`
Allows unauthenticated users to read the repository, and store data in Allows unauthenticated users to read the repository, and store data in
it, but not remove data from it. it, but not remove data from it.
This can be combined with `--authenv` or `--authenv-http` to allow
anonymous appendonly access, and authenticated remove access.
* `--wideopen` * `--wideopen`