feat: enable talos client to connect to Talos through an auth proxy

Talos client can connect to Talos API via a proxy with basic auth.
Additionally it is now optional to specify a TLS CA,key or crt. Optionally
Developers can build talosctl with WITH_DEBUG=1 to allow insecure
connections when http:// endpoints are specified.

Fixes #5980

Signed-off-by: Philipp Sauter <philipp.sauter@siderolabs.com>
This commit is contained in:
Philipp Sauter 2022-08-11 15:25:57 +02:00
parent 123d32174e
commit f37da96ef3
No known key found for this signature in database
GPG Key ID: D3F8AF32D62A348D
14 changed files with 641 additions and 112 deletions

View File

@ -46,6 +46,7 @@ func Execute() error {
rootCmd.PersistentFlags().StringSliceVarP(&talos.Endpoints, "endpoints", "e", []string{}, "override default endpoints in Talos configuration")
cli.Should(rootCmd.RegisterFlagCompletionFunc("context", talos.CompleteConfigContext))
cli.Should(rootCmd.RegisterFlagCompletionFunc("nodes", talos.CompleteNodes))
rootCmd.PersistentFlags().StringVar(&talos.Cluster, "cluster", "", "Cluster to connect to if a proxy endpoint is used.")
cmd, err := rootCmd.ExecuteC()
if err != nil {

View File

@ -37,13 +37,14 @@ var (
Endpoints []string
Nodes []string
Cmdcontext string
Cluster string
)
const pathAutoCompleteLimit = 500
// WithClientNoNodes wraps common code to initialize Talos client and provide cancellable context.
//
// WithClientNoNodes doesn't set any node information on request context.
// WithClientNoNodes doesn't set any node information on the request context.
func WithClientNoNodes(action func(context.Context, *client.Client) error) error {
return cli.WithContext(
context.Background(), func(ctx context.Context) error {
@ -65,6 +66,10 @@ func WithClientNoNodes(action func(context.Context, *client.Client) error) error
opts = append(opts, client.WithEndpoints(Endpoints...))
}
if Cluster != "" {
opts = append(opts, client.WithCluster(Cluster))
}
c, err := client.New(ctx, opts...)
if err != nil {
return fmt.Errorf("error constructing client: %w", err)
@ -77,6 +82,8 @@ func WithClientNoNodes(action func(context.Context, *client.Client) error) error
)
}
var errConfigContext = fmt.Errorf("failed to resolve config context")
// WithClient builds upon WithClientNoNodes to provide set of nodes on request context based on config & flags.
func WithClient(action func(context.Context, *client.Client) error) error {
return WithClientNoNodes(
@ -84,7 +91,7 @@ func WithClient(action func(context.Context, *client.Client) error) error {
if len(Nodes) < 1 {
configContext := c.GetConfigContext()
if configContext == nil {
return fmt.Errorf("failed to resolve config context")
return errConfigContext
}
Nodes = configContext.Nodes

View File

@ -0,0 +1,33 @@
// 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 client
import (
"context"
"encoding/base64"
"google.golang.org/grpc"
)
// BasicAuth implements the credentials.PerRPCCredentials interface and holds credentials for Basic Auth.
type BasicAuth struct {
auth string
}
// GetRequestMetadata implements credentials.PerGRPCCredentials.
func (c BasicAuth) GetRequestMetadata(ctx context.Context, url ...string) (map[string]string, error) {
enc := base64.StdEncoding.EncodeToString([]byte(c.auth))
return map[string]string{
"Authorization": "Basic " + enc,
}, nil
}
// WithGRPCBasicAuth returns gRPC credentials for basic auth.
func WithGRPCBasicAuth(username, password string) grpc.DialOption {
return grpc.WithPerRPCCredentials(BasicAuth{
auth: username + ":" + password,
})
}

View File

@ -10,21 +10,16 @@ import (
"bytes"
"compress/gzip"
"context"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
"io"
"strings"
"time"
cosiv1alpha1 "github.com/cosi-project/runtime/api/v1alpha1"
"github.com/cosi-project/runtime/pkg/state"
"github.com/cosi-project/runtime/pkg/state/protobuf/client"
grpctls "github.com/talos-systems/crypto/tls"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/emptypb"
@ -37,22 +32,13 @@ import (
storageapi "github.com/talos-systems/talos/pkg/machinery/api/storage"
timeapi "github.com/talos-systems/talos/pkg/machinery/api/time"
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
"github.com/talos-systems/talos/pkg/machinery/client/resolver"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// Credentials represents the set of values required to initialize a valid
// Client.
type Credentials struct {
CA []byte
Crt tls.Certificate
}
// Client implements the proto.MachineServiceClient interface. It serves as the
// concrete type with the required methods.
type Client struct {
options *Options
conn *grpc.ClientConn
conn *grpcConnectionWrapper
MachineClient machineapi.MachineServiceClient
TimeClient timeapi.TimeServiceClient
@ -138,6 +124,24 @@ func (c *Client) GetEndpoints() []string {
return nil
}
// GetClusterName returns the client's cluster name from the override set with WithClustername
// or from the configuration.
func (c *Client) GetClusterName() string {
if c.options.clusterNameOverride != "" {
return c.options.clusterNameOverride
}
if c.options.config != nil {
if err := c.resolveConfigContext(); err != nil {
return ""
}
return c.options.configContext.Cluster
}
return ""
}
// New returns a new Client.
func New(ctx context.Context, opts ...OptionFunc) (c *Client, err error) {
c = new(Client)
@ -173,93 +177,6 @@ func New(ctx context.Context, opts ...OptionFunc) (c *Client, err error) {
return c, nil
}
// getConn creates new gRPC connection.
func (c *Client) getConn(ctx context.Context, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
endpoints := resolver.EnsureEndpointsHavePorts(c.GetEndpoints(), constants.ApidPort)
var target string
switch {
case c.options.unixSocketPath != "":
target = fmt.Sprintf("unix:///%s", c.options.unixSocketPath)
case len(endpoints) > 1:
target = fmt.Sprintf("%s:///%s", resolver.RoundRobinResolverScheme, strings.Join(endpoints, ","))
default:
// NB: we use the `dns` scheme here in order to handle fancier situations
// when there is a single endpoint.
// Such possibilities include SRV records, multiple IPs from A and/or AAAA
// records, and descriptive TXT records which include things like load
// balancer specs.
target = fmt.Sprintf("dns:///%s", endpoints[0])
}
dialOpts := []grpc.DialOption(nil)
if c.options.unixSocketPath == "" {
// Add TLS credentials to gRPC DialOptions
tlsConfig := c.options.tlsConfig
if tlsConfig == nil {
if err := c.resolveConfigContext(); err != nil {
return nil, fmt.Errorf("failed to resolve configuration context: %w", err)
}
creds, err := CredentialsFromConfigContext(c.options.configContext)
if err != nil {
return nil, fmt.Errorf("failed to acquire credentials: %w", err)
}
tlsConfig, err = grpctls.New(
grpctls.WithKeypair(creds.Crt),
grpctls.WithClientAuthType(grpctls.Mutual),
grpctls.WithCACertPEM(creds.CA),
)
if err != nil {
return nil, fmt.Errorf("failed to construct TLS credentials: %w", err)
}
}
dialOpts = append(dialOpts,
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
grpc.WithInitialWindowSize(65535*32),
grpc.WithInitialConnWindowSize(65535*16),
)
}
dialOpts = append(dialOpts, c.options.grpcDialOptions...)
dialOpts = append(dialOpts, opts...)
return grpc.DialContext(ctx, target, dialOpts...)
}
// CredentialsFromConfigContext constructs the client Credentials from the given configuration Context.
func CredentialsFromConfigContext(context *clientconfig.Context) (*Credentials, error) {
caBytes, err := base64.StdEncoding.DecodeString(context.CA)
if err != nil {
return nil, fmt.Errorf("error decoding CA: %w", err)
}
crtBytes, err := base64.StdEncoding.DecodeString(context.Crt)
if err != nil {
return nil, fmt.Errorf("error decoding certificate: %w", err)
}
keyBytes, err := base64.StdEncoding.DecodeString(context.Key)
if err != nil {
return nil, fmt.Errorf("error decoding key: %w", err)
}
crt, err := tls.X509KeyPair(crtBytes, keyBytes)
if err != nil {
return nil, fmt.Errorf("could not load client key pair: %s", err)
}
return &Credentials{
CA: caBytes,
Crt: crt,
}, nil
}
// Close shuts down client protocol.
func (c *Client) Close() error {
return c.conn.Close()

View File

@ -51,9 +51,22 @@ type Context struct {
DeprecatedTarget string `yaml:"target,omitempty"` // Field deprecated in favor of Endpoints
Endpoints []string `yaml:"endpoints"`
Nodes []string `yaml:"nodes,omitempty"`
CA string `yaml:"ca"`
Crt string `yaml:"crt"`
Key string `yaml:"key"`
CA string `yaml:"ca,omitempty"`
Crt string `yaml:"crt,omitempty"`
Key string `yaml:"key,omitempty"`
Auth Auth `yaml:"auth,omitempty"`
Cluster string `yaml:"cluster,omitempty"`
}
// Auth may hold credentials for an authentication method such as Basic Auth.
type Auth struct {
Basic *Basic `yaml:"basic,omitempty"`
}
// Basic holds Basic Auth credentials.
type Basic struct {
Username string `yaml:"username"`
Password string `yaml:"password"`
}
func (c *Context) upgrade() {

View File

@ -0,0 +1,187 @@
// 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 client
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"net"
"net/url"
"strings"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
"github.com/talos-systems/talos/pkg/machinery/client/resolver"
"github.com/talos-systems/talos/pkg/machinery/constants"
"github.com/talos-systems/talos/pkg/machinery/generic/slices"
)
// getConn creates new gRPC connection.
func (c *Client) getConn(ctx context.Context, opts ...grpc.DialOption) (*grpcConnectionWrapper, error) {
endpoints := c.GetEndpoints()
target := c.getTarget(
resolver.EnsureEndpointsHavePorts(
reduceURLsToAddresses(endpoints),
constants.ApidPort),
)
dialOpts := []grpc.DialOption(nil)
dialOpts = append(dialOpts, c.options.grpcDialOptions...)
dialOpts = append(dialOpts, opts...)
if c.options.unixSocketPath != "" {
conn, err := grpc.DialContext(ctx, target, dialOpts...)
return newGRPCConnectionWrapper(c.GetClusterName(), conn), err
}
tlsConfig := c.options.tlsConfig
if tlsConfig != nil {
return c.makeConnection(ctx, target, credentials.NewTLS(tlsConfig), dialOpts)
}
if err := c.resolveConfigContext(); err != nil {
return nil, fmt.Errorf("failed to resolve configuration context: %w", err)
}
basicAuth := c.options.configContext.Auth.Basic
if basicAuth != nil {
dialOpts = append(dialOpts, WithGRPCBasicAuth(basicAuth.Username, basicAuth.Password))
}
creds, err := buildCredentials(c.options.configContext, endpoints)
if err != nil {
return nil, err
}
return c.makeConnection(ctx, target, creds, dialOpts)
}
func buildTLSConfig(configContext *clientconfig.Context) (*tls.Config, error) {
tlsConfig := &tls.Config{}
caBytes, err := getCA(configContext)
if err != nil {
return nil, fmt.Errorf("failed to get CA: %w", err)
}
if len(caBytes) > 0 {
tlsConfig.RootCAs = x509.NewCertPool()
if ok := tlsConfig.RootCAs.AppendCertsFromPEM(caBytes); !ok {
return nil, fmt.Errorf("failed to append CA certificate to RootCAs pool")
}
}
crt, err := CertificateFromConfigContext(configContext)
if err != nil {
return nil, fmt.Errorf("failed to acquire credentials: %w", err)
}
if crt != nil {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
tlsConfig.Certificates = append(tlsConfig.Certificates, *crt)
}
return tlsConfig, nil
}
func (c *Client) makeConnection(ctx context.Context, target string, creds credentials.TransportCredentials, dialOpts []grpc.DialOption) (*grpcConnectionWrapper, error) {
dialOpts = append(dialOpts,
grpc.WithTransportCredentials(creds),
grpc.WithInitialWindowSize(65535*32),
grpc.WithInitialConnWindowSize(65535*16))
conn, err := grpc.DialContext(ctx, target, dialOpts...)
return newGRPCConnectionWrapper(c.GetClusterName(), conn), err
}
func (c *Client) getTarget(endpoints []string) string {
switch {
case c.options.unixSocketPath != "":
return fmt.Sprintf("unix:///%s", c.options.unixSocketPath)
case len(endpoints) > 1:
return fmt.Sprintf("%s:///%s", resolver.RoundRobinResolverScheme, strings.Join(endpoints, ","))
default:
// NB: we use the `dns` scheme here in order to handle fancier situations
// when there is a single endpoint.
// Such possibilities include SRV records, multiple IPs from A and/or AAAA
// records, and descriptive TXT records which include things like load
// balancer specs.
return fmt.Sprintf("dns:///%s", endpoints[0])
}
}
func getCA(context *clientconfig.Context) ([]byte, error) {
if context.CA == "" {
return nil, nil
}
caBytes, err := base64.StdEncoding.DecodeString(context.CA)
if err != nil {
return nil, fmt.Errorf("error decoding CA: %w", err)
}
return caBytes, err
}
// CertificateFromConfigContext constructs the client Credentials from the given configuration Context.
func CertificateFromConfigContext(context *clientconfig.Context) (*tls.Certificate, error) {
if context.Crt == "" && context.Key == "" {
return nil, nil
}
crtBytes, err := base64.StdEncoding.DecodeString(context.Crt)
if err != nil {
return nil, fmt.Errorf("error decoding certificate: %w", err)
}
keyBytes, err := base64.StdEncoding.DecodeString(context.Key)
if err != nil {
return nil, fmt.Errorf("error decoding key: %w", err)
}
crt, err := tls.X509KeyPair(crtBytes, keyBytes)
if err != nil {
return nil, fmt.Errorf("could not load client key pair: %s", err)
}
return &crt, nil
}
func reduceURLsToAddresses(endpoints []string) []string {
return slices.Map(endpoints, func(endpoint string) string {
u, err := url.Parse(endpoint)
if err != nil {
return endpoint
}
if u.Scheme == "https" && u.Port() == "" {
return net.JoinHostPort(u.Hostname(), "443")
}
if u.Scheme != "" {
if u.Port() != "" {
return net.JoinHostPort(u.Hostname(), u.Port())
}
if u.Opaque == "" {
return u.Host
}
}
return endpoint
})
}

View File

@ -0,0 +1,151 @@
// 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 client_test
import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"testing"
"github.com/stretchr/testify/assert"
"github.com/talos-systems/talos/pkg/machinery/client"
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
)
func TestReduceURLsToAddresses(t *testing.T) {
endpoints := []string{
"123.123.123.123",
"exammple.com:111",
"234.234.234.234:4000",
"https://111.111.222.222:444",
"localhost",
"localhost:890",
"https://[42a1:cfa:5458:3967:e2ce:afaa:6194:12f]:40000",
"https://localhost:890",
"2001:db8:0:0:0:ff00:42:8329",
"https://[be4d:c25e:aca0:9366:68b7:c84:a23b:f7be]",
"https://www.somecompany.com",
"www.company.com",
"[2001:db8:4006:812::200e]:8080",
"grpc://222.22.2.1",
"grpc://[794b:389:73cb:76a2:59de:62fd:ee38:7c]:111",
}
expected := []string{
"123.123.123.123",
"exammple.com:111",
"234.234.234.234:4000",
"111.111.222.222:444",
"localhost",
"localhost:890",
"[42a1:cfa:5458:3967:e2ce:afaa:6194:12f]:40000",
"localhost:890",
"2001:db8:0:0:0:ff00:42:8329",
"[be4d:c25e:aca0:9366:68b7:c84:a23b:f7be]:443",
"www.somecompany.com:443",
"www.company.com",
"[2001:db8:4006:812::200e]:8080",
"222.22.2.1",
"[794b:389:73cb:76a2:59de:62fd:ee38:7c]:111",
}
actual := client.ReduceURLsToAddresses(endpoints)
assert.Equal(t, expected, actual)
}
func TestBuildTLSConfig(t *testing.T) {
//nolint:lll
ca := `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQakNCOGFBREFnRUNBaEFtbGVURnRuRVY3b3NHYTJFSU9RVUJNQVVHQXl0bGNEQVFNUTR3REFZRFZRUUsKRXdWMFlXeHZjekFlRncweU1qQTRNVEl4T0RNeE1EZGFGdzB6TWpBNE1Ea3hPRE14TURkYU1CQXhEakFNQmdOVgpCQW9UQlhSaGJHOXpNQ293QlFZREsyVndBeUVBVGZ3RjFMQjVwVjg2cGw4cHN2aS93R2dWWmkvTm5NME8wYUZNCjBoenZZdzZqWVRCZk1BNEdBMVVkRHdFQi93UUVBd0lDaERBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUkKS3dZQkJRVUhBd0l3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVWTRhSGg3UnJxRnVObFNydAo4bXY4ZHduUjRKQXdCUVlESzJWd0EwRUFTaE5jYURXMGwrU24xYSt5c21Sd2M2NGlBa3Y5dUlZNGdXU0t3RWJ4CnpYQlR3SkZWcmNPWlZNNS9pM0Y0UjFWZVkzM3QwdFBQMFBGZVF5MVRWTDlVQ0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==`
caBytes, err := base64.StdEncoding.DecodeString(ca)
assert.Nil(t, err)
expectedRootCAs := x509.NewCertPool()
expectedRootCAs.AppendCertsFromPEM(caBytes)
//nolint:lll
crt := `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJNekNCNXFBREFnRUNBaEVBZ1BscnFYWUtDeVNHRkxmazVVK2JQekFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdPREV5TVRnek1UQTNXaGNOTXpJd09EQTVNVGd6TVRBM1dqQVRNUkV3RHdZRApWUVFLRXdodmN6cGhaRzFwYmpBcU1BVUdBeXRsY0FNaEFKblVxM1V1TzNTaGg4YW50eEZzNGJnZDlXeGRtcit6CmZURkxIcGpQVWlUaG8xSXdVREFPQmdOVkhROEJBZjhFQkFNQ0I0QXdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUgKQXdFR0NDc0dBUVVGQndNQ01COEdBMVVkSXdRWU1CYUFGR09HaDRlMGE2aGJqWlVxN2ZKci9IY0owZUNRTUFVRwpBeXRsY0FOQkFNaW1wdnlxa0RHWDhROFErMTBtVWowYXJoQUpqdHl4OHErQll2QnlWOThxYyt3VldnYlFBc3FmClV3Sy9lN2ZLak1qMi9kRUZqOCs2SGZpOVJMTE5udzQ9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K`
key := `LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJQ3FTdHpMTTNzaHNqMlZld2dXaVBPaDJUT01uUmM3cmNyRkczTGhNaFdkQQotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K`
keyBytes, err := base64.StdEncoding.DecodeString(key)
assert.Nil(t, err)
crtBytes, err := base64.StdEncoding.DecodeString(crt)
assert.Nil(t, err)
expectedCert, err := tls.X509KeyPair(crtBytes, keyBytes)
assert.Nil(t, err)
expectedCerts := []tls.Certificate{expectedCert}
t.Run("Returns default tls config for empty config context.", func(t *testing.T) {
// given
configContext := clientconfig.Context{}
// when
tlsConfig, err := client.BuildTLSConfig(&configContext)
assert.Nil(t, err)
// then
expected := &tls.Config{}
assert.Equal(t, expected, tlsConfig)
})
t.Run("Returns tls config with CA for config context with CA.", func(t *testing.T) {
// given
configContext := clientconfig.Context{
CA: ca,
}
// when
tlsConfig, err := client.BuildTLSConfig(&configContext)
assert.Nil(t, err)
// then
assert.True(t, expectedRootCAs.Equal(tlsConfig.RootCAs))
assert.Len(t, tlsConfig.Certificates, 0)
})
t.Run("Returns tls config with Certificate for config context with Crt and Key.", func(t *testing.T) {
// given
configContext := clientconfig.Context{
Crt: crt,
Key: key,
}
// when
tlsConfig, err := client.BuildTLSConfig(&configContext)
assert.Nil(t, err)
// then
assert.Equal(t, expectedCerts, tlsConfig.Certificates)
assert.Equal(t, tls.RequireAndVerifyClientCert, tlsConfig.ClientAuth)
assert.Nil(t, tlsConfig.RootCAs)
})
t.Run("Returns tls config with CA and Certificate for config context with CA, Crt and Key.", func(t *testing.T) {
// given
configContext := clientconfig.Context{
CA: ca,
Crt: crt,
Key: key,
}
// when
tlsConfig, err := client.BuildTLSConfig(&configContext)
assert.Nil(t, err)
// then
assert.True(t, expectedRootCAs.Equal(tlsConfig.RootCAs))
assert.Equal(t, expectedCerts, tlsConfig.Certificates)
assert.Equal(t, tls.RequireAndVerifyClientCert, tlsConfig.ClientAuth)
})
}

View File

@ -0,0 +1,19 @@
// 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 client
import (
"crypto/tls"
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
)
func ReduceURLsToAddresses(endpoints []string) []string {
return reduceURLsToAddresses(endpoints)
}
func BuildTLSConfig(configContext *clientconfig.Context) (*tls.Config, error) {
return buildTLSConfig(configContext)
}

View File

@ -0,0 +1,46 @@
// 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 client
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
type grpcConnectionWrapper struct {
*grpc.ClientConn
clusterName string
}
func newGRPCConnectionWrapper(clusterName string, conn *grpc.ClientConn) *grpcConnectionWrapper {
return &grpcConnectionWrapper{
ClientConn: conn,
clusterName: clusterName,
}
}
// Invoke performs a unary RPC and returns after the response is received
// into reply.
func (c *grpcConnectionWrapper) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, opts ...grpc.CallOption) error {
return c.ClientConn.Invoke(c.appendMetadata(ctx), method, args, reply, opts...)
}
// NewStream begins a streaming RPC.
func (c *grpcConnectionWrapper) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
return c.ClientConn.NewStream(c.appendMetadata(ctx), desc, method, opts...)
}
func (c *grpcConnectionWrapper) appendMetadata(ctx context.Context) context.Context {
ctx = metadata.AppendToOutgoingContext(ctx, "runtime", "Talos")
if c.clusterName != "" {
ctx = metadata.AppendToOutgoingContext(ctx, "context", c.clusterName)
}
return ctx
}

View File

@ -0,0 +1,47 @@
// 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 sidero.debug
// +build sidero.debug
package client
import (
"net/url"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
)
// shouldInsecureConnectionsBeAllowed returns true if one endpoint starts with http://
func shouldInsecureConnectionsBeAllowed(endpoints []string) bool {
for _, endpoint := range endpoints {
u, _ := url.Parse(endpoint)
if u.Scheme == "http" {
return true
}
}
return false
}
// RequireTransportSecurity enables basic auth with insecure gRPC transport credentials.
func (c BasicAuth) RequireTransportSecurity() bool {
return false
}
func buildCredentials(configContext *clientconfig.Context, endpoints []string) (credentials.TransportCredentials, error) {
if shouldInsecureConnectionsBeAllowed(endpoints) {
return insecure.NewCredentials(), nil
}
tlsConfig, err := buildTLSConfig(configContext)
if err != nil {
return nil, err
}
return credentials.NewTLS(tlsConfig), nil
}

View File

@ -24,7 +24,8 @@ type Options struct {
contextOverride string
contextOverrideSet bool
unixSocketPath string
unixSocketPath string
clusterNameOverride string
}
// OptionFunc sets an option for the creation of the Client.
@ -123,3 +124,12 @@ func WithUnixSocket(path string) OptionFunc {
return nil
}
}
// WithCluster creates a Client which connects to the named cluster.
func WithCluster(cluster string) OptionFunc {
return func(o *Options) error {
o.clusterNameOverride = cluster
return nil
}
}

View File

@ -0,0 +1,28 @@
// 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 !sidero.debug
// +build !sidero.debug
package client
import (
"google.golang.org/grpc/credentials"
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
)
// RequireTransportSecurity implements credentials.PerRPCCredentials.
func (c BasicAuth) RequireTransportSecurity() bool {
return true
}
func buildCredentials(configContext *clientconfig.Context, endpoints []string) (credentials.TransportCredentials, error) {
tlsConfig, err := buildTLSConfig(configContext)
if err != nil {
return nil, err
}
return credentials.NewTLS(tlsConfig), nil
}

View File

@ -122,12 +122,12 @@ func (suite *GenerateSuite) TestGenerateTalosconfigSuccess() {
cfg, err := genv1alpha1.Talosconfig(suite.input)
suite.Require().NoError(err)
creds, err := client.CredentialsFromConfigContext(cfg.Contexts[cfg.Context])
creds, err := client.CertificateFromConfigContext(cfg.Contexts[cfg.Context])
suite.Require().NoError(err)
suite.Require().Nil(creds.Crt.Leaf)
suite.Require().Len(creds.Crt.Certificate, 1)
suite.Require().Nil(creds.Leaf)
suite.Require().Len(creds.Certificate, 1)
cert, err := x509.ParseCertificate(creds.Crt.Certificate[0])
cert, err := x509.ParseCertificate(creds.Certificate[0])
suite.Require().NoError(err)
suite.Equal([]string{string(role.Admin)}, cert.Subject.Organization)

View File

@ -29,6 +29,7 @@ talosctl apply-config [flags]
### 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
@ -69,6 +70,7 @@ talosctl bootstrap [flags]
### 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
@ -157,6 +159,7 @@ talosctl cluster create [flags]
### 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
--name string the name of the cluster (default "talos-default")
@ -187,6 +190,7 @@ talosctl cluster destroy [flags]
### 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
--name string the name of the cluster (default "talos-default")
@ -217,6 +221,7 @@ talosctl cluster show [flags]
### 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
--name string the name of the cluster (default "talos-default")
@ -246,6 +251,7 @@ A collection of commands for managing local docker-based or QEMU-based clusters
### 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
@ -319,6 +325,7 @@ talosctl completion SHELL [flags]
### 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
@ -349,6 +356,7 @@ talosctl config add <context> [flags]
### 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
@ -376,6 +384,7 @@ talosctl config context <context> [flags]
### 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
@ -403,6 +412,7 @@ talosctl config contexts [flags]
### 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
@ -430,6 +440,7 @@ talosctl config endpoint <endpoint>... [flags]
### 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
@ -457,6 +468,7 @@ talosctl config info [flags]
### 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
@ -488,6 +500,7 @@ talosctl config merge <from> [flags]
### 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
@ -517,6 +530,7 @@ talosctl config new [<path>] [flags]
### 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
@ -544,6 +558,7 @@ talosctl config node <endpoint>... [flags]
### 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
@ -567,6 +582,7 @@ Manage the client configuration file (talosconfig)
### 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
@ -603,6 +619,7 @@ talosctl conformance kubernetes [flags]
### 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
@ -626,6 +643,7 @@ Run conformance tests
### 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
@ -655,6 +673,7 @@ talosctl containers [flags]
### 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
@ -693,6 +712,7 @@ talosctl copy <src-path> -|<local-path> [flags]
### 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
@ -737,6 +757,7 @@ talosctl dashboard [flags]
### 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
@ -765,6 +786,7 @@ talosctl disks [flags]
### 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
@ -794,6 +816,7 @@ talosctl dmesg [flags]
### 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
@ -834,6 +857,7 @@ talosctl edit <type> [<id>] [flags]
### 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
@ -861,6 +885,7 @@ talosctl etcd forfeit-leadership [flags]
### 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
@ -888,6 +913,7 @@ talosctl etcd leave [flags]
### 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
@ -915,6 +941,7 @@ talosctl etcd members [flags]
### 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
@ -948,6 +975,7 @@ talosctl etcd remove-member <hostname> [flags]
### 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
@ -975,6 +1003,7 @@ talosctl etcd snapshot <path> [flags]
### 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
@ -998,6 +1027,7 @@ Manage etcd
### 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
@ -1034,6 +1064,7 @@ talosctl events [flags]
### 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
@ -1064,6 +1095,7 @@ talosctl gen ca [flags]
### 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
@ -1116,6 +1148,7 @@ talosctl gen config <cluster name> <cluster endpoint> [flags]
### 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
@ -1147,6 +1180,7 @@ talosctl gen crt [flags]
### 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
@ -1177,6 +1211,7 @@ talosctl gen csr [flags]
### 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
@ -1205,6 +1240,7 @@ talosctl gen key [flags]
### 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
@ -1234,6 +1270,7 @@ talosctl gen keypair [flags]
### 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
@ -1265,6 +1302,7 @@ talosctl gen secrets [flags]
### 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
@ -1288,6 +1326,7 @@ Generate CAs, certificates, and private keys
### 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
@ -1331,6 +1370,7 @@ talosctl get <type> [<id>] [flags]
### 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
@ -1365,6 +1405,7 @@ talosctl health [flags]
### 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
@ -1392,6 +1433,7 @@ talosctl images [flags]
### 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
@ -1431,6 +1473,7 @@ cat deployment.yaml | talosctl inject serviceaccount --roles="os:admin" -f - > d
### 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
@ -1454,6 +1497,7 @@ Inject Talos API resources into Kubernetes manifests
### 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
@ -1493,6 +1537,7 @@ talosctl inspect dependencies [flags]
### 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
@ -1516,6 +1561,7 @@ Inspect internals of Talos
### 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
@ -1553,6 +1599,7 @@ talosctl kubeconfig [local-path] [flags]
### 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
@ -1588,6 +1635,7 @@ talosctl list [path] [flags]
### 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
@ -1618,6 +1666,7 @@ talosctl logs <service name> [flags]
### 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
@ -1646,6 +1695,7 @@ talosctl memory [flags]
### 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
@ -1673,6 +1723,7 @@ talosctl mounts [flags]
### 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
@ -1706,6 +1757,7 @@ talosctl patch <type> [<id>] [flags]
### 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
@ -1767,6 +1819,7 @@ talosctl pcap [flags]
### 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
@ -1796,6 +1849,7 @@ talosctl processes [flags]
### 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
@ -1823,6 +1877,7 @@ talosctl read <path> [flags]
### 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
@ -1851,6 +1906,7 @@ talosctl reboot [flags]
### 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
@ -1881,6 +1937,7 @@ talosctl reset [flags]
### 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
@ -1909,6 +1966,7 @@ talosctl restart <id> [flags]
### 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
@ -1936,6 +1994,7 @@ talosctl rollback [flags]
### 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
@ -1969,6 +2028,7 @@ talosctl service [<id> [start|stop|restart|status]] [flags]
### 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
@ -1997,6 +2057,7 @@ talosctl shutdown [flags]
### 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
@ -2025,6 +2086,7 @@ talosctl stats [flags]
### 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
@ -2077,6 +2139,7 @@ talosctl support [flags]
### 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
@ -2105,6 +2168,7 @@ talosctl time [--check server] [flags]
### 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
@ -2136,6 +2200,7 @@ talosctl upgrade [flags]
### 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
@ -2172,6 +2237,7 @@ talosctl upgrade-k8s [flags]
### 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
@ -2203,6 +2269,7 @@ talosctl usage [path1] [path2] ... [pathN] [flags]
### 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
@ -2233,6 +2300,7 @@ talosctl validate [flags]
### 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
@ -2263,6 +2331,7 @@ talosctl version [flags]
### 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
@ -2280,6 +2349,7 @@ A CLI for out-of-band management of Kubernetes nodes created by Talos
### Options
```
--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
-h, --help help for talosctl