From f3a7ac43116deba7111df1033a81266daa421885 Mon Sep 17 00:00:00 2001 From: Suyog Barve Date: Tue, 25 Apr 2017 02:23:30 -0500 Subject: [PATCH] allow kubectl proxy to handle specified reject methods and default to allow all --- pkg/kubectl/cmd/proxy.go | 9 +- pkg/kubectl/proxy_server.go | 2 +- pkg/kubectl/proxy_server_test.go | 302 +++++++++++++++++++------------ 3 files changed, 195 insertions(+), 118 deletions(-) diff --git a/pkg/kubectl/cmd/proxy.go b/pkg/kubectl/cmd/proxy.go index a89f68b26ed..02fa75ccdf1 100644 --- a/pkg/kubectl/cmd/proxy.go +++ b/pkg/kubectl/cmd/proxy.go @@ -81,7 +81,7 @@ func NewCmdProxy(f cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().String("accept-paths", kubectl.DefaultPathAcceptRE, "Regular expression for paths that the proxy should accept.") cmd.Flags().String("reject-paths", kubectl.DefaultPathRejectRE, "Regular expression for paths that the proxy should reject. Paths specified here will be rejected even accepted by --accept-paths.") cmd.Flags().String("accept-hosts", kubectl.DefaultHostAcceptRE, "Regular expression for hosts that the proxy should accept.") - cmd.Flags().String("reject-methods", kubectl.DefaultMethodRejectRE, "Regular expression for HTTP methods that the proxy should reject.") + cmd.Flags().String("reject-methods", kubectl.DefaultMethodRejectRE, "Regular expression for HTTP methods that the proxy should reject (example --reject-methods='POST,PUT,PATCH'). ") cmd.Flags().IntP("port", "p", defaultPort, "The port on which to run the proxy. Set to 0 to pick a random port.") cmd.Flags().StringP("address", "", "127.0.0.1", "The IP address on which to serve on.") cmd.Flags().Bool("disable-filter", false, "If true, disable request filtering in the proxy. This is dangerous, and can leave you vulnerable to XSRF attacks, when used with an accessible port.") @@ -122,9 +122,10 @@ func RunProxy(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { apiProxyPrefix += "/" } filter := &kubectl.FilterServer{ - AcceptPaths: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-paths")), - RejectPaths: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "reject-paths")), - AcceptHosts: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-hosts")), + AcceptPaths: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-paths")), + RejectPaths: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "reject-paths")), + AcceptHosts: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-hosts")), + RejectMethods: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "reject-methods")), } if cmdutil.GetFlagBool(cmd, "disable-filter") { if path == "" { diff --git a/pkg/kubectl/proxy_server.go b/pkg/kubectl/proxy_server.go index 39b870c5aab..8ae65004759 100644 --- a/pkg/kubectl/proxy_server.go +++ b/pkg/kubectl/proxy_server.go @@ -36,7 +36,7 @@ const ( DefaultHostAcceptRE = "^localhost$,^127\\.0\\.0\\.1$,^\\[::1\\]$" DefaultPathAcceptRE = "^.*" DefaultPathRejectRE = "^/api/.*/pods/.*/exec,^/api/.*/pods/.*/attach" - DefaultMethodRejectRE = "POST,PUT,PATCH" + DefaultMethodRejectRE = "^$" ) var ( diff --git a/pkg/kubectl/proxy_server_test.go b/pkg/kubectl/proxy_server_test.go index 13213a9ff10..394259070a7 100644 --- a/pkg/kubectl/proxy_server_test.go +++ b/pkg/kubectl/proxy_server_test.go @@ -32,149 +32,225 @@ import ( func TestAccept(t *testing.T) { tests := []struct { - acceptPaths string - rejectPaths string - acceptHosts string - path string - host string - method string - expectAccept bool + acceptPaths string + rejectPaths string + acceptHosts string + rejectMethods string + path string + host string + method string + expectAccept bool }{ { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "", - host: "127.0.0.1", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "", + host: "127.0.0.1", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "127.0.0.1", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/pods", + host: "127.0.0.1", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "localhost", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/pods", + host: "localhost", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/foo", - host: "localhost", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/foo", + host: "localhost", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/attachfoo", - host: "localhost", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/attachfoo", + host: "localhost", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/execfoo", - host: "localhost", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/execfoo", + host: "localhost", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/foo/exec", - host: "127.0.0.1", - method: "GET", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/foo/exec", + host: "127.0.0.1", + method: "GET", + expectAccept: false, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/foo/attach", - host: "127.0.0.1", - method: "GET", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/foo/attach", + host: "127.0.0.1", + method: "GET", + expectAccept: false, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "evil.com", - method: "GET", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/pods", + host: "evil.com", + method: "GET", + expectAccept: false, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "localhost.evil.com", - method: "GET", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/pods", + host: "localhost.evil.com", + method: "GET", + expectAccept: false, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "127a0b0c1", - method: "GET", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/pods", + host: "127a0b0c1", + method: "GET", + expectAccept: false, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/ui", - host: "localhost", - method: "GET", - expectAccept: true, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/ui", + host: "localhost", + method: "GET", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "localhost", - method: "POST", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/pods", + host: "localhost", + method: "POST", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/somepod", - host: "localhost", - method: "PUT", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/somepod", + host: "localhost", + method: "PUT", + expectAccept: true, }, { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/namespaces/default/pods/somepod", - host: "localhost", - method: "PATCH", - expectAccept: false, + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: DefaultMethodRejectRE, + path: "/api/v1/namespaces/default/pods/somepod", + host: "localhost", + method: "PATCH", + expectAccept: true, + }, + { + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: "GET", + path: "/api/v1/pods", + host: "127.0.0.1", + method: "GET", + expectAccept: false, + }, + { + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: "POST", + path: "/api/v1/pods", + host: "localhost", + method: "POST", + expectAccept: false, + }, + { + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: "PUT", + path: "/api/v1/namespaces/default/pods/somepod", + host: "localhost", + method: "PUT", + expectAccept: false, + }, + { + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: "PATCH", + path: "/api/v1/namespaces/default/pods/somepod", + host: "localhost", + method: "PATCH", + expectAccept: false, + }, + { + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: "POST,PUT,PATCH", + path: "/api/v1/namespaces/default/pods/somepod", + host: "localhost", + method: "PATCH", + expectAccept: false, + }, + { + acceptPaths: DefaultPathAcceptRE, + rejectPaths: DefaultPathRejectRE, + acceptHosts: DefaultHostAcceptRE, + rejectMethods: "POST,PUT,PATCH", + path: "/api/v1/namespaces/default/pods/somepod", + host: "localhost", + method: "PUT", + expectAccept: false, }, } for _, test := range tests { @@ -182,7 +258,7 @@ func TestAccept(t *testing.T) { AcceptPaths: MakeRegexpArrayOrDie(test.acceptPaths), RejectPaths: MakeRegexpArrayOrDie(test.rejectPaths), AcceptHosts: MakeRegexpArrayOrDie(test.acceptHosts), - RejectMethods: MakeRegexpArrayOrDie(DefaultMethodRejectRE), + RejectMethods: MakeRegexpArrayOrDie(test.rejectMethods), } accept := filter.accept(test.method, test.path, test.host) if accept != test.expectAccept {