Skip to content

Commit

Permalink
etcd: use a separate connection to check peer versions (#6905)
Browse files Browse the repository at this point in the history
There is a data race in etcd that breaks the internal state in etcd client
implementation for some server setups (user/pass authentication with
JWTs).
  • Loading branch information
Andrew Lytvynov authored and awly committed May 19, 2021
1 parent 7319ab3 commit fc99e87
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions lib/backend/etcdbk/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import (
"github.com/gravitational/teleport/lib/utils"

"github.com/coreos/go-semver/semver"
"github.com/gravitational/teleport"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/prometheus/client_golang/prometheus"
Expand All @@ -46,6 +45,8 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/gravitational/teleport"
)

var (
Expand Down Expand Up @@ -224,11 +225,10 @@ func New(ctx context.Context, params backend.Params) (*EtcdBackend, error) {
buf: buf,
}

// Check that the etcd nodes are at least the minimum version supported
if err = b.reconnect(ctx); err != nil {
return nil, trace.Wrap(err)
}

// Check that the etcd nodes are at least the minimum version supported
timeout, cancel := context.WithTimeout(ctx, time.Second*3*time.Duration(len(cfg.Nodes)))
defer cancel()
for _, n := range cfg.Nodes {
Expand All @@ -245,6 +245,13 @@ func New(ctx context.Context, params backend.Params) (*EtcdBackend, error) {
}
}

// Reconnect the etcd client to work around a data race in their code.
// Upstream fix: https://github.com/etcd-io/etcd/pull/12992
if err = b.reconnect(ctx); err != nil {
return nil, trace.Wrap(err)
}
go b.asyncWatch()

// Wrap backend in a input sanitizer and return it.
return b, nil
}
Expand Down Expand Up @@ -300,6 +307,12 @@ func (b *EtcdBackend) CloseWatchers() {
}

func (b *EtcdBackend) reconnect(ctx context.Context) error {
if b.client != nil {
if err := b.client.Close(); err != nil {
b.Entry.WithError(err).Warning("Failed closing existing etcd client on reconnect.")
}
}

tlsConfig := utils.TLSConfig(nil)

if b.cfg.TLSCertFile != "" {
Expand Down Expand Up @@ -350,7 +363,6 @@ func (b *EtcdBackend) reconnect(ctx context.Context) error {
return trace.Wrap(err)
}
b.client = clt
go b.asyncWatch()
return nil
}

Expand Down

0 comments on commit fc99e87

Please sign in to comment.