feat(pki): Add PKI schemas and protos
This commit is contained in:
1 parent
1f550722a2
commit
88a6ca036f
13 files changed
+1813
-8
No files matched your search
@@ -149,6 +149,8 @@ protobuild:
|
||||
@protoc-go-inject-tag -input=./internal/kms/store/oidc_key.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/servers/store/controller.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/servers/store/worker.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/servers/store/root_certificate.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/servers/store/worker_auth.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/target/store/target.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/target/targettest/store/target.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/target/tcp/store/target.pb.go
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
begin;
|
||||
|
||||
create table worker_auth_operational_indicator_enm(
|
||||
state text primary key
|
||||
constraint only_predefined_worker_auth_states_allowed
|
||||
check (
|
||||
state in ('next','current')
|
||||
)
|
||||
);
|
||||
|
||||
comment on table worker_auth_operational_indicator_enm is
|
||||
'worker_auth_operational_indicator_enm is an enumeration table representing the state of certificates used for worker authentication.';
|
||||
|
||||
insert into worker_auth_operational_indicator_enm (state)
|
||||
values
|
||||
('next'),
|
||||
('current');
|
||||
|
||||
create table worker_auth_ca_certificate(
|
||||
serial_number numeric,
|
||||
certificate bytea not null
|
||||
constraint certificate_must_not_be_empty
|
||||
check(length(certificate) > 0),
|
||||
not_valid_before wt_timestamp not null,
|
||||
not_valid_after wt_timestamp not null
|
||||
constraint not_valid_before_must_be_before_not_valid_after
|
||||
check(not_valid_before < not_valid_after),
|
||||
public_key bytea primary key
|
||||
constraint public_key_must_not_be_empty
|
||||
check(length(public_key) > 0),
|
||||
private_key bytea not null -- encrypted PEM encoded private key
|
||||
constraint private_key_must_not_be_empty
|
||||
check(length(private_key) > 0),
|
||||
key_id kms_private_id not null -- key used to encrypt entries via wrapping wrapper.
|
||||
constraint kms_data_key_version_fkey
|
||||
references kms_data_key_version (private_id)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
state text unique not null
|
||||
constraint worker_auth_operational_indicator_enm_fkey
|
||||
references worker_auth_operational_indicator_enm(state)
|
||||
on delete restrict
|
||||
on update cascade
|
||||
);
|
||||
|
||||
comment on table worker_auth_ca_certificate is
|
||||
'worker_auth_ca_certificate is a table where each row represents a root certificate for used for worker authentication.';
|
||||
|
||||
create table worker_auth_authorized(
|
||||
worker_key_identifier text primary key, -- The public key id for this WorkerAuth entry, generated from the signing pub key
|
||||
worker_id wt_public_id not null
|
||||
constraint server_worker_fkey
|
||||
references server_worker (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
worker_signing_pub_key bytea not null
|
||||
constraint worker_signing_pub_key_must_not_be_empty
|
||||
check(length(worker_signing_pub_key) > 0),
|
||||
worker_encryption_pub_key bytea not null
|
||||
constraint worker_encryption_pub_key_must_not_be_empty
|
||||
check(length(worker_encryption_pub_key) > 0),
|
||||
controller_encryption_priv_key bytea not null -- encrypted PEM encoded private key
|
||||
constraint controller_encryption_priv_key_must_not_be_empty
|
||||
check(length(controller_encryption_priv_key) > 0),
|
||||
key_id kms_private_id not null -- key used to encrypt entries via wrapping wrapper.
|
||||
constraint kms_data_key_version_fkey
|
||||
references kms_data_key_version (private_id)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
nonce bytea
|
||||
);
|
||||
|
||||
comment on table worker_auth_authorized is
|
||||
'worker_auth_authorized is a table where each row represents key and cert data associated with an authorized worker.';
|
||||
|
||||
create table worker_auth_certificate_bundle(
|
||||
certificate_public_key bytea not null
|
||||
constraint worker_auth_ca_certificate_fkey
|
||||
references worker_auth_ca_certificate(public_key)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
worker_key_identifier text not null
|
||||
constraint worker_auth_authorized_fkey
|
||||
references worker_auth_authorized(worker_key_identifier)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
cert_bundle bytea
|
||||
constraint current_cert_bundle_must_not_be_empty
|
||||
check(length(cert_bundle) > 0),
|
||||
primary key(certificate_public_key, worker_key_identifier)
|
||||
);
|
||||
|
||||
comment on table worker_auth_certificate_bundle is
|
||||
'worker_auth_certificate_bundle is a table where each row represents a cert bundle issued by a ca certificate for a worker.';
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,42 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// Package store provides protobufs for storing types in the pki package.
|
||||
package controller.storage.servers.store.v1;
|
||||
|
||||
import "controller/storage/timestamp/v1/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/hashicorp/boundary/internal/servers/store;store";
|
||||
|
||||
// RootCertificate contains all fields related to a RootCertificate resource
|
||||
message RootCertificate {
|
||||
// The serial number of the root certificate
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
uint64 serial_number = 10;
|
||||
|
||||
// Certificate is the PEM encoded certificate.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes certificate = 20;
|
||||
|
||||
// Not valid before is the timestamp at which this certificate's validity period starts
|
||||
storage.timestamp.v1.Timestamp not_valid_before = 30;
|
||||
|
||||
// Not valid after is the timestamp at which this certificate's validity period ends
|
||||
storage.timestamp.v1.Timestamp not_valid_after = 40;
|
||||
|
||||
// The public key associated with this certificate
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes public_key = 50;
|
||||
|
||||
// The private key associated with this certificate
|
||||
// This is a ciphertext field
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes private_key = 60;
|
||||
|
||||
// The id of the kms database key used for encrypting this entry.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string key_id = 70;
|
||||
|
||||
// State is an enum value indicating if this is the next or current root cert
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string state = 80;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// Package store provides protobufs for storing types in the pki package.
|
||||
package controller.storage.servers.store.v1;
|
||||
|
||||
option go_package = "github.com/hashicorp/boundary/internal/servers/store;store";
|
||||
|
||||
// WorkerAuth contains all fields related to an authorized Worker resource
|
||||
message WorkerAuth {
|
||||
// The key id for this worker auth record, generated from the signing pub key
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string worker_key_identifier = 10;
|
||||
|
||||
// The worker id this worker authentication record is for
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string worker_id = 20;
|
||||
|
||||
// The worker's public signing key
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes worker_signing_pub_key = 30;
|
||||
|
||||
// The worker's public encryption key
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes worker_encryption_pub_key = 40;
|
||||
|
||||
// The private key associated with this certificate
|
||||
// This is a ciphertext field
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes controller_encryption_priv_key = 50;
|
||||
|
||||
// The id of the kms database key used for encrypting this entry.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string key_id = 60;
|
||||
|
||||
// Nonce used by a worker in authenticating
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
bytes nonce = 70;
|
||||
}
|
||||
|
||||
// WorkerCertBundle contains all fields related to a WorkerCertBundle resource
|
||||
message WorkerCertBundle {
|
||||
// The public key of the issuing root certificate
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes certificate_public_key = 10;
|
||||
|
||||
// The WorkerAuth worker_key_identifier this cert bundle record is for
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string worker_key_identifier = 20;
|
||||
|
||||
// CertBundle is the marshaled protobuf certificate bundle for a WorkerAuth
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes cert_bundle = 30;
|
||||
}
|
||||
@@ -18,14 +18,19 @@ type Option func(*options)
|
||||
|
||||
// options = how options are represented
|
||||
type options struct {
|
||||
withName string
|
||||
withDescription string
|
||||
withAddress string
|
||||
withPublicId string
|
||||
withLimit int
|
||||
withLiveness time.Duration
|
||||
withUpdateTags bool
|
||||
withWorkerTags []*Tag
|
||||
withName string
|
||||
withDescription string
|
||||
withAddress string
|
||||
withPublicId string
|
||||
withLimit int
|
||||
withLiveness time.Duration
|
||||
withUpdateTags bool
|
||||
withWorkerTags []*Tag
|
||||
withWorkerKeyIdentifier string
|
||||
withWorkerKeys WorkerKeys
|
||||
withControllerEncryptionPrivateKey []byte
|
||||
withKeyId string
|
||||
withNonce []byte
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
@@ -93,3 +98,33 @@ func WithWorkerTags(tags ...*Tag) Option {
|
||||
o.withWorkerTags = tags
|
||||
}
|
||||
}
|
||||
|
||||
func WithWorkerKeyIdentifier(workerKeyIdentifier string) Option {
|
||||
return func(o *options) {
|
||||
o.withWorkerKeyIdentifier = workerKeyIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
func WithWorkerKeys(workerKeys WorkerKeys) Option {
|
||||
return func(o *options) {
|
||||
o.withWorkerKeys = workerKeys
|
||||
}
|
||||
}
|
||||
|
||||
func WithControllerEncryptionPrivateKey(controllerKey []byte) Option {
|
||||
return func(o *options) {
|
||||
o.withControllerEncryptionPrivateKey = controllerKey
|
||||
}
|
||||
}
|
||||
|
||||
func WithKeyId(keyId string) Option {
|
||||
return func(o *options) {
|
||||
o.withKeyId = keyId
|
||||
}
|
||||
}
|
||||
|
||||
func WithNonce(nonce []byte) Option {
|
||||
return func(o *options) {
|
||||
o.withNonce = nonce
|
||||
}
|
||||
}
|
||||
@@ -65,4 +65,49 @@ func Test_GetOpts(t *testing.T) {
|
||||
testOpts.withWorkerTags = tags
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithWorkerKeys", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
testOpts := getDefaultOptions()
|
||||
|
||||
keys := WorkerKeys{
|
||||
workerEncryptionPubKey: populateBytes(20),
|
||||
workerSigningPubKey: populateBytes(20),
|
||||
}
|
||||
|
||||
opts := getOpts(WithWorkerKeys(keys))
|
||||
testOpts = getDefaultOptions()
|
||||
testOpts.withWorkerKeys = keys
|
||||
assert.Equal(opts, testOpts)
|
||||
})
|
||||
t.Run("WithControllerEncryptionPrivateKey", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
testOpts := getDefaultOptions()
|
||||
|
||||
key := populateBytes(20)
|
||||
|
||||
opts := getOpts(WithControllerEncryptionPrivateKey(key))
|
||||
testOpts = getDefaultOptions()
|
||||
testOpts.withControllerEncryptionPrivateKey = key
|
||||
assert.Equal(opts, testOpts)
|
||||
})
|
||||
t.Run("WithKeyId", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
testOpts := getDefaultOptions()
|
||||
|
||||
opts := getOpts(WithKeyId("hi i'm another key id"))
|
||||
testOpts = getDefaultOptions()
|
||||
testOpts.withKeyId = "hi i'm another key id"
|
||||
assert.Equal(opts, testOpts)
|
||||
})
|
||||
t.Run("WithNonce", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
testOpts := getDefaultOptions()
|
||||
|
||||
nonce := populateBytes(20)
|
||||
|
||||
opts := getOpts(WithNonce(nonce))
|
||||
testOpts = getDefaultOptions()
|
||||
testOpts.withNonce = nonce
|
||||
assert.Equal(opts, testOpts)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
|
||||
timestamp "github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/servers/store"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// RootCertificate contains fields related to a RootCertificate resource
|
||||
// This includes public/ private keys, the PEM encoded certificate, and the certificate validity period
|
||||
type RootCertificate struct {
|
||||
*store.RootCertificate
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
type RootCertificateKeys struct {
|
||||
publicKey []byte
|
||||
privateKey []byte
|
||||
}
|
||||
|
||||
func newRootCertificate(ctx context.Context, serialNumber uint64, certificate []byte, notValidBefore, notValidAfter *timestamp.Timestamp,
|
||||
rootCertificateKeys RootCertificateKeys, keyId string, state CertificateState,
|
||||
) (*RootCertificate, error) {
|
||||
const op = "servers.newRootCertificate"
|
||||
|
||||
if &serialNumber == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no serialNumber")
|
||||
}
|
||||
if certificate == nil || len(certificate) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "empty certificate")
|
||||
}
|
||||
if notValidAfter == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no notValidAfter")
|
||||
}
|
||||
if notValidBefore == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no notValidBefore")
|
||||
}
|
||||
if rootCertificateKeys.publicKey == nil || len(rootCertificateKeys.publicKey) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "empty publicKey")
|
||||
}
|
||||
if rootCertificateKeys.privateKey == nil || len(rootCertificateKeys.privateKey) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "empty privateKey")
|
||||
}
|
||||
if keyId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no keyId")
|
||||
}
|
||||
if !validState(state) {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is not a valid certificate state", state))
|
||||
}
|
||||
|
||||
l := &RootCertificate{
|
||||
RootCertificate: &store.RootCertificate{
|
||||
SerialNumber: serialNumber,
|
||||
Certificate: certificate,
|
||||
NotValidAfter: notValidAfter,
|
||||
NotValidBefore: notValidBefore,
|
||||
PublicKey: rootCertificateKeys.publicKey,
|
||||
PrivateKey: rootCertificateKeys.privateKey,
|
||||
KeyId: keyId,
|
||||
State: string(state),
|
||||
},
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func AllocRootCertificate() *RootCertificate {
|
||||
return &RootCertificate{
|
||||
RootCertificate: &store.RootCertificate{},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RootCertificate) clone() *RootCertificate {
|
||||
cp := proto.Clone(r.RootCertificate)
|
||||
return &RootCertificate{
|
||||
RootCertificate: cp.(*store.RootCertificate),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RootCertificate) ValidateNewRootCertificate(ctx context.Context) error {
|
||||
const op = "servers.(RootCertificate).ValidateNewRootCertificate"
|
||||
if &r.SerialNumber == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing SerialNumber")
|
||||
}
|
||||
if r.Certificate == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing Certificate")
|
||||
}
|
||||
if r.NotValidBefore.GetTimestamp().AsTime().IsZero() {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing not valid before timestamp")
|
||||
}
|
||||
if r.NotValidAfter.GetTimestamp().AsTime().IsZero() {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing not valid after timestamp")
|
||||
}
|
||||
if r.PublicKey == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing public key")
|
||||
}
|
||||
if r.PrivateKey == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing private key")
|
||||
}
|
||||
if r.KeyId == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing key id")
|
||||
}
|
||||
if r.State == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing state")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (r *RootCertificate) TableName() string {
|
||||
if r.tableName != "" {
|
||||
return r.tableName
|
||||
}
|
||||
return "worker_auth_ca_certificate"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (r *RootCertificate) SetTableName(n string) {
|
||||
r.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package servers
|
||||
|
||||
// CertificateState defines the possible states for a workerauth certificate
|
||||
type CertificateState string
|
||||
|
||||
const (
|
||||
UnknownState CertificateState = "unknown"
|
||||
CurrentState CertificateState = "current"
|
||||
NextState CertificateState = "next"
|
||||
)
|
||||
|
||||
func validState(s CertificateState) bool {
|
||||
st := CertificateState(s)
|
||||
switch st {
|
||||
case CurrentState, NextState:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc (unknown)
|
||||
// source: controller/storage/servers/store/v1/root_certificate.proto
|
||||
|
||||
// Package store provides protobufs for storing types in the pki package.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
timestamp "github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// RootCertificate contains all fields related to a RootCertificate resource
|
||||
type RootCertificate struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The serial number of the root certificate
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
SerialNumber uint64 `protobuf:"varint,10,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty" gorm:"not_null"`
|
||||
// Certificate is the PEM encoded certificate.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
Certificate []byte `protobuf:"bytes,20,opt,name=certificate,proto3" json:"certificate,omitempty" gorm:"not_null"`
|
||||
// Not valid before is the timestamp at which this certificate's validity period starts
|
||||
NotValidBefore *timestamp.Timestamp `protobuf:"bytes,30,opt,name=not_valid_before,json=notValidBefore,proto3" json:"not_valid_before,omitempty"`
|
||||
// Not valid after is the timestamp at which this certificate's validity period ends
|
||||
NotValidAfter *timestamp.Timestamp `protobuf:"bytes,40,opt,name=not_valid_after,json=notValidAfter,proto3" json:"not_valid_after,omitempty"`
|
||||
// The public key associated with this certificate
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
PublicKey []byte `protobuf:"bytes,50,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" gorm:"not_null"`
|
||||
// The private key associated with this certificate
|
||||
// This is a ciphertext field
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
PrivateKey []byte `protobuf:"bytes,60,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty" gorm:"not_null"`
|
||||
// The id of the kms database key used for encrypting this entry.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
KeyId string `protobuf:"bytes,70,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty" gorm:"not_null"`
|
||||
// State is an enum value indicating if this is the next or current root cert
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
State string `protobuf:"bytes,80,opt,name=state,proto3" json:"state,omitempty" gorm:"not_null"`
|
||||
}
|
||||
|
||||
func (x *RootCertificate) Reset() {
|
||||
*x = RootCertificate{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RootCertificate) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RootCertificate) ProtoMessage() {}
|
||||
|
||||
func (x *RootCertificate) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RootCertificate.ProtoReflect.Descriptor instead.
|
||||
func (*RootCertificate) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_servers_store_v1_root_certificate_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetSerialNumber() uint64 {
|
||||
if x != nil {
|
||||
return x.SerialNumber
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetCertificate() []byte {
|
||||
if x != nil {
|
||||
return x.Certificate
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetNotValidBefore() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.NotValidBefore
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetNotValidAfter() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.NotValidAfter
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetPrivateKey() []byte {
|
||||
if x != nil {
|
||||
return x.PrivateKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetKeyId() string {
|
||||
if x != nil {
|
||||
return x.KeyId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RootCertificate) GetState() string {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_controller_storage_servers_store_v1_root_certificate_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc = []byte{
|
||||
0x0a, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69,
|
||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76,
|
||||
0x31, 0x1a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x22, 0xef, 0x02, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69,
|
||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
|
||||
0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x63,
|
||||
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x54, 0x0a,
|
||||
0x10, 0x6e, 0x6f, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72,
|
||||
0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66,
|
||||
0x6f, 0x72, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
|
||||
0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x56, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
|
||||
0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69,
|
||||
0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x46, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_rawDescOnce sync.Once
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_rawDescData = file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_controller_storage_servers_store_v1_root_certificate_proto_rawDescGZIP() []byte {
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_rawDescOnce.Do(func() {
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_storage_servers_store_v1_root_certificate_proto_rawDescData)
|
||||
})
|
||||
return file_controller_storage_servers_store_v1_root_certificate_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_controller_storage_servers_store_v1_root_certificate_proto_goTypes = []interface{}{
|
||||
(*RootCertificate)(nil), // 0: controller.storage.servers.store.v1.RootCertificate
|
||||
(*timestamp.Timestamp)(nil), // 1: controller.storage.timestamp.v1.Timestamp
|
||||
}
|
||||
var file_controller_storage_servers_store_v1_root_certificate_proto_depIdxs = []int32{
|
||||
1, // 0: controller.storage.servers.store.v1.RootCertificate.not_valid_before:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
1, // 1: controller.storage.servers.store.v1.RootCertificate.not_valid_after:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_controller_storage_servers_store_v1_root_certificate_proto_init() }
|
||||
func file_controller_storage_servers_store_v1_root_certificate_proto_init() {
|
||||
if File_controller_storage_servers_store_v1_root_certificate_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RootCertificate); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_controller_storage_servers_store_v1_root_certificate_proto_goTypes,
|
||||
DependencyIndexes: file_controller_storage_servers_store_v1_root_certificate_proto_depIdxs,
|
||||
MessageInfos: file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes,
|
||||
}.Build()
|
||||
File_controller_storage_servers_store_v1_root_certificate_proto = out.File
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc = nil
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_goTypes = nil
|
||||
file_controller_storage_servers_store_v1_root_certificate_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc (unknown)
|
||||
// source: controller/storage/servers/store/v1/worker_auth.proto
|
||||
|
||||
// Package store provides protobufs for storing types in the pki package.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// WorkerAuth contains all fields related to an authorized Worker resource
|
||||
type WorkerAuth struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The key id for this worker auth record, generated from the signing pub key
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
WorkerKeyIdentifier string `protobuf:"bytes,10,opt,name=worker_key_identifier,json=workerKeyIdentifier,proto3" json:"worker_key_identifier,omitempty" gorm:"primary_key"`
|
||||
// The worker id this worker authentication record is for
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
WorkerId string `protobuf:"bytes,20,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty" gorm:"not_null"`
|
||||
// The worker's public signing key
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
WorkerSigningPubKey []byte `protobuf:"bytes,30,opt,name=worker_signing_pub_key,json=workerSigningPubKey,proto3" json:"worker_signing_pub_key,omitempty" gorm:"not_null"`
|
||||
// The worker's public encryption key
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
WorkerEncryptionPubKey []byte `protobuf:"bytes,40,opt,name=worker_encryption_pub_key,json=workerEncryptionPubKey,proto3" json:"worker_encryption_pub_key,omitempty" gorm:"not_null"`
|
||||
// The private key associated with this certificate
|
||||
// This is a ciphertext field
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
ControllerEncryptionPrivKey []byte `protobuf:"bytes,50,opt,name=controller_encryption_priv_key,json=controllerEncryptionPrivKey,proto3" json:"controller_encryption_priv_key,omitempty" gorm:"not_null"`
|
||||
// The id of the kms database key used for encrypting this entry.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
KeyId string `protobuf:"bytes,60,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty" gorm:"not_null"`
|
||||
// Nonce used by a worker in authenticating
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Nonce []byte `protobuf:"bytes,70,opt,name=nonce,proto3" json:"nonce,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) Reset() {
|
||||
*x = WorkerAuth{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WorkerAuth) ProtoMessage() {}
|
||||
|
||||
func (x *WorkerAuth) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use WorkerAuth.ProtoReflect.Descriptor instead.
|
||||
func (*WorkerAuth) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_servers_store_v1_worker_auth_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetWorkerKeyIdentifier() string {
|
||||
if x != nil {
|
||||
return x.WorkerKeyIdentifier
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetWorkerId() string {
|
||||
if x != nil {
|
||||
return x.WorkerId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetWorkerSigningPubKey() []byte {
|
||||
if x != nil {
|
||||
return x.WorkerSigningPubKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetWorkerEncryptionPubKey() []byte {
|
||||
if x != nil {
|
||||
return x.WorkerEncryptionPubKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetControllerEncryptionPrivKey() []byte {
|
||||
if x != nil {
|
||||
return x.ControllerEncryptionPrivKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetKeyId() string {
|
||||
if x != nil {
|
||||
return x.KeyId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WorkerAuth) GetNonce() []byte {
|
||||
if x != nil {
|
||||
return x.Nonce
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WorkerCertBundle contains all fields related to a WorkerCertBundle resource
|
||||
type WorkerCertBundle struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The public key of the issuing root certificate
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
CertificatePublicKey []byte `protobuf:"bytes,10,opt,name=certificate_public_key,json=certificatePublicKey,proto3" json:"certificate_public_key,omitempty" gorm:"not_null"`
|
||||
// The WorkerAuth worker_key_identifier this cert bundle record is for
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
WorkerKeyIdentifier string `protobuf:"bytes,20,opt,name=worker_key_identifier,json=workerKeyIdentifier,proto3" json:"worker_key_identifier,omitempty" gorm:"not_null"`
|
||||
// CertBundle is the marshaled protobuf certificate bundle for a WorkerAuth
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
CertBundle []byte `protobuf:"bytes,30,opt,name=cert_bundle,json=certBundle,proto3" json:"cert_bundle,omitempty" gorm:"not_null"`
|
||||
}
|
||||
|
||||
func (x *WorkerCertBundle) Reset() {
|
||||
*x = WorkerCertBundle{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *WorkerCertBundle) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WorkerCertBundle) ProtoMessage() {}
|
||||
|
||||
func (x *WorkerCertBundle) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use WorkerCertBundle.ProtoReflect.Descriptor instead.
|
||||
func (*WorkerCertBundle) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_servers_store_v1_worker_auth_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *WorkerCertBundle) GetCertificatePublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.CertificatePublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkerCertBundle) GetWorkerKeyIdentifier() string {
|
||||
if x != nil {
|
||||
return x.WorkerKeyIdentifier
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WorkerCertBundle) GetCertBundle() []byte {
|
||||
if x != nil {
|
||||
return x.CertBundle
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_controller_storage_servers_store_v1_worker_auth_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_storage_servers_store_v1_worker_auth_proto_rawDesc = []byte{
|
||||
0x0a, 0x35, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x61, 0x75, 0x74,
|
||||
0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x22, 0xbf, 0x02, 0x0a,
|
||||
0x0a, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x41, 0x75, 0x74, 0x68, 0x12, 0x32, 0x0a, 0x15, 0x77,
|
||||
0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x66, 0x69, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b,
|
||||
0x65, 0x72, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12,
|
||||
0x1b, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x70,
|
||||
0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x77, 0x6f,
|
||||
0x72, 0x6b, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65,
|
||||
0x79, 0x12, 0x39, 0x0a, 0x19, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x63, 0x72,
|
||||
0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x28,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x72,
|
||||
0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x1e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x32,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x1b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x69, 0x76, 0x4b, 0x65,
|
||||
0x79, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x3c, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63,
|
||||
0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x9d,
|
||||
0x01, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x42, 0x75, 0x6e,
|
||||
0x64, 0x6c, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x14, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72,
|
||||
0x6b, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72,
|
||||
0x4b, 0x65, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1f, 0x0a,
|
||||
0x0b, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x1e, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x52, 0x0a, 0x63, 0x65, 0x72, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x42, 0x3c,
|
||||
0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73,
|
||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73,
|
||||
0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_rawDescOnce sync.Once
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_rawDescData = file_controller_storage_servers_store_v1_worker_auth_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_controller_storage_servers_store_v1_worker_auth_proto_rawDescGZIP() []byte {
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_rawDescOnce.Do(func() {
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_storage_servers_store_v1_worker_auth_proto_rawDescData)
|
||||
})
|
||||
return file_controller_storage_servers_store_v1_worker_auth_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_controller_storage_servers_store_v1_worker_auth_proto_goTypes = []interface{}{
|
||||
(*WorkerAuth)(nil), // 0: controller.storage.servers.store.v1.WorkerAuth
|
||||
(*WorkerCertBundle)(nil), // 1: controller.storage.servers.store.v1.WorkerCertBundle
|
||||
}
|
||||
var file_controller_storage_servers_store_v1_worker_auth_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_controller_storage_servers_store_v1_worker_auth_proto_init() }
|
||||
func file_controller_storage_servers_store_v1_worker_auth_proto_init() {
|
||||
if File_controller_storage_servers_store_v1_worker_auth_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkerAuth); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkerCertBundle); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_storage_servers_store_v1_worker_auth_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_controller_storage_servers_store_v1_worker_auth_proto_goTypes,
|
||||
DependencyIndexes: file_controller_storage_servers_store_v1_worker_auth_proto_depIdxs,
|
||||
MessageInfos: file_controller_storage_servers_store_v1_worker_auth_proto_msgTypes,
|
||||
}.Build()
|
||||
File_controller_storage_servers_store_v1_worker_auth_proto = out.File
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_rawDesc = nil
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_goTypes = nil
|
||||
file_controller_storage_servers_store_v1_worker_auth_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/servers/store"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
const defaultLength = 20
|
||||
|
||||
// Generate random bytes for byte fields
|
||||
func populateBytes(length int) []byte {
|
||||
fieldBytes := make([]byte, length)
|
||||
rand.Read(fieldBytes)
|
||||
return fieldBytes
|
||||
}
|
||||
|
||||
func TestKkmsKey(ctx context.Context, t *testing.T, conn *db.DB, wrapper wrapping.Wrapper) string {
|
||||
t.Helper()
|
||||
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
testKey, err := databaseWrapper.KeyId(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
return testKey
|
||||
}
|
||||
|
||||
func TestRootCertificate(ctx context.Context, t *testing.T, conn *db.DB, kmsKey string) *store.RootCertificate {
|
||||
t.Helper()
|
||||
rw := db.New(conn)
|
||||
|
||||
beforeTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(-1 * time.Hour))}
|
||||
afterTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(1 * time.Hour))}
|
||||
|
||||
rootCertKeys := RootCertificateKeys{
|
||||
publicKey: populateBytes(defaultLength),
|
||||
privateKey: populateBytes(defaultLength),
|
||||
}
|
||||
|
||||
cert, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp,
|
||||
rootCertKeys, kmsKey, CurrentState)
|
||||
err = rw.Create(ctx, cert)
|
||||
require.NoError(t, err)
|
||||
return cert.RootCertificate
|
||||
}
|
||||
|
||||
func TestWorkerAuth(ctx context.Context, t *testing.T, conn *db.DB, worker *store.Worker, kmsKey string) *store.WorkerAuth {
|
||||
t.Helper()
|
||||
rw := db.New(conn)
|
||||
wSignPubKey := populateBytes(defaultLength)
|
||||
wEncPubKey := populateBytes(defaultLength)
|
||||
workerKeys := WorkerKeys{workerSigningPubKey: wSignPubKey, workerEncryptionPubKey: wEncPubKey}
|
||||
controllerKey := populateBytes(defaultLength)
|
||||
nonce := populateBytes(defaultLength)
|
||||
opt := []Option{
|
||||
WithKeyId(kmsKey),
|
||||
WithWorkerKeys(workerKeys),
|
||||
WithControllerEncryptionPrivateKey(controllerKey),
|
||||
WithNonce(nonce),
|
||||
}
|
||||
|
||||
workerAuth, err := newWorkerAuth(ctx, "worker-key-identifier", worker.PublicId, opt...)
|
||||
require.NoError(t, err)
|
||||
err = rw.Create(ctx, workerAuth)
|
||||
require.NoError(t, err)
|
||||
|
||||
return workerAuth.WorkerAuth
|
||||
}
|
||||
|
||||
func TestWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper) *store.Worker {
|
||||
t.Helper()
|
||||
rw := db.New(conn)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
serversRepo, err := NewRepository(rw, rw, kms)
|
||||
require.NoError(t, err)
|
||||
|
||||
id, err := uuid.GenerateUUID()
|
||||
require.NoError(t, err)
|
||||
id = "test-session-worker-" + id
|
||||
|
||||
name := "test-worker-" + id
|
||||
worker := &store.Worker{
|
||||
PublicId: id,
|
||||
Name: name,
|
||||
Address: "127.0.0.1",
|
||||
}
|
||||
_, _, err = serversRepo.UpsertWorker(context.Background(), worker)
|
||||
require.NoError(t, err)
|
||||
return worker
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/servers/store"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// WorkerAuth contains all fields related to an authorized Worker resource
|
||||
// This includes worker public keys, the controller encryption key,
|
||||
// and certificate bundles issued by the Boundary CA
|
||||
type WorkerAuth struct {
|
||||
*store.WorkerAuth
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// WorkerKeys contain the signing and encryption keys for a WorkerAuth resource
|
||||
type WorkerKeys struct {
|
||||
workerSigningPubKey []byte
|
||||
workerEncryptionPubKey []byte
|
||||
}
|
||||
|
||||
func newWorkerAuth(ctx context.Context, workerKeyIdentifier, workerId string, opt ...Option) (*WorkerAuth, error) {
|
||||
const op = "servers.newWorkerAuth"
|
||||
opts := getOpts(opt...)
|
||||
|
||||
if workerKeyIdentifier == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no workerKeyIdentifier")
|
||||
}
|
||||
if workerId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no workerId")
|
||||
}
|
||||
|
||||
l := &WorkerAuth{
|
||||
WorkerAuth: &store.WorkerAuth{
|
||||
WorkerKeyIdentifier: workerKeyIdentifier,
|
||||
WorkerId: workerId,
|
||||
},
|
||||
}
|
||||
|
||||
if &opts.withWorkerKeys != nil {
|
||||
l.WorkerSigningPubKey = opts.withWorkerKeys.workerSigningPubKey
|
||||
l.WorkerEncryptionPubKey = opts.withWorkerKeys.workerEncryptionPubKey
|
||||
}
|
||||
if &opts.withControllerEncryptionPrivateKey != nil {
|
||||
l.ControllerEncryptionPrivKey = opts.withControllerEncryptionPrivateKey
|
||||
}
|
||||
if opts.withKeyId != "" {
|
||||
l.KeyId = opts.withKeyId
|
||||
}
|
||||
if opts.withNonce != nil {
|
||||
l.Nonce = opts.withNonce
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func AllocWorkerAuth() *WorkerAuth {
|
||||
return &WorkerAuth{
|
||||
WorkerAuth: &store.WorkerAuth{},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WorkerAuth) clone() *WorkerAuth {
|
||||
cp := proto.Clone(w.WorkerAuth)
|
||||
return &WorkerAuth{
|
||||
WorkerAuth: cp.(*store.WorkerAuth),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate is called before storing a WorkerAuth in the db
|
||||
func (w *WorkerAuth) ValidateNewWorkerAuth(ctx context.Context) error {
|
||||
const op = "servers.(WorkerAuth).validateNewWorkerAuth"
|
||||
if w.WorkerKeyIdentifier == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing WorkerKeyIdentifier")
|
||||
}
|
||||
if w.WorkerId == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing WorkerId")
|
||||
}
|
||||
if w.WorkerSigningPubKey == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing WorkerSigningPubKey")
|
||||
}
|
||||
if w.WorkerEncryptionPubKey == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing WorkerEncryptionPubKey")
|
||||
}
|
||||
if w.ControllerEncryptionPrivKey == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing ControllerEncryptionPrivKey")
|
||||
}
|
||||
if w.KeyId == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing KeyId")
|
||||
}
|
||||
if w.Nonce == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing Nonce")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (w *WorkerAuth) TableName() string {
|
||||
if w.tableName != "" {
|
||||
return w.tableName
|
||||
}
|
||||
return "worker_auth_authorized"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (w *WorkerAuth) SetTableName(n string) {
|
||||
w.tableName = n
|
||||
}
|
||||
|
||||
// WorkerCertBundle contains all fields related to a WorkerCertBundle resource
|
||||
// This includes the serial number of the issuing CA, the worker id, and the certificate bundles issued by the CA
|
||||
type WorkerCertBundle struct {
|
||||
*store.WorkerCertBundle
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
func newWorkerCertBundle(ctx context.Context, certificatePublicKey []byte, workerKeyIdentifier string, certBundle []byte) (*WorkerCertBundle, error) {
|
||||
const op = "servers.newWorkerCertBundle"
|
||||
|
||||
if certificatePublicKey == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no certificatePublicKey")
|
||||
}
|
||||
if workerKeyIdentifier == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no workerKeyIdentifier")
|
||||
}
|
||||
if certBundle == nil || len(certBundle) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "empty certBundle")
|
||||
}
|
||||
|
||||
l := &WorkerCertBundle{
|
||||
WorkerCertBundle: &store.WorkerCertBundle{
|
||||
CertificatePublicKey: certificatePublicKey,
|
||||
WorkerKeyIdentifier: workerKeyIdentifier,
|
||||
CertBundle: certBundle,
|
||||
},
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func AllocWorkerCertBundle() *WorkerCertBundle {
|
||||
return &WorkerCertBundle{
|
||||
WorkerCertBundle: &store.WorkerCertBundle{},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WorkerCertBundle) clone() *WorkerCertBundle {
|
||||
cp := proto.Clone(w.WorkerCertBundle)
|
||||
return &WorkerCertBundle{
|
||||
WorkerCertBundle: cp.(*store.WorkerCertBundle),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate is called before storing a WorkerCertBundle in the db
|
||||
func (w *WorkerCertBundle) ValidateNewWorkerCertBundle(ctx context.Context) error {
|
||||
const op = "servers.(WorkerAuth).validateNewWorkerCertBundle"
|
||||
if w.CertificatePublicKey == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing CertificatePublicKey")
|
||||
}
|
||||
if w.WorkerKeyIdentifier == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing WorkerKeyIdentifier")
|
||||
}
|
||||
if w.CertBundle == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing certificate bundle")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (w *WorkerCertBundle) TableName() string {
|
||||
if w.tableName != "" {
|
||||
return w.tableName
|
||||
}
|
||||
return "worker_auth_certificate_bundle"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (w *WorkerCertBundle) SetTableName(n string) {
|
||||
w.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/servers/store"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func TestRootCertStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
testKey, err := databaseWrapper.KeyId(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
beforeTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(-1 * time.Hour))}
|
||||
afterTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(1 * time.Hour))}
|
||||
publicKey := populateBytes(defaultLength)
|
||||
privateKey := populateBytes(defaultLength)
|
||||
certificate := populateBytes(defaultLength)
|
||||
|
||||
type args struct {
|
||||
serialNumber uint64
|
||||
certificate []byte
|
||||
rootCertKeys RootCertificateKeys
|
||||
notValidBefore *timestamp.Timestamp
|
||||
notValidAfter *timestamp.Timestamp
|
||||
keyId string
|
||||
state CertificateState
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expectedRootCert *store.RootCertificate
|
||||
wantErr bool
|
||||
wantCreateErr bool
|
||||
}{
|
||||
{
|
||||
name: "rootcert-store-next",
|
||||
args: args{
|
||||
serialNumber: 1234567890,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: NextState,
|
||||
},
|
||||
expectedRootCert: &store.RootCertificate{
|
||||
SerialNumber: 1234567890,
|
||||
PublicKey: publicKey,
|
||||
PrivateKey: privateKey,
|
||||
Certificate: certificate,
|
||||
NotValidBefore: beforeTimestamp,
|
||||
NotValidAfter: afterTimestamp,
|
||||
KeyId: testKey,
|
||||
State: "next",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "rootcert-store-current",
|
||||
args: args{
|
||||
serialNumber: 9876543210,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: CurrentState,
|
||||
},
|
||||
expectedRootCert: &store.RootCertificate{
|
||||
SerialNumber: 9876543210,
|
||||
PublicKey: publicKey,
|
||||
PrivateKey: privateKey,
|
||||
Certificate: certificate,
|
||||
NotValidBefore: beforeTimestamp,
|
||||
NotValidAfter: afterTimestamp,
|
||||
KeyId: testKey,
|
||||
State: "current",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "rootcert-store-empty-key",
|
||||
args: args{
|
||||
serialNumber: 9876543210,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: populateBytes(0), privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: NextState,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "rootcert-no-keys",
|
||||
args: args{
|
||||
serialNumber: 1011121314,
|
||||
certificate: certificate,
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: NextState,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "rootcert-no-cert",
|
||||
args: args{
|
||||
serialNumber: 15161718,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: NextState,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "rootcert-invalid-timestamps",
|
||||
args: args{
|
||||
serialNumber: 1920212223,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: afterTimestamp,
|
||||
notValidAfter: beforeTimestamp,
|
||||
keyId: testKey,
|
||||
state: NextState,
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "rootcert-invalid-timestamps-2",
|
||||
args: args{
|
||||
serialNumber: 2425262728,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: afterTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: NextState,
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "rootcert-invalid-state",
|
||||
args: args{
|
||||
serialNumber: 3031323334,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
keyId: testKey,
|
||||
state: UnknownState,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "rootcert-no-key-id",
|
||||
args: args{
|
||||
serialNumber: 4041424344,
|
||||
rootCertKeys: RootCertificateKeys{publicKey: publicKey, privateKey: privateKey},
|
||||
certificate: certificate,
|
||||
notValidBefore: beforeTimestamp,
|
||||
notValidAfter: afterTimestamp,
|
||||
state: NextState,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
cert, err := newRootCertificate(ctx, tt.args.serialNumber, tt.args.certificate, tt.args.notValidBefore, tt.args.notValidAfter,
|
||||
tt.args.rootCertKeys, tt.args.keyId, tt.args.state)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.NotNil(cert)
|
||||
|
||||
err = rw.Create(ctx, cert)
|
||||
if tt.wantCreateErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tt.expectedRootCert, cert.RootCertificate)
|
||||
assert.Empty(cmp.Diff(tt.expectedRootCert, cert, protocmp.Transform()))
|
||||
}
|
||||
|
||||
deleteWhere := `state = ?`
|
||||
deleted, err := rw.Delete(ctx, &RootCertificate{}, db.WithWhere(deleteWhere, cert.State))
|
||||
assert.NoError(err)
|
||||
assert.Equal(1, deleted)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateRootCert(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
testKey, err := databaseWrapper.KeyId(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
beforeTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(-1 * time.Hour))}
|
||||
afterTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(1 * time.Hour))}
|
||||
|
||||
// Make two current and next root CAs
|
||||
current1, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp,
|
||||
RootCertificateKeys{publicKey: populateBytes(defaultLength), privateKey: populateBytes(defaultLength)},
|
||||
testKey, CurrentState)
|
||||
require.NoError(t, err)
|
||||
current2, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp,
|
||||
RootCertificateKeys{publicKey: populateBytes(defaultLength), privateKey: populateBytes(defaultLength)},
|
||||
testKey, CurrentState)
|
||||
next1, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp,
|
||||
RootCertificateKeys{publicKey: populateBytes(defaultLength), privateKey: populateBytes(defaultLength)},
|
||||
testKey, NextState)
|
||||
require.NoError(t, err)
|
||||
next2, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp,
|
||||
RootCertificateKeys{publicKey: populateBytes(defaultLength), privateKey: populateBytes(defaultLength)},
|
||||
testKey, NextState)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Insert first set of certs
|
||||
err = rw.Create(ctx, current1)
|
||||
require.NoError(t, err)
|
||||
err = rw.Create(ctx, next1)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Insert second current cert and expect an error
|
||||
err = rw.Create(ctx, current2)
|
||||
require.Error(t, err)
|
||||
err = rw.Create(ctx, next2)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestWorkerAuthStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
testKey, err := databaseWrapper.KeyId(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
worker := TestWorker(t, conn, wrapper)
|
||||
|
||||
wSignPubKey := populateBytes(defaultLength)
|
||||
wEncPubKey := populateBytes(defaultLength)
|
||||
workerKeys := WorkerKeys{workerSigningPubKey: wSignPubKey, workerEncryptionPubKey: wEncPubKey}
|
||||
controllerKey := populateBytes(defaultLength)
|
||||
nonce := populateBytes(defaultLength)
|
||||
|
||||
type args struct {
|
||||
workerKeyIdentifier string
|
||||
workerId string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expectedWorkerAuth *store.WorkerAuth
|
||||
opt []Option
|
||||
wantErr bool
|
||||
wantCreateErr bool
|
||||
}{
|
||||
{
|
||||
name: "workerauth-store",
|
||||
args: args{
|
||||
workerKeyIdentifier: "worker-auth-id-123",
|
||||
workerId: worker.PublicId,
|
||||
},
|
||||
opt: []Option{
|
||||
WithWorkerKeys(workerKeys),
|
||||
WithControllerEncryptionPrivateKey(controllerKey),
|
||||
WithNonce(nonce),
|
||||
WithKeyId(testKey),
|
||||
},
|
||||
expectedWorkerAuth: &store.WorkerAuth{
|
||||
WorkerKeyIdentifier: "worker-auth-id-123",
|
||||
WorkerId: worker.PublicId,
|
||||
WorkerSigningPubKey: wSignPubKey,
|
||||
WorkerEncryptionPubKey: wEncPubKey,
|
||||
ControllerEncryptionPrivKey: controllerKey,
|
||||
KeyId: testKey,
|
||||
Nonce: nonce,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "workerauth-store-invalid-key-id",
|
||||
args: args{
|
||||
workerKeyIdentifier: "worker-auth-id-456",
|
||||
workerId: worker.PublicId,
|
||||
},
|
||||
opt: []Option{
|
||||
WithWorkerKeys(workerKeys),
|
||||
WithControllerEncryptionPrivateKey(controllerKey),
|
||||
WithNonce(nonce),
|
||||
WithKeyId("fakeyityfake"),
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "workerauth-no-pkey",
|
||||
args: args{
|
||||
workerId: worker.PublicId,
|
||||
},
|
||||
opt: []Option{
|
||||
WithWorkerKeys(workerKeys),
|
||||
WithControllerEncryptionPrivateKey(controllerKey),
|
||||
WithNonce(nonce),
|
||||
WithKeyId(testKey),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "workerauth-empty-pkey",
|
||||
args: args{
|
||||
workerKeyIdentifier: "",
|
||||
workerId: worker.PublicId,
|
||||
},
|
||||
opt: []Option{
|
||||
WithWorkerKeys(workerKeys),
|
||||
WithControllerEncryptionPrivateKey(controllerKey),
|
||||
WithNonce(nonce),
|
||||
WithKeyId(testKey),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "workerauth-invalid-workerid",
|
||||
args: args{
|
||||
workerKeyIdentifier: "worker-auth-id-101",
|
||||
workerId: "bogus-worker",
|
||||
},
|
||||
opt: []Option{
|
||||
WithWorkerKeys(workerKeys),
|
||||
WithControllerEncryptionPrivateKey(controllerKey),
|
||||
WithNonce(nonce),
|
||||
WithKeyId(testKey),
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty-workerauth",
|
||||
args: args{},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
wAuth, err := newWorkerAuth(ctx, tt.args.workerKeyIdentifier, tt.args.workerId, tt.opt...)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.NotNil(wAuth)
|
||||
|
||||
err = rw.Create(ctx, wAuth)
|
||||
if tt.wantCreateErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tt.expectedWorkerAuth, wAuth.WorkerAuth)
|
||||
assert.Empty(cmp.Diff(tt.expectedWorkerAuth, wAuth, protocmp.Transform()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkerCertBundle(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
testKey := TestKkmsKey(ctx, t, conn, wrapper)
|
||||
|
||||
worker := TestWorker(t, conn, wrapper)
|
||||
workerAuth := TestWorkerAuth(ctx, t, conn, worker, testKey)
|
||||
rootCA := TestRootCertificate(ctx, t, conn, testKey)
|
||||
certBundle := populateBytes(defaultLength)
|
||||
|
||||
type args struct {
|
||||
certificatePubKey []byte
|
||||
workerAuthId string
|
||||
certificateBundle []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expected *store.WorkerCertBundle
|
||||
wantErr bool
|
||||
wantCreateErr bool
|
||||
}{
|
||||
{
|
||||
name: "workercertbundle-store",
|
||||
args: args{
|
||||
certificatePubKey: rootCA.PublicKey,
|
||||
workerAuthId: workerAuth.WorkerKeyIdentifier,
|
||||
certificateBundle: certBundle,
|
||||
},
|
||||
expected: &store.WorkerCertBundle{
|
||||
CertificatePublicKey: rootCA.PublicKey,
|
||||
WorkerKeyIdentifier: workerAuth.WorkerKeyIdentifier,
|
||||
CertBundle: certBundle,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "workercertbundle-empty-cert-bundle",
|
||||
args: args{
|
||||
certificatePubKey: rootCA.PublicKey,
|
||||
workerAuthId: workerAuth.WorkerKeyIdentifier,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "workercertbundle-no-worker-id",
|
||||
args: args{
|
||||
certificatePubKey: rootCA.PublicKey,
|
||||
certificateBundle: certBundle,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "workercertbundle-invalid-worker-id",
|
||||
args: args{
|
||||
certificatePubKey: rootCA.PublicKey,
|
||||
workerAuthId: "bogus-worker",
|
||||
certificateBundle: certBundle,
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "workercertbundle-empty-publickey",
|
||||
args: args{
|
||||
workerAuthId: workerAuth.WorkerKeyIdentifier,
|
||||
certificateBundle: certBundle,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "workercertbundle-invalid-publickey",
|
||||
args: args{
|
||||
certificatePubKey: populateBytes(defaultLength),
|
||||
workerAuthId: workerAuth.WorkerKeyIdentifier,
|
||||
certificateBundle: certBundle,
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
workerCertBundle, err := newWorkerCertBundle(ctx, tt.args.certificatePubKey, tt.args.workerAuthId, tt.args.certificateBundle)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.NotNil(workerCertBundle)
|
||||
|
||||
err = rw.Create(ctx, workerCertBundle)
|
||||
if tt.wantCreateErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tt.expected, workerCertBundle.WorkerCertBundle)
|
||||
assert.Empty(cmp.Diff(tt.expected, workerCertBundle, protocmp.Transform()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user