feat: support rotation of Talos API CA

This allows to roll all nodes to use a new CA, to refresh it, or e.g.
when the `talosconfig` was exposed accidentally.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
Andrey Smirnov 2024-03-15 18:50:42 +04:00
parent 92808e3bcf
commit 8eacc4ba80
No known key found for this signature in database
GPG Key ID: FE042E3D4085A811
59 changed files with 1967 additions and 577 deletions

Binary file not shown.

View File

@ -107,6 +107,10 @@ message PEMEncodedKey {
bytes key = 1;
}
message PEMEncodedCertificate {
bytes crt = 1;
}
message NetIP {
bytes ip = 1;
}

View File

@ -8,9 +8,9 @@ import "common/common.proto";
// APICertsSpec describes etcd certs secrets.
message APICertsSpec {
common.PEMEncodedCertificateAndKey ca = 1;
common.PEMEncodedCertificateAndKey client = 2;
common.PEMEncodedCertificateAndKey server = 3;
repeated common.PEMEncodedCertificate accepted_c_as = 4;
}
// CertSANSpec describes fields of the cert SANs.
@ -86,15 +86,16 @@ message MaintenanceServiceCertsSpec {
// OSRootSpec describes operating system CA.
message OSRootSpec {
common.PEMEncodedCertificateAndKey ca = 1;
common.PEMEncodedCertificateAndKey issuing_ca = 1;
repeated common.NetIP cert_sani_ps = 2;
repeated string cert_sandns_names = 3;
string token = 4;
repeated common.PEMEncodedCertificate accepted_c_as = 5;
}
// TrustdCertsSpec describes etcd certs secrets.
message TrustdCertsSpec {
common.PEMEncodedCertificateAndKey ca = 1;
common.PEMEncodedCertificateAndKey server = 2;
repeated common.PEMEncodedCertificate accepted_c_as = 3;
}

View File

@ -125,7 +125,7 @@ func healthOnClient(ctx context.Context, c *client.Client) error {
}
defer clientProvider.Close() //nolint:errcheck
clusterInfo, err := buildClusterInfo()
clusterInfo, err := buildClusterInfo(healthCmdFlags.clusterState)
if err != nil {
return err
}
@ -225,9 +225,7 @@ func init() {
healthCmd.Flags().BoolVar(&healthCmdFlags.runE2E, "run-e2e", false, "run Kubernetes e2e test")
}
func buildClusterInfo() (cluster.Info, error) {
clusterState := healthCmdFlags.clusterState
func buildClusterInfo(clusterState clusterNodes) (cluster.Info, error) {
// if nodes are set explicitly via command line args, use them
if len(clusterState.ControlPlaneNodes) > 0 || len(clusterState.WorkerNodes) > 0 {
return &clusterState, nil

View File

@ -0,0 +1,122 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package talos
import (
"context"
"fmt"
"time"
"github.com/spf13/cobra"
"github.com/siderolabs/talos/pkg/machinery/client"
clientconfig "github.com/siderolabs/talos/pkg/machinery/client/config"
"github.com/siderolabs/talos/pkg/machinery/config"
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/siderolabs/talos/pkg/machinery/config/generate/secrets"
"github.com/siderolabs/talos/pkg/rotate/pki/talos"
)
var rotateCACmdFlags struct {
clusterState clusterNodes
forceEndpoint string
output string
withExamples bool
withDocs bool
dryRun bool
}
// rotateCACmd represents the rotate-ca command.
var rotateCACmd = &cobra.Command{
Use: "rotate-ca",
Short: "Rotate cluster CAs (Talos and Kubernetes APIs).",
Long: `The command starts by generating new CAs, and gracefully applying it to the cluster.`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
err := rotateCACmdFlags.clusterState.InitNodeInfos()
if err != nil {
return err
}
return WithClient(rotateCA)
},
}
func rotateCA(ctx context.Context, oldClient *client.Client) error {
commentsFlags := encoder.CommentsDisabled
if upgradeK8sCmdFlags.withDocs {
commentsFlags |= encoder.CommentsDocs
}
if upgradeK8sCmdFlags.withExamples {
commentsFlags |= encoder.CommentsExamples
}
encoderOpt := encoder.WithComments(commentsFlags)
clusterInfo, err := buildClusterInfo(rotateCACmdFlags.clusterState)
if err != nil {
return err
}
oldTalosconfig, err := clientconfig.Open(GlobalArgs.Talosconfig)
if err != nil {
return fmt.Errorf("failed to open config file %q: %w", GlobalArgs.Talosconfig, err)
}
configContext := oldTalosconfig.Context
if GlobalArgs.CmdContext != "" {
configContext = GlobalArgs.CmdContext
}
newBundle, err := secrets.NewBundle(secrets.NewFixedClock(time.Now()), config.TalosVersionCurrent)
if err != nil {
return fmt.Errorf("error generating new Talos CA: %w", err)
}
options := talos.Options{
DryRun: rotateCACmdFlags.dryRun,
CurrentClient: oldClient,
ClusterInfo: clusterInfo,
ContextName: configContext,
Endpoints: oldClient.GetEndpoints(),
NewTalosCA: newBundle.Certs.OS,
EncoderOption: encoderOpt,
Printf: func(format string, args ...any) { fmt.Printf(format, args...) },
}
newTalosconfig, err := talos.Rotate(ctx, options)
if err != nil {
return err
}
if rotateCACmdFlags.dryRun {
fmt.Println("> Dry-run mode enabled, no changes were made to the cluster, re-run with `--dry-run=false` to apply the changes.")
return nil
}
fmt.Printf("> Writing new talosconfig to %q\n", rotateCACmdFlags.output)
return newTalosconfig.Save(rotateCACmdFlags.output)
}
func init() {
addCommand(rotateCACmd)
rotateCACmd.Flags().StringVar(&rotateCACmdFlags.clusterState.InitNode, "init-node", "", "specify IPs of init node")
rotateCACmd.Flags().StringSliceVar(&rotateCACmdFlags.clusterState.ControlPlaneNodes, "control-plane-nodes", nil, "specify IPs of control plane nodes")
rotateCACmd.Flags().StringSliceVar(&rotateCACmdFlags.clusterState.WorkerNodes, "worker-nodes", nil, "specify IPs of worker nodes")
rotateCACmd.Flags().StringVar(&rotateCACmdFlags.forceEndpoint, "k8s-endpoint", "", "use endpoint instead of kubeconfig default")
rotateCACmd.Flags().BoolVarP(&rotateCACmdFlags.withExamples, "with-examples", "", true, "patch all machine configs with the commented examples")
rotateCACmd.Flags().BoolVarP(&rotateCACmdFlags.withDocs, "with-docs", "", true, "patch all machine configs adding the documentation for each field")
rotateCACmd.Flags().StringVarP(&rotateCACmdFlags.output, "output", "o", "talosconfig", "path to the output new `talosconfig`")
rotateCACmd.Flags().BoolVarP(&rotateCACmdFlags.dryRun, "dry-run", "", true, "dry-run mode (no changes to the cluster)")
}

2
go.mod
View File

@ -111,7 +111,7 @@ require (
github.com/ryanuber/go-glob v1.0.0
github.com/safchain/ethtool v0.3.0
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25
github.com/siderolabs/crypto v0.4.2
github.com/siderolabs/crypto v0.4.4
github.com/siderolabs/discovery-api v0.1.4
github.com/siderolabs/discovery-client v0.1.8
github.com/siderolabs/gen v0.4.8

4
go.sum
View File

@ -652,8 +652,8 @@ github.com/sethgrid/pester v1.2.0 h1:adC9RS29rRUef3rIKWPOuP1Jm3/MmB6ke+OhE5giENI
github.com/sethgrid/pester v1.2.0/go.mod h1:hEUINb4RqvDxtoCaU0BNT/HV4ig5kfgOasrf1xcvr0A=
github.com/siderolabs/coredns v1.11.52 h1:L0jzzyRvmhiA3mf21yjXh8OjTEz95sVknOHfgq1I9Dk=
github.com/siderolabs/coredns v1.11.52/go.mod h1:dePXyKhQsTe3Ks228EAaiBWxV37jyquDDVHc8zwiWSY=
github.com/siderolabs/crypto v0.4.2 h1:ahAwmm1+0xd3QfGiZ0jYpWxtCVngsy+PK0cgR9frOA8=
github.com/siderolabs/crypto v0.4.2/go.mod h1:rnjC/Z6m/mI2vMv98glgU6oU8lXNi8YceiTxALohfzY=
github.com/siderolabs/crypto v0.4.4 h1:Q6EDBMR2Ub2oAZW5Xl8lrKB27bM3Sn8Gkfw3rngco5U=
github.com/siderolabs/crypto v0.4.4/go.mod h1:hsR3tJ3aaeuhCChsLF4dBd9vlJVPvmhg4vvx2ez4aD4=
github.com/siderolabs/discovery-api v0.1.4 h1:2fMEFSMiWaD1zDiBDY5md8VxItvL1rDQRSOfeXNjYKc=
github.com/siderolabs/discovery-api v0.1.4/go.mod h1:kaBy+G42v2xd/uAF/NIe383sjNTBE2AhxPTyi9SZI0s=
github.com/siderolabs/discovery-client v0.1.8 h1:8WhJiNyVmjZ0F+tSfeaDyQ04n02lRK2dh/CvWp+zlnY=

View File

@ -155,6 +155,12 @@ machine:
servers:
- /dev/ptp0
```
"""
[notes.ca-rotation]
title = "CA Rotation"
description = """\
Talos Linux now supports rotating the root CA certificate and key for Talos API and Kubernetes API.
"""
[make_deps]

View File

@ -390,6 +390,8 @@ func formatTypeName(fieldTypePkg string, fieldType string, declPkg string) (stri
return commoProto, "common.PEMEncodedCertificateAndKey"
case typeData{"github.com/siderolabs/crypto/x509", "PEMEncodedKey"}:
return commoProto, "common.PEMEncodedKey"
case typeData{"github.com/siderolabs/crypto/x509", "PEMEncodedCertificate"}:
return commoProto, "common.PEMEncodedCertificate"
default:
return "", ""
}

View File

@ -100,11 +100,15 @@ func apidMain() error {
return fmt.Errorf("failed to create client TLS config: %w", err)
}
var remoteFactory director.RemoteBackendFactory
var (
remoteFactory director.RemoteBackendFactory
onPKIUpdate func()
)
if clientTLSConfig != nil {
backendFactory := apidbackend.NewAPIDFactory(clientTLSConfig)
backendFactory := apidbackend.NewAPIDFactory(tlsConfig)
remoteFactory = backendFactory.Get
onPKIUpdate = backendFactory.Flush
}
localAddressProvider, err := director.NewLocalAddressProvider(resources)
@ -226,7 +230,7 @@ func apidMain() error {
})
errGroup.Go(func() error {
return tlsConfig.Watch(ctx)
return tlsConfig.Watch(ctx, onPKIUpdate)
})
errGroup.Go(func() error {

View File

@ -6,6 +6,7 @@ package backend
import (
"context"
"crypto/tls"
"fmt"
"sync"
"time"
@ -32,22 +33,23 @@ var _ proxy.Backend = (*APID)(nil)
// Backend authenticates itself using given grpc credentials.
type APID struct {
target string
creds credentials.TransportCredentials
tlsConfigProvider func() (*tls.Config, error)
mu sync.Mutex
conn *grpc.ClientConn
}
// NewAPID creates new instance of APID backend.
func NewAPID(target string, creds credentials.TransportCredentials) (*APID, error) {
func NewAPID(target string, tlsConfigProvider func() (*tls.Config, error)) (*APID, error) {
// perform very basic validation on target, trying to weed out empty addresses or addresses with the port appended
if target == "" || net.AddressContainsPort(target) {
return nil, fmt.Errorf("invalid target %q", target)
}
return &APID{
target: target,
creds: creds,
target: target,
tlsConfigProvider: tlsConfigProvider,
}, nil
}
@ -81,6 +83,11 @@ func (a *APID) GetConnection(ctx context.Context, fullMethodName string) (contex
return outCtx, a.conn, nil
}
tlsConfig, err := a.tlsConfigProvider()
if err != nil {
return outCtx, nil, err
}
// override max delay to avoid excessive backoff when the another node is unavailable (e.g. rebooted),
// and apid used as an endpoint considers another node to be down for longer than expected.
//
@ -88,13 +95,12 @@ func (a *APID) GetConnection(ctx context.Context, fullMethodName string) (contex
backoffConfig := backoff.DefaultConfig
backoffConfig.MaxDelay = 15 * time.Second
var err error
a.conn, err = grpc.DialContext(
ctx,
fmt.Sprintf("%s:%d", net.FormatAddress(a.target), constants.ApidPort),
grpc.WithInitialWindowSize(65535*32),
grpc.WithInitialConnWindowSize(65535*16),
grpc.WithTransportCredentials(a.creds),
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoffConfig,
// not published as a constant in gRPC library

View File

@ -6,26 +6,30 @@ package backend
import (
"crypto/tls"
"sync"
"github.com/siderolabs/gen/containers"
"github.com/siderolabs/grpc-proxy/proxy"
"google.golang.org/grpc/credentials"
)
// APIDFactory caches connection to apid instances by target.
//
// TODO: need to clean up idle connections from time to time.
type APIDFactory struct {
cache sync.Map
creds credentials.TransportCredentials
cache containers.SyncMap[string, *APID]
provider TLSConfigProvider
}
// TLSConfigProvider provides tls.Config for client connections.
type TLSConfigProvider interface {
ClientConfig() (*tls.Config, error)
}
// NewAPIDFactory creates new APIDFactory with given tls.Config.
//
// Client TLS config is used to connect to other apid instances.
func NewAPIDFactory(config *tls.Config) *APIDFactory {
func NewAPIDFactory(provider TLSConfigProvider) *APIDFactory {
return &APIDFactory{
creds: credentials.NewTLS(config),
provider: provider,
}
}
@ -35,10 +39,10 @@ func NewAPIDFactory(config *tls.Config) *APIDFactory {
func (factory *APIDFactory) Get(target string) (proxy.Backend, error) {
b, ok := factory.cache.Load(target)
if ok {
return b.(proxy.Backend), nil
return b, nil
}
backend, err := NewAPID(target, factory.creds)
backend, err := NewAPID(target, factory.provider.ClientConfig)
if err != nil {
return nil, err
}
@ -48,8 +52,19 @@ func (factory *APIDFactory) Get(target string) (proxy.Backend, error) {
// race: another Get() call built different backend
backend.Close()
return existing.(proxy.Backend), nil
return existing, nil
}
return backend, nil
}
// Flush all cached backends.
//
// This ensures that all connections are closed.
func (factory *APIDFactory) Flush() {
factory.cache.Range(func(key string, backend *APID) bool {
backend.Close()
return true
})
}

View File

@ -21,8 +21,14 @@ type APIDFactorySuite struct {
f *backend.APIDFactory
}
type fakeTLSConfigProvider struct{}
func (fakeTLSConfigProvider) ClientConfig() (*tls.Config, error) {
return &tls.Config{}, nil
}
func (suite *APIDFactorySuite) SetupSuite() {
suite.f = backend.NewAPIDFactory(&tls.Config{})
suite.f = backend.NewAPIDFactory(fakeTLSConfigProvider{})
}
func (suite *APIDFactorySuite) TestGet() {

View File

@ -14,7 +14,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
protobuf "google.golang.org/protobuf/proto" //nolint:depguard
"google.golang.org/protobuf/reflect/protoreflect"
@ -42,8 +41,12 @@ type APIDSuite struct {
}
func (suite *APIDSuite) SetupSuite() {
tlsConfigProvider := func() (*tls.Config, error) {
return &tls.Config{}, nil
}
var err error
suite.b, err = backend.NewAPID("127.0.0.1", credentials.NewTLS(&tls.Config{}))
suite.b, err = backend.NewAPID("127.0.0.1", tlsConfigProvider)
suite.Require().NoError(err)
}

View File

@ -6,14 +6,18 @@
package provider
import (
"bytes"
"context"
stdlibtls "crypto/tls"
stdx509 "crypto/x509"
"fmt"
"sync"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/state"
"github.com/siderolabs/crypto/tls"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/gen/xslices"
"github.com/siderolabs/talos/pkg/machinery/resources/secrets"
)
@ -68,7 +72,7 @@ func NewTLSConfig(ctx context.Context, resources state.State) (*TLSConfig, error
}
// Watch for changes in API certificates and updates the TLSConfig.
func (tlsConfig *TLSConfig) Watch(ctx context.Context) error {
func (tlsConfig *TLSConfig) Watch(ctx context.Context, onUpdate func()) error {
for {
var event state.Event
@ -93,19 +97,18 @@ func (tlsConfig *TLSConfig) Watch(ctx context.Context) error {
if err := tlsConfig.certificateProvider.Update(apiCerts); err != nil {
return fmt.Errorf("failed updating cert: %v", err)
}
if onUpdate != nil {
onUpdate()
}
}
}
// ServerConfig generates server-side tls.Config.
func (tlsConfig *TLSConfig) ServerConfig() (*stdlibtls.Config, error) {
ca, err := tlsConfig.certificateProvider.GetCA()
if err != nil {
return nil, fmt.Errorf("failed to get root CA: %w", err)
}
return tls.New(
tls.WithClientAuthType(tls.Mutual),
tls.WithCACertPEM(ca),
tls.WithDynamicClientCA(tlsConfig.certificateProvider),
tls.WithServerCertificateProvider(tlsConfig.certificateProvider),
)
}
@ -131,7 +134,8 @@ func (tlsConfig *TLSConfig) ClientConfig() (*stdlibtls.Config, error) {
type certificateProvider struct {
mu sync.Mutex
apiCerts *secrets.API
ca []byte
caCertPool *stdx509.CertPool
clientCert, serverCert *stdlibtls.Certificate
}
@ -139,17 +143,30 @@ func (p *certificateProvider) Update(apiCerts *secrets.API) error {
p.mu.Lock()
defer p.mu.Unlock()
p.apiCerts = apiCerts
serverCert, err := stdlibtls.X509KeyPair(p.apiCerts.TypedSpec().Server.Crt, p.apiCerts.TypedSpec().Server.Key)
serverCert, err := stdlibtls.X509KeyPair(apiCerts.TypedSpec().Server.Crt, apiCerts.TypedSpec().Server.Key)
if err != nil {
return fmt.Errorf("failed to parse server cert and key into a TLS Certificate: %w", err)
}
p.serverCert = &serverCert
if p.apiCerts.TypedSpec().Client != nil {
clientCert, err := stdlibtls.X509KeyPair(p.apiCerts.TypedSpec().Client.Crt, p.apiCerts.TypedSpec().Client.Key)
p.ca = bytes.Join(
xslices.Map(
apiCerts.TypedSpec().AcceptedCAs,
func(cert *x509.PEMEncodedCertificate) []byte {
return cert.Crt
},
),
nil,
)
p.caCertPool = stdx509.NewCertPool()
if !p.caCertPool.AppendCertsFromPEM(p.ca) {
return fmt.Errorf("failed to parse CA certs into a CertPool")
}
if apiCerts.TypedSpec().Client != nil {
clientCert, err := stdlibtls.X509KeyPair(apiCerts.TypedSpec().Client.Crt, apiCerts.TypedSpec().Client.Key)
if err != nil {
return fmt.Errorf("failed to parse client cert and key into a TLS Certificate: %w", err)
}
@ -166,7 +183,14 @@ func (p *certificateProvider) GetCA() ([]byte, error) {
p.mu.Lock()
defer p.mu.Unlock()
return p.apiCerts.TypedSpec().CA.Crt, nil
return p.ca, nil
}
func (p *certificateProvider) GetCACertPool() (*stdx509.CertPool, error) {
p.mu.Lock()
defer p.mu.Unlock()
return p.caCertPool, nil
}
func (p *certificateProvider) GetCertificate(h *stdlibtls.ClientHelloInfo) (*stdlibtls.Certificate, error) {

View File

@ -171,7 +171,7 @@ func (ctrl *CRDController) Run(ctx context.Context, r controller.Runtime, logger
go func() {
crdControllerErrCh <- ctrl.runCRDController(
crdControllerCtx,
osSecretsSpec.CA,
osSecretsSpec.IssuingCA,
kubeconfig,
kubeaccessConfigSpec,
logger,

View File

@ -278,7 +278,7 @@ func (ctrl *APIController) reconcile(ctx context.Context, r controller.Runtime,
}
func (ctrl *APIController) generateControlPlane(ctx context.Context, r controller.Runtime, logger *zap.Logger, rootSpec *secrets.OSRootSpec, certSANs *secrets.CertSANSpec) error {
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(rootSpec.CA)
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(rootSpec.IssuingCA)
if err != nil {
return fmt.Errorf("failed to parse CA certificate: %w", err)
}
@ -314,9 +314,7 @@ func (ctrl *APIController) generateControlPlane(ctx context.Context, r controlle
func(r resource.Resource) error {
apiSecrets := r.(*secrets.API).TypedSpec()
apiSecrets.CA = &x509.PEMEncodedCertificateAndKey{
Crt: rootSpec.CA.Crt,
}
apiSecrets.AcceptedCAs = rootSpec.AcceptedCAs
apiSecrets.Server = x509.NewCertificateAndKeyFromKeyPair(serverCert)
apiSecrets.Client = x509.NewCertificateAndKeyFromKeyPair(clientCert)
@ -339,7 +337,7 @@ func (ctrl *APIController) generateControlPlane(ctx context.Context, r controlle
func (ctrl *APIController) generateWorker(ctx context.Context, r controller.Runtime, logger *zap.Logger,
rootSpec *secrets.OSRootSpec, endpointsStr []string, certSANs *secrets.CertSANSpec,
) error {
remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, rootSpec.CA)
remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, rootSpec.IssuingCA)
if err != nil {
return fmt.Errorf("failed creating trustd client: %w", err)
}
@ -393,8 +391,10 @@ func (ctrl *APIController) generateWorker(ctx context.Context, r controller.Runt
func(r resource.Resource) error {
apiSecrets := r.(*secrets.API).TypedSpec()
apiSecrets.CA = &x509.PEMEncodedCertificateAndKey{
Crt: ca,
apiSecrets.AcceptedCAs = []*x509.PEMEncodedCertificate{
{
Crt: ca,
},
}
apiSecrets.Server = serverCert

View File

@ -48,10 +48,15 @@ func (suite *APISuite) TestReconcileControlPlane() {
)
suite.Require().NoError(err)
rootSecrets.TypedSpec().CA = &x509.PEMEncodedCertificateAndKey{
rootSecrets.TypedSpec().IssuingCA = &x509.PEMEncodedCertificateAndKey{
Crt: talosCA.CrtPEM,
Key: talosCA.KeyPEM,
}
rootSecrets.TypedSpec().AcceptedCAs = []*x509.PEMEncodedCertificate{
{
Crt: talosCA.CrtPEM,
},
}
rootSecrets.TypedSpec().CertSANDNSNames = []string{"example.com"}
rootSecrets.TypedSpec().CertSANIPs = []netip.Addr{netip.MustParseAddr("10.4.3.2"), netip.MustParseAddr("10.2.1.3")}
rootSecrets.TypedSpec().Token = "something"
@ -99,8 +104,14 @@ func (suite *APISuite) TestReconcileControlPlane() {
apiCerts := certs.TypedSpec()
suite.Assert().Equal(talosCA.CrtPEM, apiCerts.CA.Crt)
suite.Assert().Nil(apiCerts.CA.Key)
suite.Assert().Equal(
[]*x509.PEMEncodedCertificate{
{
Crt: talosCA.CrtPEM,
},
},
apiCerts.AcceptedCAs,
)
serverCert, err := apiCerts.Server.GetCert()
suite.Require().NoError(err)

View File

@ -14,6 +14,7 @@ import (
"github.com/cosi-project/runtime/pkg/controller"
"github.com/cosi-project/runtime/pkg/controller/generic"
"github.com/cosi-project/runtime/pkg/controller/generic/transform"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/gen/optional"
"go.uber.org/zap"
@ -145,7 +146,19 @@ func NewRootOSController() *RootOSController {
cfgProvider := cfg.Config()
osSecrets := res.TypedSpec()
osSecrets.CA = cfgProvider.Machine().Security().CA()
osSecrets.IssuingCA = cfgProvider.Machine().Security().IssuingCA()
osSecrets.AcceptedCAs = cfgProvider.Machine().Security().AcceptedCAs()
if osSecrets.IssuingCA != nil {
osSecrets.AcceptedCAs = append(osSecrets.AcceptedCAs, &x509.PEMEncodedCertificate{
Crt: osSecrets.IssuingCA.Crt,
})
}
if len(osSecrets.IssuingCA.Key) == 0 {
// drop incomplete issuing CA, as the machine config for workers contains just the cert
osSecrets.IssuingCA = nil
}
osSecrets.CertSANIPs = nil
osSecrets.CertSANDNSNames = nil

View File

@ -10,6 +10,7 @@ import (
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
"github.com/siderolabs/crypto/x509"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@ -77,7 +78,15 @@ func (suite *RootSuite) TestReconcileControlPlane() {
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{secrets.OSRootID},
func(res *secrets.OSRoot, asrt *assert.Assertions) {
asrt.Equal(res.TypedSpec().CA, cfg.Machine().Security().CA())
asrt.Equal(res.TypedSpec().IssuingCA, cfg.Machine().Security().IssuingCA())
asrt.Equal(
[]*x509.PEMEncodedCertificate{
{
Crt: cfg.Machine().Security().IssuingCA().Crt,
},
},
res.TypedSpec().AcceptedCAs,
)
},
)
}
@ -87,7 +96,15 @@ func (suite *RootSuite) TestReconcileWorker() {
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{secrets.OSRootID},
func(res *secrets.OSRoot, asrt *assert.Assertions) {
asrt.Equal(res.TypedSpec().CA, cfg.Machine().Security().CA())
asrt.Nil(res.TypedSpec().IssuingCA)
asrt.Equal(
[]*x509.PEMEncodedCertificate{
{
Crt: cfg.Machine().Security().IssuingCA().Crt,
},
},
res.TypedSpec().AcceptedCAs,
)
},
)

View File

@ -216,7 +216,7 @@ func (ctrl *TrustdController) reconcile(ctx context.Context, r controller.Runtim
}
func (ctrl *TrustdController) generateControlPlane(ctx context.Context, r controller.Runtime, logger *zap.Logger, rootSpec *secrets.OSRootSpec, certSANs *secrets.CertSANSpec) error {
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(rootSpec.CA)
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(rootSpec.IssuingCA)
if err != nil {
return fmt.Errorf("failed to parse CA certificate: %w", err)
}
@ -239,9 +239,7 @@ func (ctrl *TrustdController) generateControlPlane(ctx context.Context, r contro
func(r *secrets.Trustd) error {
trustdSecrets := r.TypedSpec()
trustdSecrets.CA = &x509.PEMEncodedCertificateAndKey{
Crt: rootSpec.CA.Crt,
}
trustdSecrets.AcceptedCAs = rootSpec.AcceptedCAs
trustdSecrets.Server = x509.NewCertificateAndKeyFromKeyPair(serverCert)
return nil

View File

@ -49,10 +49,15 @@ func (suite *TrustdSuite) TestReconcileControlPlane() {
)
suite.Require().NoError(err)
rootSecrets.TypedSpec().CA = &x509.PEMEncodedCertificateAndKey{
rootSecrets.TypedSpec().IssuingCA = &x509.PEMEncodedCertificateAndKey{
Crt: talosCA.CrtPEM,
Key: talosCA.KeyPEM,
}
rootSecrets.TypedSpec().AcceptedCAs = []*x509.PEMEncodedCertificate{
{
Crt: talosCA.CrtPEM,
},
}
rootSecrets.TypedSpec().CertSANDNSNames = []string{"example.com"}
rootSecrets.TypedSpec().CertSANIPs = []netip.Addr{netip.MustParseAddr("10.4.3.2"), netip.MustParseAddr("10.2.1.3")}
rootSecrets.TypedSpec().Token = "something"
@ -100,8 +105,14 @@ func (suite *TrustdSuite) TestReconcileControlPlane() {
trustdCerts := certs.TypedSpec()
suite.Assert().Equal(talosCA.CrtPEM, trustdCerts.CA.Crt)
suite.Assert().Nil(trustdCerts.CA.Key)
suite.Assert().Equal(
[]*x509.PEMEncodedCertificate{
{
Crt: talosCA.CrtPEM,
},
},
trustdCerts.AcceptedCAs,
)
serverCert, err := trustdCerts.Server.GetCert()
suite.Require().NoError(err)

View File

@ -115,6 +115,8 @@ func (r *Runtime) CanApplyImmediate(cfg config.Provider) error {
// the config changes allowed to be applied immediately are:
// * .debug
// * .cluster
// * .machine.ca
// * .machine.acceptedCAs
// * .machine.time
// * .machine.certCANs
// * .machine.install
@ -137,6 +139,8 @@ func (r *Runtime) CanApplyImmediate(cfg config.Provider) error {
newConfig.ClusterConfig = currentConfig.ClusterConfig
if newConfig.MachineConfig != nil && currentConfig.MachineConfig != nil {
newConfig.MachineConfig.MachineCA = currentConfig.MachineConfig.MachineCA
newConfig.MachineConfig.MachineAcceptedCAs = currentConfig.MachineConfig.MachineAcceptedCAs
newConfig.MachineConfig.MachineTime = currentConfig.MachineConfig.MachineTime
newConfig.MachineConfig.MachineCertSANs = currentConfig.MachineConfig.MachineCertSANs
newConfig.MachineConfig.MachineInstall = currentConfig.MachineConfig.MachineInstall

View File

@ -6,6 +6,7 @@ package maintenance
import (
stdlibtls "crypto/tls"
"crypto/x509"
"fmt"
"sync/atomic"
@ -51,6 +52,11 @@ func (provider *TLSProvider) GetCA() ([]byte, error) {
return nil, nil
}
// GetCACertPool implements tls.CertificateProvider interface.
func (provider *TLSProvider) GetCACertPool() (*x509.CertPool, error) {
return nil, nil
}
// GetCertificate implements tls.CertificateProvider interface.
func (provider *TLSProvider) GetCertificate(h *stdlibtls.ClientHelloInfo) (*stdlibtls.Certificate, error) {
return provider.serverCert.Load(), nil

View File

@ -6,8 +6,10 @@
package provider
import (
"bytes"
"context"
stdlibtls "crypto/tls"
stdx509 "crypto/x509"
"fmt"
"log"
"sync"
@ -15,6 +17,8 @@ import (
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/state"
"github.com/siderolabs/crypto/tls"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/gen/xslices"
"github.com/siderolabs/talos/pkg/machinery/resources/secrets"
)
@ -115,17 +119,32 @@ func (tlsConfig *TLSConfig) ServerConfig() (*stdlibtls.Config, error) {
type certificateProvider struct {
mu sync.Mutex
trustdCerts *secrets.Trustd
serverCert *stdlibtls.Certificate
ca []byte
caCertPool *stdx509.CertPool
serverCert *stdlibtls.Certificate
}
func (p *certificateProvider) Update(trustdCerts *secrets.Trustd) error {
p.mu.Lock()
defer p.mu.Unlock()
p.trustdCerts = trustdCerts
p.ca = bytes.Join(
xslices.Map(
trustdCerts.TypedSpec().AcceptedCAs,
func(cert *x509.PEMEncodedCertificate) []byte {
return cert.Crt
},
),
nil,
)
serverCert, err := stdlibtls.X509KeyPair(p.trustdCerts.TypedSpec().Server.Crt, p.trustdCerts.TypedSpec().Server.Key)
p.caCertPool = stdx509.NewCertPool()
if !p.caCertPool.AppendCertsFromPEM(p.ca) {
return fmt.Errorf("failed to parse root CA")
}
serverCert, err := stdlibtls.X509KeyPair(trustdCerts.TypedSpec().Server.Crt, trustdCerts.TypedSpec().Server.Key)
if err != nil {
return fmt.Errorf("failed to parse server cert and key into a TLS Certificate: %w", err)
}
@ -139,7 +158,14 @@ func (p *certificateProvider) GetCA() ([]byte, error) {
p.mu.Lock()
defer p.mu.Unlock()
return p.trustdCerts.TypedSpec().CA.Crt, nil
return p.ca, nil
}
func (p *certificateProvider) GetCACertPool() (*stdx509.CertPool, error) {
p.mu.Lock()
defer p.mu.Unlock()
return p.caCertPool, nil
}
func (p *certificateProvider) GetCertificate(h *stdlibtls.ClientHelloInfo) (*stdlibtls.Certificate, error) {

View File

@ -5,6 +5,7 @@
package reg
import (
"bytes"
"context"
stdx509 "crypto/x509"
"crypto/x509/pkix"
@ -15,6 +16,7 @@ import (
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/gen/xslices"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/peer"
@ -90,8 +92,8 @@ func (r *Registrator) Certificate(ctx context.Context, in *securityapi.Certifica
// TODO: Verify that the request is coming from the IP address declared in
// the CSR.
signed, err := x509.NewCertificateFromCSRBytes(
osRoot.TypedSpec().CA.Crt,
osRoot.TypedSpec().CA.Key,
osRoot.TypedSpec().IssuingCA.Crt,
osRoot.TypedSpec().IssuingCA.Key,
in.Csr,
x509Opts...,
)
@ -100,7 +102,15 @@ func (r *Registrator) Certificate(ctx context.Context, in *securityapi.Certifica
}
resp = &securityapi.CertificateResponse{
Ca: osRoot.TypedSpec().CA.Crt,
Ca: bytes.Join(
xslices.Map(
osRoot.TypedSpec().AcceptedCAs,
func(cert *x509.PEMEncodedCertificate) []byte {
return cert.Crt
},
),
nil,
),
Crt: signed.X509CertificatePEM,
}

View File

@ -37,10 +37,15 @@ func TestCertificate(t *testing.T) {
require.NoError(t, err)
osRoot := secrets.NewOSRoot(secrets.OSRootID)
osRoot.TypedSpec().CA = &x509.PEMEncodedCertificateAndKey{
osRoot.TypedSpec().IssuingCA = &x509.PEMEncodedCertificateAndKey{
Crt: ca.CrtPEM,
Key: ca.KeyPEM,
}
osRoot.TypedSpec().AcceptedCAs = []*x509.PEMEncodedCertificate{
{
Crt: ca.CrtPEM,
},
}
require.NoError(t, resources.Create(ctx, osRoot))
ctx = peer.NewContext(ctx, &peer.Peer{

View File

@ -173,7 +173,7 @@ func (suite *GenerateConfigSuite) TestGenerate() {
joinedConfig.Machine().Network().Hostname(),
)
suite.Require().EqualValues(config.Machine().Security().CA(), joinedConfig.Machine().Security().CA())
suite.Require().EqualValues(config.Machine().Security().IssuingCA(), joinedConfig.Machine().Security().IssuingCA())
suite.Require().EqualValues(config.Machine().Security().Token(), joinedConfig.Machine().Security().Token())
suite.Require().EqualValues(
config.Cluster().AESCBCEncryptionSecret(),

View File

@ -0,0 +1,158 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build integration_api
package api
import (
"context"
"testing"
"time"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/siderolabs/talos/internal/integration/base"
"github.com/siderolabs/talos/pkg/machinery/api/common"
"github.com/siderolabs/talos/pkg/machinery/client"
"github.com/siderolabs/talos/pkg/machinery/config"
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/siderolabs/talos/pkg/machinery/config/generate/secrets"
"github.com/siderolabs/talos/pkg/machinery/config/machine"
"github.com/siderolabs/talos/pkg/machinery/constants"
secretsres "github.com/siderolabs/talos/pkg/machinery/resources/secrets"
"github.com/siderolabs/talos/pkg/provision/access"
"github.com/siderolabs/talos/pkg/rotate/pki/talos"
)
// RotateCASuite verifies rotation of Talos and Kubernetes CAs.
type RotateCASuite struct {
base.APISuite
ctx context.Context //nolint:containedctx
ctxCancel context.CancelFunc
}
// SuiteName ...
func (suite *RotateCASuite) SuiteName() string {
return "api.RotateCASuite"
}
// SetupTest ...
func (suite *RotateCASuite) SetupTest() {
// make sure API calls have timeout
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 5*time.Minute)
}
// TearDownTest ...
func (suite *RotateCASuite) TearDownTest() {
if suite.ctxCancel != nil {
suite.ctxCancel()
}
}
// TestTalos updates Talos CA in the cluster.
func (suite *RotateCASuite) TestTalos() {
if suite.Cluster == nil {
suite.T().Skip("cluster information is not available")
}
suite.T().Logf("capturing current Talos CA")
nodeInternalIP := suite.RandomDiscoveredNodeInternalIP(machine.TypeControlPlane)
// save osRoot
osRoot, err := safe.StateGetByID[*secretsres.OSRoot](client.WithNode(suite.ctx, nodeInternalIP), suite.Client.COSI, secretsres.OSRootID)
suite.Require().NoError(err)
suite.T().Logf("rotating current CA -> new CA")
newBundle, err := secrets.NewBundle(secrets.NewFixedClock(time.Now()), config.TalosVersionCurrent)
suite.Require().NoError(err)
options := talos.Options{
CurrentClient: suite.Client,
ClusterInfo: access.NewAdapter(suite.Cluster),
ContextName: suite.Talosconfig.Context,
Endpoints: suite.Client.GetEndpoints(),
NewTalosCA: newBundle.Certs.OS,
EncoderOption: encoder.WithComments(encoder.CommentsAll),
Printf: suite.T().Logf,
}
newTalosconfig, err := talos.Rotate(suite.ctx, options)
suite.Require().NoError(err)
newClient, err := client.New(suite.ctx, client.WithConfig(newTalosconfig))
suite.Require().NoError(err)
if !testing.Short() {
suite.restartAPIServices(newClient)
}
suite.T().Logf("rotating back new CA -> old CA")
options = talos.Options{
CurrentClient: newClient,
ClusterInfo: access.NewAdapter(suite.Cluster),
ContextName: suite.Talosconfig.Context,
Endpoints: suite.Client.GetEndpoints(),
NewTalosCA: osRoot.TypedSpec().IssuingCA,
EncoderOption: encoder.WithComments(encoder.CommentsAll),
Printf: suite.T().Logf,
}
_, err = talos.Rotate(suite.ctx, options)
suite.Require().NoError(err)
suite.AssertClusterHealthy(suite.ctx)
}
func (suite *RotateCASuite) restartAPIServices(c *client.Client) {
suite.T().Logf("restarting API services")
var oldClient *client.Client
oldClient, suite.Client = suite.Client, c
defer func() {
suite.Client = oldClient
}()
for _, node := range suite.DiscoverNodeInternalIPsByType(suite.ctx, machine.TypeControlPlane) {
suite.T().Logf("restarting API services on %s", node)
err := c.Restart(client.WithNode(suite.ctx, node), constants.SystemContainerdNamespace, common.ContainerDriver_CONTAINERD, "trustd")
suite.Require().NoError(err)
suite.ClearConnectionRefused(suite.ctx, node)
err = c.Restart(client.WithNode(suite.ctx, node), constants.SystemContainerdNamespace, common.ContainerDriver_CONTAINERD, "apid")
suite.Require().NoError(err)
suite.ClearConnectionRefused(suite.ctx, node)
}
for _, node := range suite.DiscoverNodeInternalIPsByType(suite.ctx, machine.TypeWorker) {
suite.T().Logf("restarting API services on %s", node)
err := c.Restart(client.WithNode(suite.ctx, node), constants.SystemContainerdNamespace, common.ContainerDriver_CONTAINERD, "apid")
suite.Require().NoError(err)
suite.ClearConnectionRefused(suite.ctx, node)
}
suite.AssertClusterHealthy(suite.ctx)
}
func init() {
allSuites = append(allSuites, new(RotateCASuite))
}

View File

@ -644,6 +644,53 @@ func (x *PEMEncodedKey) GetKey() []byte {
return nil
}
type PEMEncodedCertificate struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Crt []byte `protobuf:"bytes,1,opt,name=crt,proto3" json:"crt,omitempty"`
}
func (x *PEMEncodedCertificate) Reset() {
*x = PEMEncodedCertificate{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PEMEncodedCertificate) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PEMEncodedCertificate) ProtoMessage() {}
func (x *PEMEncodedCertificate) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[9]
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 PEMEncodedCertificate.ProtoReflect.Descriptor instead.
func (*PEMEncodedCertificate) Descriptor() ([]byte, []int) {
return file_common_common_proto_rawDescGZIP(), []int{9}
}
func (x *PEMEncodedCertificate) GetCrt() []byte {
if x != nil {
return x.Crt
}
return nil
}
type NetIP struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -655,7 +702,7 @@ type NetIP struct {
func (x *NetIP) Reset() {
*x = NetIP{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[9]
mi := &file_common_common_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -668,7 +715,7 @@ func (x *NetIP) String() string {
func (*NetIP) ProtoMessage() {}
func (x *NetIP) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[9]
mi := &file_common_common_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -681,7 +728,7 @@ func (x *NetIP) ProtoReflect() protoreflect.Message {
// Deprecated: Use NetIP.ProtoReflect.Descriptor instead.
func (*NetIP) Descriptor() ([]byte, []int) {
return file_common_common_proto_rawDescGZIP(), []int{9}
return file_common_common_proto_rawDescGZIP(), []int{10}
}
func (x *NetIP) GetIp() []byte {
@ -703,7 +750,7 @@ type NetIPPort struct {
func (x *NetIPPort) Reset() {
*x = NetIPPort{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[10]
mi := &file_common_common_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -716,7 +763,7 @@ func (x *NetIPPort) String() string {
func (*NetIPPort) ProtoMessage() {}
func (x *NetIPPort) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[10]
mi := &file_common_common_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -729,7 +776,7 @@ func (x *NetIPPort) ProtoReflect() protoreflect.Message {
// Deprecated: Use NetIPPort.ProtoReflect.Descriptor instead.
func (*NetIPPort) Descriptor() ([]byte, []int) {
return file_common_common_proto_rawDescGZIP(), []int{10}
return file_common_common_proto_rawDescGZIP(), []int{11}
}
func (x *NetIPPort) GetIp() []byte {
@ -758,7 +805,7 @@ type NetIPPrefix struct {
func (x *NetIPPrefix) Reset() {
*x = NetIPPrefix{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[11]
mi := &file_common_common_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -771,7 +818,7 @@ func (x *NetIPPrefix) String() string {
func (*NetIPPrefix) ProtoMessage() {}
func (x *NetIPPrefix) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[11]
mi := &file_common_common_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -784,7 +831,7 @@ func (x *NetIPPrefix) ProtoReflect() protoreflect.Message {
// Deprecated: Use NetIPPrefix.ProtoReflect.Descriptor instead.
func (*NetIPPrefix) Descriptor() ([]byte, []int) {
return file_common_common_proto_rawDescGZIP(), []int{11}
return file_common_common_proto_rawDescGZIP(), []int{12}
}
func (x *NetIPPrefix) GetIp() []byte {
@ -948,64 +995,67 @@ var file_common_common_proto_rawDesc = []byte{
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x22, 0x21, 0x0a, 0x0d, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64,
0x4b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x17, 0x0a, 0x05, 0x4e, 0x65, 0x74, 0x49, 0x50, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x22, 0x2f,
0x0a, 0x09, 0x4e, 0x65, 0x74, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70,
0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22,
0x42, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x49, 0x50, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x23,
0x0a, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e,
0x67, 0x74, 0x68, 0x2a, 0x2b, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x46,
0x41, 0x54, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x02,
0x2a, 0x2a, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x72, 0x69,
0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52,
0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x52, 0x49, 0x10, 0x01, 0x2a, 0x40, 0x0a, 0x13,
0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x53, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d,
0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x53, 0x5f, 0x43, 0x52, 0x49, 0x10, 0x02, 0x3a, 0x5d,
0x0a, 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72,
0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x57, 0x0a,
0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x29, 0x0a, 0x15, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f,
0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x10,
0x0a, 0x03, 0x63, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x72, 0x74,
0x22, 0x17, 0x0a, 0x05, 0x4e, 0x65, 0x74, 0x49, 0x50, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x22, 0x2f, 0x0a, 0x09, 0x4e, 0x65, 0x74,
0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x42, 0x0a, 0x0b, 0x4e, 0x65,
0x74, 0x49, 0x50, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x65,
0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2a, 0x2b,
0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10,
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a,
0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x2a, 0x2a, 0x0a, 0x0f, 0x43,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x0e,
0x0a, 0x0a, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x44, 0x10, 0x00, 0x12, 0x07,
0x0a, 0x03, 0x43, 0x52, 0x49, 0x10, 0x01, 0x2a, 0x40, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x0e,
0x0a, 0x0a, 0x4e, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d,
0x0a, 0x09, 0x4e, 0x53, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x01, 0x12, 0x0a, 0x0a,
0x06, 0x4e, 0x53, 0x5f, 0x43, 0x52, 0x49, 0x10, 0x02, 0x3a, 0x5d, 0x0a, 0x19, 0x72, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
0x15, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x3a, 0x54, 0x0a, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd,
0xd7, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65,
0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x64, 0x0a, 0x1c,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
0x64, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
0xbd, 0xd7, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44,
0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x3a, 0x5a, 0x0a, 0x18, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70,
0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1e,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd,
0xd7, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65,
0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3a, 0x5d,
0x0a, 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72,
0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x36, 0x5a,
0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65,
0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67,
0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x57, 0x0a, 0x17, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69,
0x65, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c,
0x64, 0x3a, 0x54, 0x0a, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72,
0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x1c, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x64, 0x0a, 0x1c, 0x72, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x75,
0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05, 0x20, 0x01,
0x28, 0x09, 0x52, 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63,
0x61, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x5a, 0x0a,
0x18, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3a, 0x5d, 0x0a, 0x19, 0x72, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xbd, 0xd7, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62,
0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1021,7 +1071,7 @@ func file_common_common_proto_rawDescGZIP() []byte {
}
var file_common_common_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
var file_common_common_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_common_common_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_common_common_proto_goTypes = []interface{}{
(Code)(0), // 0: common.Code
(ContainerDriver)(0), // 1: common.ContainerDriver
@ -1035,32 +1085,33 @@ var file_common_common_proto_goTypes = []interface{}{
(*URL)(nil), // 9: common.URL
(*PEMEncodedCertificateAndKey)(nil), // 10: common.PEMEncodedCertificateAndKey
(*PEMEncodedKey)(nil), // 11: common.PEMEncodedKey
(*NetIP)(nil), // 12: common.NetIP
(*NetIPPort)(nil), // 13: common.NetIPPort
(*NetIPPrefix)(nil), // 14: common.NetIPPrefix
(*anypb.Any)(nil), // 15: google.protobuf.Any
(*status.Status)(nil), // 16: google.rpc.Status
(*descriptorpb.MessageOptions)(nil), // 17: google.protobuf.MessageOptions
(*descriptorpb.FieldOptions)(nil), // 18: google.protobuf.FieldOptions
(*descriptorpb.EnumOptions)(nil), // 19: google.protobuf.EnumOptions
(*descriptorpb.EnumValueOptions)(nil), // 20: google.protobuf.EnumValueOptions
(*descriptorpb.MethodOptions)(nil), // 21: google.protobuf.MethodOptions
(*descriptorpb.ServiceOptions)(nil), // 22: google.protobuf.ServiceOptions
(*PEMEncodedCertificate)(nil), // 12: common.PEMEncodedCertificate
(*NetIP)(nil), // 13: common.NetIP
(*NetIPPort)(nil), // 14: common.NetIPPort
(*NetIPPrefix)(nil), // 15: common.NetIPPrefix
(*anypb.Any)(nil), // 16: google.protobuf.Any
(*status.Status)(nil), // 17: google.rpc.Status
(*descriptorpb.MessageOptions)(nil), // 18: google.protobuf.MessageOptions
(*descriptorpb.FieldOptions)(nil), // 19: google.protobuf.FieldOptions
(*descriptorpb.EnumOptions)(nil), // 20: google.protobuf.EnumOptions
(*descriptorpb.EnumValueOptions)(nil), // 21: google.protobuf.EnumValueOptions
(*descriptorpb.MethodOptions)(nil), // 22: google.protobuf.MethodOptions
(*descriptorpb.ServiceOptions)(nil), // 23: google.protobuf.ServiceOptions
}
var file_common_common_proto_depIdxs = []int32{
0, // 0: common.Error.code:type_name -> common.Code
15, // 1: common.Error.details:type_name -> google.protobuf.Any
16, // 2: common.Metadata.status:type_name -> google.rpc.Status
16, // 1: common.Error.details:type_name -> google.protobuf.Any
17, // 2: common.Metadata.status:type_name -> google.rpc.Status
4, // 3: common.Data.metadata:type_name -> common.Metadata
5, // 4: common.DataResponse.messages:type_name -> common.Data
4, // 5: common.Empty.metadata:type_name -> common.Metadata
7, // 6: common.EmptyResponse.messages:type_name -> common.Empty
17, // 7: common.remove_deprecated_message:extendee -> google.protobuf.MessageOptions
18, // 8: common.remove_deprecated_field:extendee -> google.protobuf.FieldOptions
19, // 9: common.remove_deprecated_enum:extendee -> google.protobuf.EnumOptions
20, // 10: common.remove_deprecated_enum_value:extendee -> google.protobuf.EnumValueOptions
21, // 11: common.remove_deprecated_method:extendee -> google.protobuf.MethodOptions
22, // 12: common.remove_deprecated_service:extendee -> google.protobuf.ServiceOptions
18, // 7: common.remove_deprecated_message:extendee -> google.protobuf.MessageOptions
19, // 8: common.remove_deprecated_field:extendee -> google.protobuf.FieldOptions
20, // 9: common.remove_deprecated_enum:extendee -> google.protobuf.EnumOptions
21, // 10: common.remove_deprecated_enum_value:extendee -> google.protobuf.EnumValueOptions
22, // 11: common.remove_deprecated_method:extendee -> google.protobuf.MethodOptions
23, // 12: common.remove_deprecated_service:extendee -> google.protobuf.ServiceOptions
13, // [13:13] is the sub-list for method output_type
13, // [13:13] is the sub-list for method input_type
13, // [13:13] is the sub-list for extension type_name
@ -1183,7 +1234,7 @@ func file_common_common_proto_init() {
}
}
file_common_common_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NetIP); i {
switch v := v.(*PEMEncodedCertificate); i {
case 0:
return &v.state
case 1:
@ -1195,7 +1246,7 @@ func file_common_common_proto_init() {
}
}
file_common_common_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NetIPPort); i {
switch v := v.(*NetIP); i {
case 0:
return &v.state
case 1:
@ -1207,6 +1258,18 @@ func file_common_common_proto_init() {
}
}
file_common_common_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NetIPPort); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_common_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NetIPPrefix); i {
case 0:
return &v.state
@ -1225,7 +1288,7 @@ func file_common_common_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_common_common_proto_rawDesc,
NumEnums: 3,
NumMessages: 12,
NumMessages: 13,
NumExtensions: 6,
NumServices: 0,
},

View File

@ -459,6 +459,46 @@ func (m *PEMEncodedKey) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *PEMEncodedCertificate) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
}
size := m.SizeVT()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PEMEncodedCertificate) MarshalToVT(dAtA []byte) (int, error) {
size := m.SizeVT()
return m.MarshalToSizedBufferVT(dAtA[:size])
}
func (m *PEMEncodedCertificate) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
if m == nil {
return 0, nil
}
i := len(dAtA)
_ = i
var l int
_ = l
if m.unknownFields != nil {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.Crt) > 0 {
i -= len(m.Crt)
copy(dAtA[i:], m.Crt)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Crt)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *NetIP) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
@ -750,6 +790,20 @@ func (m *PEMEncodedKey) SizeVT() (n int) {
return n
}
func (m *PEMEncodedCertificate) SizeVT() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Crt)
if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
n += len(m.unknownFields)
return n
}
func (m *NetIP) SizeVT() (n int) {
if m == nil {
return 0
@ -1758,6 +1812,91 @@ func (m *PEMEncodedKey) UnmarshalVT(dAtA []byte) error {
}
return nil
}
func (m *PEMEncodedCertificate) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PEMEncodedCertificate: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PEMEncodedCertificate: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Crt", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Crt = append(m.Crt[:0], dAtA[iNdEx:postIndex]...)
if m.Crt == nil {
m.Crt = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return protohelpers.ErrInvalidLength
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *NetIP) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View File

@ -29,9 +29,9 @@ type APICertsSpec struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Ca *common.PEMEncodedCertificateAndKey `protobuf:"bytes,1,opt,name=ca,proto3" json:"ca,omitempty"`
Client *common.PEMEncodedCertificateAndKey `protobuf:"bytes,2,opt,name=client,proto3" json:"client,omitempty"`
Server *common.PEMEncodedCertificateAndKey `protobuf:"bytes,3,opt,name=server,proto3" json:"server,omitempty"`
Client *common.PEMEncodedCertificateAndKey `protobuf:"bytes,2,opt,name=client,proto3" json:"client,omitempty"`
Server *common.PEMEncodedCertificateAndKey `protobuf:"bytes,3,opt,name=server,proto3" json:"server,omitempty"`
AcceptedCAs []*common.PEMEncodedCertificate `protobuf:"bytes,4,rep,name=accepted_c_as,json=acceptedCAs,proto3" json:"accepted_c_as,omitempty"`
}
func (x *APICertsSpec) Reset() {
@ -66,13 +66,6 @@ func (*APICertsSpec) Descriptor() ([]byte, []int) {
return file_resource_definitions_secrets_secrets_proto_rawDescGZIP(), []int{0}
}
func (x *APICertsSpec) GetCa() *common.PEMEncodedCertificateAndKey {
if x != nil {
return x.Ca
}
return nil
}
func (x *APICertsSpec) GetClient() *common.PEMEncodedCertificateAndKey {
if x != nil {
return x.Client
@ -87,6 +80,13 @@ func (x *APICertsSpec) GetServer() *common.PEMEncodedCertificateAndKey {
return nil
}
func (x *APICertsSpec) GetAcceptedCAs() []*common.PEMEncodedCertificate {
if x != nil {
return x.AcceptedCAs
}
return nil
}
// CertSANSpec describes fields of the cert SANs.
type CertSANSpec struct {
state protoimpl.MessageState
@ -733,10 +733,11 @@ type OSRootSpec struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Ca *common.PEMEncodedCertificateAndKey `protobuf:"bytes,1,opt,name=ca,proto3" json:"ca,omitempty"`
IssuingCa *common.PEMEncodedCertificateAndKey `protobuf:"bytes,1,opt,name=issuing_ca,json=issuingCa,proto3" json:"issuing_ca,omitempty"`
CertSaniPs []*common.NetIP `protobuf:"bytes,2,rep,name=cert_sani_ps,json=certSaniPs,proto3" json:"cert_sani_ps,omitempty"`
CertSandnsNames []string `protobuf:"bytes,3,rep,name=cert_sandns_names,json=certSandnsNames,proto3" json:"cert_sandns_names,omitempty"`
Token string `protobuf:"bytes,4,opt,name=token,proto3" json:"token,omitempty"`
AcceptedCAs []*common.PEMEncodedCertificate `protobuf:"bytes,5,rep,name=accepted_c_as,json=acceptedCAs,proto3" json:"accepted_c_as,omitempty"`
}
func (x *OSRootSpec) Reset() {
@ -771,9 +772,9 @@ func (*OSRootSpec) Descriptor() ([]byte, []int) {
return file_resource_definitions_secrets_secrets_proto_rawDescGZIP(), []int{10}
}
func (x *OSRootSpec) GetCa() *common.PEMEncodedCertificateAndKey {
func (x *OSRootSpec) GetIssuingCa() *common.PEMEncodedCertificateAndKey {
if x != nil {
return x.Ca
return x.IssuingCa
}
return nil
}
@ -799,14 +800,21 @@ func (x *OSRootSpec) GetToken() string {
return ""
}
func (x *OSRootSpec) GetAcceptedCAs() []*common.PEMEncodedCertificate {
if x != nil {
return x.AcceptedCAs
}
return nil
}
// TrustdCertsSpec describes etcd certs secrets.
type TrustdCertsSpec struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Ca *common.PEMEncodedCertificateAndKey `protobuf:"bytes,1,opt,name=ca,proto3" json:"ca,omitempty"`
Server *common.PEMEncodedCertificateAndKey `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"`
Server *common.PEMEncodedCertificateAndKey `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"`
AcceptedCAs []*common.PEMEncodedCertificate `protobuf:"bytes,3,rep,name=accepted_c_as,json=acceptedCAs,proto3" json:"accepted_c_as,omitempty"`
}
func (x *TrustdCertsSpec) Reset() {
@ -841,16 +849,16 @@ func (*TrustdCertsSpec) Descriptor() ([]byte, []int) {
return file_resource_definitions_secrets_secrets_proto_rawDescGZIP(), []int{11}
}
func (x *TrustdCertsSpec) GetCa() *common.PEMEncodedCertificateAndKey {
func (x *TrustdCertsSpec) GetServer() *common.PEMEncodedCertificateAndKey {
if x != nil {
return x.Ca
return x.Server
}
return nil
}
func (x *TrustdCertsSpec) GetServer() *common.PEMEncodedCertificateAndKey {
func (x *TrustdCertsSpec) GetAcceptedCAs() []*common.PEMEncodedCertificate {
if x != nil {
return x.Server
return x.AcceptedCAs
}
return nil
}
@ -864,173 +872,180 @@ var file_resource_definitions_secrets_secrets_proto_rawDesc = []byte{
0x6c, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66,
0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73,
0x1a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbd, 0x01, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x43, 0x65, 0x72,
0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45,
0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x12, 0x3b, 0x0a, 0x06, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43,
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79,
0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x60, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x53, 0x41, 0x4e,
0x53, 0x70, 0x65, 0x63, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x5f, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x74, 0x49,
0x50, 0x52, 0x03, 0x69, 0x50, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61,
0x6d, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x22, 0x9b, 0x02, 0x0a, 0x0d, 0x45, 0x74, 0x63, 0x64,
0x43, 0x65, 0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x37, 0x0a, 0x04, 0x65, 0x74, 0x63,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x65, 0x74,
0x63, 0x64, 0x12, 0x40, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50,
0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x08, 0x65, 0x74, 0x63, 0x64,
0x50, 0x65, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x0a, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x61, 0x64, 0x6d,
0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x65,
0x74, 0x63, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0f, 0x65, 0x74, 0x63, 0x64,
0x5f, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e,
0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x65, 0x74, 0x63, 0x64, 0x41, 0x70, 0x69, 0x53,
0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x45, 0x74, 0x63, 0x64, 0x52, 0x6f, 0x6f,
0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x3c, 0x0a, 0x07, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x63, 0x61,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcb, 0x01, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x43, 0x65, 0x72,
0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x3b, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x65, 0x74, 0x63,
0x64, 0x43, 0x61, 0x22, 0xcf, 0x01, 0x0a, 0x0b, 0x4b, 0x75, 0x62, 0x65, 0x6c, 0x65, 0x74, 0x53,
0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55,
0x52, 0x4c, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x02,
0x63, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63,
0x61, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74,
0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62,
0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x12,
0x34, 0x0a, 0x16, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x14, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53,
0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0xf5, 0x01, 0x0a, 0x13, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e,
0x65, 0x74, 0x65, 0x73, 0x43, 0x65, 0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x31, 0x0a,
0x14, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x63, 0x68,
0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x42, 0x0a, 0x1d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x6d,
0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
0x74, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68,
0x6f, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6b, 0x75, 0x62, 0x65,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x64,
0x6d, 0x69, 0x6e, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x86, 0x02,
0x0a, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x44, 0x79, 0x6e, 0x61,
0x6d, 0x69, 0x63, 0x43, 0x65, 0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x42, 0x0a, 0x0a,
0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63,
0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41,
0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x12, 0x5e, 0x0a, 0x19, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6b,
0x75, 0x62, 0x65, 0x6c, 0x65, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20,
0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d,
0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x16, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x6c, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x12, 0x44, 0x0a, 0x0b, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50,
0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6e,
0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x22, 0x94, 0x05, 0x0a, 0x12, 0x4b, 0x75, 0x62, 0x65, 0x72,
0x6e, 0x65, 0x74, 0x65, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x27, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x52, 0x4c,
0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x0e, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x52, 0x4c, 0x52,
0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1c,
0x0a, 0x0a, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03,
0x28, 0x09, 0x52, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x61, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a,
0x64, 0x6e, 0x73, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
0x52, 0x09, 0x64, 0x6e, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x33, 0x0a, 0x02, 0x63,
0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x12, 0x41, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x5f, 0x61,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61,
0x12, 0x3e, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4b, 0x65, 0x79,
0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x12, 0x48, 0x0a, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x63,
0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x0c, 0x61, 0x67,
0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x61, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x65,
0x73, 0x63, 0x62, 0x63, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x61, 0x65,
0x73, 0x63, 0x62, 0x63, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65,
0x63, 0x72, 0x65, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61,
0x70, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09,
0x52, 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x0c, 0x20, 0x01,
0x28, 0x09, 0x52, 0x14, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b,
0x65, 0x6e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x3e, 0x0a, 0x1b, 0x73, 0x65, 0x63, 0x72,
0x65, 0x74, 0x62, 0x6f, 0x78, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x73,
0x65, 0x63, 0x72, 0x65, 0x74, 0x62, 0x6f, 0x78, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x70, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64,
0x43, 0x41, 0x73, 0x22, 0x60, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x53, 0x41, 0x4e, 0x53, 0x70,
0x65, 0x63, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x5f, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x50, 0x52,
0x0c, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x70, 0x73, 0x22, 0x4a, 0x0a,
0x13, 0x4d, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x6f, 0x6f, 0x74,
0x53, 0x70, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63,
0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41,
0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x22, 0x8f, 0x01, 0x0a, 0x1b, 0x4d, 0x61,
0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x43, 0x65, 0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18,
0x03, 0x69, 0x50, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65,
0x73, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x66, 0x71, 0x64, 0x6e, 0x22, 0x9b, 0x02, 0x0a, 0x0d, 0x45, 0x74, 0x63, 0x64, 0x43, 0x65,
0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x37, 0x0a, 0x04, 0x65, 0x74, 0x63, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50,
0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x12, 0x3b,
0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64,
0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64,
0x4b, 0x65, 0x79, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0xb4, 0x01, 0x0a, 0x0a,
0x4f, 0x53, 0x52, 0x6f, 0x6f, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x65, 0x74, 0x63, 0x64,
0x12, 0x40, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d,
0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x08, 0x65, 0x74, 0x63, 0x64, 0x50, 0x65,
0x65, 0x72, 0x12, 0x42, 0x0a, 0x0a, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x65, 0x74, 0x63,
0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0f, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x61,
0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f,
0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e,
0x64, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x65, 0x74, 0x63, 0x64, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x45, 0x74, 0x63, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x53,
0x70, 0x65, 0x63, 0x12, 0x3c, 0x0a, 0x07, 0x65, 0x74, 0x63, 0x64, 0x5f, 0x63, 0x61, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45,
0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x65, 0x74, 0x63, 0x64, 0x43,
0x61, 0x22, 0xcf, 0x01, 0x0a, 0x0b, 0x4b, 0x75, 0x62, 0x65, 0x6c, 0x65, 0x74, 0x53, 0x70, 0x65,
0x63, 0x12, 0x27, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x52, 0x4c,
0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x12,
0x2f, 0x0a, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x6e, 0x69, 0x5f, 0x70, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4e,
0x65, 0x74, 0x49, 0x50, 0x52, 0x0a, 0x63, 0x65, 0x72, 0x74, 0x53, 0x61, 0x6e, 0x69, 0x50, 0x73,
0x12, 0x2a, 0x0a, 0x11, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x6e, 0x64, 0x6e, 0x73, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x65, 0x72,
0x74, 0x53, 0x61, 0x6e, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x22, 0x83, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x64, 0x43, 0x65, 0x72,
0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45,
0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x12, 0x3b, 0x0a, 0x06, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43,
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79,
0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62,
0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73,
0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x2c, 0x0a, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x6f, 0x6f,
0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a,
0x16, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x62,
0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x63,
0x72, 0x65, 0x74, 0x22, 0xf5, 0x01, 0x0a, 0x13, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74,
0x65, 0x73, 0x43, 0x65, 0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x31, 0x0a, 0x14, 0x73,
0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x63, 0x68, 0x65, 0x64,
0x75, 0x6c, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42,
0x0a, 0x1d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x6e,
0x61, 0x67, 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x3c, 0x0a, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x5f,
0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x29, 0x0a, 0x10, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x64, 0x6d, 0x69,
0x6e, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x86, 0x02, 0x0a, 0x1a,
0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69,
0x63, 0x43, 0x65, 0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x42, 0x0a, 0x0a, 0x61, 0x70,
0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64,
0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64,
0x4b, 0x65, 0x79, 0x52, 0x09, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x5e,
0x0a, 0x19, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62,
0x65, 0x6c, 0x65, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e,
0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x16, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x4b, 0x75, 0x62, 0x65, 0x6c, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x44,
0x0a, 0x0b, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d,
0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x50,
0x72, 0x6f, 0x78, 0x79, 0x22, 0x94, 0x05, 0x0a, 0x12, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65,
0x74, 0x65, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x27, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x08,
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x0d, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x0a,
0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09,
0x52, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x61, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6e,
0x73, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x64, 0x6e, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18,
0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50,
0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x12, 0x3e,
0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x0e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x48,
0x0a, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x61, 0x18,
0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50,
0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x0c, 0x61, 0x67, 0x67, 0x72,
0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x61, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x65, 0x73, 0x63,
0x62, 0x63, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65,
0x63, 0x72, 0x65, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x61, 0x65, 0x73, 0x63,
0x62, 0x63, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x72,
0x65, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10,
0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64,
0x12, 0x34, 0x0a, 0x16, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74, 0x6f,
0x6b, 0x65, 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09,
0x52, 0x14, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x3e, 0x0a, 0x1b, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
0x62, 0x6f, 0x78, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73,
0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x73, 0x65, 0x63,
0x72, 0x65, 0x74, 0x62, 0x6f, 0x78, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x70, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x50, 0x52, 0x0c, 0x61,
0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x70, 0x73, 0x22, 0x4a, 0x0a, 0x13, 0x4d,
0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x53, 0x70,
0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64,
0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64,
0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x22, 0x8f, 0x01, 0x0a, 0x1b, 0x4d, 0x61, 0x69, 0x6e,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x65,
0x72, 0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d,
0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x02, 0x63, 0x61, 0x12, 0x3b, 0x0a, 0x06,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65,
0x79, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x86, 0x02, 0x0a, 0x0a, 0x4f, 0x53,
0x52, 0x6f, 0x6f, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x42, 0x0a, 0x0a, 0x69, 0x73, 0x73, 0x75,
0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65,
0x79, 0x52, 0x09, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x43, 0x61, 0x12, 0x2f, 0x0a, 0x0c,
0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x6e, 0x69, 0x5f, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x74, 0x49,
0x50, 0x52, 0x0a, 0x63, 0x65, 0x72, 0x74, 0x53, 0x61, 0x6e, 0x69, 0x50, 0x73, 0x12, 0x2a, 0x0a,
0x11, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x6e, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x53, 0x61,
0x6e, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12,
0x41, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x5f, 0x61, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x43,
0x41, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x64, 0x43, 0x65, 0x72,
0x74, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f,
0x63, 0x5f, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x45, 0x4d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x65,
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x70,
0x74, 0x65, 0x64, 0x43, 0x41, 0x73, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f,
0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x65, 0x63,
0x72, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1060,43 +1075,45 @@ var file_resource_definitions_secrets_secrets_proto_goTypes = []interface{}{
(*OSRootSpec)(nil), // 10: talos.resource.definitions.secrets.OSRootSpec
(*TrustdCertsSpec)(nil), // 11: talos.resource.definitions.secrets.TrustdCertsSpec
(*common.PEMEncodedCertificateAndKey)(nil), // 12: common.PEMEncodedCertificateAndKey
(*common.NetIP)(nil), // 13: common.NetIP
(*common.URL)(nil), // 14: common.URL
(*common.PEMEncodedKey)(nil), // 15: common.PEMEncodedKey
(*common.PEMEncodedCertificate)(nil), // 13: common.PEMEncodedCertificate
(*common.NetIP)(nil), // 14: common.NetIP
(*common.URL)(nil), // 15: common.URL
(*common.PEMEncodedKey)(nil), // 16: common.PEMEncodedKey
}
var file_resource_definitions_secrets_secrets_proto_depIdxs = []int32{
12, // 0: talos.resource.definitions.secrets.APICertsSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
12, // 1: talos.resource.definitions.secrets.APICertsSpec.client:type_name -> common.PEMEncodedCertificateAndKey
12, // 2: talos.resource.definitions.secrets.APICertsSpec.server:type_name -> common.PEMEncodedCertificateAndKey
13, // 3: talos.resource.definitions.secrets.CertSANSpec.i_ps:type_name -> common.NetIP
12, // 0: talos.resource.definitions.secrets.APICertsSpec.client:type_name -> common.PEMEncodedCertificateAndKey
12, // 1: talos.resource.definitions.secrets.APICertsSpec.server:type_name -> common.PEMEncodedCertificateAndKey
13, // 2: talos.resource.definitions.secrets.APICertsSpec.accepted_c_as:type_name -> common.PEMEncodedCertificate
14, // 3: talos.resource.definitions.secrets.CertSANSpec.i_ps:type_name -> common.NetIP
12, // 4: talos.resource.definitions.secrets.EtcdCertsSpec.etcd:type_name -> common.PEMEncodedCertificateAndKey
12, // 5: talos.resource.definitions.secrets.EtcdCertsSpec.etcd_peer:type_name -> common.PEMEncodedCertificateAndKey
12, // 6: talos.resource.definitions.secrets.EtcdCertsSpec.etcd_admin:type_name -> common.PEMEncodedCertificateAndKey
12, // 7: talos.resource.definitions.secrets.EtcdCertsSpec.etcd_api_server:type_name -> common.PEMEncodedCertificateAndKey
12, // 8: talos.resource.definitions.secrets.EtcdRootSpec.etcd_ca:type_name -> common.PEMEncodedCertificateAndKey
14, // 9: talos.resource.definitions.secrets.KubeletSpec.endpoint:type_name -> common.URL
15, // 9: talos.resource.definitions.secrets.KubeletSpec.endpoint:type_name -> common.URL
12, // 10: talos.resource.definitions.secrets.KubeletSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
12, // 11: talos.resource.definitions.secrets.KubernetesDynamicCertsSpec.api_server:type_name -> common.PEMEncodedCertificateAndKey
12, // 12: talos.resource.definitions.secrets.KubernetesDynamicCertsSpec.api_server_kubelet_client:type_name -> common.PEMEncodedCertificateAndKey
12, // 13: talos.resource.definitions.secrets.KubernetesDynamicCertsSpec.front_proxy:type_name -> common.PEMEncodedCertificateAndKey
14, // 14: talos.resource.definitions.secrets.KubernetesRootSpec.endpoint:type_name -> common.URL
14, // 15: talos.resource.definitions.secrets.KubernetesRootSpec.local_endpoint:type_name -> common.URL
15, // 14: talos.resource.definitions.secrets.KubernetesRootSpec.endpoint:type_name -> common.URL
15, // 15: talos.resource.definitions.secrets.KubernetesRootSpec.local_endpoint:type_name -> common.URL
12, // 16: talos.resource.definitions.secrets.KubernetesRootSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
15, // 17: talos.resource.definitions.secrets.KubernetesRootSpec.service_account:type_name -> common.PEMEncodedKey
16, // 17: talos.resource.definitions.secrets.KubernetesRootSpec.service_account:type_name -> common.PEMEncodedKey
12, // 18: talos.resource.definitions.secrets.KubernetesRootSpec.aggregator_ca:type_name -> common.PEMEncodedCertificateAndKey
13, // 19: talos.resource.definitions.secrets.KubernetesRootSpec.api_server_ips:type_name -> common.NetIP
14, // 19: talos.resource.definitions.secrets.KubernetesRootSpec.api_server_ips:type_name -> common.NetIP
12, // 20: talos.resource.definitions.secrets.MaintenanceRootSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
12, // 21: talos.resource.definitions.secrets.MaintenanceServiceCertsSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
12, // 22: talos.resource.definitions.secrets.MaintenanceServiceCertsSpec.server:type_name -> common.PEMEncodedCertificateAndKey
12, // 23: talos.resource.definitions.secrets.OSRootSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
13, // 24: talos.resource.definitions.secrets.OSRootSpec.cert_sani_ps:type_name -> common.NetIP
12, // 25: talos.resource.definitions.secrets.TrustdCertsSpec.ca:type_name -> common.PEMEncodedCertificateAndKey
12, // 23: talos.resource.definitions.secrets.OSRootSpec.issuing_ca:type_name -> common.PEMEncodedCertificateAndKey
14, // 24: talos.resource.definitions.secrets.OSRootSpec.cert_sani_ps:type_name -> common.NetIP
13, // 25: talos.resource.definitions.secrets.OSRootSpec.accepted_c_as:type_name -> common.PEMEncodedCertificate
12, // 26: talos.resource.definitions.secrets.TrustdCertsSpec.server:type_name -> common.PEMEncodedCertificateAndKey
27, // [27:27] is the sub-list for method output_type
27, // [27:27] is the sub-list for method input_type
27, // [27:27] is the sub-list for extension type_name
27, // [27:27] is the sub-list for extension extendee
0, // [0:27] is the sub-list for field type_name
13, // 27: talos.resource.definitions.secrets.TrustdCertsSpec.accepted_c_as:type_name -> common.PEMEncodedCertificate
28, // [28:28] is the sub-list for method output_type
28, // [28:28] is the sub-list for method input_type
28, // [28:28] is the sub-list for extension type_name
28, // [28:28] is the sub-list for extension extendee
0, // [0:28] is the sub-list for field type_name
}
func init() { file_resource_definitions_secrets_secrets_proto_init() }

View File

@ -52,6 +52,30 @@ func (m *APICertsSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.AcceptedCAs) > 0 {
for iNdEx := len(m.AcceptedCAs) - 1; iNdEx >= 0; iNdEx-- {
if vtmsg, ok := interface{}(m.AcceptedCAs[iNdEx]).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
}); ok {
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
} else {
encoded, err := proto.Marshal(m.AcceptedCAs[iNdEx])
if err != nil {
return 0, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
}
i--
dAtA[i] = 0x22
}
}
if m.Server != nil {
if vtmsg, ok := interface{}(m.Server).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
@ -96,28 +120,6 @@ func (m *APICertsSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i--
dAtA[i] = 0x12
}
if m.Ca != nil {
if vtmsg, ok := interface{}(m.Ca).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
}); ok {
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
} else {
encoded, err := proto.Marshal(m.Ca)
if err != nil {
return 0, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
}
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
@ -1001,6 +1003,30 @@ func (m *OSRootSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.AcceptedCAs) > 0 {
for iNdEx := len(m.AcceptedCAs) - 1; iNdEx >= 0; iNdEx-- {
if vtmsg, ok := interface{}(m.AcceptedCAs[iNdEx]).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
}); ok {
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
} else {
encoded, err := proto.Marshal(m.AcceptedCAs[iNdEx])
if err != nil {
return 0, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
}
i--
dAtA[i] = 0x2a
}
}
if len(m.Token) > 0 {
i -= len(m.Token)
copy(dAtA[i:], m.Token)
@ -1041,8 +1067,8 @@ func (m *OSRootSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
dAtA[i] = 0x12
}
}
if m.Ca != nil {
if vtmsg, ok := interface{}(m.Ca).(interface {
if m.IssuingCa != nil {
if vtmsg, ok := interface{}(m.IssuingCa).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
}); ok {
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
@ -1052,7 +1078,7 @@ func (m *OSRootSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= size
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
} else {
encoded, err := proto.Marshal(m.Ca)
encoded, err := proto.Marshal(m.IssuingCa)
if err != nil {
return 0, err
}
@ -1096,6 +1122,30 @@ func (m *TrustdCertsSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.AcceptedCAs) > 0 {
for iNdEx := len(m.AcceptedCAs) - 1; iNdEx >= 0; iNdEx-- {
if vtmsg, ok := interface{}(m.AcceptedCAs[iNdEx]).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
}); ok {
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
} else {
encoded, err := proto.Marshal(m.AcceptedCAs[iNdEx])
if err != nil {
return 0, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
}
i--
dAtA[i] = 0x1a
}
}
if m.Server != nil {
if vtmsg, ok := interface{}(m.Server).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
@ -1118,28 +1168,6 @@ func (m *TrustdCertsSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i--
dAtA[i] = 0x12
}
if m.Ca != nil {
if vtmsg, ok := interface{}(m.Ca).(interface {
MarshalToSizedBufferVT([]byte) (int, error)
}); ok {
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
} else {
encoded, err := proto.Marshal(m.Ca)
if err != nil {
return 0, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
}
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
@ -1149,16 +1177,6 @@ func (m *APICertsSpec) SizeVT() (n int) {
}
var l int
_ = l
if m.Ca != nil {
if size, ok := interface{}(m.Ca).(interface {
SizeVT() int
}); ok {
l = size.SizeVT()
} else {
l = proto.Size(m.Ca)
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
if m.Client != nil {
if size, ok := interface{}(m.Client).(interface {
SizeVT() int
@ -1179,6 +1197,18 @@ func (m *APICertsSpec) SizeVT() (n int) {
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
if len(m.AcceptedCAs) > 0 {
for _, e := range m.AcceptedCAs {
if size, ok := interface{}(e).(interface {
SizeVT() int
}); ok {
l = size.SizeVT()
} else {
l = proto.Size(e)
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
}
n += len(m.unknownFields)
return n
}
@ -1547,13 +1577,13 @@ func (m *OSRootSpec) SizeVT() (n int) {
}
var l int
_ = l
if m.Ca != nil {
if size, ok := interface{}(m.Ca).(interface {
if m.IssuingCa != nil {
if size, ok := interface{}(m.IssuingCa).(interface {
SizeVT() int
}); ok {
l = size.SizeVT()
} else {
l = proto.Size(m.Ca)
l = proto.Size(m.IssuingCa)
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
@ -1579,6 +1609,18 @@ func (m *OSRootSpec) SizeVT() (n int) {
if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
if len(m.AcceptedCAs) > 0 {
for _, e := range m.AcceptedCAs {
if size, ok := interface{}(e).(interface {
SizeVT() int
}); ok {
l = size.SizeVT()
} else {
l = proto.Size(e)
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
}
n += len(m.unknownFields)
return n
}
@ -1589,16 +1631,6 @@ func (m *TrustdCertsSpec) SizeVT() (n int) {
}
var l int
_ = l
if m.Ca != nil {
if size, ok := interface{}(m.Ca).(interface {
SizeVT() int
}); ok {
l = size.SizeVT()
} else {
l = proto.Size(m.Ca)
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
if m.Server != nil {
if size, ok := interface{}(m.Server).(interface {
SizeVT() int
@ -1609,6 +1641,18 @@ func (m *TrustdCertsSpec) SizeVT() (n int) {
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
if len(m.AcceptedCAs) > 0 {
for _, e := range m.AcceptedCAs {
if size, ok := interface{}(e).(interface {
SizeVT() int
}); ok {
l = size.SizeVT()
} else {
l = proto.Size(e)
}
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
}
n += len(m.unknownFields)
return n
}
@ -1642,50 +1686,6 @@ func (m *APICertsSpec) UnmarshalVT(dAtA []byte) error {
return fmt.Errorf("proto: APICertsSpec: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ca", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Ca == nil {
m.Ca = &common.PEMEncodedCertificateAndKey{}
}
if unmarshal, ok := interface{}(m.Ca).(interface {
UnmarshalVT([]byte) error
}); ok {
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
} else {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Ca); err != nil {
return err
}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Client", wireType)
@ -1774,6 +1774,48 @@ func (m *APICertsSpec) UnmarshalVT(dAtA []byte) error {
}
}
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AcceptedCAs", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AcceptedCAs = append(m.AcceptedCAs, &common.PEMEncodedCertificate{})
if unmarshal, ok := interface{}(m.AcceptedCAs[len(m.AcceptedCAs)-1]).(interface {
UnmarshalVT([]byte) error
}); ok {
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
} else {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.AcceptedCAs[len(m.AcceptedCAs)-1]); err != nil {
return err
}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
@ -3642,7 +3684,7 @@ func (m *OSRootSpec) UnmarshalVT(dAtA []byte) error {
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ca", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field IssuingCa", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@ -3669,17 +3711,17 @@ func (m *OSRootSpec) UnmarshalVT(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Ca == nil {
m.Ca = &common.PEMEncodedCertificateAndKey{}
if m.IssuingCa == nil {
m.IssuingCa = &common.PEMEncodedCertificateAndKey{}
}
if unmarshal, ok := interface{}(m.Ca).(interface {
if unmarshal, ok := interface{}(m.IssuingCa).(interface {
UnmarshalVT([]byte) error
}); ok {
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
} else {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Ca); err != nil {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.IssuingCa); err != nil {
return err
}
}
@ -3790,6 +3832,48 @@ func (m *OSRootSpec) UnmarshalVT(dAtA []byte) error {
}
m.Token = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AcceptedCAs", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AcceptedCAs = append(m.AcceptedCAs, &common.PEMEncodedCertificate{})
if unmarshal, ok := interface{}(m.AcceptedCAs[len(m.AcceptedCAs)-1]).(interface {
UnmarshalVT([]byte) error
}); ok {
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
} else {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.AcceptedCAs[len(m.AcceptedCAs)-1]); err != nil {
return err
}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
@ -3841,50 +3925,6 @@ func (m *TrustdCertsSpec) UnmarshalVT(dAtA []byte) error {
return fmt.Errorf("proto: TrustdCertsSpec: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ca", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Ca == nil {
m.Ca = &common.PEMEncodedCertificateAndKey{}
}
if unmarshal, ok := interface{}(m.Ca).(interface {
UnmarshalVT([]byte) error
}); ok {
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
} else {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Ca); err != nil {
return err
}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Server", wireType)
@ -3929,6 +3969,48 @@ func (m *TrustdCertsSpec) UnmarshalVT(dAtA []byte) error {
}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AcceptedCAs", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AcceptedCAs = append(m.AcceptedCAs, &common.PEMEncodedCertificate{})
if unmarshal, ok := interface{}(m.AcceptedCAs[len(m.AcceptedCAs)-1]).(interface {
UnmarshalVT([]byte) error
}); ok {
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
} else {
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.AcceptedCAs[len(m.AcceptedCAs)-1]); err != nil {
return err
}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := protohelpers.Skip(dAtA[iNdEx:])

View File

@ -102,7 +102,8 @@ type Extension interface {
// Security defines the requirements for a config that pertains to security
// related options.
type Security interface {
CA() *x509.PEMEncodedCertificateAndKey
IssuingCA() *x509.PEMEncodedCertificateAndKey
AcceptedCAs() []*x509.PEMEncodedCertificate
Token() string
CertSANs() []string
}

View File

@ -172,7 +172,7 @@ func NewBundleFromConfig(clock Clock, c config.Config) *Bundle {
K8sAggregator: c.Cluster().AggregatorCA(),
K8sServiceAccount: c.Cluster().ServiceAccount(),
Etcd: c.Cluster().Etcd().CA(),
OS: c.Machine().Security().CA(),
OS: c.Machine().Security().IssuingCA(),
}
cluster := &Cluster{

View File

@ -2283,6 +2283,19 @@
"markdownDescription": "The root certificate authority of the PKI.\nIt is composed of a base64 encoded `crt` and `key`.",
"x-intellij-html-description": "\u003cp\u003eThe root certificate authority of the PKI.\nIt is composed of a base64 encoded \u003ccode\u003ecrt\u003c/code\u003e and \u003ccode\u003ekey\u003c/code\u003e.\u003c/p\u003e\n"
},
"acceptedCAs": {
"properties": {
"crt": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"title": "acceptedCAs",
"description": "The certificates issued by certificate authorities are accepted in addition to issuing ca.\nIt is composed of a base64 encoded crt`.\n",
"markdownDescription": "The certificates issued by certificate authorities are accepted in addition to issuing 'ca'.\nIt is composed of a base64 encoded `crt``.",
"x-intellij-html-description": "\u003cp\u003eThe certificates issued by certificate authorities are accepted in addition to issuing \u0026lsquo;ca\u0026rsquo;.\nIt is composed of a base64 encoded \u003ccode\u003ecrt\u003c/code\u003e`.\u003c/p\u003e\n"
},
"certSANs": {
"items": {
"type": "string"

View File

@ -284,11 +284,16 @@ func (m *MachineConfig) Sysfs() map[string]string {
return m.MachineSysfs
}
// CA implements the config.Provider interface.
func (m *MachineConfig) CA() *x509.PEMEncodedCertificateAndKey {
// IssuingCA implements the config.Provider interface.
func (m *MachineConfig) IssuingCA() *x509.PEMEncodedCertificateAndKey {
return m.MachineCA
}
// AcceptedCAs implements the config.Provider interface.
func (m *MachineConfig) AcceptedCAs() []*x509.PEMEncodedCertificate {
return slices.Clone(m.MachineAcceptedCAs)
}
// Token implements the config.Provider interface.
func (m *MachineConfig) Token() string {
return m.MachineToken

View File

@ -40,7 +40,7 @@ func TestRedactSecrets(t *testing.T) {
config.Redact(replacement)
require.Equal(t, replacement, config.Machine().Security().Token())
require.Equal(t, replacement, string(config.Machine().Security().CA().Key))
require.Equal(t, replacement, string(config.Machine().Security().IssuingCA().Key))
require.Equal(t, replacement, config.Cluster().Secret())
require.Equal(t, "***", config.Cluster().Token().Secret())
require.Equal(t, "", config.Cluster().AESCBCEncryptionSecret())

View File

@ -126,6 +126,16 @@ type MachineConfig struct {
// type: string
MachineCA *x509.PEMEncodedCertificateAndKey `yaml:"ca,omitempty"`
// description: |
// The certificates issued by certificate authorities are accepted in addition to issuing 'ca'.
// It is composed of a base64 encoded `crt``.
// schema:
// type: object
// additionalProperties: false
// properties:
// crt:
// type: string
MachineAcceptedCAs []*x509.PEMEncodedCertificate `yaml:"acceptedCAs,omitempty"`
// description: |
// Extra certificate subject alternative names for the machine's certificate.
// By default, all non-loopback interface IPs are automatically added to the certificate's SANs.
// examples:

View File

@ -102,6 +102,13 @@ func (MachineConfig) Doc() *encoder.Doc {
Description: "The root certificate authority of the PKI.\nIt is composed of a base64 encoded `crt` and `key`.",
Comments: [3]string{"" /* encoder.HeadComment */, "The root certificate authority of the PKI." /* encoder.LineComment */, "" /* encoder.FootComment */},
},
{
Name: "acceptedCAs",
Type: "[]PEMEncodedCertificate",
Note: "",
Description: "The certificates issued by certificate authorities are accepted in addition to issuing 'ca'.\nIt is composed of a base64 encoded `crt``.",
Comments: [3]string{"" /* encoder.HeadComment */, "The certificates issued by certificate authorities are accepted in addition to issuing 'ca'." /* encoder.LineComment */, "" /* encoder.FootComment */},
},
{
Name: "certSANs",
Type: "[]string",
@ -263,29 +270,29 @@ func (MachineConfig) Doc() *encoder.Doc {
doc.Fields[1].AddExample("example token", "328hom.uqjzh6jnn2eie9oi")
doc.Fields[2].AddExample("machine CA example", pemEncodedCertificateExample())
doc.Fields[3].AddExample("Uncomment this to enable SANs.", []string{"10.0.0.10", "172.16.0.10", "192.168.0.10"})
doc.Fields[4].AddExample("ControlPlane definition example.", machineControlplaneExample())
doc.Fields[5].AddExample("Kubelet definition example.", machineKubeletExample())
doc.Fields[6].AddExample("nginx static pod.", machinePodsExample())
doc.Fields[7].AddExample("Network definition example.", machineNetworkConfigExample())
doc.Fields[8].AddExample("MachineDisks list example.", machineDisksExample())
doc.Fields[9].AddExample("MachineInstall config usage example.", machineInstallExample())
doc.Fields[10].AddExample("MachineFiles usage example.", machineFilesExample())
doc.Fields[11].AddExample("Environment variables definition examples.", machineEnvExamples0())
doc.Fields[11].AddExample("", machineEnvExamples1())
doc.Fields[11].AddExample("", machineEnvExamples2())
doc.Fields[12].AddExample("Example configuration for cloudflare ntp server.", machineTimeExample())
doc.Fields[13].AddExample("MachineSysctls usage example.", machineSysctlsExample())
doc.Fields[14].AddExample("MachineSysfs usage example.", machineSysfsExample())
doc.Fields[15].AddExample("", machineConfigRegistriesExample())
doc.Fields[16].AddExample("", machineSystemDiskEncryptionExample())
doc.Fields[17].AddExample("", machineFeaturesExample())
doc.Fields[18].AddExample("", machineUdevExample())
doc.Fields[19].AddExample("", machineLoggingExample())
doc.Fields[20].AddExample("", machineKernelExample())
doc.Fields[21].AddExample("", machineSeccompExample())
doc.Fields[22].AddExample("node labels example.", map[string]string{"exampleLabel": "exampleLabelValue"})
doc.Fields[23].AddExample("node taints example.", map[string]string{"exampleTaint": "exampleTaintValue:NoSchedule"})
doc.Fields[4].AddExample("Uncomment this to enable SANs.", []string{"10.0.0.10", "172.16.0.10", "192.168.0.10"})
doc.Fields[5].AddExample("ControlPlane definition example.", machineControlplaneExample())
doc.Fields[6].AddExample("Kubelet definition example.", machineKubeletExample())
doc.Fields[7].AddExample("nginx static pod.", machinePodsExample())
doc.Fields[8].AddExample("Network definition example.", machineNetworkConfigExample())
doc.Fields[9].AddExample("MachineDisks list example.", machineDisksExample())
doc.Fields[10].AddExample("MachineInstall config usage example.", machineInstallExample())
doc.Fields[11].AddExample("MachineFiles usage example.", machineFilesExample())
doc.Fields[12].AddExample("Environment variables definition examples.", machineEnvExamples0())
doc.Fields[12].AddExample("", machineEnvExamples1())
doc.Fields[12].AddExample("", machineEnvExamples2())
doc.Fields[13].AddExample("Example configuration for cloudflare ntp server.", machineTimeExample())
doc.Fields[14].AddExample("MachineSysctls usage example.", machineSysctlsExample())
doc.Fields[15].AddExample("MachineSysfs usage example.", machineSysfsExample())
doc.Fields[16].AddExample("", machineConfigRegistriesExample())
doc.Fields[17].AddExample("", machineSystemDiskEncryptionExample())
doc.Fields[18].AddExample("", machineFeaturesExample())
doc.Fields[19].AddExample("", machineUdevExample())
doc.Fields[20].AddExample("", machineLoggingExample())
doc.Fields[21].AddExample("", machineKernelExample())
doc.Fields[22].AddExample("", machineSeccompExample())
doc.Fields[23].AddExample("node labels example.", map[string]string{"exampleLabel": "exampleLabelValue"})
doc.Fields[24].AddExample("node taints example.", map[string]string{"exampleTaint": "exampleTaintValue:NoSchedule"})
return doc
}

View File

@ -139,6 +139,13 @@ func (c *Config) Validate(mode validation.RuntimeMode, options ...validation.Opt
}
}
if c.Machine().Security().IssuingCA() != nil && len(c.Machine().Security().IssuingCA().Key) > 0 {
result = multierror.Append(result, errors.New("issuing Talos API CA key is not allowed on non-controlplane nodes (.machine.ca)"))
}
if c.Cluster().CA() != nil && len(c.Cluster().CA().Key) > 0 {
result = multierror.Append(result, errors.New("issuing Kubernetes API CA key is not allowed on non-controlplane nodes (.cluster.ca)"))
}
case machine.TypeUnknown:
fallthrough

View File

@ -9,6 +9,10 @@
package v1alpha1
import (
x509 "github.com/siderolabs/crypto/x509"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *APIServerConfig) DeepCopyInto(out *APIServerConfig) {
*out = *in
@ -1509,6 +1513,16 @@ func (in *MachineConfig) DeepCopyInto(out *MachineConfig) {
in, out := &in.MachineCA, &out.MachineCA
*out = (*in).DeepCopy()
}
if in.MachineAcceptedCAs != nil {
in, out := &in.MachineAcceptedCAs, &out.MachineAcceptedCAs
*out = make([]*x509.PEMEncodedCertificate, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = (*in).DeepCopy()
}
}
}
if in.MachineCertSANs != nil {
in, out := &in.MachineCertSANs, &out.MachineCertSANs
*out = make([]string, len(*in))

View File

@ -20,7 +20,7 @@ require (
github.com/opencontainers/runtime-spec v1.2.0
github.com/planetscale/vtprotobuf v0.6.0
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/siderolabs/crypto v0.4.2
github.com/siderolabs/crypto v0.4.4
github.com/siderolabs/gen v0.4.8
github.com/siderolabs/go-api-signature v0.3.2
github.com/siderolabs/go-blockdevice v0.4.7

View File

@ -119,8 +119,8 @@ github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkB
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/siderolabs/crypto v0.4.2 h1:ahAwmm1+0xd3QfGiZ0jYpWxtCVngsy+PK0cgR9frOA8=
github.com/siderolabs/crypto v0.4.2/go.mod h1:rnjC/Z6m/mI2vMv98glgU6oU8lXNi8YceiTxALohfzY=
github.com/siderolabs/crypto v0.4.4 h1:Q6EDBMR2Ub2oAZW5Xl8lrKB27bM3Sn8Gkfw3rngco5U=
github.com/siderolabs/crypto v0.4.4/go.mod h1:hsR3tJ3aaeuhCChsLF4dBd9vlJVPvmhg4vvx2ez4aD4=
github.com/siderolabs/gen v0.4.8 h1:VNpbmDLhkXp7qcSEkKk1Ee7vU2afs3xvHrWLGR2UuiY=
github.com/siderolabs/gen v0.4.8/go.mod h1:7ROKVHHB68R3Amrd4a1ZXz/oMrXWF3Mg3lSEgnkJY5c=
github.com/siderolabs/go-api-signature v0.3.2 h1:blqrZF1GM7TWgq7mY7CsR+yQ93u6az0Kf0mfsw+hvf0=

View File

@ -162,6 +162,27 @@ func registerDefaultTypes() {
},
)
protoenc.RegisterEncoderDecoder(
func(v *x509.PEMEncodedCertificate) ([]byte, error) {
source := common.PEMEncodedCertificate{
Crt: v.Crt,
}
return proto.Marshal(&source)
},
func(slc []byte) (*x509.PEMEncodedCertificate, error) {
var dest common.PEMEncodedCertificate
if err := proto.Unmarshal(slc, &dest); err != nil {
return nil, err
}
return &x509.PEMEncodedCertificate{
Crt: dest.Crt,
}, nil
},
)
protoenc.RegisterEncoderDecoder(
func(v netip.Addr) ([]byte, error) {
ipEncoded, err := v.MarshalBinary()

View File

@ -27,9 +27,9 @@ type API = typed.Resource[APICertsSpec, APIExtension]
//
//gotagsrewrite:gen
type APICertsSpec struct {
CA *x509.PEMEncodedCertificateAndKey `yaml:"ca" protobuf:"1"` // only cert is passed, without key
Client *x509.PEMEncodedCertificateAndKey `yaml:"client" protobuf:"2"`
Server *x509.PEMEncodedCertificateAndKey `yaml:"server" protobuf:"3"`
AcceptedCAs []*x509.PEMEncodedCertificate `yaml:"acceptedCAs" protobuf:"4"`
Client *x509.PEMEncodedCertificateAndKey `yaml:"client" protobuf:"2"`
Server *x509.PEMEncodedCertificateAndKey `yaml:"server" protobuf:"3"`
}
// NewAPI initializes an API resource.

View File

@ -17,8 +17,10 @@ import (
func TestAPIProtobufMarshal(t *testing.T) {
r := secrets.NewAPI()
r.TypedSpec().CA = &x509.PEMEncodedCertificateAndKey{
Crt: []byte("foo"),
r.TypedSpec().AcceptedCAs = []*x509.PEMEncodedCertificate{
{
Crt: []byte("foo"),
},
}
r.TypedSpec().Client = &x509.PEMEncodedCertificateAndKey{
Crt: []byte("bar"),

View File

@ -9,13 +9,21 @@ package secrets
import (
"net/netip"
"net/url"
"github.com/siderolabs/crypto/x509"
)
// DeepCopy generates a deep copy of APICertsSpec.
func (o APICertsSpec) DeepCopy() APICertsSpec {
var cp APICertsSpec = o
if o.CA != nil {
cp.CA = o.CA.DeepCopy()
if o.AcceptedCAs != nil {
cp.AcceptedCAs = make([]*x509.PEMEncodedCertificate, len(o.AcceptedCAs))
copy(cp.AcceptedCAs, o.AcceptedCAs)
for i2 := range o.AcceptedCAs {
if o.AcceptedCAs[i2] != nil {
cp.AcceptedCAs[i2] = o.AcceptedCAs[i2].DeepCopy()
}
}
}
if o.Client != nil {
cp.Client = o.Client.DeepCopy()
@ -168,8 +176,17 @@ func (o MaintenanceRootSpec) DeepCopy() MaintenanceRootSpec {
// DeepCopy generates a deep copy of OSRootSpec.
func (o OSRootSpec) DeepCopy() OSRootSpec {
var cp OSRootSpec = o
if o.CA != nil {
cp.CA = o.CA.DeepCopy()
if o.IssuingCA != nil {
cp.IssuingCA = o.IssuingCA.DeepCopy()
}
if o.AcceptedCAs != nil {
cp.AcceptedCAs = make([]*x509.PEMEncodedCertificate, len(o.AcceptedCAs))
copy(cp.AcceptedCAs, o.AcceptedCAs)
for i2 := range o.AcceptedCAs {
if o.AcceptedCAs[i2] != nil {
cp.AcceptedCAs[i2] = o.AcceptedCAs[i2].DeepCopy()
}
}
}
if o.CertSANIPs != nil {
cp.CertSANIPs = make([]netip.Addr, len(o.CertSANIPs))
@ -185,8 +202,14 @@ func (o OSRootSpec) DeepCopy() OSRootSpec {
// DeepCopy generates a deep copy of TrustdCertsSpec.
func (o TrustdCertsSpec) DeepCopy() TrustdCertsSpec {
var cp TrustdCertsSpec = o
if o.CA != nil {
cp.CA = o.CA.DeepCopy()
if o.AcceptedCAs != nil {
cp.AcceptedCAs = make([]*x509.PEMEncodedCertificate, len(o.AcceptedCAs))
copy(cp.AcceptedCAs, o.AcceptedCAs)
for i2 := range o.AcceptedCAs {
if o.AcceptedCAs[i2] != nil {
cp.AcceptedCAs[i2] = o.AcceptedCAs[i2].DeepCopy()
}
}
}
if o.Server != nil {
cp.Server = o.Server.DeepCopy()

View File

@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package secrets //nolint:dupl
package secrets
import (
"github.com/cosi-project/runtime/pkg/resource"

View File

@ -29,7 +29,8 @@ type OSRoot = typed.Resource[OSRootSpec, OSRootExtension]
//
//gotagsrewrite:gen
type OSRootSpec struct {
CA *x509.PEMEncodedCertificateAndKey `yaml:"ca" protobuf:"1"`
IssuingCA *x509.PEMEncodedCertificateAndKey `yaml:"issuingCA" protobuf:"1"`
AcceptedCAs []*x509.PEMEncodedCertificate `yaml:"acceptedCAs" protobuf:"5"`
CertSANIPs []netip.Addr `yaml:"certSANIPs" protobuf:"2"`
CertSANDNSNames []string `yaml:"certSANDNSNames" protobuf:"3"`

View File

@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package secrets //nolint:dupl
package secrets
import (
"github.com/cosi-project/runtime/pkg/resource"
@ -27,8 +27,8 @@ type Trustd = typed.Resource[TrustdCertsSpec, TrustdExtension]
//
//gotagsrewrite:gen
type TrustdCertsSpec struct {
CA *x509.PEMEncodedCertificateAndKey `yaml:"ca" protobuf:"1"` // only cert is passed, without key
Server *x509.PEMEncodedCertificateAndKey `yaml:"server" protobuf:"2"`
AcceptedCAs []*x509.PEMEncodedCertificate `yaml:"acceptedCAs" protobuf:"3"`
Server *x509.PEMEncodedCertificateAndKey `yaml:"server" protobuf:"2"`
}
// NewTrustd initializes a Trustd resource.

View File

@ -17,8 +17,10 @@ import (
func TestTrustdProtobufMarshal(t *testing.T) {
r := secrets.NewTrustd()
r.TypedSpec().CA = &x509.PEMEncodedCertificateAndKey{
Crt: []byte("foo"),
r.TypedSpec().AcceptedCAs = []*x509.PEMEncodedCertificate{
{
Crt: []byte("foo"),
},
}
r.TypedSpec().Server = &x509.PEMEncodedCertificateAndKey{
Crt: []byte("car"),

View File

@ -0,0 +1,76 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package talos
import (
"context"
"fmt"
"time"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/siderolabs/gen/xslices"
"github.com/siderolabs/go-retry/retry"
"google.golang.org/grpc/codes"
"github.com/siderolabs/talos/pkg/cluster"
machineapi "github.com/siderolabs/talos/pkg/machinery/api/machine"
"github.com/siderolabs/talos/pkg/machinery/client"
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
configres "github.com/siderolabs/talos/pkg/machinery/resources/config"
)
func mapToInternalIP(in []cluster.NodeInfo) []string {
return xslices.Map(in, func(i cluster.NodeInfo) string {
return i.InternalIP.String()
})
}
func patchNodeConfig(ctx context.Context, c *client.Client, node string, encoderOpt encoder.Option, patchFunc func(config *v1alpha1.Config) error) error {
return retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond), retry.WithErrorLogging(true)).RetryWithContext(
ctx,
func(ctx context.Context) error {
err := patchNodeConfigInternal(ctx, c, node, encoderOpt, patchFunc)
if err != nil {
if client.StatusCode(err) == codes.Unavailable || client.StatusCode(err) == codes.Canceled {
return retry.ExpectedError(err)
}
}
return err
},
)
}
func patchNodeConfigInternal(ctx context.Context, c *client.Client, node string, encoderOpt encoder.Option, patchFunc func(config *v1alpha1.Config) error) error {
ctx = client.WithNode(ctx, node)
mc, err := safe.StateGetByID[*configres.MachineConfig](ctx, c.COSI, configres.V1Alpha1ID)
if err != nil {
return fmt.Errorf("error fetching config resource: %w", err)
}
provider := mc.Provider()
newProvider, err := provider.PatchV1Alpha1(patchFunc)
if err != nil {
return fmt.Errorf("error patching config: %w", err)
}
cfgBytes, err := newProvider.EncodeBytes(encoderOpt)
if err != nil {
return fmt.Errorf("error serializing config: %w", err)
}
_, err = c.ApplyConfiguration(ctx, &machineapi.ApplyConfigurationRequest{
Data: cfgBytes,
Mode: machineapi.ApplyConfigurationRequest_NO_REBOOT,
})
if err != nil {
return fmt.Errorf("error applying config: %w", err)
}
return nil
}

View File

@ -0,0 +1,383 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package talos implements safe Talos API PKI rotation for the cluster.
package talos
import (
"bufio"
"bytes"
"context"
"fmt"
"slices"
"time"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/go-retry/retry"
"google.golang.org/grpc/codes"
"gopkg.in/yaml.v3"
"github.com/siderolabs/talos/pkg/cluster"
machineapi "github.com/siderolabs/talos/pkg/machinery/api/machine"
"github.com/siderolabs/talos/pkg/machinery/client"
clientconfig "github.com/siderolabs/talos/pkg/machinery/client/config"
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/siderolabs/talos/pkg/machinery/config/generate/secrets"
"github.com/siderolabs/talos/pkg/machinery/config/machine"
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
secretsres "github.com/siderolabs/talos/pkg/machinery/resources/secrets"
"github.com/siderolabs/talos/pkg/machinery/role"
)
// Options is the input to the Talos API rotation process.
type Options struct {
// DryRun is the flag to enable dry-run mode.
//
// In dry-run mode, the rotation process will not make any changes to the cluster.
DryRun bool
// CurrentClient is a Talos client for the existing PKI.
CurrentClient *client.Client
// ClusterInfo provides information about cluster topology.
ClusterInfo cluster.Info
// ContextName is the context name for the 'talosconfig'.
ContextName string
// Endpoints is the list of endpoints for the 'talosconfig'.
Endpoints []string
// NewTalosCA is the new CA for Talos API.
NewTalosCA *x509.PEMEncodedCertificateAndKey
// EncoderOption is the option for encoding machine configuration (while patching).
EncoderOption encoder.Option
// Printf is the function used to print messages.
Printf func(format string, args ...any)
}
type rotator struct {
opts Options
currentCA []byte
intermediateTalosconfig *clientconfig.Config
newTalosconfig *clientconfig.Config
intermediateClient *client.Client
newClient *client.Client
}
// Rotate rotates the Talos API PKI.
//
// The process overview:
// - fetch current information
// - verify connectivity with the existing PKI
// - add new Talos CA as accepted
// - verify connectivity with the intermediate PKI
// - make new CA issuing, old CA is still accepted
// - verify connectivity with the new PKI
// - remove old Talos CA
// - verify connectivity with the new PKI.
func Rotate(ctx context.Context, opts Options) (*clientconfig.Config, error) {
r := rotator{
opts: opts,
}
defer func() {
if r.intermediateClient != nil {
r.intermediateClient.Close() //nolint:errcheck
}
if r.newClient != nil {
r.newClient.Close() //nolint:errcheck
}
}()
err := r.rotate(ctx)
return r.newTalosconfig, err
}
//nolint:gocyclo
func (r *rotator) rotate(ctx context.Context) error {
r.printIntro()
if err := r.fetchCurrentCA(ctx); err != nil {
return err
}
if err := r.printNewCA(); err != nil {
return err
}
if err := r.generateClients(ctx); err != nil {
return err
}
if err := r.verifyConnectivity(ctx, r.opts.CurrentClient, "existing PKI"); err != nil {
return err
}
if err := r.addNewCAAccepted(ctx); err != nil {
return err
}
if err := r.verifyConnectivity(ctx, r.intermediateClient, "new client cert, but old server CA"); err != nil {
return err
}
if err := r.swapCAs(ctx); err != nil {
return err
}
if err := r.verifyConnectivity(ctx, r.newClient, "new PKI"); err != nil {
return err
}
if err := r.dropOldCA(ctx); err != nil {
return err
}
if err := r.verifyConnectivity(ctx, r.newClient, "new PKI"); err != nil {
return err
}
return nil
}
func (r *rotator) printIntro() {
r.opts.Printf("> Starting Talos API PKI rotation, dry-run mode %v...\n", r.opts.DryRun)
r.opts.Printf("> Using config context: %q\n", r.opts.ContextName)
r.opts.Printf("> Using Talos API endpoints: %q\n", r.opts.Endpoints)
r.opts.Printf("> Cluster topology:\n")
r.opts.Printf(" - control plane nodes: %q\n",
append(
mapToInternalIP(r.opts.ClusterInfo.NodesByType(machine.TypeInit)),
mapToInternalIP(r.opts.ClusterInfo.NodesByType(machine.TypeControlPlane))...,
),
)
r.opts.Printf(" - worker nodes: %q\n",
mapToInternalIP(r.opts.ClusterInfo.NodesByType(machine.TypeWorker)),
)
}
func (r *rotator) fetchCurrentCA(ctx context.Context) error {
r.opts.Printf("> Current Talos CA:\n")
firstNode := append(
r.opts.ClusterInfo.NodesByType(machine.TypeInit),
r.opts.ClusterInfo.NodesByType(machine.TypeControlPlane)...,
)[0]
osRoot, err := safe.StateGetByID[*secretsres.OSRoot](client.WithNode(ctx, firstNode.InternalIP.String()), r.opts.CurrentClient.COSI, secretsres.OSRootID)
if err != nil {
return fmt.Errorf("error fetching existing Talos CA: %w", err)
}
r.currentCA = osRoot.TypedSpec().IssuingCA.Crt
var b bytes.Buffer
if err = yaml.NewEncoder(&b).Encode(osRoot.TypedSpec().IssuingCA); err != nil {
return fmt.Errorf("error encoding new Talos CA: %w", err)
}
for scanner := bufio.NewScanner(&b); scanner.Scan(); {
r.opts.Printf(" %s\n", scanner.Text())
}
return nil
}
func (r *rotator) printNewCA() error {
r.opts.Printf("> New Talos CA:\n")
var b bytes.Buffer
if err := yaml.NewEncoder(&b).Encode(r.opts.NewTalosCA); err != nil {
return fmt.Errorf("error encoding new Talos CA: %w", err)
}
for scanner := bufio.NewScanner(&b); scanner.Scan(); {
r.opts.Printf(" %s\n", scanner.Text())
}
return nil
}
func (r *rotator) generateClients(ctx context.Context) error {
r.opts.Printf("> Generating new talosconfig:\n")
newBundle := &secrets.Bundle{
Clock: secrets.NewFixedClock(time.Now()),
Certs: &secrets.Certs{
OS: r.opts.NewTalosCA,
},
}
cert, err := newBundle.GenerateTalosAPIClientCertificate(role.MakeSet(role.Admin))
if err != nil {
return fmt.Errorf("error generating new talosconfig: %w", err)
}
// using old server CA, but new client cert
r.intermediateTalosconfig = clientconfig.NewConfig(r.opts.ContextName, r.opts.Endpoints, r.currentCA, cert)
// using new server CA and a new client cert
r.newTalosconfig = clientconfig.NewConfig(r.opts.ContextName, r.opts.Endpoints, r.opts.NewTalosCA.Crt, cert)
marshalledTalosconfig, err := r.newTalosconfig.Bytes()
if err != nil {
return fmt.Errorf("error marshaling talosconfig: %w", err)
}
r.opts.Printf("%s\n", string(marshalledTalosconfig))
r.intermediateClient, err = client.New(ctx,
client.WithConfig(r.intermediateTalosconfig),
)
if err != nil {
return fmt.Errorf("error creating intermediate client: %w", err)
}
r.newClient, err = client.New(ctx,
client.WithConfig(r.newTalosconfig),
)
if err != nil {
return fmt.Errorf("error creating new client: %w", err)
}
return nil
}
func (r *rotator) verifyConnectivity(ctx context.Context, c *client.Client, label string) error {
r.opts.Printf("> Verifying connectivity with %s:\n", label)
for _, node := range r.opts.ClusterInfo.Nodes() {
if r.opts.DryRun {
r.opts.Printf(" - %s: OK (dry-run)\n", node.InternalIP)
continue
}
var resp *machineapi.VersionResponse
if err := retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond), retry.WithErrorLogging(true)).RetryWithContext(ctx, func(ctx context.Context) error {
nodeCtx := client.WithNode(ctx, node.InternalIP.String())
var respErr error
resp, respErr = c.Version(nodeCtx)
if respErr != nil {
if client.StatusCode(respErr) == codes.Unavailable {
return retry.ExpectedError(respErr)
}
return respErr
}
return nil
}); err != nil {
return fmt.Errorf("error calling version API on node %s: %w", node.InternalIP, err)
}
r.opts.Printf(" - %s: OK (version %s)\n", node.InternalIP, resp.Messages[0].Version.GetTag())
}
return nil
}
func (r *rotator) addNewCAAccepted(ctx context.Context) error {
r.opts.Printf("> Adding new Talos CA as accepted...\n")
if err := r.patchAllNodes(ctx, r.opts.CurrentClient,
func(_ machine.Type, config *v1alpha1.Config) error {
config.MachineConfig.MachineAcceptedCAs = append(
config.MachineConfig.MachineAcceptedCAs,
&x509.PEMEncodedCertificate{
Crt: r.opts.NewTalosCA.Crt,
},
)
return nil
}); err != nil {
return fmt.Errorf("error patching all machine configs: %w", err)
}
return nil
}
func (r *rotator) swapCAs(ctx context.Context) error {
r.opts.Printf("> Making new Talos CA the issuing CA, old Talos CA the accepted CA...\n")
if err := r.patchAllNodes(ctx, r.intermediateClient,
func(machineType machine.Type, config *v1alpha1.Config) error {
config.MachineConfig.MachineAcceptedCAs = append(
config.MachineConfig.MachineAcceptedCAs,
&x509.PEMEncodedCertificate{
Crt: r.currentCA,
},
)
config.MachineConfig.MachineAcceptedCAs = slices.DeleteFunc(config.Machine().Security().AcceptedCAs(), func(ca *x509.PEMEncodedCertificate) bool {
return bytes.Equal(ca.Crt, r.opts.NewTalosCA.Crt)
})
if machineType.IsControlPlane() {
config.MachineConfig.MachineCA = r.opts.NewTalosCA
} else {
config.MachineConfig.MachineCA = &x509.PEMEncodedCertificateAndKey{
Crt: r.opts.NewTalosCA.Crt,
}
}
return nil
}); err != nil {
return fmt.Errorf("error patching all machine configs: %w", err)
}
return nil
}
func (r *rotator) dropOldCA(ctx context.Context) error {
r.opts.Printf("> Removing old Talos CA from the accepted CAs...\n")
if err := r.patchAllNodes(ctx, r.newClient,
func(_ machine.Type, config *v1alpha1.Config) error {
config.MachineConfig.MachineAcceptedCAs = slices.DeleteFunc(config.Machine().Security().AcceptedCAs(), func(ca *x509.PEMEncodedCertificate) bool {
return bytes.Equal(ca.Crt, r.currentCA)
})
return nil
}); err != nil {
return fmt.Errorf("error patching all machine configs: %w", err)
}
return nil
}
func (r *rotator) patchAllNodes(ctx context.Context, c *client.Client, patchFunc func(machineType machine.Type, config *v1alpha1.Config) error) error {
for _, machineType := range []machine.Type{machine.TypeInit, machine.TypeControlPlane, machine.TypeWorker} {
for _, node := range r.opts.ClusterInfo.NodesByType(machineType) {
if r.opts.DryRun {
r.opts.Printf(" - %s: skipped (dry-run)\n", node.InternalIP)
continue
}
if err := patchNodeConfig(ctx, c, node.InternalIP.String(), r.opts.EncoderOption, func(config *v1alpha1.Config) error {
return patchFunc(machineType, config)
}); err != nil {
return fmt.Errorf("error patching node %s: %w", node.InternalIP, err)
}
r.opts.Printf(" - %s: OK\n", node.InternalIP)
}
}
return nil
}

View File

@ -15,6 +15,7 @@ description: Talos gRPC API reference.
- [NetIP](#common.NetIP)
- [NetIPPort](#common.NetIPPort)
- [NetIPPrefix](#common.NetIPPrefix)
- [PEMEncodedCertificate](#common.PEMEncodedCertificate)
- [PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey)
- [PEMEncodedKey](#common.PEMEncodedKey)
- [URL](#common.URL)
@ -628,6 +629,21 @@ Common metadata message nested in all reply message types
<a name="common.PEMEncodedCertificate"></a>
### PEMEncodedCertificate
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| crt | [bytes](#bytes) | | |
<a name="common.PEMEncodedCertificateAndKey"></a>
### PEMEncodedCertificateAndKey
@ -4211,9 +4227,9 @@ APICertsSpec describes etcd certs secrets.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| ca | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| client | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| server | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| accepted_c_as | [common.PEMEncodedCertificate](#common.PEMEncodedCertificate) | repeated | |
@ -4389,10 +4405,11 @@ OSRootSpec describes operating system CA.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| ca | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| issuing_ca | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| cert_sani_ps | [common.NetIP](#common.NetIP) | repeated | |
| cert_sandns_names | [string](#string) | repeated | |
| token | [string](#string) | | |
| accepted_c_as | [common.PEMEncodedCertificate](#common.PEMEncodedCertificate) | repeated | |
@ -4407,8 +4424,8 @@ TrustdCertsSpec describes etcd certs secrets.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| ca | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| server | [common.PEMEncodedCertificateAndKey](#common.PEMEncodedCertificateAndKey) | | |
| accepted_c_as | [common.PEMEncodedCertificate](#common.PEMEncodedCertificate) | repeated | |

View File

@ -2659,6 +2659,46 @@ talosctl rollback [flags]
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
## talosctl rotate-ca
Rotate cluster CAs (Talos and Kubernetes APIs).
### Synopsis
The command starts by generating new CAs, and gracefully applying it to the cluster.
```
talosctl rotate-ca [flags]
```
### Options
```
--control-plane-nodes strings specify IPs of control plane nodes
--dry-run dry-run mode (no changes to the cluster) (default true)
-h, --help help for rotate-ca
--init-node string specify IPs of init node
--k8s-endpoint string use endpoint instead of kubeconfig default
-o, --output talosconfig path to the output new talosconfig (default "talosconfig")
--with-docs patch all machine configs adding the documentation for each field (default true)
--with-examples patch all machine configs with the commented examples (default true)
--worker-nodes strings specify IPs of worker nodes
```
### Options inherited from parent commands
```
--cluster string Cluster to connect to if a proxy endpoint is used.
--context string Context to be used in command
-e, --endpoints strings override default endpoints in Talos configuration
-n, --nodes strings target the specified nodes
--talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order.
```
### SEE ALSO
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
## talosctl service
Retrieve the state of a service (or all services), control service state
@ -3065,6 +3105,7 @@ A CLI for out-of-band management of Kubernetes nodes created by Talos
* [talosctl reset](#talosctl-reset) - Reset a node
* [talosctl restart](#talosctl-restart) - Restart a process
* [talosctl rollback](#talosctl-rollback) - Rollback a node to the previous installation
* [talosctl rotate-ca](#talosctl-rotate-ca) - Rotate cluster CAs (Talos and Kubernetes APIs).
* [talosctl service](#talosctl-service) - Retrieve the state of a service (or all services), control service state
* [talosctl shutdown](#talosctl-shutdown) - Shutdown a node
* [talosctl stats](#talosctl-stats) - Get container stats

View File

@ -72,6 +72,7 @@ ca:
crt: LS0tIEVYQU1QTEUgQ0VSVElGSUNBVEUgLS0t
key: LS0tIEVYQU1QTEUgS0VZIC0tLQ==
{{< /highlight >}}</details> | |
|`acceptedCAs` |[]PEMEncodedCertificate |<details><summary>The certificates issued by certificate authorities are accepted in addition to issuing 'ca'.</summary>It is composed of a base64 encoded `crt``.</details> | |
|`certSANs` |[]string |<details><summary>Extra certificate subject alternative names for the machine's certificate.</summary>By default, all non-loopback interface IPs are automatically added to the certificate's SANs.</details> <details><summary>Show example(s)</summary>{{< highlight yaml >}}
certSANs:
- 10.0.0.10

View File

@ -2283,6 +2283,19 @@
"markdownDescription": "The root certificate authority of the PKI.\nIt is composed of a base64 encoded `crt` and `key`.",
"x-intellij-html-description": "\u003cp\u003eThe root certificate authority of the PKI.\nIt is composed of a base64 encoded \u003ccode\u003ecrt\u003c/code\u003e and \u003ccode\u003ekey\u003c/code\u003e.\u003c/p\u003e\n"
},
"acceptedCAs": {
"properties": {
"crt": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"title": "acceptedCAs",
"description": "The certificates issued by certificate authorities are accepted in addition to issuing ca.\nIt is composed of a base64 encoded crt`.\n",
"markdownDescription": "The certificates issued by certificate authorities are accepted in addition to issuing 'ca'.\nIt is composed of a base64 encoded `crt``.",
"x-intellij-html-description": "\u003cp\u003eThe certificates issued by certificate authorities are accepted in addition to issuing \u0026lsquo;ca\u0026rsquo;.\nIt is composed of a base64 encoded \u003ccode\u003ecrt\u003c/code\u003e`.\u003c/p\u003e\n"
},
"certSANs": {
"items": {
"type": "string"

View File

@ -34,6 +34,8 @@ The list of config changes allowed to be applied immediately in Talos {{< releas
* `.debug`
* `.cluster`
* `.machine.time`
* `.machine.ca`
* `.machine.acceptedCAs`
* `.machine.certCANs`
* `.machine.install` (configuration is only applied during install/upgrade)
* `.machine.network`