mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 06:54:01 +00:00
Merge pull request #10608 from stefwalter/proxy-unix-socket
kubectl: Add proxy --unix-socket=/file/path option
This commit is contained in:
commit
5175bb0b91
@ -595,6 +595,8 @@ _kubectl_proxy()
|
||||
two_word_flags+=("-p")
|
||||
flags+=("--reject-methods=")
|
||||
flags+=("--reject-paths=")
|
||||
flags+=("--unix-socket=")
|
||||
two_word_flags+=("-u")
|
||||
flags+=("--www=")
|
||||
two_word_flags+=("-w")
|
||||
flags+=("--www-prefix=")
|
||||
|
@ -52,7 +52,7 @@ The above lets you 'curl localhost:8001/custom/api/v1/pods'
|
||||
|
||||
.PP
|
||||
\fB\-\-disable\-filter\fP=false
|
||||
If true, disable request filtering in the proxy. This is dangerous, and can leave you vulnerable to XSRF attacks. Use with caution.
|
||||
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.
|
||||
|
||||
.PP
|
||||
\fB\-h\fP, \fB\-\-help\fP=false
|
||||
@ -70,6 +70,10 @@ The above lets you 'curl localhost:8001/custom/api/v1/pods'
|
||||
\fB\-\-reject\-paths\fP="^/api/.\fI/exec,^/api/.\fP/run"
|
||||
Regular expression for paths that the proxy should reject.
|
||||
|
||||
.PP
|
||||
\fB\-u\fP, \fB\-\-unix\-socket\fP=""
|
||||
Unix socket on which to run the proxy.
|
||||
|
||||
.PP
|
||||
\fB\-w\fP, \fB\-\-www\fP=""
|
||||
Also serve static files from the given directory under the specified prefix.
|
||||
|
@ -80,11 +80,12 @@ $ kubectl proxy --api-prefix=/k8s-api
|
||||
--accept-hosts="^localhost$,^127\\.0\\.0\\.1$,^\\[::1\\]$": Regular expression for hosts that the proxy should accept.
|
||||
--accept-paths="^/.*": Regular expression for paths that the proxy should accept.
|
||||
--api-prefix="/api/": Prefix to serve the proxied API under.
|
||||
--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.
|
||||
--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.
|
||||
-h, --help=false: help for proxy
|
||||
-p, --port=8001: The port on which to run the proxy. Set to 0 to pick a random port.
|
||||
--reject-methods="POST,PUT,PATCH": Regular expression for HTTP methods that the proxy should reject.
|
||||
--reject-paths="^/api/.*/exec,^/api/.*/run": Regular expression for paths that the proxy should reject.
|
||||
-u, --unix-socket="": Unix socket on which to run the proxy.
|
||||
-w, --www="": Also serve static files from the given directory under the specified prefix.
|
||||
-P, --www-prefix="/static/": Prefix to serve static files under, if static file directory is specified.
|
||||
```
|
||||
@ -122,7 +123,7 @@ $ kubectl proxy --api-prefix=/k8s-api
|
||||
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-07-14 00:11:42.957150329 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-08-04 15:27:44.354669483 +0000 UTC
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
|
@ -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")
|
||||
}
|
@ -21,7 +21,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -544,8 +546,35 @@ var _ = Describe("Kubectl client", func() {
|
||||
Failf("Expected at least one supported apiversion, got %v", apiVersions)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
It("should support --unix-socket=/path", func() {
|
||||
By("Starting the proxy")
|
||||
tmpdir, err := ioutil.TempDir("", "kubectl-proxy-unix")
|
||||
if err != nil {
|
||||
Failf("Failed to create temporary directory: %v", err)
|
||||
}
|
||||
path := filepath.Join(tmpdir, "test")
|
||||
defer os.Remove(path)
|
||||
defer os.Remove(tmpdir)
|
||||
cmd := kubectlCmd("proxy", fmt.Sprintf("--unix-socket=%s", path))
|
||||
stdout, stderr, err := startCmdAndStreamOutput(cmd)
|
||||
if err != nil {
|
||||
Failf("Failed to start kubectl command: %v", err)
|
||||
}
|
||||
defer stdout.Close()
|
||||
defer stderr.Close()
|
||||
defer tryKill(cmd)
|
||||
buf := make([]byte, 128)
|
||||
if _, err = stdout.Read(buf); err != nil {
|
||||
Failf("Expected output from kubectl proxy: %v", err)
|
||||
}
|
||||
By("retrieving proxy /api/ output")
|
||||
_, err = curlUnix("http://unused/api", path)
|
||||
if err != nil {
|
||||
Failf("Failed get of /api at %s: %v", path, err)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Checks whether the output split by line contains the required elements.
|
||||
@ -603,8 +632,19 @@ func startProxyServer() (int, *exec.Cmd, error) {
|
||||
return -1, cmd, fmt.Errorf("Failed to parse port from proxy stdout: %s", output)
|
||||
}
|
||||
|
||||
func curl(addr string) (string, error) {
|
||||
resp, err := http.Get(addr)
|
||||
func curlUnix(url string, path string) (string, error) {
|
||||
dial := func(proto, addr string) (net.Conn, error) {
|
||||
return net.Dial("unix", path)
|
||||
}
|
||||
transport := &http.Transport{
|
||||
Dial: dial,
|
||||
}
|
||||
return curlTransport(url, transport)
|
||||
}
|
||||
|
||||
func curlTransport(url string, transport *http.Transport) (string, error) {
|
||||
client := &http.Client{Transport: transport}
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -616,6 +656,10 @@ func curl(addr string) (string, error) {
|
||||
return string(body[:]), nil
|
||||
}
|
||||
|
||||
func curl(url string) (string, error) {
|
||||
return curlTransport(url, &http.Transport{})
|
||||
}
|
||||
|
||||
func validateGuestbookApp(c *client.Client, ns string) {
|
||||
Logf("Waiting for frontend to serve content.")
|
||||
if !waitForGuestbookResponse(c, "get", "", `{"data": ""}`, guestbookStartupTimeout, ns) {
|
||||
|
Loading…
Reference in New Issue
Block a user