feat: use key provider with fallback option for auth type SideroV1

Use key provider with fallback option for auth type SideroV1:
- Attempt to use $HOME/.talos/keys directory to read/remove existing PGP file if it exists or write new PGP file if directory is writable.
- Otherwise fallback to using $XDG_DATA_HOME/talos/keys directory.
- Add new talosctl flag --siderov1-key-dir (also configurable via SIDEROV1_KEYS_DIR env var) to allow customizing the directory to use for PGP keys

Update documentation to remove reference for $XDG_CONFIG_HOME for storing talosctl configuration, as it's not used anymore.

Signed-off-by: Oguz Kilcan <oguz.kilcan@siderolabs.com>
This commit is contained in:
Oguz Kilcan 2025-08-12 14:08:22 +02:00
parent 7a52d7489c
commit b08b20a100
No known key found for this signature in database
GPG Key ID: 372F271E3AD80BFC
13 changed files with 1087 additions and 900 deletions

View File

@ -71,6 +71,15 @@ func addCommand(cmd *cobra.Command) {
cli.Should(cmd.RegisterFlagCompletionFunc("nodes", CompleteNodes))
cmd.PersistentFlags().StringVar(&GlobalArgs.Cluster, "cluster", "", "Cluster to connect to if a proxy endpoint is used.")
cmd.PersistentFlags().StringVar(&GlobalArgs.CmdContext, "context", "", "Context to be used in command")
cmd.PersistentFlags().StringVar(
&GlobalArgs.SideroV1KeysDir,
"siderov1-keys-dir",
"",
fmt.Sprintf("The path to the SideroV1 auth PGP keys directory. Defaults to '%s' env variable if set, otherwise '%s'. Only valid for Contexts that use SideroV1 auth.",
constants.SideroV1KeysDirEnvVar,
filepath.Join("$HOME", constants.TalosDir, constants.SideroV1KeysDir),
),
)
cli.Should(cmd.RegisterFlagCompletionFunc("context", CompleteConfigContext))
Commands = append(Commands, cmd)

View File

@ -21,11 +21,12 @@ import (
// Args is a context for the Talos command line client.
type Args struct {
Talosconfig string
CmdContext string
Cluster string
Nodes []string
Endpoints []string
Talosconfig string
CmdContext string
Cluster string
Nodes []string
Endpoints []string
SideroV1KeysDir string
}
// NodeList returns the list of nodes to run the command against.
@ -47,6 +48,7 @@ func (c *Args) WithClientNoNodes(action func(context.Context, *client.Client) er
opts := []client.OptionFunc{
client.WithConfig(cfg),
client.WithGRPCDialOptions(dialOptions...),
client.WithSideroV1KeysDir(c.SideroV1KeysDir),
}
if c.CmdContext != "" {

2
go.mod
View File

@ -144,7 +144,7 @@ require (
github.com/siderolabs/discovery-api v0.1.6
github.com/siderolabs/discovery-client v0.1.13
github.com/siderolabs/gen v0.8.5
github.com/siderolabs/go-api-signature v0.3.6
github.com/siderolabs/go-api-signature v0.3.7
github.com/siderolabs/go-blockdevice v0.4.8
github.com/siderolabs/go-blockdevice/v2 v2.0.19
github.com/siderolabs/go-circular v0.2.3

4
go.sum
View File

@ -621,8 +621,8 @@ github.com/siderolabs/ethtool v0.4.0-sidero/go.mod h1:nOIR88fiFTdBfakYLEUAhxdy75
github.com/siderolabs/gen v0.8.0/go.mod h1:an3a2Y53O7kUjnnK8Bfu3gewtvnIOu5RTU6HalFtXQQ=
github.com/siderolabs/gen v0.8.5 h1:xlWXTynnGD/epaj7uplvKvmAkBH+Fp51bLnw1JC0xME=
github.com/siderolabs/gen v0.8.5/go.mod h1:CRrktDXQf3yDJI7xKv+cDYhBbKdfd/YE16OpgcHoT9E=
github.com/siderolabs/go-api-signature v0.3.6 h1:wDIsXbpl7Oa/FXvxB6uz4VL9INA9fmr3EbmjEZYFJrU=
github.com/siderolabs/go-api-signature v0.3.6/go.mod h1:hoH13AfunHflxbXfh+NoploqV13ZTDfQ1mQJWNVSW9U=
github.com/siderolabs/go-api-signature v0.3.7 h1:Qx5NH3BrtYucCgiLObAJhx7pouLR4tivr1moOClII3M=
github.com/siderolabs/go-api-signature v0.3.7/go.mod h1:MQy+DcXCQIFFXZr+E4tbMmnQSQs7WpubSpJFRN694mI=
github.com/siderolabs/go-blockdevice v0.4.8 h1:KfdWvIx0Jft5YVuCsFIJFwjWEF1oqtzkgX9PeU9cX4c=
github.com/siderolabs/go-blockdevice v0.4.8/go.mod h1:4PeOuk71pReJj1JQEXDE7kIIQJPVe8a+HZQa+qjxSEA=
github.com/siderolabs/go-blockdevice/v2 v2.0.19 h1:V2a7HHzXlgMcZWUxpYp6BdapnwJGDAs/oGy1zkPicNA=

View File

@ -92,7 +92,7 @@ func (c *Client) getConn(opts ...grpc.DialOption) (*grpcConnectionWrapper, error
}
authInterceptor := interceptor.New(interceptor.Options{
UserKeyProvider: client.NewKeyProvider("talos/keys"),
UserKeyProvider: getKeyProvider(c.options.sideroV1KeysDir),
ContextName: contextName,
Identity: sideroV1.Identity,
ClientName: "Talos",
@ -112,6 +112,20 @@ func (c *Client) getConn(opts ...grpc.DialOption) (*grpcConnectionWrapper, error
return c.makeConnection(target, creds, dialOpts)
}
func getKeyProvider(customKeysDir string) *client.KeyProvider {
if customKeysDir != "" {
return client.NewKeyProviderWithFallback("talos/keys", customKeysDir, "", true)
}
talosDir, err := clientconfig.GetTalosDirectory()
if err != nil {
// TODO: start failing instead of falling back to XDG data directory if we can't resolve Talos directory
return client.NewKeyProvider("talos/keys")
}
return client.NewKeyProviderWithFallback("talos/keys", talosDir, "keys", true)
}
func buildTLSConfig(configContext *clientconfig.Context) (*tls.Config, error) {
tlsConfig := &tls.Config{}

View File

@ -26,6 +26,7 @@ type Options struct {
unixSocketPath string
clusterNameOverride string
sideroV1KeysDir string
}
// OptionFunc sets an option for the creation of the Client.
@ -133,3 +134,12 @@ func WithCluster(cluster string) OptionFunc {
return nil
}
}
// WithSideroV1KeysDir overrides the default SideroV1KeysDir configuration with the one provided.
func WithSideroV1KeysDir(keysDir string) OptionFunc {
return func(o *Options) error {
o.sideroV1KeysDir = keysDir
return nil
}
}

View File

@ -1281,6 +1281,12 @@ const (
// DiskEncryptionSaltSize is the size of the disk encryption salt in bytes.
DiskEncryptionSaltSize = 32
// SideroV1KeysDirEnvVar is the environment variable that points to the directory containing user PGP keys for SideroV1 auth.
SideroV1KeysDirEnvVar = "SIDEROV1_KEYS_DIR"
// SideroV1KeysDir is the default directory containing user PGP keys for SideroV1 auth.
SideroV1KeysDir = "keys"
)
// See https://linux.die.net/man/3/klogctl

View File

@ -31,7 +31,7 @@ require (
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/siderolabs/crypto v0.6.3
github.com/siderolabs/gen v0.8.5
github.com/siderolabs/go-api-signature v0.3.6
github.com/siderolabs/go-api-signature v0.3.7
github.com/siderolabs/go-pointer v1.0.1
github.com/siderolabs/net v0.4.0
github.com/siderolabs/protoenc v0.2.3

View File

@ -115,8 +115,8 @@ github.com/siderolabs/ethtool v0.4.0-sidero h1:Ls/M4bFUjfcB1RDVviPZlL3kWcXaEVVSb
github.com/siderolabs/ethtool v0.4.0-sidero/go.mod h1:nOIR88fiFTdBfakYLEUAhxdy75Ih/fgnSlsSKAHRpfc=
github.com/siderolabs/gen v0.8.5 h1:xlWXTynnGD/epaj7uplvKvmAkBH+Fp51bLnw1JC0xME=
github.com/siderolabs/gen v0.8.5/go.mod h1:CRrktDXQf3yDJI7xKv+cDYhBbKdfd/YE16OpgcHoT9E=
github.com/siderolabs/go-api-signature v0.3.6 h1:wDIsXbpl7Oa/FXvxB6uz4VL9INA9fmr3EbmjEZYFJrU=
github.com/siderolabs/go-api-signature v0.3.6/go.mod h1:hoH13AfunHflxbXfh+NoploqV13ZTDfQ1mQJWNVSW9U=
github.com/siderolabs/go-api-signature v0.3.7 h1:Qx5NH3BrtYucCgiLObAJhx7pouLR4tivr1moOClII3M=
github.com/siderolabs/go-api-signature v0.3.7/go.mod h1:MQy+DcXCQIFFXZr+E4tbMmnQSQs7WpubSpJFRN694mI=
github.com/siderolabs/go-pointer v1.0.1 h1:f7Yi4IK1jptS8yrT9GEbwhmGcVxvPQgBUG/weH3V3DM=
github.com/siderolabs/go-pointer v1.0.1/go.mod h1:C8Q/3pNHT4RE9e4rYR9PHeS6KPMlStRBgYrJQJNy/vA=
github.com/siderolabs/go-retry v0.3.3 h1:zKV+S1vumtO72E6sYsLlmIdV/G/GcYSBLiEx/c9oCEg=

View File

@ -15,8 +15,7 @@ To see some live examples of talosctl usage, view the following video:
## Client Configuration
Talosctl configuration is located in `$XDG_CONFIG_HOME/talos/config.yaml` if `$XDG_CONFIG_HOME` is defined.
Otherwise it is in `$HOME/.talos/config`.
Talosctl configuration is located in `$HOME/.talos/config`.
The location can always be overridden by the `TALOSCONFIG` environment variable or the `--talosconfig` parameter.
Like `kubectl`, `talosctl` uses the concept of configuration contexts, so any number of Talos clusters can be managed with a single configuration file.

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,7 @@ To see some live examples of talosctl usage, view the following video:
## Client Configuration
Talosctl configuration is located in `$XDG_CONFIG_HOME/talos/config.yaml` if `$XDG_CONFIG_HOME` is defined.
Otherwise it is in `$HOME/.talos/config`.
Talosctl configuration is located in `$HOME/.talos/config`.
The location can always be overridden by the `TALOSCONFIG` environment variable or the `--talosconfig` parameter.
Like `kubectl`, `talosctl` uses the concept of configuration contexts, so any number of Talos clusters can be managed with a single configuration file.

File diff suppressed because it is too large Load Diff