Skip to content

Commit

Permalink
*: enable tls support for store
Browse files Browse the repository at this point in the history
To enable tls the endpoints should be provided with an https scheme.

Add an option to define the ca file to verify the server certificate.
Add options to set the client cert and key pairs (for client
authentication with etcd)
Add an option to skip server tls cert verification.
  • Loading branch information
sgotti committed Nov 30, 2016
1 parent b173c68 commit 3961924
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 62 deletions.
19 changes: 17 additions & 2 deletions cmd/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type config struct {
id string
storeBackend string
storeEndpoints string
storeCertFile string
storeKeyFile string
storeCAFile string
storeSkipTlsVerify bool
dataDir string
clusterName string
debug bool
Expand Down Expand Up @@ -95,7 +99,11 @@ func init() {

cmdKeeper.PersistentFlags().StringVar(&cfg.id, "id", "", "keeper id (must be unique in the cluster and can contain only lower-case letters, numbers and the underscore character). If not provided a random id will be generated.")
cmdKeeper.PersistentFlags().StringVar(&cfg.storeBackend, "store-backend", "", "store backend type (etcd or consul)")
cmdKeeper.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: 127.0.0.1:2379 for etcd, 127.0.0.1:8500 for consul)")
cmdKeeper.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: http://127.0.0.1:2379 for etcd, http://127.0.0.1:8500 for consul)")
cmdKeeper.PersistentFlags().StringVar(&cfg.storeCertFile, "store-cert-file", "", "certificate file for client identification to the store")
cmdKeeper.PersistentFlags().StringVar(&cfg.storeKeyFile, "store-key", "", "private key file for client identification to the store")
cmdKeeper.PersistentFlags().StringVar(&cfg.storeCAFile, "store-ca-file", "", "verify certificates of HTTPS-enabled store servers using this CA bundle")
cmdKeeper.PersistentFlags().BoolVar(&cfg.storeSkipTlsVerify, "store-skip-tls-verify", false, "skip store certificate verification (insecure!!!)")
cmdKeeper.PersistentFlags().StringVar(&cfg.dataDir, "data-dir", "", "data directory")
cmdKeeper.PersistentFlags().StringVar(&cfg.clusterName, "cluster-name", "", "cluster name")
cmdKeeper.PersistentFlags().StringVar(&cfg.pgListenAddress, "pg-listen-address", "localhost", "postgresql instance listening address")
Expand Down Expand Up @@ -304,7 +312,14 @@ type PostgresKeeper struct {
func NewPostgresKeeper(cfg *config, stop chan bool, end chan error) (*PostgresKeeper, error) {
storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)

kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)
kvstore, err := store.NewStore(store.Config{
Backend: store.Backend(cfg.storeBackend),
Endpoints: cfg.storeEndpoints,
CertFile: cfg.storeCertFile,
KeyFile: cfg.storeKeyFile,
CAFile: cfg.storeCAFile,
SkipTLSVerify: cfg.storeSkipTlsVerify,
})
if err != nil {
return nil, fmt.Errorf("cannot create store: %v", err)
}
Expand Down
33 changes: 24 additions & 9 deletions cmd/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,28 @@ var cmdProxy = &cobra.Command{
}

type config struct {
storeBackend string
storeEndpoints string
clusterName string
listenAddress string
port string
stopListening bool
debug bool
storeBackend string
storeEndpoints string
storeCertFile string
storeKeyFile string
storeCAFile string
storeSkipTlsVerify bool
clusterName string
listenAddress string
port string
stopListening bool
debug bool
}

var cfg config

func init() {
cmdProxy.PersistentFlags().StringVar(&cfg.storeBackend, "store-backend", "", "store backend type (etcd or consul)")
cmdProxy.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: 127.0.0.1:2379 for etcd, 127.0.0.1:8500 for consul)")
cmdProxy.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: http://127.0.0.1:2379 for etcd, http://127.0.0.1:8500 for consul)")
cmdProxy.PersistentFlags().StringVar(&cfg.storeCertFile, "store-cert-file", "", "certificate file for client identification to the store")
cmdProxy.PersistentFlags().StringVar(&cfg.storeKeyFile, "store-key", "", "private key file for client identification to the store")
cmdProxy.PersistentFlags().StringVar(&cfg.storeCAFile, "store-ca-file", "", "verify certificates of HTTPS-enabled store servers using this CA bundle")
cmdProxy.PersistentFlags().BoolVar(&cfg.storeSkipTlsVerify, "store-skip-tls-verify", false, "skip store certificate verification (insecure!!!)")
cmdProxy.PersistentFlags().StringVar(&cfg.clusterName, "cluster-name", "", "cluster name")
cmdProxy.PersistentFlags().StringVar(&cfg.listenAddress, "listen-address", "127.0.0.1", "proxy listening address")
cmdProxy.PersistentFlags().StringVar(&cfg.port, "port", "5432", "proxy listening port")
Expand All @@ -78,7 +86,14 @@ type ClusterChecker struct {
func NewClusterChecker(id string, cfg config) (*ClusterChecker, error) {
storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)

kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)
kvstore, err := store.NewStore(store.Config{
Backend: store.Backend(cfg.storeBackend),
Endpoints: cfg.storeEndpoints,
CertFile: cfg.storeCertFile,
KeyFile: cfg.storeKeyFile,
CAFile: cfg.storeCAFile,
SkipTLSVerify: cfg.storeSkipTlsVerify,
})
if err != nil {
return nil, fmt.Errorf("cannot create store: %v", err)
}
Expand Down
20 changes: 18 additions & 2 deletions cmd/sentinel/sentinel.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ var cmdSentinel = &cobra.Command{
type config struct {
storeBackend string
storeEndpoints string
storeCertFile string
storeKeyFile string
storeCAFile string
storeSkipTlsVerify bool
clusterName string
initialClusterSpecFile string
debug bool
Expand All @@ -58,7 +62,11 @@ var cfg config

func init() {
cmdSentinel.PersistentFlags().StringVar(&cfg.storeBackend, "store-backend", "", "store backend type (etcd or consul)")
cmdSentinel.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: 127.0.0.1:2379 for etcd, 127.0.0.1:8500 for consul)")
cmdSentinel.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: http://127.0.0.1:2379 for etcd, http://127.0.0.1:8500 for consul)")
cmdSentinel.PersistentFlags().StringVar(&cfg.storeCertFile, "store-cert-file", "", "certificate file for client identification to the store")
cmdSentinel.PersistentFlags().StringVar(&cfg.storeKeyFile, "store-key", "", "private key file for client identification to the store")
cmdSentinel.PersistentFlags().BoolVar(&cfg.storeSkipTlsVerify, "store-skip-tls-verify", false, "skip store certificate verification (insecure!!!)")
cmdSentinel.PersistentFlags().StringVar(&cfg.storeCAFile, "store-ca-file", "", "verify certificates of HTTPS-enabled store servers using this CA bundle")
cmdSentinel.PersistentFlags().StringVar(&cfg.clusterName, "cluster-name", "", "cluster name")
cmdSentinel.PersistentFlags().StringVar(&cfg.initialClusterSpecFile, "initial-cluster-spec", "", "a file providing the initial cluster specification, used only at cluster initialization, ignored if cluster is already initialized")
cmdSentinel.PersistentFlags().BoolVar(&cfg.debug, "debug", false, "enable debug logging")
Expand Down Expand Up @@ -760,7 +768,15 @@ func NewSentinel(id string, cfg *config, stop chan bool, end chan bool) (*Sentin
}

storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)
kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)

kvstore, err := store.NewStore(store.Config{
Backend: store.Backend(cfg.storeBackend),
Endpoints: cfg.storeEndpoints,
CertFile: cfg.storeCertFile,
KeyFile: cfg.storeKeyFile,
CAFile: cfg.storeCAFile,
SkipTLSVerify: cfg.storeSkipTlsVerify,
})
if err != nil {
return nil, fmt.Errorf("cannot create store: %v", err)
}
Expand Down
6 changes: 1 addition & 5 deletions cmd/stolonctl/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"

"github.com/sorintlab/stolon/common"
"github.com/sorintlab/stolon/pkg/cluster"
"github.com/sorintlab/stolon/pkg/store"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -72,12 +70,10 @@ func initCluster(cmd *cobra.Command, args []string) {
}
}

storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)
kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)
e, err := NewStore()
if err != nil {
die("cannot create store: %v", err)
}
e := store.NewStoreManager(kvstore, storePath)

cd, _, err := e.GetClusterData()
if err != nil {
Expand Down
9 changes: 1 addition & 8 deletions cmd/stolonctl/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ package main

import (
"encoding/json"
"path/filepath"

"github.com/sorintlab/stolon/common"
"github.com/sorintlab/stolon/pkg/store"

"github.com/spf13/cobra"
)
Expand All @@ -35,13 +31,10 @@ func init() {
}

func spec(cmd *cobra.Command, args []string) {
storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)

kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)
e, err := NewStore()
if err != nil {
die("cannot create store: %v", err)
}
e := store.NewStoreManager(kvstore, storePath)

cd, _, err := getClusterData(e)
if err != nil {
Expand Down
6 changes: 1 addition & 5 deletions cmd/stolonctl/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ package main
import (
"fmt"
"os"
"path/filepath"
"sort"
"text/tabwriter"

"github.com/sorintlab/stolon/common"
"github.com/sorintlab/stolon/pkg/cluster"
"github.com/sorintlab/stolon/pkg/store"

"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -84,13 +82,11 @@ func status(cmd *cobra.Command, args []string) {
if cfg.clusterName == "" {
die("cluster name required")
}
storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)

kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)
e, err := NewStore()
if err != nil {
die("cannot create store: %v", err)
}
e := store.NewStoreManager(kvstore, storePath)

