Added bootstrap CA
This adds a self-contained CA for bootstrapping and securing etcd
using certificates of infinite duration and a CRL for near-instant
revocation.
The bootstrapping problem is addressed by first
generating the CA and issuing initial certificates and then
injecting them once the consensus system is up and running.
All files are also kept on the encrypted persistent data store to
prevent the same bootstrapping problem when the node is already
initialized. The CRL is synchronized using a sync loop on every
node running the consensus service and distributed inside that.
The CA uses Ed25519-based cryptography and identifies the
hosts by their external hostname.
Test Plan:
Initial bootstrapping manually tested on a single node using a
manual gRPC call for Setup() and openssl s_client for connecting
to etcd.
X-Origin-Diff: phab/D233
GitOrigin-RevId: bd67818b5b649b13e0c098e480059ef990826542
diff --git a/core/internal/node/BUILD.bazel b/core/internal/node/BUILD.bazel
index 0596269..763df36 100644
--- a/core/internal/node/BUILD.bazel
+++ b/core/internal/node/BUILD.bazel
@@ -9,6 +9,7 @@
importpath = "git.monogon.dev/source/nexantic.git/core/internal/node",
visibility = ["//:__subpackages__"],
deps = [
+ "//core/api/api:go_default_library",
"//core/internal/api:go_default_library",
"//core/internal/common:go_default_library",
"//core/internal/consensus:go_default_library",
diff --git a/core/internal/node/setup.go b/core/internal/node/setup.go
index 28585dd..5d8953d 100644
--- a/core/internal/node/setup.go
+++ b/core/internal/node/setup.go
@@ -17,9 +17,11 @@
package node
import (
+ "git.monogon.dev/source/nexantic.git/core/generated/api"
"git.monogon.dev/source/nexantic.git/core/internal/common"
"errors"
+
"go.uber.org/zap"
)
@@ -67,11 +69,19 @@
config.DataDir = dataPath
s.Consensus.SetConfig(config)
+ if err := s.Consensus.PrecreateCA(); err != nil {
+ return err
+ }
+
err = s.Consensus.Start()
if err != nil {
return err
}
+ if err := s.Consensus.InjectCA(); err != nil {
+ return err
+ }
+
// Change system state
s.state = common.StateConfigured
@@ -91,7 +101,7 @@
return nil
}
-func (s *SmalltownNode) JoinCluster(name string, clusterString string, externalHost string) error {
+func (s *SmalltownNode) JoinCluster(name string, clusterString string, externalHost string, certs *api.ConsensusCertificates) error {
if s.state != common.StateClusterJoinMode {
return ErrNotInJoinMode
}
@@ -108,6 +118,9 @@
config.InitialCluster = clusterString
config.ExternalHost = externalHost
s.Consensus.SetConfig(config)
+ if err := s.Consensus.SetupCertificates(certs); err != nil {
+ return err
+ }
// Start consensus
err = s.Consensus.Start()