From 7d09da3c8b0b5d2dd2cf0d357cb4976093fafa92 Mon Sep 17 00:00:00 2001 From: Mildred Ki'Lya Date: Wed, 28 Jan 2015 12:57:09 +0100 Subject: [PATCH] Make gateway read-only by default and add option to make it writable --- cmd/ipfs-gateway-fs/main.go | 3 ++- cmd/ipfs/daemon.go | 20 ++++++++++++++++++-- cmd/ipfswatch/main.go | 2 +- core/corehttp/gateway.go | 16 +++++++++------- core/corehttp/gateway_handler.go | 26 +++++++++++++++++--------- repo/config/gateway.go | 1 + repo/config/init.go | 1 + 7 files changed, 49 insertions(+), 20 deletions(-) diff --git a/cmd/ipfs-gateway-fs/main.go b/cmd/ipfs-gateway-fs/main.go index a138abc9d..f1d8a7307 100644 --- a/cmd/ipfs-gateway-fs/main.go +++ b/cmd/ipfs-gateway-fs/main.go @@ -17,6 +17,7 @@ import ( ) var ( + writable = flag.Bool("writable", false, "enable writing objects (with POST, PUT and DELETE)") refreshAssetsInterval = flag.Duration("refresh-assets-interval", 30*time.Second, "refresh assets") garbageCollectInterval = flag.Duration("gc-interval", 24*time.Hour, "frequency of repo garbage collection") assetsPath = flag.String("assets-path", "", "if provided, periodically adds contents of path to IPFS") @@ -93,7 +94,7 @@ func run() error { } opts := []corehttp.ServeOption{ - corehttp.GatewayOption, + corehttp.GatewayOption(*writable), } if err := corehttp.ListenAndServe(node, *host, opts...); err != nil { return err diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 5062d51ca..d89c133ed 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "fmt" ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" cmds "github.com/jbenet/go-ipfs/commands" @@ -15,6 +16,7 @@ import ( const ( initOptionKwd = "init" mountKwd = "mount" + writableKwd = "writable" ipfsMountKwd = "mount-ipfs" ipnsMountKwd = "mount-ipns" // apiAddrKwd = "address-api" @@ -36,6 +38,7 @@ the daemon. Options: []cmds.Option{ cmds.BoolOption(initOptionKwd, "Initialize IPFS with default settings if not already initialized"), cmds.BoolOption(mountKwd, "Mounts IPFS to the filesystem"), + cmds.BoolOption(writableKwd, "Enable writing objects (with POST, PUT and DELETE)"), cmds.StringOption(ipfsMountKwd, "Path to the mountpoint for IPFS (if using --mount)"), cmds.StringOption(ipnsMountKwd, "Path to the mountpoint for IPNS (if using --mount)"), @@ -161,9 +164,22 @@ func daemonFunc(req cmds.Request, res cmds.Response) { rootRedirect = corehttp.RedirectOption("", cfg.Gateway.RootRedirect) } + writable, writableOptionFound, err := req.Option(writableKwd).Bool() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + if !writableOptionFound { + writable = cfg.Gateway.Writable + } + + if writable { + fmt.Printf("IPNS gateway mounted read-write\n") + } + if gatewayMaddr != nil { go func() { - var opts = []corehttp.ServeOption{corehttp.GatewayOption} + var opts = []corehttp.ServeOption{corehttp.GatewayOption(writable)} if rootRedirect != nil { opts = append(opts, rootRedirect) } @@ -177,7 +193,7 @@ func daemonFunc(req cmds.Request, res cmds.Response) { var opts = []corehttp.ServeOption{ corehttp.CommandsOption(*req.Context()), corehttp.WebUIOption, - corehttp.GatewayOption, + corehttp.GatewayOption(true), } if rootRedirect != nil { opts = append(opts, rootRedirect) diff --git a/cmd/ipfswatch/main.go b/cmd/ipfswatch/main.go index d4beb6208..2f1c49978 100644 --- a/cmd/ipfswatch/main.go +++ b/cmd/ipfswatch/main.go @@ -80,7 +80,7 @@ func run(ipfsPath, watchPath string) error { if *http { addr := "/ip4/127.0.0.1/tcp/5001" var opts = []corehttp.ServeOption{ - corehttp.GatewayOption, + corehttp.GatewayOption(true), corehttp.WebUIOption, corehttp.CommandsOption(cmdCtx(node, ipfsPath)), } diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index d9de13903..43ba3fffd 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -6,12 +6,14 @@ import ( core "github.com/jbenet/go-ipfs/core" ) -func GatewayOption(n *core.IpfsNode, mux *http.ServeMux) error { - gateway, err := newGatewayHandler(n) - if err != nil { - return err - } - mux.Handle("/ipfs/", gateway) +func GatewayOption(writable bool) ServeOption { + return func(n *core.IpfsNode, mux *http.ServeMux) error { + gateway, err := newGatewayHandler(n, writable) + if err != nil { + return err + } + mux.Handle("/ipfs/", gateway) mux.Handle("/ipns/", gateway) - return nil + return nil + } } diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 6140c17e3..e06762a15 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -48,13 +48,15 @@ type directoryItem struct { // gatewayHandler is a HTTP handler that serves IPFS objects (accessible by default at /ipfs/) // (it serves requests like GET /ipfs/QmVRzPKPzNtSrEzBFm2UZfxmPAgnaLke4DMcerbsGGSaFe/link) type gatewayHandler struct { - node *core.IpfsNode - dirList *template.Template + node *core.IpfsNode + dirList *template.Template + writable bool } -func newGatewayHandler(node *core.IpfsNode) (*gatewayHandler, error) { +func newGatewayHandler(node *core.IpfsNode, writable bool) (*gatewayHandler, error) { i := &gatewayHandler{ - node: node, + node: node, + writable: writable, } err := i.loadTemplate() if err != nil { @@ -116,17 +118,17 @@ func (i *gatewayHandler) NewDagReader(nd *dag.Node) (uio.ReadSeekCloser, error) } func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { + if i.writable && r.Method == "POST" { i.postHandler(w, r) return } - if r.Method == "PUT" { + if i.writable && r.Method == "PUT" { i.putHandler(w, r) return } - if r.Method == "DELETE" { + if i.writable && r.Method == "DELETE" { i.deleteHandler(w, r) return } @@ -136,8 +138,14 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - errmsg := "Method " + r.Method + " not allowed: " + "bad request for " + r.URL.Path - w.WriteHeader(http.StatusBadRequest) + errmsg := "Method " + r.Method + " not allowed: " + if !i.writable { + w.WriteHeader(http.StatusMethodNotAllowed) + errmsg = errmsg + "read only access" + } else { + w.WriteHeader(http.StatusBadRequest) + errmsg = errmsg + "bad request for " + r.URL.Path + } w.Write([]byte(errmsg)) log.Error(errmsg) } diff --git a/repo/config/gateway.go b/repo/config/gateway.go index 7bc3eb020..c0885778d 100644 --- a/repo/config/gateway.go +++ b/repo/config/gateway.go @@ -3,4 +3,5 @@ package config // Gateway contains options for the HTTP gateway server. type Gateway struct { RootRedirect string + Writable bool } diff --git a/repo/config/init.go b/repo/config/init.go index aef5624ec..976d26688 100644 --- a/repo/config/init.go +++ b/repo/config/init.go @@ -54,6 +54,7 @@ func Init(out io.Writer, nBitsForKeypair int) (*Config, error) { Gateway: Gateway{ RootRedirect: "", + Writable: false, }, }