sentinelsInfo, err := e.GetSentinelsInfo()
if err != nil {
Expand Down
35 changes: 31 additions & 4 deletions cmd/stolonctl/stolonctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/sorintlab/stolon/common"
"github.com/sorintlab/stolon/pkg/cluster"
"github.com/sorintlab/stolon/pkg/flagutil"
"github.com/sorintlab/stolon/pkg/store"
Expand All @@ -46,16 +48,24 @@ var cmdStolonCtl = &cobra.Command{
}

type config struct {
storeBackend string
storeEndpoints string
clusterName string
storeBackend string
storeEndpoints string
storeCertFile string
storeKeyFile string
storeCAFile string
storeSkipTlsVerify bool
clusterName string
}

var cfg config

func init() {
cmdStolonCtl.PersistentFlags().StringVar(&cfg.storeBackend, "store-backend", "", "store backend type (etcd or consul)")
cmdStolonCtl.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: 127.0.0.1:2379 for etcd, 127.0.0.1:8500 for consul)")
cmdStolonCtl.PersistentFlags().StringVar(&cfg.storeEndpoints, "store-endpoints", "", "a comma-delimited list of store endpoints (defaults: http://127.0.0.1:2379 for etcd, http://127.0.0.1:8500 for consul)")
cmdStolonCtl.PersistentFlags().StringVar(&cfg.storeCertFile, "store-cert-file", "", "certificate file for client identification to the store")
cmdStolonCtl.PersistentFlags().StringVar(&cfg.storeKeyFile, "store-key", "", "private key file for client identification to the store")
cmdStolonCtl.PersistentFlags().StringVar(&cfg.storeCAFile, "store-ca-file", "", "verify certificates of HTTPS-enabled store servers using this CA bundle")
cmdStolonCtl.PersistentFlags().BoolVar(&cfg.storeSkipTlsVerify, "store-skip-tls-verify", false, "skip store certificate verification (insecure!!!)")
cmdStolonCtl.PersistentFlags().StringVar(&cfg.clusterName, "cluster-name", "", "cluster name")
}

