Merge pull request #10608 from stefwalter/proxy-unix-socket
kubectl: Add proxy --unix-socket=/file/path option
This commit is contained in:
@@ -17,8 +17,10 @@ limitations under the License.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@@ -28,6 +30,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
default_port = 8001
|
||||
proxy_example = `// Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/
|
||||
$ kubectl proxy --port=8011 --www=./local/www/
|
||||
|
||||
@@ -73,14 +76,20 @@ The above lets you 'curl localhost:8001/custom/api/v1/pods'
|
||||
cmd.Flags().String("reject-paths", kubectl.DefaultPathRejectRE, "Regular expression for paths that the proxy should reject.")
|
||||
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().IntP("port", "p", 8001, "The port on which to run the proxy. Set to 0 to pick a random port.")
|
||||
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. Use with caution.")
|
||||
cmd.Flags().IntP("port", "p", default_port, "The port on which to run the proxy. Set to 0 to pick a random port.")
|
||||
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.")
|
||||
cmd.Flags().StringP("unix-socket", "u", "", "Unix socket on which to run the proxy.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunProxy(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
path := cmdutil.GetFlagString(cmd, "unix-socket")
|
||||
port := cmdutil.GetFlagInt(cmd, "port")
|
||||
|
||||
if port != default_port && path != "" {
|
||||
return errors.New("Don't specify both --unix-socket and --port")
|
||||
}
|
||||
|
||||
clientConfig, err := f.ClientConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -101,18 +110,22 @@ func RunProxy(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
AcceptHosts: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-hosts")),
|
||||
}
|
||||
if cmdutil.GetFlagBool(cmd, "disable-filter") {
|
||||
glog.Warning("Request filter disabled, your proxy is vulnerable to XSRF attacks, please be cautious")
|
||||
if path == "" {
|
||||
glog.Warning("Request filter disabled, your proxy is vulnerable to XSRF attacks, please be cautious")
|
||||
}
|
||||
filter = nil
|
||||
}
|
||||
|
||||
server, err := kubectl.NewProxyServer(port, cmdutil.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, filter, clientConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
server, err := kubectl.NewProxyServer(cmdutil.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, filter, clientConfig)
|
||||
|
||||
// Separate listening from serving so we can report the bound port
|
||||
// when it is chosen by os (port == 0)
|
||||
l, err := server.Listen()
|
||||
// when it is chosen by os (eg: port == 0)
|
||||
var l net.Listener
|
||||
if path == "" {
|
||||
l, err = server.Listen(port)
|
||||
} else {
|
||||
l, err = server.ListenUnix(path)
|
||||
}
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
|
@@ -22,12 +22,14 @@ import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/client"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -139,13 +141,12 @@ func (f *FilterServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
|
||||
type ProxyServer struct {
|
||||
handler http.Handler
|
||||
port int
|
||||
}
|
||||
|
||||
// NewProxyServer creates and installs a new ProxyServer.
|
||||
// It automatically registers the created ProxyServer to http.DefaultServeMux.
|
||||
// 'filter', if non-nil, protects requests to the api only.
|
||||
func NewProxyServer(port int, filebase string, apiProxyPrefix string, staticPrefix string, filter *FilterServer, cfg *client.Config) (*ProxyServer, error) {
|
||||
func NewProxyServer(filebase string, apiProxyPrefix string, staticPrefix string, filter *FilterServer, cfg *client.Config) (*ProxyServer, error) {
|
||||
host := cfg.Host
|
||||
if !strings.HasSuffix(host, "/") {
|
||||
host = host + "/"
|
||||
@@ -174,12 +175,26 @@ func NewProxyServer(port int, filebase string, apiProxyPrefix string, staticPref
|
||||
// serving their working directory by default.
|
||||
mux.Handle(staticPrefix, newFileHandler(staticPrefix, filebase))
|
||||
}
|
||||
return &ProxyServer{handler: mux, port: port}, nil
|
||||
return &ProxyServer{handler: mux}, nil
|
||||
}
|
||||
|
||||
// Listen is a simple wrapper around net.Listen.
|
||||
func (s *ProxyServer) Listen() (net.Listener, error) {
|
||||
return net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", s.port))
|
||||
func (s *ProxyServer) Listen(port int) (net.Listener, error) {
|
||||
return net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||
}
|
||||
|
||||
// ListenUnix does net.Listen for a unix socket
|
||||
func (s *ProxyServer) ListenUnix(path string) (net.Listener, error) {
|
||||
// Remove any socket, stale or not, but fall through for other files
|
||||
fi, err := os.Stat(path)
|
||||
if err == nil && (fi.Mode()&os.ModeSocket) != 0 {
|
||||
os.Remove(path)
|
||||
}
|
||||
// Default to only user accessible socket, caller can open up later if desired
|
||||
oldmask, _ := util.Umask(0077)
|
||||
l, err := net.Listen("unix", path)
|
||||
util.Umask(oldmask)
|
||||
return l, err
|
||||
}
|
||||
|
||||
// Serve starts the server using given listener, loops forever.
|
||||
|
@@ -287,7 +287,7 @@ func TestPathHandling(t *testing.T) {
|
||||
|
||||
for _, item := range table {
|
||||
func() {
|
||||
p, err := NewProxyServer(0, "", item.prefix, "/not/used/for/this/test", nil, cc)
|
||||
p, err := NewProxyServer("", item.prefix, "/not/used/for/this/test", nil, cc)
|
||||
if err != nil {
|
||||
t.Fatalf("%#v: %v", item, err)
|
||||
}
|
||||
|
27
pkg/util/umask.go
Normal file
27
pkg/util/umask.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Umask(mask int) (old int, err error) {
|
||||
return syscall.Umask(mask), nil
|
||||
}
|
27
pkg/util/umask_windows.go
Normal file
27
pkg/util/umask_windows.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
func Umask(mask int) (old int, err error) {
|
||||
return 0, errors.New("platform and architecture is not supported")
|
||||
}
|
Reference in New Issue
Block a user