mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	Chroot Listener (#22304)
* Initial oss-patch apply * Added changelog * Renamed changelog txt * Added the imports to the handler file * Added a check that no two ports are the same, and modified changelog * Edited go sum entry * Tidy up using go mod * Use strutil instead * Revert go sum and go mod * Revert sdk go sum * Edited go.sum to before * Edited go.sum again to initial * Revert changes
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/22304.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/22304.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | ```release-note:improvement | ||||||
|  | core: add a listener configuration "chroot_namespace" that forces requests to use a namespace hierarchy | ||||||
|  | ``` | ||||||
| @@ -789,7 +789,8 @@ func testConfig_Sanitized(t *testing.T) { | |||||||
| 		"listeners": []interface{}{ | 		"listeners": []interface{}{ | ||||||
| 			map[string]interface{}{ | 			map[string]interface{}{ | ||||||
| 				"config": map[string]interface{}{ | 				"config": map[string]interface{}{ | ||||||
| 					"address": "127.0.0.1:443", | 					"address":          "127.0.0.1:443", | ||||||
|  | 					"chroot_namespace": "admin/", | ||||||
| 				}, | 				}, | ||||||
| 				"type": "tcp", | 				"type": "tcp", | ||||||
| 			}, | 			}, | ||||||
| @@ -882,6 +883,7 @@ listener "tcp" { | |||||||
|   proxy_api { |   proxy_api { | ||||||
|     enable_quit = true |     enable_quit = true | ||||||
|   } |   } | ||||||
|  |   chroot_namespace = "admin" | ||||||
| }`)) | }`)) | ||||||
|  |  | ||||||
| 	config := Config{ | 	config := Config{ | ||||||
| @@ -926,6 +928,7 @@ listener "tcp" { | |||||||
| 						EnableQuit: true, | 						EnableQuit: true, | ||||||
| 					}, | 					}, | ||||||
| 					CustomResponseHeaders: DefaultCustomHeaders, | 					CustomResponseHeaders: DefaultCustomHeaders, | ||||||
|  | 					ChrootNamespace:       "admin/", | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ cluster_addr = "top_level_cluster_addr" | |||||||
|  |  | ||||||
| listener "tcp" { | listener "tcp" { | ||||||
|   address = "127.0.0.1:443" |   address = "127.0.0.1:443" | ||||||
|  |   chroot_namespace="admin/" | ||||||
| } | } | ||||||
|  |  | ||||||
| backend "consul" { | backend "consul" { | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1815,6 +1815,7 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9 | |||||||
| github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= | ||||||
| github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 h1:phcbL8urUzF/kxA/Oj6awENaRwfWsjP59GW7u2qlDyY= | github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 h1:phcbL8urUzF/kxA/Oj6awENaRwfWsjP59GW7u2qlDyY= | ||||||
| github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= | github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= | ||||||
|  | github.com/hashicorp/go-set v0.1.13/go.mod h1:0/D+R4MFUzJ6XmvjU7liXtznF1eQDxh84GJlhXw+lvo= | ||||||
| github.com/hashicorp/go-slug v0.11.1 h1:c6lLdQnlhUWbS5I7hw8SvfymoFuy6EmiFDedy6ir994= | github.com/hashicorp/go-slug v0.11.1 h1:c6lLdQnlhUWbS5I7hw8SvfymoFuy6EmiFDedy6ir994= | ||||||
| github.com/hashicorp/go-slug v0.11.1/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41RKLH301v4= | github.com/hashicorp/go-slug v0.11.1/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41RKLH301v4= | ||||||
| github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= | ||||||
| @@ -2620,6 +2621,7 @@ github.com/sethvargo/go-limiter v0.7.1/go.mod h1:C0kbSFbiriE5k2FFOe18M1YZbAR2Fiw | |||||||
| github.com/shirou/gopsutil/v3 v3.22.6 h1:FnHOFOh+cYAM0C30P+zysPISzlknLC5Z1G4EAElznfQ= | github.com/shirou/gopsutil/v3 v3.22.6 h1:FnHOFOh+cYAM0C30P+zysPISzlknLC5Z1G4EAElznfQ= | ||||||
| github.com/shirou/gopsutil/v3 v3.22.6/go.mod h1:EdIubSnZhbAvBS1yJ7Xi+AShB/hxwLHOMz4MCYz7yMs= | github.com/shirou/gopsutil/v3 v3.22.6/go.mod h1:EdIubSnZhbAvBS1yJ7Xi+AShB/hxwLHOMz4MCYz7yMs= | ||||||
| github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= | github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= | ||||||
|  | github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= | ||||||
| github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= | github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= | ||||||
| github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | ||||||
| github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= | github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= | ||||||
|   | |||||||
| @@ -358,6 +358,7 @@ func wrapGenericHandler(core *vault.Core, h http.Handler, props *vault.HandlerPr | |||||||
| 		} else { | 		} else { | ||||||
| 			ctx, cancelFunc = context.WithTimeout(ctx, maxRequestDuration) | 			ctx, cancelFunc = context.WithTimeout(ctx, maxRequestDuration) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// if maxRequestSize < 0, no need to set context value | 		// if maxRequestSize < 0, no need to set context value | ||||||
| 		// Add a size limiter if desired | 		// Add a size limiter if desired | ||||||
| 		if maxRequestSize > 0 { | 		if maxRequestSize > 0 { | ||||||
| @@ -379,11 +380,14 @@ func wrapGenericHandler(core *vault.Core, h http.Handler, props *vault.HandlerPr | |||||||
| 			nw.Header().Set("X-Vault-Hostname", hostname) | 			nw.Header().Set("X-Vault-Hostname", hostname) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// Extract the namespace from the header before we modify it | ||||||
|  | 		ns := r.Header.Get(consts.NamespaceHeaderName) | ||||||
| 		switch { | 		switch { | ||||||
| 		case strings.HasPrefix(r.URL.Path, "/v1/"): | 		case strings.HasPrefix(r.URL.Path, "/v1/"): | ||||||
| 			newR, status := adjustRequest(core, r) | 			// Setting the namespace in the header to be included in the error message | ||||||
|  | 			newR, status, err := adjustRequest(core, props.ListenerConfig, r) | ||||||
| 			if status != 0 { | 			if status != 0 { | ||||||
| 				respondError(nw, status, nil) | 				respondError(nw, status, err) | ||||||
| 				cancelFunc() | 				cancelFunc() | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| @@ -434,7 +438,6 @@ func wrapGenericHandler(core *vault.Core, h http.Handler, props *vault.HandlerPr | |||||||
| 		}() | 		}() | ||||||
|  |  | ||||||
| 		// Setting the namespace in the header to be included in the error message | 		// Setting the namespace in the header to be included in the error message | ||||||
| 		ns := r.Header.Get(consts.NamespaceHeaderName) |  | ||||||
| 		if ns != "" { | 		if ns != "" { | ||||||
| 			nw.Header().Set(consts.NamespaceHeaderName, ns) | 			nw.Header().Set(consts.NamespaceHeaderName, ns) | ||||||
| 		} | 		} | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								http/handler_stubs_oss.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								http/handler_stubs_oss.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | //go:build !enterprise | ||||||
|  |  | ||||||
|  | package http | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	"github.com/hashicorp/vault/internalshared/configutil" | ||||||
|  | 	"github.com/hashicorp/vault/vault" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | //go:generate go run github.com/hashicorp/vault/tools/stubmaker | ||||||
|  |  | ||||||
|  | func adjustRequest(c *vault.Core, listener *configutil.Listener, r *http.Request) (*http.Request, int, error) { | ||||||
|  | 	return r, 0, nil | ||||||
|  | } | ||||||
| @@ -20,10 +20,6 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	adjustRequest = func(c *vault.Core, r *http.Request) (*http.Request, int) { |  | ||||||
| 		return r, 0 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	genericWrapping = func(core *vault.Core, in http.Handler, props *vault.HandlerProperties) http.Handler { | 	genericWrapping = func(core *vault.Core, in http.Handler, props *vault.HandlerProperties) http.Handler { | ||||||
| 		// Wrap the help wrapped handler with another layer with a generic | 		// Wrap the help wrapped handler with another layer with a generic | ||||||
| 		// handler | 		// handler | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ import ( | |||||||
| 	"github.com/hashicorp/go-sockaddr/template" | 	"github.com/hashicorp/go-sockaddr/template" | ||||||
| 	"github.com/hashicorp/hcl" | 	"github.com/hashicorp/hcl" | ||||||
| 	"github.com/hashicorp/hcl/hcl/ast" | 	"github.com/hashicorp/hcl/hcl/ast" | ||||||
|  | 	"github.com/hashicorp/vault/helper/namespace" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ListenerTelemetry struct { | type ListenerTelemetry struct { | ||||||
| @@ -118,6 +119,10 @@ type Listener struct { | |||||||
| 	// Custom Http response headers | 	// Custom Http response headers | ||||||
| 	CustomResponseHeaders    map[string]map[string]string `hcl:"-"` | 	CustomResponseHeaders    map[string]map[string]string `hcl:"-"` | ||||||
| 	CustomResponseHeadersRaw interface{}                  `hcl:"custom_response_headers"` | 	CustomResponseHeadersRaw interface{}                  `hcl:"custom_response_headers"` | ||||||
|  |  | ||||||
|  | 	// ChrootNamespace will prepend the specified namespace to requests | ||||||
|  | 	ChrootNamespaceRaw interface{} `hcl:"chroot_namespace"` | ||||||
|  | 	ChrootNamespace    string      `hcl:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // AgentAPI allows users to select which parts of the Agent API they want enabled. | // AgentAPI allows users to select which parts of the Agent API they want enabled. | ||||||
| @@ -201,7 +206,6 @@ func ParseListeners(result *SharedConfig, list *ast.ObjectList) error { | |||||||
| 				return multierror.Prefix(fmt.Errorf("unsupported listener role %q", l.Role), fmt.Sprintf("listeners.%d:", i)) | 				return multierror.Prefix(fmt.Errorf("unsupported listener role %q", l.Role), fmt.Sprintf("listeners.%d:", i)) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Request Parameters | 		// Request Parameters | ||||||
| 		{ | 		{ | ||||||
| 			if l.MaxRequestSizeRaw != nil { | 			if l.MaxRequestSizeRaw != nil { | ||||||
| @@ -423,6 +427,20 @@ func ParseListeners(result *SharedConfig, list *ast.ObjectList) error { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		result.Listeners = append(result.Listeners, &l) | 		result.Listeners = append(result.Listeners, &l) | ||||||
|  |  | ||||||
|  | 		// Chroot Namespace | ||||||
|  | 		{ | ||||||
|  | 			// If a valid ChrootNamespace value exists, then canonicalize the namespace value | ||||||
|  | 			if l.ChrootNamespaceRaw != nil { | ||||||
|  | 				if l.ChrootNamespace, err = parseutil.ParseString(l.ChrootNamespaceRaw); err != nil { | ||||||
|  | 					return multierror.Prefix(fmt.Errorf("invalid value for chroot_namespace: %w", err), fmt.Sprintf("listeners.%d", i)) | ||||||
|  | 				} else { | ||||||
|  | 					l.ChrootNamespace = namespace.Canonicalize(l.ChrootNamespace) | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				l.ChrootNamespaceRaw = nil | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ require ( | |||||||
| 	github.com/hashicorp/go-secure-stdlib/password v0.1.1 | 	github.com/hashicorp/go-secure-stdlib/password v0.1.1 | ||||||
| 	github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 | 	github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 | ||||||
| 	github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 | 	github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 | ||||||
|  | 	github.com/hashicorp/go-set v0.1.13 | ||||||
| 	github.com/hashicorp/go-sockaddr v1.0.2 | 	github.com/hashicorp/go-sockaddr v1.0.2 | ||||||
| 	github.com/hashicorp/go-uuid v1.0.3 | 	github.com/hashicorp/go-uuid v1.0.3 | ||||||
| 	github.com/hashicorp/go-version v1.6.0 | 	github.com/hashicorp/go-version v1.6.0 | ||||||
|   | |||||||
| @@ -119,6 +119,8 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9 | |||||||
| github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= | ||||||
| github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 h1:phcbL8urUzF/kxA/Oj6awENaRwfWsjP59GW7u2qlDyY= | github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 h1:phcbL8urUzF/kxA/Oj6awENaRwfWsjP59GW7u2qlDyY= | ||||||
| github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= | github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= | ||||||
|  | github.com/hashicorp/go-set v0.1.13 h1:k1B5goY3c7OKEzpK+gwAhJexxzAJwDN8kId8YvWrihA= | ||||||
|  | github.com/hashicorp/go-set v0.1.13/go.mod h1:0/D+R4MFUzJ6XmvjU7liXtznF1eQDxh84GJlhXw+lvo= | ||||||
| github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= | github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= | ||||||
| github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= | github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= | ||||||
| github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||||
| @@ -231,6 +233,7 @@ github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4 | |||||||
| github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= | github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= | ||||||
| github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= | github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= | ||||||
| github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= | github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= | ||||||
|  | github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= | ||||||
| github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= | ||||||
| github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | ||||||
| github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= | github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ import ( | |||||||
| 	"github.com/hashicorp/vault/api" | 	"github.com/hashicorp/vault/api" | ||||||
| 	dockhelper "github.com/hashicorp/vault/sdk/helper/docker" | 	dockhelper "github.com/hashicorp/vault/sdk/helper/docker" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/logging" | 	"github.com/hashicorp/vault/sdk/helper/logging" | ||||||
|  | 	"github.com/hashicorp/vault/sdk/helper/strutil" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/testcluster" | 	"github.com/hashicorp/vault/sdk/helper/testcluster" | ||||||
| 	uberAtomic "go.uber.org/atomic" | 	uberAtomic "go.uber.org/atomic" | ||||||
| 	"golang.org/x/net/http2" | 	"golang.org/x/net/http2" | ||||||
| @@ -479,6 +480,7 @@ type DockerClusterNode struct { | |||||||
| 	ImageTag             string | 	ImageTag             string | ||||||
| 	DataVolumeName       string | 	DataVolumeName       string | ||||||
| 	cleanupVolume        func() | 	cleanupVolume        func() | ||||||
|  | 	AllClients           []*api.Client | ||||||
| } | } | ||||||
|  |  | ||||||
| func (n *DockerClusterNode) TLSConfig() *tls.Config { | func (n *DockerClusterNode) TLSConfig() *tls.Config { | ||||||
| @@ -506,6 +508,30 @@ func (n *DockerClusterNode) APIClient() *api.Client { | |||||||
| 	return client | 	return client | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (n *DockerClusterNode) APIClientN(listenerNumber int) (*api.Client, error) { | ||||||
|  | 	// We clone to ensure that whenever this method is called, the caller gets | ||||||
|  | 	// back a pristine client, without e.g. any namespace or token changes that | ||||||
|  | 	// might pollute a shared client.  We clone the config instead of the | ||||||
|  | 	// client because (1) Client.clone propagates the replicationStateStore and | ||||||
|  | 	// the httpClient pointers, (2) it doesn't copy the tlsConfig at all, and | ||||||
|  | 	// (3) if clone returns an error, it doesn't feel as appropriate to panic | ||||||
|  | 	// below.  Who knows why clone might return an error? | ||||||
|  | 	if listenerNumber >= len(n.AllClients) { | ||||||
|  | 		return nil, fmt.Errorf("invalid listener number %d", listenerNumber) | ||||||
|  | 	} | ||||||
|  | 	cfg := n.AllClients[listenerNumber].CloneConfig() | ||||||
|  | 	client, err := api.NewClient(cfg) | ||||||
|  | 	if err != nil { | ||||||
|  | 		// It seems fine to panic here, since this should be the same input | ||||||
|  | 		// we provided to NewClient when we were setup, and we didn't panic then. | ||||||
|  | 		// Better not to completely ignore the error though, suppose there's a | ||||||
|  | 		// bug in CloneConfig? | ||||||
|  | 		panic(fmt.Sprintf("NewClient error on cloned config: %v", err)) | ||||||
|  | 	} | ||||||
|  | 	client.SetToken(n.Cluster.rootToken) | ||||||
|  | 	return client, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // NewAPIClient creates and configures a Vault API client to communicate with | // NewAPIClient creates and configures a Vault API client to communicate with | ||||||
| // the running Vault Cluster for this DockerClusterNode | // the running Vault Cluster for this DockerClusterNode | ||||||
| func (n *DockerClusterNode) apiConfig() (*api.Config, error) { | func (n *DockerClusterNode) apiConfig() (*api.Config, error) { | ||||||
| @@ -544,6 +570,20 @@ func (n *DockerClusterNode) newAPIClient() (*api.Client, error) { | |||||||
| 	return client, nil | 	return client, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (n *DockerClusterNode) newAPIClientForAddress(address string) (*api.Client, error) { | ||||||
|  | 	config, err := n.apiConfig() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	config.Address = fmt.Sprintf("https://%s", address) | ||||||
|  | 	client, err := api.NewClient(config) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	client.SetToken(n.Cluster.GetRootToken()) | ||||||
|  | 	return client, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Cleanup kills the container of the node and deletes its data volume | // Cleanup kills the container of the node and deletes its data volume | ||||||
| func (n *DockerClusterNode) Cleanup() { | func (n *DockerClusterNode) Cleanup() { | ||||||
| 	n.cleanup() | 	n.cleanup() | ||||||
| @@ -563,6 +603,17 @@ func (n *DockerClusterNode) cleanup() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (n *DockerClusterNode) createDefaultListenerConfig() map[string]interface{} { | ||||||
|  | 	return map[string]interface{}{"tcp": map[string]interface{}{ | ||||||
|  | 		"address":       fmt.Sprintf("%s:%d", "0.0.0.0", 8200), | ||||||
|  | 		"tls_cert_file": "/vault/config/cert.pem", | ||||||
|  | 		"tls_key_file":  "/vault/config/key.pem", | ||||||
|  | 		"telemetry": map[string]interface{}{ | ||||||
|  | 			"unauthenticated_metrics_access": true, | ||||||
|  | 		}, | ||||||
|  | 	}} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOptions) error { | func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOptions) error { | ||||||
| 	if n.DataVolumeName == "" { | 	if n.DataVolumeName == "" { | ||||||
| 		vol, err := n.DockerAPI.VolumeCreate(ctx, volume.CreateOptions{}) | 		vol, err := n.DockerAPI.VolumeCreate(ctx, volume.CreateOptions{}) | ||||||
| @@ -575,16 +626,25 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	vaultCfg := map[string]interface{}{} | 	vaultCfg := map[string]interface{}{} | ||||||
| 	vaultCfg["listener"] = map[string]interface{}{ | 	var listenerConfig []map[string]interface{} | ||||||
| 		"tcp": map[string]interface{}{ | 	listenerConfig = append(listenerConfig, n.createDefaultListenerConfig()) | ||||||
| 			"address":       fmt.Sprintf("%s:%d", "0.0.0.0", 8200), | 	ports := []string{"8200/tcp", "8201/tcp"} | ||||||
| 			"tls_cert_file": "/vault/config/cert.pem", |  | ||||||
| 			"tls_key_file":  "/vault/config/key.pem", | 	if opts.VaultNodeConfig != nil && opts.VaultNodeConfig.AdditionalListeners != nil { | ||||||
| 			"telemetry": map[string]interface{}{ | 		for _, config := range opts.VaultNodeConfig.AdditionalListeners { | ||||||
| 				"unauthenticated_metrics_access": true, | 			cfg := n.createDefaultListenerConfig() | ||||||
| 			}, | 			listener := cfg["tcp"].(map[string]interface{}) | ||||||
| 		}, | 			listener["address"] = fmt.Sprintf("%s:%d", "0.0.0.0", config.Port) | ||||||
|  | 			listener["chroot_namespace"] = config.ChrootNamespace | ||||||
|  | 			listenerConfig = append(listenerConfig, cfg) | ||||||
|  | 			portStr := fmt.Sprintf("%d/tcp", config.Port) | ||||||
|  | 			if strutil.StrListContains(ports, portStr) { | ||||||
|  | 				return fmt.Errorf("duplicate port %d specified", config.Port) | ||||||
|  | 			} | ||||||
|  | 			ports = append(ports, portStr) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | 	vaultCfg["listener"] = listenerConfig | ||||||
| 	vaultCfg["telemetry"] = map[string]interface{}{ | 	vaultCfg["telemetry"] = map[string]interface{}{ | ||||||
| 		"disable_hostname": true, | 		"disable_hostname": true, | ||||||
| 	} | 	} | ||||||
| @@ -675,6 +735,7 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption | |||||||
| 		} | 		} | ||||||
| 		testcluster.JSONLogNoTimestamp(n.Logger, s) | 		testcluster.JSONLogNoTimestamp(n.Logger, s) | ||||||
| 	}} | 	}} | ||||||
|  |  | ||||||
| 	r, err := dockhelper.NewServiceRunner(dockhelper.RunOptions{ | 	r, err := dockhelper.NewServiceRunner(dockhelper.RunOptions{ | ||||||
| 		ImageRepo: n.ImageRepo, | 		ImageRepo: n.ImageRepo, | ||||||
| 		ImageTag:  n.ImageTag, | 		ImageTag:  n.ImageTag, | ||||||
| @@ -689,7 +750,7 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption | |||||||
| 			"VAULT_LOG_FORMAT=json", | 			"VAULT_LOG_FORMAT=json", | ||||||
| 			"VAULT_LICENSE=" + opts.VaultLicense, | 			"VAULT_LICENSE=" + opts.VaultLicense, | ||||||
| 		}, | 		}, | ||||||
| 		Ports:           []string{"8200/tcp", "8201/tcp"}, | 		Ports:           ports, | ||||||
| 		ContainerName:   n.Name(), | 		ContainerName:   n.Name(), | ||||||
| 		NetworkName:     opts.NetworkName, | 		NetworkName:     opts.NetworkName, | ||||||
| 		CopyFromTo:      copyFromTo, | 		CopyFromTo:      copyFromTo, | ||||||
| @@ -772,6 +833,19 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption | |||||||
| 	} | 	} | ||||||
| 	client.SetToken(n.Cluster.rootToken) | 	client.SetToken(n.Cluster.rootToken) | ||||||
| 	n.client = client | 	n.client = client | ||||||
|  |  | ||||||
|  | 	n.AllClients = append(n.AllClients, client) | ||||||
|  |  | ||||||
|  | 	for _, addr := range svc.StartResult.Addrs[2:] { | ||||||
|  | 		// The second element of this list of addresses is the cluster address | ||||||
|  | 		// We do not want to create a client for the cluster address mapping | ||||||
|  | 		client, err := n.newAPIClientForAddress(addr) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		client.SetToken(n.Cluster.rootToken) | ||||||
|  | 		n.AllClients = append(n.AllClients, client) | ||||||
|  | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -53,7 +53,8 @@ type VaultNodeConfig struct { | |||||||
| 	//   ServiceRegistrationType        string | 	//   ServiceRegistrationType        string | ||||||
| 	//   ServiceRegistrationOptions    map[string]string | 	//   ServiceRegistrationOptions    map[string]string | ||||||
|  |  | ||||||
| 	StorageOptions map[string]string | 	StorageOptions      map[string]string | ||||||
|  | 	AdditionalListeners []VaultNodeListenerConfig | ||||||
|  |  | ||||||
| 	DefaultMaxRequestDuration      time.Duration `json:"default_max_request_duration"` | 	DefaultMaxRequestDuration      time.Duration `json:"default_max_request_duration"` | ||||||
| 	LogFormat                      string        `json:"log_format"` | 	LogFormat                      string        `json:"log_format"` | ||||||
| @@ -102,6 +103,11 @@ type ClusterOptions struct { | |||||||
| 	AdministrativeNamespacePath string | 	AdministrativeNamespacePath string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type VaultNodeListenerConfig struct { | ||||||
|  | 	Port            int | ||||||
|  | 	ChrootNamespace string | ||||||
|  | } | ||||||
|  |  | ||||||
| type CA struct { | type CA struct { | ||||||
| 	CACert        *x509.Certificate | 	CACert        *x509.Certificate | ||||||
| 	CACertBytes   []byte | 	CACertBytes   []byte | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 divyaac
					divyaac