Expand All @@ -80,6 +90,23 @@ func die(format string, a ...interface{}) {
os.Exit(1)
}

func NewStore() (*store.StoreManager, error) {
storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)

kvstore, err := store.NewStore(store.Config{
Backend: store.Backend(cfg.storeBackend),
Endpoints: cfg.storeEndpoints,
CertFile: cfg.storeCertFile,
KeyFile: cfg.storeKeyFile,
CAFile: cfg.storeCAFile,
SkipTLSVerify: cfg.storeSkipTlsVerify,
})
if err != nil {
return nil, fmt.Errorf("cannot create store: %v", err)
}
return store.NewStoreManager(kvstore, storePath), nil
}

func getClusterData(e *store.StoreManager) (*cluster.ClusterData, *kvstore.KVPair, error) {
cd, pair, err := e.GetClusterData()
if err != nil {
Expand Down
7 changes: 1 addition & 6 deletions cmd/stolonctl/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"

"github.com/sorintlab/stolon/common"
"github.com/sorintlab/stolon/pkg/cluster"
"github.com/sorintlab/stolon/pkg/store"

libkvstore "github.com/docker/libkv/store"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -96,12 +93,10 @@ func update(cmd *cobra.Command, args []string) {
}
}

storePath := filepath.Join(common.StoreBasePath, cfg.clusterName)
kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints)
e, err := NewStore()
if err != nil {
die("cannot create store: %v", err)
}
e := store.NewStoreManager(kvstore, storePath)

retry := 0
for retry < maxRetries {
Expand Down
64 changes: 64 additions & 0 deletions common/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2016 Sorint.lab
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
// See the License for the specific language governing permissions and
// limitations under the License.

package common

import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"io/ioutil"
)

func NewTLSConfig(certFile, keyFile, caFile string, insecureSkipVerify bool) (*tls.Config, error) {
tlsConfig := tls.Config{}

// Populate root CA certs
if caFile != "" {
pemBytes, err := ioutil.ReadFile(caFile)
if err != nil {
return nil, err
}
roots := x509.NewCertPool()

for {
var block *pem.Block
block, pemBytes = pem.Decode(pemBytes)
if block == nil {
break
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
roots.AddCert(cert)
}

tlsConfig.RootCAs = roots
}

// Populate keypair
// both must be defined
if certFile != "" && keyFile != "" {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
tlsConfig.Certificates = []tls.Certificate{cert}
}

tlsConfig.InsecureSkipVerify = insecureSkipVerify

return &tlsConfig, nil
}
2 changes: 1 addition & 1 deletion examples/kubernetes/stolon-keeper.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spec:
- name: STKEEPER_STORE_BACKEND
value: "etcd" # Or consul
- name: STKEEPER_STORE_ENDPOINTS
value: "10.245.1.1:2379"
value: "http://10.245.1.1:2379"
# Enable debugging
- name: STKEEPER_PG_REPL_USERNAME
value: "repluser"
Expand Down
2 changes: 1 addition & 1 deletion examples/kubernetes/stolon-proxy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spec:
- name: STPROXY_STORE_BACKEND
value: "etcd" # Or consul
- name: STPROXY_STORE_ENDPOINTS
value: "10.245.1.1:2379"
value: "http://10.245.1.1:2379"
# Enable debugging
- name: STPROXY_DEBUG
value: "true"
Expand Down
2 changes: 1 addition & 1 deletion examples/kubernetes/stolon-sentinel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ spec:
- name: STSENTINEL_STORE_BACKEND
value: "etcd" # Or consul
- name: STSENTINEL_STORE_ENDPOINTS
value: "10.245.1.1:2379"
value: "http://10.245.1.1:2379"
# Enable debugging
- name: STSENTINEL_DEBUG
value: "true"
Loading

0 comments on commit 3961924

Please sign in to comment.