Merge branch 'release-next' of github.com:openziti/ziti into enhance-docker-entrypoint

This commit is contained in:
Kenneth Bingham
2021-07-08 18:01:51 -04:00
11 changed files with 318 additions and 33 deletions
+118
View File
@@ -1,9 +1,127 @@
# Release 0.20.11
* Bug fix: CLI Admin create/update/delete for UPDB authenticators now function properly
* Maintenance: better logging [sdk-golang#161](https://github.com/openziti/sdk-golang/pull/161) and [edge#700](https://github.com/openziti/edge/pull/700)
* Bug fix: [sdk-golang#162](https://github.com/openziti/sdk-golang/pull/162) fix race condition on close of ziti connections
# Release 0.20.10
## What's New
* Bug fix: patch for process multi would clear information
* Bug fix: [ziti#420](https://github.com/openziti/ziti/issues/420) fix ziti-tunnel failover with multiple interfaces when once becomes unavailable
* Bug fix: [edge#670](https://github.com/openziti/edge/issues/670) fix ziti-tunnel issue where address were left assigned to loopback after clean shutdown
* Bug fix: race condition in edge session sync could cause router panic. Regression since 0.20.9
* Bug fix: terminator updates and deletes from the combined router/tunneler weren't working
* Feature: Router health checks
* Feature: Controller health check
## Router Health Checks
Routers can now enable an HTTP health check endpoint. The health check is configured in the router config file with the new `healthChecks` section.
```
healthChecks:
ctrlPingCheck:
# How often to ping the controller over the control channel. Defaults to 30 seconds
interval: 30s
# When to timeout the ping. Defaults to 15 seconds
timeout: 15s
# How long to wait before pinging the controller. Defaults to 15 seconds
initialDelay: 15s
```
The health check endpoint is configured via XWeb, same as in the controller. As section like the following can be added to the router config to enable the endpoint.
```
web:
- name: health-check
bindPoints:
- interface: 127.0.0.1:8081
address: 127.0.0.1:8081
apis:
- binding: health-checks
```
The health check output will look like this:
```
$ curl -k https://localhost:8081/health-checks
{
"data": {
"checks": [
{
"healthy": true,
"id": "controllerPing",
"lastCheckDuration": "767.381µs",
"lastCheckTime": "2021-06-21T16:22:36-04:00"
}
],
"healthy": true
},
"meta": {}
}
```
The endpoint will return a 200 if the health checks are passing and 503 if they are not.
# Controller Health Check
Routers can now enable an HTTP health check endpoint. The health check is configured in the router config file with the new `healthChecks` section.
```
healthChecks:
boltCheck:
# How often to check the bolt db. Defaults to 30 seconds
interval: 30s
# When to timeout the bolt db check. Defaults to 15 seconds
timeout: 15s
# How long to wait before starting bolt db checks. Defaults to 15 seconds
initialDelay: 15s
```
The health check endpoint is configured via XWeb. In order to enable the health check endpoint, add it **first** to the list of apis.
```
apis:
# binding - required
# Specifies an API to bind to this webListener. Built-in APIs are
# - edge-management
# - edge-client
# - fabric-management
- binding: health-checks
options: { }
- binding: edge-management
# options - variable optional/required
# This section is used to define values that are specified by the API they are associated with.
# These settings are per API. The example below is for the `edge-api` and contains both optional values and
# required values.
options: { }
- binding: edge-client
options: { }
```
The health check output will look like this:
```
$ curl -k https://localhost:1280/health-checks
{
"data": {
"checks": [
{
"healthy": true,
"id": "bolt.read",
"lastCheckDuration": "27.46µs",
"lastCheckTime": "2021-06-21T17:32:31-04:00"
}
],
"healthy": true
},
"meta": {}
}
```
# Release 0.20.9
+14 -1
View File
@@ -79,6 +79,15 @@ mgmt:
# enabled: false
# delay: 5
healthChecks:
boltCheck:
# How often to try entering a bolt read tx. Defaults to 30 seconds
interval: 30s
# When to timeout the check. Defaults to 15 seconds
timeout: 15s
# How long to wait before starting the check. Defaults to 15 seconds
initialDelay: 15s
# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this
# section, commenting out, or altering the name of the section will cause the edge to not run.
edge:
@@ -179,9 +188,12 @@ web:
apis:
# binding - required
# Specifies an API to bind to this webListener. Built-in APIs are
# - health-checks
# - edge-management
# - edge-client
# - fabric-management
- binding: health-checks
options: { }
- binding: edge-management
# options - variable optional/required
# This section is used to define values that are specified by the API they are associated with.
@@ -189,4 +201,5 @@ web:
# required values.
options: { }
- binding: edge-client
options: { }
options: { }
+34
View File
@@ -36,6 +36,15 @@ link:
dialers:
- binding: transport
healthChecks:
ctrlPingCheck:
# How often to ping the controller over the control channel. Defaults to 30 seconds
interval: 30s
# When to timeout the ping. Defaults to 15 seconds
timeout: 15s
# How long to wait before pinging the controller. Defaults to 15 seconds
initialDelay: 15s
metrics:
reportInterval: 15s
messageQueueSize: 10
@@ -102,3 +111,28 @@ listeners:
- binding: transport
address: tls:0.0.0.0:7099
web:
# name - required
# Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested.
- name: health-check
# bindPoints - required
# One or more bind points are required. A bind point specifies an interface (interface:port string) that defines
# where on the host machine the webListener will listen and the address (host:port) that should be used to
# publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for
# incoming address resolution as well as used in responses in the API.
bindPoints:
#interface - required
# A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces
- interface: 127.0.0.1:8081
# address - required
# The public address that external incoming requests will be able to resolve. Used in request processing and
# response content that requires full host:port/path addresses.
address: 127.0.0.1:8081
# apis - required
# Allows one or more APIs to be bound to this webListener
apis:
# binding - required
# Specifies an API to bind to this webListener. Built-in APIs are
# - health-checks
- binding: health-checks
~
+13 -1
View File
@@ -58,6 +58,18 @@ forwarder:
ctrl:
endpoint: tls:127.0.0.1:6262
healthCheck:
# Specifies the health check port. If not present, the health check will be disabled
#port: 8081
# Specifies what address to bind to. Default to blank, which will bind to all available addresses
bindAddress: ""
# How often to ping the controller over the control channel. Defaults to 30 seconds
ctrlPingInterval: 30s
# When to timeout the ping. Defaults to 15 seconds
ctrlPingTimeout: 15s
# How long to wait before pinging the controller. Defaults to 15 seconds
initialDelay: 15s
# Listener Configuration
#
# Define the Xgress listeners to start up, and their configuration.
@@ -105,4 +117,4 @@ listeners:
options:
retransmission: true
randomDrops: true
drop1InN: 5000
drop1InN: 5000
+4 -4
View File
@@ -29,10 +29,10 @@ require (
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19
github.com/michaelquigley/pfxlog v0.3.7
github.com/openziti/edge v0.19.135
github.com/openziti/fabric v0.16.68
github.com/openziti/foundation v0.15.55
github.com/openziti/sdk-golang v0.15.55
github.com/openziti/edge v0.19.149
github.com/openziti/fabric v0.16.71
github.com/openziti/foundation v0.15.56
github.com/openziti/sdk-golang v0.15.59
github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.9.1
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
+10 -10
View File
@@ -30,8 +30,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/AppsFlyer/go-sundheit v0.3.1 h1:Zqnr3wV3WQmXonc234k9XZAoV2KHUHw3osR5k2iHQZE=
github.com/AppsFlyer/go-sundheit v0.3.1/go.mod h1:iZ8zWMS7idcvmqewf5mEymWWgoOiG/0WD4+aeh+heX4=
github.com/AppsFlyer/go-sundheit v0.4.0 h1:7ECd0YWaXJQ9LzdCFrpGxJVeAgXvNarN6uwxrJsh69A=
github.com/AppsFlyer/go-sundheit v0.4.0/go.mod h1:iZ8zWMS7idcvmqewf5mEymWWgoOiG/0WD4+aeh+heX4=
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw=
@@ -622,14 +622,14 @@ github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e h1:ST9+54UtCr96S5
github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k=
github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo=
github.com/openziti/edge v0.19.135 h1:8KHrF1Tyy6+WTD+uKRggA/ck+mfNI8BjSKERfdDoF0Y=
github.com/openziti/edge v0.19.135/go.mod h1:Fr9fF1X6FF3RRjytq909+0nmboKS74Xp8jLJjnN3qZ4=
github.com/openziti/fabric v0.16.68 h1:xo432y7qewrK//nFEZYpujnTzYloYSZPzlwaLMdyd0s=
github.com/openziti/fabric v0.16.68/go.mod h1:JgQ6EWVAjjbePcsM20hqQLMMeGjAhqLDvqVjy2qnt6g=
github.com/openziti/foundation v0.15.55 h1:JNNown1ki8GHu3WRGTTAjTn0KrFIQoiSP93exoZPOI4=
github.com/openziti/foundation v0.15.55/go.mod h1:h8d47dCV3vgwAkY4pkQrgpu3wBblDwUrNb/uvDAs0sU=
github.com/openziti/sdk-golang v0.15.55 h1:ry5+Xr+xw23+WHfU6bULueOBAmW2R5f1ILvbRJzf17A=
github.com/openziti/sdk-golang v0.15.55/go.mod h1:FCQArKmdxtG+t5xyBtKpnSiXdsdTFFaVhLvRtto+YRs=
github.com/openziti/edge v0.19.149 h1:wvS5lHveGtJzAU1yuNR9K4ju883FWNyuyKvzd3R+W2A=
github.com/openziti/edge v0.19.149/go.mod h1:eGu0DblfIeppWJOhUFrF3i3mzgLO2+q+xEQMiht+ntA=
github.com/openziti/fabric v0.16.71 h1:5y66bJYXXOI2xdCfD79KCBlW3g638Vx80VVrnyq9kRc=
github.com/openziti/fabric v0.16.71/go.mod h1:RhooR5KtpxSpesOa/L9VelwlkhaToBTwzwT1QiGDB/4=
github.com/openziti/foundation v0.15.56 h1:St4FLcaBD8ER1QyO/P0enyIRw+ErOKayHc3zY6aY6aU=
github.com/openziti/foundation v0.15.56/go.mod h1:h8d47dCV3vgwAkY4pkQrgpu3wBblDwUrNb/uvDAs0sU=
github.com/openziti/sdk-golang v0.15.59 h1:1vVKO0lpzmLe5T9b2XdWjguJ9rxNJKaRW4eGFwcP+7Y=
github.com/openziti/sdk-golang v0.15.59/go.mod h1:+dbV733phFpHXLSHFJZ+3bDRy93Vv7YhmpItE03sYWs=
github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
github.com/orcaman/concurrent-map v0.0.0-20210106121528-16402b402231 h1:fa50YL1pzKW+1SsBnJDOHppJN9stOEwS+CRWyUtyYGU=
@@ -16,12 +16,10 @@ by hostname instead of IP address.
[Here's some detail on how the various intercept modes work on Linux](https://openziti.github.io/ziti/clients/linux.html)
### Solution Overview
![Diagram of solution](./sidecar-diagram.svg)
## Prerequisites
- Complete the [Ziti Network Quickstart](https://openziti.github.io/ziti/quickstarts/networks-overview.html). This guide
@@ -36,13 +34,13 @@ We will create a new identity for our client, with a new AppWAN that uses the et
Create the Identity:
$ ziti edge controller create identity device tunnel-sidecar -o tunnel-sidecar.jwt
ziti edge controller create identity device tunnel-sidecar -o tunnel-sidecar.jwt
Create the AppWAN and reference the service created in the Ziti Network Quickstart. We'll be using `eth0.ziti.cli`
here but if you created `eth0.ziti.ui` in the quickstart - use that instead. Also note that in the
tunnel-sidecar-demo.yaml:
$ ziti edge controller create app-wan ziti-tunnel-appwan -i tunnel-sidecar -s eth0.ziti.cli
ziti edge controller create app-wan ziti-tunnel-appwan -i tunnel-sidecar -s eth0.ziti.cli
## Create a Kubernetes Secret
@@ -50,6 +48,7 @@ The `ziti-tunnel` sidecar will access its identity by mounting a Kubernetes secr
We can mount the JWT as a secret like this:
$ kubectl create secret generic tunnel-sidecar.jwt --from-file=tunnel-sidecar.jwt
secret/tunnel-sidecar.jwt created
## Deploy the Pod
@@ -97,7 +96,7 @@ Save the following yaml to a file named tunnel-sidecar-demo.yaml
value: tunnel-sidecar
volumeMounts:
- name: tunnel-sidecar-jwt
mountPath: "/var/run/secrets/netfoundry.io/enrollment-token"
mountPath: "/var/run/secrets/kubernetes.io/enrollment-token"
readOnly: true
- name: ziti-tunnel-persistent-storage
mountPath: /netfoundry
@@ -119,7 +118,6 @@ Save the following yaml to a file named tunnel-sidecar-demo.yaml
secret:
secretName: tunnel-sidecar.jwt
You'll notice that the `ziti-tunnel` sidecar container has a few requirements:
1. The name of the identity that is assumed by `ziti-tunnel` must be passed into the container with the
@@ -133,6 +131,8 @@ You'll notice that the `ziti-tunnel` sidecar container has a few requirements:
Once the yaml is saved, we can deploy the Pod with `kubectl`
$ kubectl apply -f ./tunnel-sidecar-demo.yaml
persistentvolumeclaim/tunnel-sidecar-pv-claim created
deployment.apps/ziti-tunnel-sidecar-demo created
## Test the Service
@@ -149,4 +149,4 @@ Then we can tail the logs for the "testclient" container:
54.67.121.213
Notice that the `curl` client is using the DNS name that we provided in the Ziti service definition to make the
request.
request.
+1 -1
View File
@@ -72,7 +72,7 @@ func run(cmd *cobra.Command, args []string) {
stateManager := fabric.NewStateManager()
xgressEdgeFactory := xgress_edge.NewFactory(config, version.GetCmdBuildInfo(), stateManager)
xgressEdgeFactory := xgress_edge.NewFactory(config, version.GetCmdBuildInfo(), stateManager, r.MetricsRegistry())
xgress.GlobalRegistry().Register(edge_common.EdgeBinding, xgressEdgeFactory)
if err := r.RegisterXctrl(xgressEdgeFactory); err != nil {
logrus.Panicf("error registering edge in framework (%v)", err)
@@ -17,11 +17,14 @@
package edge_controller
import (
"context"
"errors"
"fmt"
"github.com/Jeffail/gabs"
"github.com/openziti/edge/rest_management_api_client/authenticator"
"github.com/openziti/foundation/util/term"
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/ziti/util"
"github.com/spf13/cobra"
)
@@ -78,24 +81,55 @@ func runCreateIdentityPassword(idType string, options *createAuthenticatorUpdb)
return errors.New("an identity must be specified")
}
id, err := mapIdentityNameToID(options.idOrName, options.edgeOptions)
identityId, err := mapIdentityNameToID(options.idOrName, options.edgeOptions)
if err != nil {
return err
}
client, err := util.DefaultEdgeManagementClient()
if err != nil {
return err
}
filter := fmt.Sprintf(`identity="%s" and method="updb"`, identityId)
result, err := client.Authenticator.ListAuthenticators(&authenticator.ListAuthenticatorsParams{
Filter: &filter,
Context: context.Background(),
}, nil)
if err != nil {
return err
}
if len(result.Payload.Data) != 0 {
return fmt.Errorf("updb authentictor already exists, update or remove it instead")
}
if options.password == "" {
if options.password, err = term.PromptPassword("Enter password: ", false); err != nil {
return err
}
verifyPassword := ""
if verifyPassword, err = term.PromptPassword("Enter password again: ", false); err != nil {
return err
}
if verifyPassword != options.password {
return errors.New("passwords did not match")
}
}
passwordData := gabs.New()
setJSONValue(passwordData, options.password, "password")
setJSONValue(passwordData, options.username, "username")
authenticatorData := gabs.New()
setJSONValue(authenticatorData, identityId, "identityId")
setJSONValue(authenticatorData, options.password, "password")
setJSONValue(authenticatorData, options.username, "username")
setJSONValue(authenticatorData, "updb", "method")
if _, err = createEntityOfType(fmt.Sprintf("identities/%s/updb", id), passwordData.String(), &options.edgeOptions); err != nil {
if _, err = createEntityOfType("authenticators", authenticatorData.String(), &options.edgeOptions); err != nil {
return err
}
return nil
}
@@ -17,7 +17,10 @@
package edge_controller
import (
"context"
"fmt"
"github.com/openziti/edge/rest_management_api_client/authenticator"
"github.com/openziti/ziti/ziti/cmd/ziti/util"
"github.com/spf13/cobra"
)
import cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
@@ -52,13 +55,43 @@ func newDeleteAuthenticatorUpdb(idType string, options *edgeOptions) *cobra.Comm
}
func runDeleteUpdb(idOrName string, options *deleteUpdbOptions) error {
id, err := mapIdentityNameToID(idOrName, options.edgeOptions)
identityId, err := mapIdentityNameToID(idOrName, options.edgeOptions)
if err != nil {
return err
}
_, err = deleteEntityOfType(fmt.Sprintf("identities/%s/updb/password", id), "", &options.edgeOptions)
client, err := util.DefaultEdgeManagementClient()
if err != nil {
return err
}
filter := fmt.Sprintf(`identity="%s" and method="updb"`, identityId)
result, err := client.Authenticator.ListAuthenticators(&authenticator.ListAuthenticatorsParams{
Filter: &filter,
Context: context.Background(),
}, nil)
if err != nil {
return err
}
if len(result.Payload.Data) != 1 {
return fmt.Errorf("incorrect number of results, expected 1, got %d", len(result.Payload.Data))
}
if result.Payload.Data[0].ID == nil {
return fmt.Errorf("authenticator contained a nil id")
}
if *result.Payload.Data[0].ID == "" {
return fmt.Errorf("authenticator contained an empty id")
}
authenticatorId := *result.Payload.Data[0].ID
_, err = deleteEntityOfType(fmt.Sprintf("authenticators/%s", authenticatorId), "", &options.edgeOptions)
if err != nil {
return err
@@ -17,9 +17,11 @@
package edge_controller
import (
"context"
"errors"
"fmt"
"github.com/Jeffail/gabs"
"github.com/openziti/edge/rest_management_api_client/authenticator"
"github.com/openziti/foundation/util/term"
"github.com/openziti/ziti/ziti/cmd/ziti/util"
"github.com/spf13/cobra"
@@ -134,16 +136,55 @@ func setIdentityPassword(identity, password string, options edgeOptions) error {
return err
}
client, err := util.DefaultEdgeManagementClient()
if err != nil {
return err
}
filter := fmt.Sprintf(`identity="%s" and method="updb"`, id)
result, err := client.Authenticator.ListAuthenticators(&authenticator.ListAuthenticatorsParams{
Filter: &filter,
Context: context.Background(),
}, nil)
if err != nil {
return err
}
if len(result.Payload.Data) != 1 {
return fmt.Errorf("incorrect number of results, expected 1, got %d", len(result.Payload.Data))
}
if result.Payload.Data[0].ID == nil {
return fmt.Errorf("authenticator contained a nil id")
}
if *result.Payload.Data[0].ID == "" {
return fmt.Errorf("authenticator contained an empty id")
}
authenticatorId := result.Payload.Data[0].ID
if password == "" {
if password, err = term.PromptPassword("Enter the identity's new password : ", false); err != nil {
return err
}
verifyPassword := ""
if verifyPassword, err = term.PromptPassword("Enter password again: ", false); err != nil {
return err
}
if verifyPassword != password {
return errors.New("passwords did not match")
}
}
passwordData := gabs.New()
setJSONValue(passwordData, password, "password")
_, err = putEntityOfType(fmt.Sprintf("identities/%s/updb/password", id), passwordData.String(), &options)
_, err = patchEntityOfType(fmt.Sprintf("authenticators/%s", *authenticatorId), passwordData.String(), &options)
if err != nil {
return err