agent/consul/state: CARoot structs and initial state store

This commit is contained in:
Mitchell Hashimoto 2018-03-16 21:20:54 -07:00
parent 4d852e62a3
commit 130098b7b5
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
3 changed files with 147 additions and 0 deletions

View File

@ -0,0 +1,106 @@
package state
import (
"fmt"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/go-memdb"
)
const (
caRootTableName = "connect-ca-roots"
)
// caRootTableSchema returns a new table schema used for storing
// CA roots for Connect.
func caRootTableSchema() *memdb.TableSchema {
return &memdb.TableSchema{
Name: caRootTableName,
Indexes: map[string]*memdb.IndexSchema{
"id": &memdb.IndexSchema{
Name: "id",
AllowMissing: false,
Unique: true,
Indexer: &memdb.UUIDFieldIndex{
Field: "ID",
},
},
},
}
}
func init() {
registerSchema(caRootTableSchema)
}
// CARoots returns the list of all CA roots.
func (s *Store) CARoots(ws memdb.WatchSet) (uint64, structs.CARoots, error) {
tx := s.db.Txn(false)
defer tx.Abort()
// Get the index
idx := maxIndexTxn(tx, caRootTableName)
// Get all
iter, err := tx.Get(caRootTableName, "id")
if err != nil {
return 0, nil, fmt.Errorf("failed CA root lookup: %s", err)
}
ws.Add(iter.WatchCh())
var results structs.CARoots
for v := iter.Next(); v != nil; v = iter.Next() {
results = append(results, v.(*structs.CARoot))
}
return idx, results, nil
}
// CARootSet creates or updates a CA root.
//
// NOTE(mitchellh): I have a feeling we'll want a CARootMultiSetCAS to
// perform a check-and-set on the entire set of CARoots versus an individual
// set, since we'll want to modify them atomically during events such as
// rotation.
func (s *Store) CARootSet(idx uint64, v *structs.CARoot) error {
tx := s.db.Txn(true)
defer tx.Abort()
if err := s.caRootSetTxn(tx, idx, v); err != nil {
return err
}
tx.Commit()
return nil
}
// caRootSetTxn is the inner method used to insert or update a CA root with
// the proper indexes into the state store.
func (s *Store) caRootSetTxn(tx *memdb.Txn, idx uint64, v *structs.CARoot) error {
// ID is required
if v.ID == "" {
return ErrMissingCARootID
}
// Check for an existing value
existing, err := tx.First(caRootTableName, "id", v.ID)
if err != nil {
return fmt.Errorf("failed CA root lookup: %s", err)
}
if existing != nil {
old := existing.(*structs.CARoot)
v.CreateIndex = old.CreateIndex
} else {
v.CreateIndex = idx
}
v.ModifyIndex = idx
// Insert
if err := tx.Insert(caRootTableName, v); err != nil {
return err
}
if err := tx.Insert("index", &IndexEntry{caRootTableName, idx}); err != nil {
return fmt.Errorf("failed updating index: %s", err)
}
return nil
}

View File

@ -29,6 +29,10 @@ var (
// a Query with an empty ID.
ErrMissingQueryID = errors.New("Missing Query ID")
// ErrMissingCARootID is returned when an CARoot set is called
// with an CARoot with an empty ID.
ErrMissingCARootID = errors.New("Missing CA Root ID")
// ErrMissingIntentionID is returned when an Intention set is called
// with an Intention with an empty ID.
ErrMissingIntentionID = errors.New("Missing Intention ID")

View File

@ -0,0 +1,37 @@
package structs
// IndexedCARoots is the list of currently trusted CA Roots.
type IndexedCARoots struct {
// ActiveRootID is the ID of a root in Roots that is the active CA root.
// Other roots are still valid if they're in the Roots list but are in
// the process of being rotated out.
ActiveRootID string
// Roots is a list of root CA certs to trust.
Roots []*CARoot
QueryMeta
}
// CARoot represents a root CA certificate that is trusted.
type CARoot struct {
// ID is a globally unique ID (UUID) representing this CA root.
ID string
// Name is a human-friendly name for this CA root. This value is
// opaque to Consul and is not used for anything internally.
Name string
// RootCert is the PEM-encoded public certificate.
RootCert string
// SigningCert is the PEM-encoded signing certificate and SigningKey
// is the PEM-encoded private key for the signing certificate.
SigningCert string
SigningKey string
RaftIndex
}
// CARoots is a list of CARoot structures.
type CARoots []*CARoot