Finished cleaning up storage back-ends

I hope this closes #688
This commit is contained in:
Ev Kontsevoy 2017-01-15 16:27:19 -08:00
parent 8330658526
commit ac205ad530
19 changed files with 232 additions and 81 deletions

View file

@ -2,7 +2,7 @@
# Naming convention:
# for stable releases we use "1.0.0" format
# for pre-releases, we use "1.0.0-beta.2" format
VERSION=1.3.2-beta
VERSION=1.5.0-alpha
# These are standard autotools variables, don't change them please
BUILDDIR ?= build
@ -12,26 +12,26 @@ ADDFLAGS ?=
PWD ?= `pwd`
TELEPORT_DEBUG ?= no
GITTAG=v$(VERSION)
RELEASE := teleport-$(GITTAG)-`go env GOOS`-`go env GOARCH`-bin
BUILDFLAGS := $(ADDFLAGS) -ldflags '-w -s'
RELEASE=teleport-$(GITTAG)-`go env GOOS`-`go env GOARCH`-bin
BINARIES=$(BUILDDIR)/tsh $(BUILDDIR)/teleport $(BUILDDIR)/tctl
LIBS != find lib -type f -name '*.go'
#
# Default target: builds all 3 executables and plaaces them in a current directory
#
.PHONY: all
all: setver teleport tctl tsh assets
cp -f build.assets/release.mk $(BUILDDIR)/Makefile
all: setver $(BINARIES)
.PHONY: tctl
tctl:
$(BUILDDIR)/tctl: $(LIBS) $(TOOLS) tool/tctl/*.go
go build -o $(BUILDDIR)/tctl -i $(BUILDFLAGS) ./tool/tctl
.PHONY: teleport
teleport:
$(BUILDDIR)/teleport: $(LIBS) tool/teleport/*.go
go build -o $(BUILDDIR)/teleport -i $(BUILDFLAGS) ./tool/teleport
.PHONY: tsh
tsh:
$(BUILDDIR)/tsh: $(LIBS) tool/tsh/*.go
go build -o $(BUILDDIR)/tsh -i $(BUILDFLAGS) ./tool/tsh
#
@ -46,23 +46,12 @@ install: build
mkdir -p $(DATADIR)
cp -fr web/dist/* $(DATADIR)
.PHONY: goinstall
goinstall:
go install $(BUILDFLAGS) ./tool/tctl
go install $(BUILDFLAGS) ./tool/teleport
go install $(BUILDFLAGS) ./tool/tsh
.PHONY: clean
clean:
rm -rf $(BUILDDIR)
rm -rf teleport
.PHONY: assets
assets:
rm -rf $(BUILDDIR)/app
rm -f web/dist/app/app
cp README.md $(BUILDDIR)
rm -rf $(RELEASE)*.gz
#
# Builds docs using containerized mkdocs
@ -119,19 +108,21 @@ tag:
#
# make release - produces a binary release tarball
#
.PHONY: release
release: clean setver all
cd web/dist ; zip -qr ../../$(BUILDDIR)/webassets.zip .
.PHONY:
release: clean all $(BUILDDIR)/webassets.zip
cp -f build.assets/release.mk $(BUILDDIR)/Makefile
cat $(BUILDDIR)/webassets.zip >> $(BUILDDIR)/teleport
zip -q -A $(BUILDDIR)/teleport
rm $(BUILDDIR)/webassets.zip
cp -rf $(BUILDDIR) teleport
@echo $(GITTAG) > teleport/VERSION
tar -czf $(RELEASE).tar.gz teleport
rm -rf teleport
@echo "\n"
@echo "CREATED: $(RELEASE).tar.gz"
@echo "\nCREATED: $(RELEASE).tar.gz"
# build/webassets.zip archive contains the web assets (UI) which gets
# appended to teleport binary
$(BUILDDIR)/webassets.zip:
cd web/dist ; zip -qr ../../$(BUILDDIR)/webassets.zip .
.PHONY: test-package
test-package: remove-temp-files
@ -158,12 +149,6 @@ profile:
sloccount:
find . -path ./vendor -prune -o -name "*.go" -print0 | xargs -0 wc -l
# start-test-etcd starts test etcd node using tls certificates
# TODO: this is how etcd tests can run:
#.PHONY: start-test-etcd
#start-test-etcd:
# docker run -d -p 4001:4001 -p 2380:2380 -p 2379:2379 -v $(ETCD_CERTS):/certs quay.io/coreos/etcd:v2.2.5 -name etcd0 -advertise-client-urls https://localhost:2379,https://localhost:4001 -listen-client-urls https://0.0.0.0:2379,https://0.0.0.0:4001 -initial-advertise-peer-urls https://localhost:2380 -listen-peer-urls https://0.0.0.0:2380 -initial-cluster-token etcd-cluster-1 -initial-cluster etcd0=https://localhost:2380 -initial-cluster-state new --cert-file=/certs/etcd1.pem --key-file=/certs/etcd1-key.pem --peer-cert-file=/certs/etcd1.pem --peer-key-file=/certs/etcd1-key.pem --peer-client-cert-auth --peer-trusted-ca-file=/certs/ca.pem -client-cert-auth
.PHONY: remove-temp-files
remove-temp-files:
find . -name flymake_* -delete

3
examples/etcd/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
data
certs/*.pem
certs/*.csr

65
examples/etcd/certs/Makefile Executable file
View file

@ -0,0 +1,65 @@
#!/bin/bash
# output:
# ca-key.pem : private key of the trusted CA
# ca-cert.pem : self-signed CA cert
# client-crt.pem : client cert signed by CA
# client-key.pem : private key of the client
.PHONY:all
all: clean ca-cert.pem server-cert.pem client-cert.pem
@rm -rf *csr
client-cert.pem:
# generate client key:
openssl req \
-new \
-nodes \
-keyout client-key.pem \
-subj "/C=US/ST=San Francisco/L=SOMA/O=Gravitational/CN=localhost" \
-out client.csr
# sign it with CA:
@touch index.txt
@echo '03' > serial
openssl ca -extensions etcd_client \
-config openssl.cnf \
-keyfile ca-key.pem \
-cert ca-cert.pem \
-out client-cert.pem \
-infiles client.csr
@rm -rf *old index* serial* 01.pem 03.pem
server-cert.pem:
# generate server key:
openssl req \
-new \
-nodes \
-keyout server-key.pem \
-subj "/C=US/ST=San Francisco/L=SOMA/O=Gravitational/CN=localhost" \
-out server.csr
# sign it with CA:
@touch index.txt
@echo '01' > serial
openssl ca -extensions etcd_server \
-config openssl.cnf \
-keyfile ca-key.pem \
-cert ca-cert.pem \
-out server-cert.pem \
-infiles server.csr
@rm -rf *old index* serial*
# Generates the "root" private key+cert which will become the trusted CA
# which can sign client certificates
ca-cert.pem:
openssl req -x509 \
-extensions v3_ca \
-new \
-keyout ca-key.pem \
-out ca-cert.pem \
-subj "/C=US/ST=San Francisco/L=SOMA/O=Gravitational/CN=localhost" \
-days 3650 \
-nodes
# removes everything
.PHONY:clean
clean:
rm -rf *pem *csr *crt index* serial

View file

@ -0,0 +1,4 @@
To generate self-signed certificates for secure connectivity to etcd run:
$ make

View file

@ -0,0 +1,72 @@
# etcd OpenSSL configuration file.
SAN = "IP:127.0.0.1"
dir = .
[ ca ]
default_ca = etcd_ca
[ etcd_ca ]
certs = $dir
certificate = $dir/ca-cert.pem
crl = $dir/crl.pem
crl_dir = $dir/crl
crlnumber = $dir/crlnumber
database = $dir/index.txt
email_in_dn = no
new_certs_dir = $dir
private_key = $dir/ca-key.pem
serial = $dir/serial
RANDFILE = $dir/.rand
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
default_crl_days = 30
default_md = sha512
preserve = no
policy = policy_etcd
[ policy_etcd ]
organizationName = optional
commonName = supplied
[ req ]
default_bits = 4096
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
string_mask = utf8only
req_extensions = etcd_client
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
commonName = Common Name (FQDN)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = etcd-ca
[ req_attributes ]
[ v3_ca ]
basicConstraints = CA:true
keyUsage = keyCertSign,cRLSign
subjectKeyIdentifier = hash
[ etcd_client ]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth
keyUsage = digitalSignature, keyEncipherment
[ etcd_peer ]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = digitalSignature, keyEncipherment
subjectAltName = ${ENV::SAN}
[ etcd_server ]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = digitalSignature, keyEncipherment
subjectAltName = ${ENV::SAN}

16
examples/etcd/start-etcd.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
#
# Example of how etcd must be started in the full TLS mode, i.e.
# - server cert is checked by clients
# - client cert is checked by the server
#
mdkir -p data
etcd --name teleportstorage \
--data-dir data/etcd \
--initial-cluster-state new \
--cert-file=certs/server-cert.pem \
--key-file=certs/server-key.pem \
--ca-file=certs/ca-cert.pem \
--advertise-client-urls=https://127.0.0.1:2379 \
--listen-client-urls=https://127.0.0.1:2379 \
--client-cert-auth

View file

@ -0,0 +1,4 @@
#!/bin/bash
#
# Example of how Teleport must be started to connect to etcd
teleport start -c teleport.yaml -d

View file

@ -0,0 +1,9 @@
teleport:
data_dir: data/teleport
storage:
type: etcd
peers: ["https://127.0.0.1:2379"]
prefix: teleport.secrets
tls_key_file: certs/client-key.pem
tls_cert_file: certs/client-cert.pem
tls_ca_file: certs/ca-cert.pem

View file

@ -234,7 +234,7 @@ func (i *TeleInstance) CreateEx(trustedSecrets []*InstanceSecrets, tconf *servic
tconf.Proxy.WebAddr.Addr = net.JoinHostPort(i.Hostname, i.GetPortWeb())
tconf.Proxy.DisableWebUI = true
tconf.AuthServers = append(tconf.AuthServers, tconf.Auth.SSHAddr)
tconf.Auth.KeysBackend.BackendConf = &backend.Config{
tconf.Auth.StorageConfig = backend.Config{
Type: boltbk.GetName(),
Params: backend.Params{"path": dataDir},
}

View file

@ -660,7 +660,9 @@ func NewTunClient(purpose string,
if tc.addrStorage != nil {
cachedAuthServers, err := tc.addrStorage.GetAddresses()
if err != nil {
log.Infof("unable to load the auth server cache: %v", err)
if !trace.IsNotFound(err) {
log.Warnf("unable to load the auth server cache: %s", err.Error())
}
} else {
tc.setAuthServers(cachedAuthServers)
}

View file

@ -69,7 +69,7 @@ func New(params backend.Params) (backend.Backend, error) {
}
// still nothing? return an error:
if path == "" {
return nil, trace.BadParameter("Bolt backend: 'path' is not set")
return nil, trace.BadParameter("BoltDB backend: 'path' is not set")
}
if !utils.IsDir(path) {
return nil, trace.BadParameter("%v is not a valid directory", path)

View file

@ -176,11 +176,11 @@ func (s *Suite) TestLocking(c *check.C) {
}()
time.Sleep(time.Millisecond * 2)
// make sure i did not change (the modifying gorouting was locked)
c.Assert(i, check.Equals, int32(0))
c.Assert(atomic.LoadInt32(&i), check.Equals, int32(0))
s.clock.Advance(ttl + 1)
// release the lock, and the gorouting should unlock and advance i
s.bk.ReleaseLock(lock)
time.Sleep(time.Millisecond * 2)
c.Assert(i, check.Equals, int32(1))
c.Assert(atomic.LoadInt32(&i), check.Equals, int32(1))
}

View file

@ -62,6 +62,9 @@ func GetName() string {
// New returns new instance of Etcd-powered backend
func New(params backend.Params) (backend.Backend, error) {
var err error
if params == nil {
return nil, trace.BadParameter("missing etcd configuration")
}
// convert generic backend parameters structure to etcd config:
var cfg *Config
@ -87,16 +90,16 @@ func New(params backend.Params) (backend.Backend, error) {
// Validate checks if all the parameters are present/valid
func (cfg *Config) Validate() error {
if len(cfg.Key) == 0 {
return trace.BadParameter(`Key: supply a valid root key for Teleport data`)
return trace.BadParameter(`etcd: missing "prefix" setting`)
}
if len(cfg.Nodes) == 0 {
return trace.BadParameter(`Nodes: please supply a valid dictionary, e.g. {"nodes": ["http://localhost:4001]}`)
return trace.BadParameter(`etcd: missing "peers" setting`)
}
if cfg.TLSKeyFile == "" {
return trace.BadParameter(`TLSKeyFile: please supply a path to TLS private key file`)
return trace.BadParameter(`etcd: missing "tls_key_file" setting`)
}
if cfg.TLSCertFile == "" {
return trace.BadParameter(`TLSCertFile: please supply a path to TLS certificate file`)
return trace.BadParameter(`etcd: missing "tls_cert_file" setting`)
}
return nil
}

View file

@ -32,8 +32,6 @@ import (
"golang.org/x/crypto/ssh"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/boltbk"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/limiter"
@ -152,18 +150,13 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error {
if fc.Global.DataDir != "" {
cfg.DataDir = fc.Global.DataDir
}
// use bolt by default:
if fc.Storage.Type == "" {
fc.Storage.Type = boltbk.GetName()
}
if fc.Storage.Params == nil {
fc.Storage.Params = make(backend.Params)
cfg.Auth.StorageConfig.Params["path"] = cfg.DataDir
}
// forward storage config to 'auth backend' config (same thing)
cfg.Auth.KeysBackend.BackendConf = &fc.Storage
cfg.Auth.KeysBackend.Type = fc.Storage.Type
// apply storage configuration, if present:
if fc.Storage.Type != "" {
cfg.Auth.StorageConfig = fc.Storage
}
// apply logger settings
switch fc.Logger.Output {

View file

@ -207,7 +207,6 @@ func MakeSampleFileConfig() (fc *FileConfig) {
g.Limits.MaxConnections = defaults.LimiterMaxConnections
g.Limits.MaxUsers = defaults.LimiterMaxConcurrentUsers
g.DataDir = defaults.DataDir
g.Storage.Type = conf.Auth.KeysBackend.Type
g.PIDFile = "/var/run/teleport.pid"
// sample SSH config:

View file

@ -25,6 +25,7 @@ import (
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/boltbk"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/limiter"
"github.com/gravitational/teleport/lib/services"
@ -199,13 +200,9 @@ type AuthConfig struct {
// environments where paranoid security is not needed
StaticTokens []services.ProvisionToken
// KeysBackend configures backend that stores auth keys, certificates, tokens ...
KeysBackend struct {
// Type is a backend type - etcd or boltdb
Type string
// BackendConf contains additional config data
BackendConf *backend.Config
}
// StorageConfig contains configuration settings for
// the secrets storage backend
StorageConfig backend.Config
Limiter limiter.LimiterConfig
@ -242,13 +239,19 @@ func ApplyDefaults(cfg *Config) {
}
cfg.SeedConfig = false
// global defaults
cfg.Hostname = hostname
cfg.DataDir = defaults.DataDir
cfg.Console = os.Stdout
// defaults for the auth service:
cfg.Auth.Enabled = true
cfg.Auth.SSHAddr = *defaults.AuthListenAddr()
cfg.Auth.KeysBackend.Type = defaults.BackendType
cfg.Auth.U2F.Enabled = false
cfg.Auth.U2F.AppID = fmt.Sprintf("https://%s:%d", strings.ToLower(hostname), defaults.HTTPListenPort)
cfg.Auth.U2F.Facets = []string{cfg.Auth.U2F.AppID}
cfg.Auth.StorageConfig.Type = boltbk.GetName()
cfg.Auth.StorageConfig.Params = backend.Params{"path": cfg.DataDir}
defaults.ConfigureLimiter(&cfg.Auth.Limiter)
// defaults for the SSH proxy service:
@ -263,9 +266,4 @@ func ApplyDefaults(cfg *Config) {
cfg.SSH.Addr = *defaults.SSHServerListenAddr()
cfg.SSH.Shell = defaults.DefaultShell
defaults.ConfigureLimiter(&cfg.SSH.Limiter)
// global defaults
cfg.Hostname = hostname
cfg.DataDir = defaults.DataDir
cfg.Console = os.Stdout
}

View file

@ -60,7 +60,8 @@ func (s *ConfigSuite) TestDefaultConfig(c *C) {
c.Assert(auth.SSHAddr, DeepEquals, localAuthAddr)
c.Assert(auth.Limiter.MaxConnections, Equals, int64(defaults.LimiterMaxConnections))
c.Assert(auth.Limiter.MaxNumberOfUsers, Equals, defaults.LimiterMaxConcurrentUsers)
c.Assert(auth.KeysBackend.Type, Equals, "bolt")
c.Assert(auth.StorageConfig.Type, Equals, "bolt")
c.Assert(auth.StorageConfig.Params["path"], Equals, config.DataDir)
// SSH section
ssh := config.SSH

View file

@ -796,26 +796,23 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
// initAuthStorage initializes the storage backend for the auth. service
func (process *TeleportProcess) initAuthStorage() (bk backend.Backend, err error) {
bkConf := &process.Config.Auth.KeysBackend
bc := &process.Config.Auth.StorageConfig
// pass 'data_dir' setting to a backend:
bkConf.BackendConf.Params["data_dir"] = process.Config.DataDir
switch bkConf.Type {
switch bc.Type {
// legacy bolt backend:
case boltbk.GetName():
bk, err = boltbk.New(bkConf.BackendConf.Params)
bk, err = boltbk.New(bc.Params)
// filesystem backend:
case dir.GetName():
bk, err = dir.New(bkConf.BackendConf.Params)
bk, err = dir.New(bc.Params)
// DynamoDB bakcend:
case dynamo.GetName():
bk, err = dynamo.New(bkConf.BackendConf.Params)
bk, err = dynamo.New(bc.Params)
// etcd backend:
case etcdbk.GetName():
bk, err = etcdbk.New(bkConf.BackendConf.Params)
bk, err = etcdbk.New(bc.Params)
default:
err = trace.Errorf("unsupported backend type: %v", bkConf.Type)
err = trace.Errorf("unsupported secrets storage type: '%v'", bc.Type)
}
if err != nil {
return nil, trace.Wrap(err)

View file

@ -3,7 +3,7 @@
package teleport
const (
Version = "1.3.2-beta"
Version = "1.5.0-alpha"
)
// Gitref variable is automatically set to the output of git-describe