From 090414db151815fa4f6277e488662055601d9265 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Wed, 5 Jul 2017 23:05:22 -0700 Subject: [PATCH 1/2] Add network area TLS setting to docs --- website/source/api/operator/area.html.md | 49 ++++++++++++++++++- website/source/docs/agent/encryption.html.md | 7 ++- .../commands/operator/area.html.markdown.erb | 35 +++++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/website/source/api/operator/area.html.md b/website/source/api/operator/area.html.md index dbe5b57636..dfb36d0d7e 100644 --- a/website/source/api/operator/area.html.md +++ b/website/source/api/operator/area.html.md @@ -64,12 +64,16 @@ The table below shows this endpoint's support for If this list is not supplied, joining can be done with a call to the [join endpoint](#area-join) once the network area is created. +- `UseTLS` `(bool: )` - Specifies whether gossip over this area should be + encrypted with TLS if possible. + ### Sample Payload ```json { "PeerDatacenter": "dc2", - "RetryJoin": [ "10.1.2.3", "10.1.2.4", "10.1.2.5" ] + "RetryJoin": [ "10.1.2.3", "10.1.2.4", "10.1.2.5" ], + "UseTLS": false } ``` @@ -132,6 +136,49 @@ $ curl \ ] ``` +## Update Network Area + +This endpoint updates a network area to the given configuration. + +| Method | Path | Produces | +| ------ | ---------------------------- | -------------------------- | +| `PUT` | `/operator/area/:uuid` | `application/json` | + +The table below shows this endpoint's support for +[blocking queries](/api/index.html#blocking-queries), +[consistency modes](/api/index.html#consistency-modes), and +[required ACLs](/api/index.html#acls). + +| Blocking Queries | Consistency Modes | ACL Required | +| ---------------- | ----------------- | ---------------- | +| `NO` | `none` | `operator:write` | + +### Parameters + +- `dc` `(string: "")` - Specifies the datacenter to query. This will default to + the datacenter of the agent being queried. This is specified as a URL query + parameter. + +- `UseTLS` `(bool: )` - Specifies whether gossip over this area should be + encrypted with TLS if possible. + +### Sample Payload + +```json +{ + "UseTLS": true +} +``` + +### Sample Request + +```text +$ curl \ + --request PUT \ + --data @payload.json \ + https://consul.rocks/v1/operator/area/8f246b77-f3e1-ff88-5b48-8ec93abf3e05 +``` + ## List Specific Network Area This endpoint lists a specific network area. diff --git a/website/source/docs/agent/encryption.html.md b/website/source/docs/agent/encryption.html.md index a100c98bec..814c89a5f2 100644 --- a/website/source/docs/agent/encryption.html.md +++ b/website/source/docs/agent/encryption.html.md @@ -123,8 +123,11 @@ options are set to `false`. HTTPS for the API can be enabled at this point by setting the [`https`](/docs/agent/options.html#http_port) port. 2. Perform a rolling restart of each agent in the cluster. After this step, TLS should be enabled everywhere but the agents will not yet be enforcing TLS. -3. Change the `verify_incoming` and `verify_outgoing` settings (as well as `verify_server_hostname` +3. (Optional, Enterprise-only) If applicable, set the `UseTLS` setting in any network areas to `true`. +This can be done either through the [`consul operator area update`](/docs/commands/operator/area.html) +command or the [Operator API](api/operator/area.html). +4. Change the `verify_incoming` and `verify_outgoing` settings (as well as `verify_server_hostname` if applicable) to `true`. -4. Perform another rolling restart of each agent in the cluster. +5. Perform another rolling restart of each agent in the cluster. At this point, full TLS encryption for RPC communication should be enabled. diff --git a/website/source/docs/commands/operator/area.html.markdown.erb b/website/source/docs/commands/operator/area.html.markdown.erb index cb93d5957c..239657a7e0 100644 --- a/website/source/docs/commands/operator/area.html.markdown.erb +++ b/website/source/docs/commands/operator/area.html.markdown.erb @@ -42,6 +42,7 @@ Subcommands: join Join Consul servers into an existing network area list List network areas members Display Consul server members present in network areas + update Update the configuration of a network area ``` If ACLs are enabled, the client will need to supply an ACL Token with `operator` @@ -67,6 +68,9 @@ where the area was created, and the peer datacenter. This is required. * `-retry-join=` Specifies the address of a Consul server to join to, such as an IP or hostname with an optional port number. This is optional and can be specified multiple times. +* `-use-tls=` Specifies whether gossip over this area should be encrypted with +TLS if possible. Must be either `true` or `false`. + The output looks like this, displaying the ID of the newly-created network area: ``` @@ -216,3 +220,34 @@ to the given server, in a human-readable format. This is computed using [network coordinates](/docs/internals/coordinates.html). The return code will indicate success or failure. + +## update + +This command updates the configuration of network area. + +Usage: `consul operator area update [options]` + +#### API Options + +<%= partial "docs/commands/http_api_options_client" %> +<%= partial "docs/commands/http_api_options_server" %> + +#### Command Options + +* `-id=` - Looks up the area to operate on by its ID. This can be given +instead of a peer datacenter. + +* `-peer-datacenter=` - Declares the peer Consul datacenter that will make up the other +side of this network area. Network areas always involve a pair of datacenters: the datacenter +where the area was created, and the peer datacenter. This is required. + +* `-use-tls=` Specifies whether gossip over this area should be encrypted with +TLS if possible. Must be either `true` or `false`. + +The output looks like this: + +``` +Updated area "d2872ec5-68ea-b862-b75d-0bee99aca100" +``` + +The return code will indicate success or failure. \ No newline at end of file From 78c3a86405c5a5f77623c11c6cd500bf0e7b5d9f Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Fri, 14 Jul 2017 17:31:52 -0700 Subject: [PATCH 2/2] Add TLS setting to router areas --- agent/consul/server.go | 2 +- agent/consul/servers/router.go | 25 ++++++++++++++++++++++++- agent/consul/servers/router_test.go | 22 +++++++++++----------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/agent/consul/server.go b/agent/consul/server.go index 4d8b478558..1d0418cf87 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -371,7 +371,7 @@ func NewServerLogger(config *Config, logger *log.Logger) (*Server, error) { go s.lanEventHandler() // Add a "static route" to the WAN Serf and hook it up to Serf events. - if err := s.router.AddArea(types.AreaWAN, s.serfWAN, s.connPool); err != nil { + if err := s.router.AddArea(types.AreaWAN, s.serfWAN, s.connPool, s.config.VerifyOutgoing); err != nil { s.Shutdown() return nil, fmt.Errorf("Failed to add WAN serf route: %v", err) } diff --git a/agent/consul/servers/router.go b/agent/consul/servers/router.go index 7bf4f2def9..315e3a55af 100644 --- a/agent/consul/servers/router.go +++ b/agent/consul/servers/router.go @@ -76,6 +76,9 @@ type areaInfo struct { // managers maps datacenter names to managers for that datacenter in // this area. managers map[string]*managerInfo + + // useTLS specifies whether to use TLS to communicate for this network area. + useTLS bool } // NewRouter returns a new Router with the given configuration. @@ -112,7 +115,7 @@ func (r *Router) Shutdown() { } // AddArea registers a new network area with the router. -func (r *Router) AddArea(areaID types.AreaID, cluster RouterSerfCluster, pinger Pinger) error { +func (r *Router) AddArea(areaID types.AreaID, cluster RouterSerfCluster, pinger Pinger, useTLS bool) error { r.Lock() defer r.Unlock() @@ -128,6 +131,7 @@ func (r *Router) AddArea(areaID types.AreaID, cluster RouterSerfCluster, pinger cluster: cluster, pinger: pinger, managers: make(map[string]*managerInfo), + useTLS: useTLS, } r.areas[areaID] = area @@ -168,6 +172,19 @@ func (r *Router) removeManagerFromIndex(datacenter string, manager *Manager) { panic("managers index out of sync") } +// Returns whether TLS is enabled for the given area ID +func (r *Router) TLSEnabled(areaID types.AreaID) (bool, error) { + r.RLock() + defer r.RUnlock() + + area, ok := r.areas[areaID] + if !ok { + return false, fmt.Errorf("area ID %q does not exist", areaID) + } + + return area.useTLS, nil +} + // RemoveArea removes an existing network area from the router. func (r *Router) RemoveArea(areaID types.AreaID) error { r.Lock() @@ -207,6 +224,12 @@ func (r *Router) addServer(area *areaInfo, s *agent.Server) error { go manager.Start() } + // If TLS is enabled for the area, set it on the server so the manager + // knows to use TLS when pinging it. + if area.useTLS { + s.UseTLS = true + } + info.manager.AddServer(s) return nil } diff --git a/agent/consul/servers/router_test.go b/agent/consul/servers/router_test.go index c04785c7d1..230031f8aa 100644 --- a/agent/consul/servers/router_test.go +++ b/agent/consul/servers/router_test.go @@ -105,7 +105,7 @@ func TestRouter_Shutdown(t *testing.T) { // Create a WAN-looking area. self := "node0.dc0" wan := testCluster(self) - if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}); err != nil { + if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -113,7 +113,7 @@ func TestRouter_Shutdown(t *testing.T) { otherID := types.AreaID("other") other := newMockCluster(self) other.AddMember("dcY", "node1", nil) - if err := r.AddArea(otherID, other, &fauxConnPool{}); err != nil { + if err := r.AddArea(otherID, other, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } _, _, ok := r.FindRoute("dcY") @@ -129,7 +129,7 @@ func TestRouter_Shutdown(t *testing.T) { } // You can't add areas once the router is shut down. - err := r.AddArea(otherID, other, &fauxConnPool{}) + err := r.AddArea(otherID, other, &fauxConnPool{}, false) if err == nil || !strings.Contains(err.Error(), "router is shut down") { t.Fatalf("err: %v", err) } @@ -141,7 +141,7 @@ func TestRouter_Routing(t *testing.T) { // Create a WAN-looking area. self := "node0.dc0" wan := testCluster(self) - if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}); err != nil { + if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -170,7 +170,7 @@ func TestRouter_Routing(t *testing.T) { other.AddMember("dc0", "node0", nil) other.AddMember("dc1", "node1", nil) other.AddMember("dcY", "node1", nil) - if err := r.AddArea(otherID, other, &fauxConnPool{}); err != nil { + if err := r.AddArea(otherID, other, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -275,7 +275,7 @@ func TestRouter_Routing_Offline(t *testing.T) { // Create a WAN-looking area. self := "node0.dc0" wan := testCluster(self) - if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{1.0}); err != nil { + if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{1.0}, false); err != nil { t.Fatalf("err: %v", err) } @@ -329,7 +329,7 @@ func TestRouter_Routing_Offline(t *testing.T) { other := newMockCluster(self) other.AddMember("dc0", "node0", nil) other.AddMember("dc1", "node1", nil) - if err := r.AddArea(otherID, other, &fauxConnPool{}); err != nil { + if err := r.AddArea(otherID, other, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -354,7 +354,7 @@ func TestRouter_GetDatacenters(t *testing.T) { self := "node0.dc0" wan := testCluster(self) - if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}); err != nil { + if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -386,7 +386,7 @@ func TestRouter_GetDatacentersByDistance(t *testing.T) { // Start with just the WAN area described in the diagram above. self := "node0.dc0" wan := testCluster(self) - if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}); err != nil { + if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -404,7 +404,7 @@ func TestRouter_GetDatacentersByDistance(t *testing.T) { other := newMockCluster(self) other.AddMember("dc0", "node0", lib.GenerateCoordinate(20*time.Millisecond)) other.AddMember("dc1", "node1", lib.GenerateCoordinate(21*time.Millisecond)) - if err := r.AddArea(otherID, other, &fauxConnPool{}); err != nil { + if err := r.AddArea(otherID, other, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) } @@ -423,7 +423,7 @@ func TestRouter_GetDatacenterMaps(t *testing.T) { self := "node0.dc0" wan := testCluster(self) - if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}); err != nil { + if err := r.AddArea(types.AreaWAN, wan, &fauxConnPool{}, false); err != nil { t.Fatalf("err: %v", err) }