p2phttp: Added --socket option
Used protectedOutput to set up a umask that makes the socket only accessible by the current user. Authentication is still needed when using this option unless it is combined with --wideopen. It was just simpler to keep authentication separate from this.
This commit is contained in:
parent
66b009a0f6
commit
492c484a82
6 changed files with 57 additions and 5 deletions
|
@ -1,6 +1,7 @@
|
||||||
git-annex (10.20250631) UNRELEASED; urgency=medium
|
git-annex (10.20250631) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
* p2phttp: Scan multilevel directories with --directory.
|
* p2phttp: Scan multilevel directories with --directory.
|
||||||
|
* p2phttp: Added --socket option.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Mon, 07 Jul 2025 15:59:42 -0400
|
-- Joey Hess <id@joeyh.name> Mon, 07 Jul 2025 15:59:42 -0400
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,13 @@ import qualified Git.Construct
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Types.Concurrency
|
import Types.Concurrency
|
||||||
import qualified Utility.RawFilePath as R
|
import qualified Utility.RawFilePath as R
|
||||||
|
import Utility.FileMode
|
||||||
|
|
||||||
import Servant
|
import Servant
|
||||||
import qualified Network.Wai.Handler.Warp as Warp
|
import qualified Network.Wai.Handler.Warp as Warp
|
||||||
import qualified Network.Wai.Handler.WarpTLS as Warp
|
import qualified Network.Wai.Handler.WarpTLS as Warp
|
||||||
import Network.Socket (PortNumber)
|
import Network.Socket (PortNumber)
|
||||||
|
import qualified Network.Socket as Socket
|
||||||
import System.PosixCompat.Files (isSymbolicLink)
|
import System.PosixCompat.Files (isSymbolicLink)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Data.String
|
import Data.String
|
||||||
|
@ -42,6 +44,7 @@ cmd = noMessages $ dontCheck repoExists $
|
||||||
data Options = Options
|
data Options = Options
|
||||||
{ portOption :: Maybe PortNumber
|
{ portOption :: Maybe PortNumber
|
||||||
, bindOption :: Maybe String
|
, bindOption :: Maybe String
|
||||||
|
, socketOption :: Maybe FilePath
|
||||||
, certFileOption :: Maybe FilePath
|
, certFileOption :: Maybe FilePath
|
||||||
, privateKeyFileOption :: Maybe FilePath
|
, privateKeyFileOption :: Maybe FilePath
|
||||||
, chainFileOption :: [FilePath]
|
, chainFileOption :: [FilePath]
|
||||||
|
@ -67,6 +70,10 @@ optParser _ = Options
|
||||||
( long "bind" <> metavar paramAddress
|
( long "bind" <> metavar paramAddress
|
||||||
<> help "specify address to bind to"
|
<> help "specify address to bind to"
|
||||||
))
|
))
|
||||||
|
<*> optional (strOption
|
||||||
|
( long "socket" <> metavar paramPath
|
||||||
|
<> help "bind to unix domain socket"
|
||||||
|
))
|
||||||
<*> optional (strOption
|
<*> optional (strOption
|
||||||
( long "certfile" <> metavar paramFile
|
( long "certfile" <> metavar paramFile
|
||||||
<> help "TLS certificate file for HTTPS"
|
<> help "TLS certificate file for HTTPS"
|
||||||
|
@ -174,12 +181,20 @@ runServer o mst = go `finally` serverShutdownCleanup mst
|
||||||
let settings = Warp.setPort port $ Warp.setHost host $
|
let settings = Warp.setPort port $ Warp.setHost host $
|
||||||
Warp.defaultSettings
|
Warp.defaultSettings
|
||||||
mstv <- newTMVarIO mst
|
mstv <- newTMVarIO mst
|
||||||
|
let app = p2pHttpApp mstv
|
||||||
case (certFileOption o, privateKeyFileOption o) of
|
case (certFileOption o, privateKeyFileOption o) of
|
||||||
(Nothing, Nothing) -> Warp.runSettings settings (p2pHttpApp mstv)
|
(Nothing, Nothing) -> case socketOption o of
|
||||||
(Just certfile, Just privatekeyfile) -> do
|
Nothing -> Warp.runSettings settings app
|
||||||
let tlssettings = Warp.tlsSettingsChain
|
Just socketpath ->
|
||||||
certfile (chainFileOption o) privatekeyfile
|
withsocket socketpath $ \sock ->
|
||||||
Warp.runTLS tlssettings settings (p2pHttpApp mstv)
|
Warp.runSettingsSocket settings sock app
|
||||||
|
(Just certfile, Just privatekeyfile) ->
|
||||||
|
case socketOption o of
|
||||||
|
Nothing -> do
|
||||||
|
let tlssettings = Warp.tlsSettingsChain
|
||||||
|
certfile (chainFileOption o) privatekeyfile
|
||||||
|
Warp.runTLS tlssettings settings app
|
||||||
|
Just _socketpath -> giveup "HTTPS is not supported with --socket"
|
||||||
_ -> giveup "You must use both --certfile and --privatekeyfile options to enable HTTPS."
|
_ -> giveup "You must use both --certfile and --privatekeyfile options to enable HTTPS."
|
||||||
port = maybe
|
port = maybe
|
||||||
(fromIntegral defaultP2PHttpProtocolPort)
|
(fromIntegral defaultP2PHttpProtocolPort)
|
||||||
|
@ -189,6 +204,13 @@ runServer o mst = go `finally` serverShutdownCleanup mst
|
||||||
(fromString "*") -- both ipv4 and ipv6
|
(fromString "*") -- both ipv4 and ipv6
|
||||||
fromString
|
fromString
|
||||||
(bindOption o)
|
(bindOption o)
|
||||||
|
withsocket socketpath =
|
||||||
|
bracket (opensocket socketpath) Socket.close
|
||||||
|
opensocket socketpath = protectedOutput $ do
|
||||||
|
sock <- Socket.socket Socket.AF_UNIX Socket.Stream 0
|
||||||
|
Socket.bind sock $ Socket.SockAddrUnix socketpath
|
||||||
|
Socket.listen sock Socket.maxListenQueue
|
||||||
|
return sock
|
||||||
|
|
||||||
mkServerState :: Options -> M.Map Auth P2P.ServerMode -> Annex P2PHttpServerState
|
mkServerState :: Options -> M.Map Auth P2P.ServerMode -> Annex P2PHttpServerState
|
||||||
mkServerState o authenv =
|
mkServerState o authenv =
|
||||||
|
|
|
@ -103,6 +103,12 @@ convenient way to download the content of any key, by using the path
|
||||||
|
|
||||||
What address to bind to. The default is to bind to all addresses.
|
What address to bind to. The default is to bind to all addresses.
|
||||||
|
|
||||||
|
* `--socket=path`
|
||||||
|
|
||||||
|
Rather than binding to an address, create and listen to a unix domain
|
||||||
|
socket at the specified location. This can be useful when proxying
|
||||||
|
to `git-annex p2phttp`.
|
||||||
|
|
||||||
* `--certfile=filename`
|
* `--certfile=filename`
|
||||||
|
|
||||||
TLS certificate file to use. Combining this with `--privatekeyfile`
|
TLS certificate file to use. Combining this with `--privatekeyfile`
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
For p2phttp support in forgejo-aneksajo I decided to just spawn a `git annex p2phttp --wideopen` server, do authentication on the Forgejo side, and then proxy requests to p2phttp. Since p2phttp only supports serving one repository at the moment this means that I have to allocate one free port per repository. Actually finding a free port adds complexity and a race condition, as there also seems to be no way to set `--port 0` for p2phttp and then figure out which port it bound to.
|
For p2phttp support in forgejo-aneksajo I decided to just spawn a `git annex p2phttp --wideopen` server, do authentication on the Forgejo side, and then proxy requests to p2phttp. Since p2phttp only supports serving one repository at the moment this means that I have to allocate one free port per repository. Actually finding a free port adds complexity and a race condition, as there also seems to be no way to set `--port 0` for p2phttp and then figure out which port it bound to.
|
||||||
|
|
||||||
This would be simplified if p2phttp could listen on unix domain sockets instead.
|
This would be simplified if p2phttp could listen on unix domain sockets instead.
|
||||||
|
|
||||||
|
> [[done]] --[[Joey]]
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
[[!comment format=mdwn
|
||||||
|
username="joey"
|
||||||
|
subject="""comment 3"""
|
||||||
|
date="2025-07-07T19:26:56Z"
|
||||||
|
content="""
|
||||||
|
I've made it support nested directories, which was easy.
|
||||||
|
|
||||||
|
Should be possible to make it use runSettingsSocket indeed though.
|
||||||
|
"""]]
|
|
@ -0,0 +1,12 @@
|
||||||
|
[[!comment format=mdwn
|
||||||
|
username="joey"
|
||||||
|
subject="""comment 4"""
|
||||||
|
date="2025-07-07T20:28:38Z"
|
||||||
|
content="""
|
||||||
|
Implemented a --socket option. I have not tried connecting to it as a
|
||||||
|
client, but it seems to be listening to it, so I assume all is good.
|
||||||
|
|
||||||
|
Note that it still checks for authentication when using the socket,
|
||||||
|
so you will probably want to combine it with --wideopen. The socket mode
|
||||||
|
allows only the current user to access it.
|
||||||
|
"""]]
|
Loading…
Add table
Add a link
Reference in a new issue