From 1076dbab4c06dcefed59ad32bec299bc520e4412 Mon Sep 17 00:00:00 2001 From: pittu sharma Date: Sun, 22 Mar 2026 13:48:59 +0530 Subject: [PATCH 1/3] doc: Add TPM deployment walkthrough and reference architecture Signed-off-by: pittu sharma --- doc/tpm_deployment_walkthrough.md | 84 +++++++++++++++++++++++++++++++ doc/using_spire.md | 4 ++ 2 files changed, 88 insertions(+) create mode 100644 doc/tpm_deployment_walkthrough.md diff --git a/doc/tpm_deployment_walkthrough.md b/doc/tpm_deployment_walkthrough.md new file mode 100644 index 0000000000..f2e9b102cd --- /dev/null +++ b/doc/tpm_deployment_walkthrough.md @@ -0,0 +1,84 @@ +# TPM Deployment Walkthrough + +This guide describes a redundant SPIRE deployment using TPM 2.0 for node attestation in non-Kubernetes environments. + +## Architecture + +A production-ready setup consists of a high-availability SPIRE Server cluster and agents running on hardware with TPM 2.0 support. + +- **Control Plane**: Multiple servers sharing a SQL datastore (Postgres or MySQL) for persistence and HA. +- **Agent Nodes**: Physical or virtual infrastructure with `/dev/tpm0` available. +- **LDevID**: TPM-bound Local Device Identifiers provisioned out-of-band. + +## Requirements + +- **TPM 2.0 hardware**: Accessible via `/dev/tpm0`. +- **Pre-provisioned DevID**: Key blobs and certificates must be on-node before starting the agent. +- **Internal CA**: The CA that signed the LDevIDs must be trusted by the SPIRE Server. + +> [!TIP] +> Use `tpm2-tools` to verify TPM access and key residency before configuring the SPIRE plugin. + +## Setup Walkthrough + +### 1. Provisioning + +Provision each node's TPM out-of-band. You'll need to generate a key pair in the TPM, get a certificate signed by your internal CA, and save the key blobs (`.priv` and `.pub`) to disk. + +### 2. SPIRE Server Configuration + +Configure the `tpm_devid` attestor in `server.conf`. Point to the CA that signed your node certificates. + +```hcl +server { + trust_domain = "example.org" +} + +plugins { + NodeAttestor "tpm_devid" { + plugin_data { + devid_ca_path = "/etc/spire/certs/devid-ca.pem" + endorsement_ca_path = "/etc/spire/certs/tpm-manufacturer-ca.pem" + } + } +} +``` + +### 3. SPIRE Agent Configuration + +Configure the `tpm_devid` attestor in `agent.conf`. + +```hcl +agent { + trust_domain = "example.org" + server_address = "spire-control-plane.example.org" + server_port = 8081 +} + +plugins { + NodeAttestor "tpm_devid" { + plugin_data { + devid_cert_path = "/etc/spire/agent/devid.crt" + devid_priv_path = "/etc/spire/agent/devid.priv" + devid_pub_path = "/etc/spire/agent/devid.pub" + } + } +} +``` + +### 4. Node Registration + +Create a registration entry for each node. + +```shell +(in dev shell) # ./bin/spire-server entry create \ + -spiffeID spiffe://example.org/node/primary \ + -node \ + -selector tpm_devid:subject:cn:node-01.example.org +``` + +## Scaling and Recovery + +**Horizontal Scaling**: Add server instances to the cluster by pointing them to the same datastore. Scale agents by provisioning new TPM-backed nodes. + +**Trust Recovery**: If an agent's certificate expires or the node is wiped, re-provision the TPM and refresh the agent's identity. The agent will re-attest using the new hardware-bound DevID on its next cycle. diff --git a/doc/using_spire.md b/doc/using_spire.md index dbcf0dfcbb..436f47673b 100644 --- a/doc/using_spire.md +++ b/doc/using_spire.md @@ -25,3 +25,7 @@ This page describes some options to get started with SPIRE. ## MacOS * There are no pre-built SPIRE executables available for MacOS, but [Quickstart for Linux and MacOS X](https://spiffe.io/docs/latest/spire/installing/getting-started-linux-macos-x/) describes how to download and build SPIRE to test a simple one-node installation of the SPIRE Server and Agent + +## TPM + +* [TPM Deployment Walkthrough](tpm_deployment_walkthrough.md) provides a comprehensive guide for deploying a redundant SPIRE cluster using TPM for node attestation. From 4850bac79b71ac3b9f63d44c787d5021114a78c4 Mon Sep 17 00:00:00 2001 From: pittu sharma Date: Wed, 25 Mar 2026 01:16:08 +0530 Subject: [PATCH 2/3] doc: address reviewer feedback for TPM deployment walkthrough Signed-off-by: pittu sharma --- doc/tpm_deployment_walkthrough.md | 54 ++++++++++--------------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/doc/tpm_deployment_walkthrough.md b/doc/tpm_deployment_walkthrough.md index f2e9b102cd..6e029a20fc 100644 --- a/doc/tpm_deployment_walkthrough.md +++ b/doc/tpm_deployment_walkthrough.md @@ -23,52 +23,32 @@ A production-ready setup consists of a high-availability SPIRE Server cluster an ### 1. Provisioning -Provision each node's TPM out-of-band. You'll need to generate a key pair in the TPM, get a certificate signed by your internal CA, and save the key blobs (`.priv` and `.pub`) to disk. +Before configuring SPIRE, each node's TPM must be provisioned with a Local Device Identifier (LDevID) out-of-band. This process typically involves: + +1. **Key Generation**: Using a tool like `tpm2-tools`, generate an asymmetric key pair securely within the TPM. The private portion of the key never leaves the hardware. +2. **Certificate Signing Request (CSR)**: Generate a CSR from the TPM key. +3. **Certificate Issuance**: Submit the CSR to your internal Certificate Authority (CA) to obtain the signed LDevID certificate for the node. +4. **Storing Artifacts**: Securely store the returned certificate (`.pem` or `.crt`) alongside the generated key blobs (`.priv` and `.pub`) on the node's disk. + +These artifacts establish the initial hardware-bound identity that the SPIRE Agent will use to attest to the Server. ### 2. SPIRE Server Configuration -Configure the `tpm_devid` attestor in `server.conf`. Point to the CA that signed your node certificates. - -```hcl -server { - trust_domain = "example.org" -} - -plugins { - NodeAttestor "tpm_devid" { - plugin_data { - devid_ca_path = "/etc/spire/certs/devid-ca.pem" - endorsement_ca_path = "/etc/spire/certs/tpm-manufacturer-ca.pem" - } - } -} -``` +Configure the `tpm_devid` attestor in the SPIRE Server configuration file (`server.conf`). The server must be configured with a path to the CA certificates (`devid_ca_path`) that signed the agents' LDevID certificates. + +For full configuration options, including how to configure endorsement verification, please refer to the [Server `tpm_devid` plugin documentation](plugin_server_nodeattestor_tpm_devid.md). ### 3. SPIRE Agent Configuration -Configure the `tpm_devid` attestor in `agent.conf`. - -```hcl -agent { - trust_domain = "example.org" - server_address = "spire-control-plane.example.org" - server_port = 8081 -} - -plugins { - NodeAttestor "tpm_devid" { - plugin_data { - devid_cert_path = "/etc/spire/agent/devid.crt" - devid_priv_path = "/etc/spire/agent/devid.priv" - devid_pub_path = "/etc/spire/agent/devid.pub" - } - } -} -``` +Configure the `tpm_devid` attestor in the SPIRE Agent configuration file (`agent.conf`) to point to the LDevID certificate and key blobs provisioned in Step 1. + +For full configuration details and a sample configuration block, please see the [Agent `tpm_devid` plugin documentation](plugin_agent_nodeattestor_tpm_devid.md). ### 4. Node Registration -Create a registration entry for each node. +Create a registration entry to map the node's TPM identity (e.g., the Common Name in its LDevID certificate) to a specific SPIFFE ID. + +This step is strictly optional. If omitted, the server will default to issuing a SPIFFE ID based on the node's LDevID certificate fingerprint. However, explicitly registering the node is recommended to assign a recognized, human-readable SPIFFE ID (such as `spiffe://example.org/node/primary`) for associating subsequent workload entries. ```shell (in dev shell) # ./bin/spire-server entry create \ From d97a3f60b4fb39033bd57f33bfcac61a4b313f2f Mon Sep 17 00:00:00 2001 From: pittu sharma Date: Tue, 21 Apr 2026 01:24:08 +0530 Subject: [PATCH 3/3] cli: add shorthand aliases to server and agent commands This commit introduces short-form flag aliases across SPIRE server and agent command suites to improve CLI usability and align with standard conventions. Key updates: - Added reusable flag helpers in pkg/common/cli/flags.go - Integrated aliases into entry, bundle, healthcheck, and run commands - Updated documentation and test fixtures to reflect changes Signed-off-by: pittu sharma --- .../cli/healthcheck/healthcheck.go | 4 +- .../cli/healthcheck/healthcheck_posix_test.go | 2 + .../healthcheck/healthcheck_windows_test.go | 2 + cmd/spire-agent/cli/run/run.go | 6 +- cmd/spire-agent/cli/run/run_posix.go | 2 +- cmd/spire-agent/cli/run/run_posix_test.go | 13 ++++ cmd/spire-agent/cli/run/run_windows.go | 3 +- cmd/spire-agent/cli/run/run_windows_test.go | 13 ++++ .../cli/bundle/bundle_posix_test.go | 14 ++++ .../cli/bundle/bundle_windows_test.go | 14 ++++ cmd/spire-server/cli/bundle/delete.go | 2 +- cmd/spire-server/cli/bundle/list.go | 4 +- cmd/spire-server/cli/bundle/set.go | 6 +- cmd/spire-server/cli/bundle/show.go | 2 +- cmd/spire-server/cli/entry/count.go | 8 +- cmd/spire-server/cli/entry/create.go | 20 ++--- cmd/spire-server/cli/entry/delete.go | 4 +- cmd/spire-server/cli/entry/show.go | 10 +-- cmd/spire-server/cli/entry/update.go | 18 ++--- cmd/spire-server/cli/entry/util_posix_test.go | 48 ++++++++++++ .../cli/entry/util_windows_test.go | 49 ++++++++++++ .../cli/healthcheck/healthcheck.go | 4 +- .../cli/healthcheck/healthcheck_posix_test.go | 2 + .../healthcheck/healthcheck_windows_test.go | 2 + cmd/spire-server/cli/run/run.go | 6 +- cmd/spire-server/cli/run/run_posix.go | 3 +- cmd/spire-server/cli/run/run_posix_test.go | 13 ++++ cmd/spire-server/cli/run/run_windows.go | 3 +- cmd/spire-server/cli/run/run_windows_test.go | 13 ++++ doc/spire_agent.md | 14 ++-- doc/spire_server.md | 78 +++++++++---------- pkg/common/cli/flags.go | 41 ++++++++++ 32 files changed, 326 insertions(+), 97 deletions(-) diff --git a/cmd/spire-agent/cli/healthcheck/healthcheck.go b/cmd/spire-agent/cli/healthcheck/healthcheck.go index 67d677ddc7..4c88d02f61 100644 --- a/cmd/spire-agent/cli/healthcheck/healthcheck.go +++ b/cmd/spire-agent/cli/healthcheck/healthcheck.go @@ -60,8 +60,8 @@ func (c *healthCheckCommand) Run(args []string) int { func (c *healthCheckCommand) parseFlags(args []string) error { fs := flag.NewFlagSet("health", flag.ContinueOnError) fs.SetOutput(c.env.Stderr) - fs.BoolVar(&c.shallow, "shallow", false, "Perform a less stringent health check") - fs.BoolVar(&c.verbose, "verbose", false, "Print verbose information") + common_cli.BoolVar(fs, &c.shallow, "shallow", "s", false, "Perform a less stringent health check") + common_cli.BoolVar(fs, &c.verbose, "verbose", "v", false, "Print verbose information") c.addOSFlags(fs) return fs.Parse(args) } diff --git a/cmd/spire-agent/cli/healthcheck/healthcheck_posix_test.go b/cmd/spire-agent/cli/healthcheck/healthcheck_posix_test.go index 7781e48489..80c96975d1 100644 --- a/cmd/spire-agent/cli/healthcheck/healthcheck_posix_test.go +++ b/cmd/spire-agent/cli/healthcheck/healthcheck_posix_test.go @@ -11,10 +11,12 @@ import ( var ( usage = `Usage of health: + -s Perform a less stringent health check -shallow Perform a less stringent health check -socketPath string Path to the SPIRE Agent API socket (default "/tmp/spire-agent/public/api.sock") + -v Print verbose information -verbose Print verbose information ` diff --git a/cmd/spire-agent/cli/healthcheck/healthcheck_windows_test.go b/cmd/spire-agent/cli/healthcheck/healthcheck_windows_test.go index 29cfaf56fb..e5bcc349f9 100644 --- a/cmd/spire-agent/cli/healthcheck/healthcheck_windows_test.go +++ b/cmd/spire-agent/cli/healthcheck/healthcheck_windows_test.go @@ -14,8 +14,10 @@ var ( usage = `Usage of health: -namedPipeName string Pipe name of the SPIRE Agent API named pipe (default "\\spire-agent\\public\\api") + -s Perform a less stringent health check -shallow Perform a less stringent health check + -v Print verbose information -verbose Print verbose information ` diff --git a/cmd/spire-agent/cli/run/run.go b/cmd/spire-agent/cli/run/run.go index c5a334d7a9..3dd4edc0fb 100644 --- a/cmd/spire-agent/cli/run/run.go +++ b/cmd/spire-agent/cli/run/run.go @@ -339,13 +339,13 @@ func parseFlags(name string, args []string, output io.Writer) (*agentConfig, err flags.SetOutput(output) c := &agentConfig{} - flags.StringVar(&c.ConfigPath, "config", defaultConfigPath, "Path to a SPIRE config file") - flags.StringVar(&c.DataDir, "dataDir", "", "A directory the agent can use for its runtime data") + common_cli.StringVar(flags, &c.ConfigPath, "config", "c", defaultConfigPath, "Path to a SPIRE config file") + common_cli.StringVar(flags, &c.DataDir, "dataDir", "d", "", "A directory the agent can use for its runtime data") flags.StringVar(&c.JoinToken, "joinToken", "", "An optional token which has been generated by the SPIRE server") flags.StringVar(&c.JoinTokenFile, "joinTokenFile", "", "Path to a file containing an optional join token which has been generated by the SPIRE server") flags.StringVar(&c.LogFile, "logFile", "", "File to write logs to") flags.StringVar(&c.LogFormat, "logFormat", "", "'text' or 'json'") - flags.StringVar(&c.LogLevel, "logLevel", "", "'debug', 'info', 'warn', or 'error'") + common_cli.StringVar(flags, &c.LogLevel, "logLevel", "v", "", "'debug', 'info', 'warn', or 'error'") flags.BoolVar(&c.LogSourceLocation, "logSourceLocation", false, "Include source file, line number and function name in log lines") flags.StringVar(&c.ServerAddress, "serverAddress", "", "IP address or DNS name of the SPIRE server") flags.IntVar(&c.ServerPort, "serverPort", 0, "Port number of the SPIRE server") diff --git a/cmd/spire-agent/cli/run/run_posix.go b/cmd/spire-agent/cli/run/run_posix.go index 4c8ddd9d03..f49bae1470 100644 --- a/cmd/spire-agent/cli/run/run_posix.go +++ b/cmd/spire-agent/cli/run/run_posix.go @@ -18,7 +18,7 @@ import ( ) func (c *agentConfig) addOSFlags(flags *flag.FlagSet) { - flags.StringVar(&c.SocketPath, "socketPath", "", "Path to bind the SPIRE Agent API socket to") + common_cli.StringVar(flags, &c.SocketPath, "socketPath", "s", "", "Path to bind the SPIRE Agent API socket to") } func (c *agentConfig) setPlatformDefaults() { diff --git a/cmd/spire-agent/cli/run/run_posix_test.go b/cmd/spire-agent/cli/run/run_posix_test.go index 8767f9a681..9eee28694a 100644 --- a/cmd/spire-agent/cli/run/run_posix_test.go +++ b/cmd/spire-agent/cli/run/run_posix_test.go @@ -374,3 +374,16 @@ func newAgentConfigCasesOS(t *testing.T) []newAgentConfigCase { }, } } +func TestParseFlagsShorthand(t *testing.T) { + c, err := parseFlags("run", []string{ + "-c", "conf/agent/agent.conf", + "-d", "/data/dir", + "-v", "DEBUG", + "-s", "/tmp/spire-agent/public/api.sock", + }, os.Stderr) + require.NoError(t, err) + assert.Equal(t, "conf/agent/agent.conf", c.ConfigPath) + assert.Equal(t, "/data/dir", c.DataDir) + assert.Equal(t, "DEBUG", c.LogLevel) + assert.Equal(t, "/tmp/spire-agent/public/api.sock", c.SocketPath) +} diff --git a/cmd/spire-agent/cli/run/run_windows.go b/cmd/spire-agent/cli/run/run_windows.go index 015bbc3420..6c24fb8e84 100644 --- a/cmd/spire-agent/cli/run/run_windows.go +++ b/cmd/spire-agent/cli/run/run_windows.go @@ -9,11 +9,12 @@ import ( "github.com/spiffe/spire/cmd/spire-agent/cli/common" "github.com/spiffe/spire/pkg/agent" + common_cli "github.com/spiffe/spire/pkg/common/cli" "github.com/spiffe/spire/pkg/common/namedpipe" ) func (c *agentConfig) addOSFlags(flags *flag.FlagSet) { - flags.StringVar(&c.Experimental.NamedPipeName, "namedPipeName", "", "Pipe name to bind the SPIRE Agent API named pipe") + common_cli.StringVar(flags, &c.Experimental.NamedPipeName, "namedPipeName", "p", "", "Pipe name to bind the SPIRE Agent API named pipe") } func (c *agentConfig) setPlatformDefaults() { diff --git a/cmd/spire-agent/cli/run/run_windows_test.go b/cmd/spire-agent/cli/run/run_windows_test.go index 99d416451f..7e047c841f 100644 --- a/cmd/spire-agent/cli/run/run_windows_test.go +++ b/cmd/spire-agent/cli/run/run_windows_test.go @@ -282,3 +282,16 @@ func newAgentConfigCasesOS(*testing.T) []newAgentConfigCase { }, } } +func TestParseFlagsShorthand(t *testing.T) { + c, err := parseFlags("run", []string{ + "-c", "conf/agent/agent.conf", + "-d", "/data/dir", + "-v", "DEBUG", + "-p", "spire-agent-pipe", + }, os.Stderr) + require.NoError(t, err) + assert.Equal(t, "conf/agent/agent.conf", c.ConfigPath) + assert.Equal(t, "/data/dir", c.DataDir) + assert.Equal(t, "DEBUG", c.LogLevel) + assert.Equal(t, "spire-agent-pipe", c.Experimental.NamedPipeName) +} diff --git a/cmd/spire-server/cli/bundle/bundle_posix_test.go b/cmd/spire-server/cli/bundle/bundle_posix_test.go index 040087a0f9..0687fbe2b1 100644 --- a/cmd/spire-server/cli/bundle/bundle_posix_test.go +++ b/cmd/spire-server/cli/bundle/bundle_posix_test.go @@ -4,12 +4,18 @@ package bundle var ( setUsage = `Usage of bundle set: + -f string + The format of the bundle data. Either "pem" or "spiffe". (default "pem") -format string The format of the bundle data. Either "pem" or "spiffe". (default "pem") + -i string + SPIFFE ID of the trust domain -id string SPIFFE ID of the trust domain -output value Desired output format (pretty, json); default: pretty. + -p string + Path to the bundle data -path string Path to the bundle data -socketPath string @@ -22,6 +28,8 @@ var ( Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock") ` deleteUsage = `Usage of bundle delete: + -i string + SPIFFE ID of the trust domain -id string SPIFFE ID of the trust domain -mode string @@ -32,8 +40,12 @@ var ( Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock") ` listUsage = `Usage of bundle list: + -f string + The format to list federated bundles (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") -format string The format to list federated bundles (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") + -i string + SPIFFE ID of the trust domain -id string SPIFFE ID of the trust domain -output value @@ -42,6 +54,8 @@ var ( Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock") ` showUsage = `Usage of bundle show: + -f string + The format to show the bundle (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") -format string The format to show the bundle (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") -output value diff --git a/cmd/spire-server/cli/bundle/bundle_windows_test.go b/cmd/spire-server/cli/bundle/bundle_windows_test.go index 50cb993dc7..cc09e96166 100644 --- a/cmd/spire-server/cli/bundle/bundle_windows_test.go +++ b/cmd/spire-server/cli/bundle/bundle_windows_test.go @@ -4,18 +4,26 @@ package bundle var ( setUsage = `Usage of bundle set: + -f string + The format of the bundle data. Either "pem" or "spiffe". (default "pem") -format string The format of the bundle data. Either "pem" or "spiffe". (default "pem") + -i string + SPIFFE ID of the trust domain -id string SPIFFE ID of the trust domain -namedPipeName string Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api") -output value Desired output format (pretty, json); default: pretty. + -p string + Path to the bundle data -path string Path to the bundle data ` showUsage = `Usage of bundle show: + -f string + The format to show the bundle (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") -format string The format to show the bundle (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") -namedPipeName string @@ -30,8 +38,12 @@ var ( Desired output format (pretty, json); default: pretty. ` listUsage = `Usage of bundle list: + -f string + The format to list federated bundles (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") -format string The format to list federated bundles (only pretty output format supports this flag). Either "pem" or "spiffe". (default "pem") + -i string + SPIFFE ID of the trust domain -id string SPIFFE ID of the trust domain -namedPipeName string @@ -40,6 +52,8 @@ var ( Desired output format (pretty, json); default: pretty. ` deleteUsage = `Usage of bundle delete: + -i string + SPIFFE ID of the trust domain -id string SPIFFE ID of the trust domain -mode string diff --git a/cmd/spire-server/cli/bundle/delete.go b/cmd/spire-server/cli/bundle/delete.go index e3f437f884..2a5ccd4c91 100644 --- a/cmd/spire-server/cli/bundle/delete.go +++ b/cmd/spire-server/cli/bundle/delete.go @@ -48,7 +48,7 @@ func (c *deleteCommand) Synopsis() string { } func (c *deleteCommand) AppendFlags(fs *flag.FlagSet) { - fs.StringVar(&c.id, "id", "", "SPIFFE ID of the trust domain") + commoncli.StringVar(fs, &c.id, "id", "i", "", "SPIFFE ID of the trust domain") fs.StringVar(&c.mode, "mode", deleteBundleRestrict, fmt.Sprintf("Deletion mode: one of %s, %s, or %s", deleteBundleRestrict, deleteBundleDelete, deleteBundleDissociate)) cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintDelete) } diff --git a/cmd/spire-server/cli/bundle/list.go b/cmd/spire-server/cli/bundle/list.go index c107de6e71..f86d3b6fed 100644 --- a/cmd/spire-server/cli/bundle/list.go +++ b/cmd/spire-server/cli/bundle/list.go @@ -38,8 +38,8 @@ func (c *listCommand) Synopsis() string { } func (c *listCommand) AppendFlags(fs *flag.FlagSet) { - fs.StringVar(&c.id, "id", "", "SPIFFE ID of the trust domain") - fs.StringVar(&c.bundleFormat, "format", util.FormatPEM, fmt.Sprintf("The format to list federated bundles (only pretty output format supports this flag). Either %q or %q.", util.FormatPEM, util.FormatSPIFFE)) + commoncli.StringVar(fs, &c.id, "id", "i", "", "SPIFFE ID of the trust domain") + commoncli.StringVar(fs, &c.bundleFormat, "format", "f", util.FormatPEM, fmt.Sprintf("The format to list federated bundles (only pretty output format supports this flag). Either %q or %q.", util.FormatPEM, util.FormatSPIFFE)) cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, c.prettyPrintList) } diff --git a/cmd/spire-server/cli/bundle/set.go b/cmd/spire-server/cli/bundle/set.go index e6f392631a..24fce0f031 100644 --- a/cmd/spire-server/cli/bundle/set.go +++ b/cmd/spire-server/cli/bundle/set.go @@ -43,9 +43,9 @@ func (c *setCommand) Synopsis() string { } func (c *setCommand) AppendFlags(fs *flag.FlagSet) { - fs.StringVar(&c.id, "id", "", "SPIFFE ID of the trust domain") - fs.StringVar(&c.path, "path", "", "Path to the bundle data") - fs.StringVar(&c.bundleFormat, "format", util.FormatPEM, fmt.Sprintf("The format of the bundle data. Either %q or %q.", util.FormatPEM, util.FormatSPIFFE)) + common_cli.StringVar(fs, &c.id, "id", "i", "", "SPIFFE ID of the trust domain") + common_cli.StringVar(fs, &c.path, "path", "p", "", "Path to the bundle data") + common_cli.StringVar(fs, &c.bundleFormat, "format", "f", util.FormatPEM, fmt.Sprintf("The format of the bundle data. Either %q or %q.", util.FormatPEM, util.FormatSPIFFE)) cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintSet) } diff --git a/cmd/spire-server/cli/bundle/show.go b/cmd/spire-server/cli/bundle/show.go index 55469182d0..8d8d9a556c 100644 --- a/cmd/spire-server/cli/bundle/show.go +++ b/cmd/spire-server/cli/bundle/show.go @@ -37,7 +37,7 @@ func (c *showCommand) Synopsis() string { } func (c *showCommand) AppendFlags(fs *flag.FlagSet) { - fs.StringVar(&c.bundleFormat, "format", util.FormatPEM, fmt.Sprintf("The format to show the bundle (only pretty output format supports this flag). Either %q or %q.", util.FormatPEM, util.FormatSPIFFE)) + common_cli.StringVar(fs, &c.bundleFormat, "format", "f", util.FormatPEM, fmt.Sprintf("The format to show the bundle (only pretty output format supports this flag). Either %q or %q.", util.FormatPEM, util.FormatSPIFFE)) cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, c.prettyPrintBundle) } diff --git a/cmd/spire-server/cli/entry/count.go b/cmd/spire-server/cli/entry/count.go index 01444b0880..6741074084 100644 --- a/cmd/spire-server/cli/entry/count.go +++ b/cmd/spire-server/cli/entry/count.go @@ -134,11 +134,11 @@ func (c *countCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient u } func (c *countCommand) AppendFlags(fs *flag.FlagSet) { - fs.StringVar(&c.parentID, "parentID", "", "The Parent ID of the records to count") - fs.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID of the records to count") + commoncli.StringVar(fs, &c.parentID, "parentID", "p", "", "The Parent ID of the records to count") + commoncli.StringVar(fs, &c.spiffeID, "spiffeID", "s", "", "The SPIFFE ID of the records to count") fs.BoolVar(&c.downstream, "downstream", false, "A boolean value that, when set, indicates that the entry describes a downstream SPIRE server") - fs.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once") - fs.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain an entry is federate with. Can be used more than once") + commoncli.Var(fs, &c.selectors, "selector", "l", "A colon-delimited type:value selector. Can be used more than once") + commoncli.Var(fs, &c.federatesWith, "federatesWith", "f", "SPIFFE ID of a trust domain an entry is federate with. Can be used more than once") fs.StringVar(&c.matchFederatesWithOn, "matchFederatesWithOn", "superset", "The match mode used when filtering by federates with. Options: exact, any, superset and subset") fs.StringVar(&c.matchSelectorsOn, "matchSelectorsOn", "superset", "The match mode used when filtering by selectors. Options: exact, any, superset and subset") fs.StringVar(&c.hint, "hint", "", "The Hint of the records to count (optional)") diff --git a/cmd/spire-server/cli/entry/create.go b/cmd/spire-server/cli/entry/create.go index 349fa344b2..0ded6f49a5 100644 --- a/cmd/spire-server/cli/entry/create.go +++ b/cmd/spire-server/cli/entry/create.go @@ -88,16 +88,16 @@ func (*createCommand) Synopsis() string { } func (c *createCommand) AppendFlags(f *flag.FlagSet) { - f.StringVar(&c.entryID, "entryID", "", "A custom ID for this registration entry (optional). If not set, a new entry ID will be generated") - f.StringVar(&c.parentID, "parentID", "", "The SPIFFE ID of this record's parent") - f.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID that this record represents") - f.IntVar(&c.x509SVIDTTL, "x509SVIDTTL", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.") - f.IntVar(&c.jwtSVIDTTL, "jwtSVIDTTL", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.") - f.StringVar(&c.path, "data", "", "Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin.") - f.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once") - f.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain to federate with. Can be used more than once") - f.BoolVar(&c.node, "node", false, "If set, this entry will be applied to matching nodes rather than workloads") - f.BoolVar(&c.admin, "admin", false, "If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs") + commoncli.StringVar(f, &c.entryID, "entryID", "e", "", "A custom ID for this registration entry (optional). If not set, a new entry ID will be generated") + commoncli.StringVar(f, &c.parentID, "parentID", "p", "", "The SPIFFE ID of this record's parent") + commoncli.StringVar(f, &c.spiffeID, "spiffeID", "s", "", "The SPIFFE ID that this record represents") + commoncli.IntVar(f, &c.x509SVIDTTL, "x509SVIDTTL", "", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.") + commoncli.IntVar(f, &c.jwtSVIDTTL, "jwtSVIDTTL", "", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.") + commoncli.StringVar(f, &c.path, "data", "d", "", "Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin.") + commoncli.Var(f, &c.selectors, "selector", "l", "A colon-delimited type:value selector. Can be used more than once") + commoncli.Var(f, &c.federatesWith, "federatesWith", "f", "SPIFFE ID of a trust domain to federate with. Can be used more than once") + commoncli.BoolVar(f, &c.node, "node", "n", false, "If set, this entry will be applied to matching nodes rather than workloads") + commoncli.BoolVar(f, &c.admin, "admin", "a", false, "If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs") f.BoolVar(&c.storeSVID, "storeSVID", false, "A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin") f.BoolVar(&c.downstream, "downstream", false, "A boolean value that, when set, indicates that the entry describes a downstream SPIRE server") f.Int64Var(&c.entryExpiry, "entryExpiry", 0, "An expiry, from epoch in seconds, for the resulting registration entry to be pruned") diff --git a/cmd/spire-server/cli/entry/delete.go b/cmd/spire-server/cli/entry/delete.go index bedd27ffce..7cd0c72f9a 100644 --- a/cmd/spire-server/cli/entry/delete.go +++ b/cmd/spire-server/cli/entry/delete.go @@ -44,8 +44,8 @@ func (*deleteCommand) Synopsis() string { } func (c *deleteCommand) AppendFlags(f *flag.FlagSet) { - f.StringVar(&c.entryID, "entryID", "", "The Registration Entry ID of the record to delete.") - f.StringVar(&c.file, "file", "", "Path to a file containing a JSON structure for batch deletion (optional). If set to '-', read from stdin.") + commoncli.StringVar(f, &c.entryID, "entryID", "e", "", "The Registration Entry ID of the record to delete.") + commoncli.StringVar(f, &c.file, "file", "f", "", "Path to a file containing a JSON structure for batch deletion (optional). If set to '-', read from stdin.") cliprinter.AppendFlagWithCustomPretty(&c.printer, f, c.env, c.prettyPrintDelete) } diff --git a/cmd/spire-server/cli/entry/show.go b/cmd/spire-server/cli/entry/show.go index 22218f3e82..b98af2de93 100644 --- a/cmd/spire-server/cli/entry/show.go +++ b/cmd/spire-server/cli/entry/show.go @@ -70,12 +70,12 @@ func (*showCommand) Synopsis() string { } func (c *showCommand) AppendFlags(f *flag.FlagSet) { - f.StringVar(&c.entryID, "entryID", "", "The Entry ID of the records to show") - f.StringVar(&c.parentID, "parentID", "", "The Parent ID of the records to show") - f.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID of the records to show") + commoncli.StringVar(f, &c.entryID, "entryID", "e", "", "The Entry ID of the records to show") + commoncli.StringVar(f, &c.parentID, "parentID", "p", "", "The Parent ID of the records to show") + commoncli.StringVar(f, &c.spiffeID, "spiffeID", "s", "", "The SPIFFE ID of the records to show") f.BoolVar(&c.downstream, "downstream", false, "A boolean value that, when set, indicates that the entry describes a downstream SPIRE server") - f.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once") - f.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain an entry is federate with. Can be used more than once") + commoncli.Var(f, &c.selectors, "selector", "l", "A colon-delimited type:value selector. Can be used more than once") + commoncli.Var(f, &c.federatesWith, "federatesWith", "f", "SPIFFE ID of a trust domain an entry is federate with. Can be used more than once") f.StringVar(&c.matchFederatesWithOn, "matchFederatesWithOn", "superset", "The match mode used when filtering by federates with. Options: exact, any, superset and subset") f.StringVar(&c.matchSelectorsOn, "matchSelectorsOn", "superset", "The match mode used when filtering by selectors. Options: exact, any, superset and subset") f.StringVar(&c.hint, "hint", "", "The Hint of the records to show (optional)") diff --git a/cmd/spire-server/cli/entry/update.go b/cmd/spire-server/cli/entry/update.go index 369275d203..a1fecff569 100644 --- a/cmd/spire-server/cli/entry/update.go +++ b/cmd/spire-server/cli/entry/update.go @@ -84,15 +84,15 @@ func (*updateCommand) Synopsis() string { } func (c *updateCommand) AppendFlags(f *flag.FlagSet) { - f.StringVar(&c.entryID, "entryID", "", "The Registration Entry ID of the record to update") - f.StringVar(&c.parentID, "parentID", "", "The SPIFFE ID of this record's parent") - f.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID that this record represents") - f.IntVar(&c.x509SvidTTL, "x509SVIDTTL", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.") - f.IntVar(&c.jwtSvidTTL, "jwtSVIDTTL", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.") - f.StringVar(&c.path, "data", "", "Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin.") - f.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once") - f.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain to federate with. Can be used more than once") - f.BoolVar(&c.admin, "admin", false, "If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs") + commoncli.StringVar(f, &c.entryID, "entryID", "e", "", "The Registration Entry ID of the record to update") + commoncli.StringVar(f, &c.parentID, "parentID", "p", "", "The SPIFFE ID of this record's parent") + commoncli.StringVar(f, &c.spiffeID, "spiffeID", "s", "", "The SPIFFE ID that this record represents") + commoncli.IntVar(f, &c.x509SvidTTL, "x509SVIDTTL", "", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.") + commoncli.IntVar(f, &c.jwtSvidTTL, "jwtSVIDTTL", "", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.") + commoncli.StringVar(f, &c.path, "data", "d", "", "Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin.") + commoncli.Var(f, &c.selectors, "selector", "l", "A colon-delimited type:value selector. Can be used more than once") + commoncli.Var(f, &c.federatesWith, "federatesWith", "f", "SPIFFE ID of a trust domain to federate with. Can be used more than once") + commoncli.BoolVar(f, &c.admin, "admin", "a", false, "If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs") f.BoolVar(&c.downstream, "downstream", false, "A boolean value that, when set, indicates that the entry describes a downstream SPIRE server") f.BoolVar(&c.storeSVID, "storeSVID", false, "A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin") f.Int64Var(&c.entryExpiry, "entryExpiry", 0, "An expiry, from epoch in seconds, for the resulting registration entry to be pruned") diff --git a/cmd/spire-server/cli/entry/util_posix_test.go b/cmd/spire-server/cli/entry/util_posix_test.go index 2ac9598873..f97cf0e010 100644 --- a/cmd/spire-server/cli/entry/util_posix_test.go +++ b/cmd/spire-server/cli/entry/util_posix_test.go @@ -4,30 +4,43 @@ package entry const ( createUsage = `Usage of entry create: + -a If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs -admin If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs + -d string + Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -data string Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -dns value A DNS name that will be included in SVIDs issued based on this entry, where appropriate. Can be used more than once -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -e string + A custom ID for this registration entry (optional). If not set, a new entry ID will be generated -entryExpiry int An expiry, from epoch in seconds, for the resulting registration entry to be pruned -entryID string A custom ID for this registration entry (optional). If not set, a new entry ID will be generated + -f value + SPIFFE ID of a trust domain to federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain to federate with. Can be used more than once -hint string The entry hint, used to disambiguate entries with the same SPIFFE ID -jwtSVIDTTL int The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. + -l value + A colon-delimited type:value selector. Can be used more than once -node If set, this entry will be applied to matching nodes rather than workloads -output value Desired output format (pretty, json); default: pretty. + -p string + The SPIFFE ID of this record's parent -parentID string The SPIFFE ID of this record's parent + -s string + The SPIFFE ID that this record represents -selector value A colon-delimited type:value selector. Can be used more than once -socketPath string @@ -42,20 +55,30 @@ const ( showUsage = `Usage of entry show: -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -e string + The Entry ID of the records to show -entryID string The Entry ID of the records to show + -f value + SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -hint string The Hint of the records to show (optional) + -l value + A colon-delimited type:value selector. Can be used more than once -matchFederatesWithOn string The match mode used when filtering by federates with. Options: exact, any, superset and subset (default "superset") -matchSelectorsOn string The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset") -output value Desired output format (pretty, json); default: pretty. + -p string + The Parent ID of the records to show -parentID string The Parent ID of the records to show + -s string + The SPIFFE ID of the records to show -selector value A colon-delimited type:value selector. Can be used more than once -socketPath string @@ -64,28 +87,41 @@ const ( The SPIFFE ID of the records to show ` updateUsage = `Usage of entry update: + -a If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs -admin If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs + -d string + Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -data string Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -dns value A DNS name that will be included in SVIDs issued based on this entry, where appropriate. Can be used more than once -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -e string + The Registration Entry ID of the record to update -entryExpiry int An expiry, from epoch in seconds, for the resulting registration entry to be pruned -entryID string The Registration Entry ID of the record to update + -f value + SPIFFE ID of a trust domain to federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain to federate with. Can be used more than once -hint string The entry hint, used to disambiguate entries with the same SPIFFE ID -jwtSVIDTTL int The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. + -l value + A colon-delimited type:value selector. Can be used more than once -output value Desired output format (pretty, json); default: pretty. + -p string + The SPIFFE ID of this record's parent -parentID string The SPIFFE ID of this record's parent + -s string + The SPIFFE ID that this record represents -selector value A colon-delimited type:value selector. Can be used more than once -socketPath string @@ -98,8 +134,12 @@ const ( The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. ` deleteUsage = `Usage of entry delete: + -e string + The Registration Entry ID of the record to delete. -entryID string The Registration Entry ID of the record to delete. + -f string + Path to a file containing a JSON structure for batch deletion (optional). If set to '-', read from stdin. -file string Path to a file containing a JSON structure for batch deletion (optional). If set to '-', read from stdin. -output value @@ -110,18 +150,26 @@ const ( countUsage = `Usage of entry count: -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -f value + SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -hint string The Hint of the records to count (optional) + -l value + A colon-delimited type:value selector. Can be used more than once -matchFederatesWithOn string The match mode used when filtering by federates with. Options: exact, any, superset and subset (default "superset") -matchSelectorsOn string The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset") -output value Desired output format (pretty, json); default: pretty. + -p string + The Parent ID of the records to count -parentID string The Parent ID of the records to count + -s string + The SPIFFE ID of the records to count -selector value A colon-delimited type:value selector. Can be used more than once -socketPath string diff --git a/cmd/spire-server/cli/entry/util_windows_test.go b/cmd/spire-server/cli/entry/util_windows_test.go index 06fd7e4942..e1f2f108d1 100644 --- a/cmd/spire-server/cli/entry/util_windows_test.go +++ b/cmd/spire-server/cli/entry/util_windows_test.go @@ -4,32 +4,46 @@ package entry const ( createUsage = `Usage of entry create: + -a If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs -admin If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs + -d string + Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -data string Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -dns value A DNS name that will be included in SVIDs issued based on this entry, where appropriate. Can be used more than once -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -e string + A custom ID for this registration entry (optional). If not set, a new entry ID will be generated -entryExpiry int An expiry, from epoch in seconds, for the resulting registration entry to be pruned -entryID string A custom ID for this registration entry (optional). If not set, a new entry ID will be generated + -f value + SPIFFE ID of a trust domain to federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain to federate with. Can be used more than once -hint string The entry hint, used to disambiguate entries with the same SPIFFE ID -jwtSVIDTTL int The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. + -l value + A colon-delimited type:value selector. Can be used more than once + -n If set, this entry will be applied to matching nodes rather than workloads -namedPipeName string Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api") -node If set, this entry will be applied to matching nodes rather than workloads -output value Desired output format (pretty, json); default: pretty. + -p string + The SPIFFE ID of this record's parent -parentID string The SPIFFE ID of this record's parent + -s string + The SPIFFE ID that this record represents -selector value A colon-delimited type:value selector. Can be used more than once -spiffeID string @@ -42,12 +56,18 @@ const ( showUsage = `Usage of entry show: -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -e string + The Entry ID of the records to show -entryID string The Entry ID of the records to show + -f value + SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -hint string The Hint of the records to show (optional) + -l value + A colon-delimited type:value selector. Can be used more than once -matchFederatesWithOn string The match mode used when filtering by federates with. Options: exact, any, superset and subset (default "superset") -matchSelectorsOn string @@ -56,38 +76,55 @@ const ( Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api") -output value Desired output format (pretty, json); default: pretty. + -p string + The Parent ID of the records to show -parentID string The Parent ID of the records to show + -s string + The SPIFFE ID of the records to show -selector value A colon-delimited type:value selector. Can be used more than once -spiffeID string The SPIFFE ID of the records to show ` updateUsage = `Usage of entry update: + -a If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs -admin If set, the SPIFFE ID in this entry will be granted access to the SPIRE Server's management APIs + -d string + Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -data string Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin. -dns value A DNS name that will be included in SVIDs issued based on this entry, where appropriate. Can be used more than once -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -e string + The Registration Entry ID of the record to update -entryExpiry int An expiry, from epoch in seconds, for the resulting registration entry to be pruned -entryID string The Registration Entry ID of the record to update + -f value + SPIFFE ID of a trust domain to federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain to federate with. Can be used more than once -hint string The entry hint, used to disambiguate entries with the same SPIFFE ID -jwtSVIDTTL int The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. + -l value + A colon-delimited type:value selector. Can be used more than once -namedPipeName string Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api") -output value Desired output format (pretty, json); default: pretty. + -p string + The SPIFFE ID of this record's parent -parentID string The SPIFFE ID of this record's parent + -s string + The SPIFFE ID that this record represents -selector value A colon-delimited type:value selector. Can be used more than once -spiffeID string @@ -98,8 +135,12 @@ const ( The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. ` deleteUsage = `Usage of entry delete: + -e string + The Registration Entry ID of the record to delete. -entryID string The Registration Entry ID of the record to delete. + -f string + Path to a file containing a JSON structure for batch deletion (optional). If set to '-', read from stdin. -file string Path to a file containing a JSON structure for batch deletion (optional). If set to '-', read from stdin. -namedPipeName string @@ -110,10 +151,14 @@ const ( countUsage = `Usage of entry count: -downstream A boolean value that, when set, indicates that the entry describes a downstream SPIRE server + -f value + SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -federatesWith value SPIFFE ID of a trust domain an entry is federate with. Can be used more than once -hint string The Hint of the records to count (optional) + -l value + A colon-delimited type:value selector. Can be used more than once -matchFederatesWithOn string The match mode used when filtering by federates with. Options: exact, any, superset and subset (default "superset") -matchSelectorsOn string @@ -122,8 +167,12 @@ const ( Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api") -output value Desired output format (pretty, json); default: pretty. + -p string + The Parent ID of the records to count -parentID string The Parent ID of the records to count + -s string + The SPIFFE ID of the records to count -selector value A colon-delimited type:value selector. Can be used more than once -spiffeID string diff --git a/cmd/spire-server/cli/healthcheck/healthcheck.go b/cmd/spire-server/cli/healthcheck/healthcheck.go index fe65f6b211..6f226cc551 100644 --- a/cmd/spire-server/cli/healthcheck/healthcheck.go +++ b/cmd/spire-server/cli/healthcheck/healthcheck.go @@ -34,8 +34,8 @@ func (c *healthCheckCommand) Synopsis() string { } func (c *healthCheckCommand) AppendFlags(fs *flag.FlagSet) { - fs.BoolVar(&c.shallow, "shallow", false, "Perform a less stringent health check") - fs.BoolVar(&c.verbose, "verbose", false, "Print verbose information") + common_cli.BoolVar(fs, &c.shallow, "shallow", "s", false, "Perform a less stringent health check") + common_cli.BoolVar(fs, &c.verbose, "verbose", "v", false, "Print verbose information") } func (c *healthCheckCommand) Run(ctx context.Context, env *common_cli.Env, client util.ServerClient) error { diff --git a/cmd/spire-server/cli/healthcheck/healthcheck_posix_test.go b/cmd/spire-server/cli/healthcheck/healthcheck_posix_test.go index d56a982cf1..9830024c8c 100644 --- a/cmd/spire-server/cli/healthcheck/healthcheck_posix_test.go +++ b/cmd/spire-server/cli/healthcheck/healthcheck_posix_test.go @@ -4,10 +4,12 @@ package healthcheck var ( healthcheckUsage = `Usage of healthcheck: + -s Perform a less stringent health check -shallow Perform a less stringent health check -socketPath string Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock") + -v Print verbose information -verbose Print verbose information ` diff --git a/cmd/spire-server/cli/healthcheck/healthcheck_windows_test.go b/cmd/spire-server/cli/healthcheck/healthcheck_windows_test.go index 71644c1ac8..c9c263b7f4 100644 --- a/cmd/spire-server/cli/healthcheck/healthcheck_windows_test.go +++ b/cmd/spire-server/cli/healthcheck/healthcheck_windows_test.go @@ -6,8 +6,10 @@ var ( healthcheckUsage = `Usage of healthcheck: -namedPipeName string Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api") + -s Perform a less stringent health check -shallow Perform a less stringent health check + -v Print verbose information -verbose Print verbose information ` diff --git a/cmd/spire-server/cli/run/run.go b/cmd/spire-server/cli/run/run.go index f56677565d..c693a2b9f5 100644 --- a/cmd/spire-server/cli/run/run.go +++ b/cmd/spire-server/cli/run/run.go @@ -340,12 +340,12 @@ func parseFlags(name string, args []string, output io.Writer) (*serverConfig, er flags.StringVar(&c.BindAddress, "bindAddress", "", "IP address or DNS name of the SPIRE server") flags.IntVar(&c.BindPort, "serverPort", 0, "Port number of the SPIRE server") - flags.StringVar(&c.ConfigPath, "config", "", "Path to a SPIRE config file") - flags.StringVar(&c.DataDir, "dataDir", "", "Directory to store runtime data to") + common_cli.StringVar(flags, &c.ConfigPath, "config", "c", "", "Path to a SPIRE config file") + common_cli.StringVar(flags, &c.DataDir, "dataDir", "d", "", "Directory to store runtime data to") flags.StringVar(&c.LogFile, "logFile", "", "File to write logs to") flags.StringVar(&c.LogFormat, "logFormat", "", "'text' or 'json'") flags.BoolVar(&c.LogSourceLocation, "logSourceLocation", false, "Include source file, line number and function name in log lines") - flags.StringVar(&c.LogLevel, "logLevel", "", "'debug', 'info', 'warn', or 'error'") + common_cli.StringVar(flags, &c.LogLevel, "logLevel", "v", "", "'debug', 'info', 'warn', or 'error'") flags.StringVar(&c.TrustDomain, "trustDomain", "", "The trust domain that this server belongs to") flags.BoolVar(&c.ExpandEnv, "expandEnv", false, "Expand environment variables in SPIRE config file") c.addOSFlags(flags) diff --git a/cmd/spire-server/cli/run/run_posix.go b/cmd/spire-server/cli/run/run_posix.go index 2d23b63343..acc79783ca 100644 --- a/cmd/spire-server/cli/run/run_posix.go +++ b/cmd/spire-server/cli/run/run_posix.go @@ -7,6 +7,7 @@ import ( "flag" "net" + common_cli "github.com/spiffe/spire/pkg/common/cli" "github.com/spiffe/spire/pkg/common/util" ) @@ -15,7 +16,7 @@ const ( ) func (c *serverConfig) addOSFlags(flags *flag.FlagSet) { - flags.StringVar(&c.SocketPath, "socketPath", "", "Path to bind the SPIRE Server API socket to") + common_cli.StringVar(flags, &c.SocketPath, "socketPath", "s", "", "Path to bind the SPIRE Server API socket to") } func (c *serverConfig) getAddr() (net.Addr, error) { diff --git a/cmd/spire-server/cli/run/run_posix_test.go b/cmd/spire-server/cli/run/run_posix_test.go index 6b5b48b6a3..0bfefd1422 100644 --- a/cmd/spire-server/cli/run/run_posix_test.go +++ b/cmd/spire-server/cli/run/run_posix_test.go @@ -301,3 +301,16 @@ func getAvailablePort() (string, error) { return strconv.Itoa(int(addrPort.Port())), nil } +func TestParseFlagsShorthand(t *testing.T) { + c, err := parseFlags("run", []string{ + "-c", "conf/server/server.conf", + "-d", "/data/dir", + "-v", "DEBUG", + "-s", "/tmp/spire-server/private/api.sock", + }, os.Stderr) + require.NoError(t, err) + assert.Equal(t, "conf/server/server.conf", c.ConfigPath) + assert.Equal(t, "/data/dir", c.DataDir) + assert.Equal(t, "DEBUG", c.LogLevel) + assert.Equal(t, "/tmp/spire-server/private/api.sock", c.SocketPath) +} diff --git a/cmd/spire-server/cli/run/run_windows.go b/cmd/spire-server/cli/run/run_windows.go index 9162225bd6..506ce0f379 100644 --- a/cmd/spire-server/cli/run/run_windows.go +++ b/cmd/spire-server/cli/run/run_windows.go @@ -8,11 +8,12 @@ import ( "net" util_cmd "github.com/spiffe/spire/cmd/spire-server/util" + common_cli "github.com/spiffe/spire/pkg/common/cli" "github.com/spiffe/spire/pkg/common/namedpipe" ) func (c *serverConfig) addOSFlags(flags *flag.FlagSet) { - flags.StringVar(&c.Experimental.NamedPipeName, "namedPipeName", "", "Pipe name of the SPIRE Server API named pipe") + common_cli.StringVar(flags, &c.Experimental.NamedPipeName, "namedPipeName", "p", "", "Pipe name of the SPIRE Server API named pipe") } func (c *serverConfig) getAddr() (net.Addr, error) { diff --git a/cmd/spire-server/cli/run/run_windows_test.go b/cmd/spire-server/cli/run/run_windows_test.go index 697c8d4831..75b60ca9e2 100644 --- a/cmd/spire-server/cli/run/run_windows_test.go +++ b/cmd/spire-server/cli/run/run_windows_test.go @@ -198,3 +198,16 @@ func newServerConfigCasesOS(*testing.T) []newServerConfigCase { func testParseConfigGoodOS(t *testing.T, c *Config) { assert.Equal(t, c.Server.Experimental.NamedPipeName, "\\spire-server\\private\\api-test") } +func TestParseFlagsShorthand(t *testing.T) { + c, err := parseFlags("run", []string{ + "-c", "conf/server/server.conf", + "-d", "/data/dir", + "-v", "DEBUG", + "-p", "spire-server-pipe", + }, os.Stderr) + require.NoError(t, err) + assert.Equal(t, "conf/server/server.conf", c.ConfigPath) + assert.Equal(t, "/data/dir", c.DataDir) + assert.Equal(t, "DEBUG", c.LogLevel) + assert.Equal(t, "spire-server-pipe", c.Experimental.NamedPipeName) +} diff --git a/doc/spire_agent.md b/doc/spire_agent.md index 399fe8751a..541f7304f4 100644 --- a/doc/spire_agent.md +++ b/doc/spire_agent.md @@ -257,17 +257,17 @@ the following flags are available: | Command | Action | Default | |----------------------------------|-------------------------------------------------------------------------------------|-----------------------| | `-allowUnauthenticatedVerifiers` | Allow agent to release trust bundles to unauthenticated verifiers | | -| `-config` | Path to a SPIRE config file | conf/agent/agent.conf | -| `-dataDir` | A directory the agent can use for its runtime data | | +| `-config (-c)` | Path to a SPIRE config file | conf/agent/agent.conf | +| `-dataDir (-d)` | A directory the agent can use for its runtime data | | | `-expandEnv` | Expand environment $VARIABLES in the config file | | | `-joinToken` | An optional token which has been generated by the SPIRE server | | | `-joinTokenFile` | Path to a file containing an optional join token which has been generated by the SPIRE server | | | `-logFile` | File to write logs to | | | `-logFormat` | Format of logs, <text|json> | | -| `-logLevel` | DEBUG, INFO, WARN or ERROR | | +| `-logLevel (-v)` | DEBUG, INFO, WARN or ERROR | | | `-serverAddress` | IP address or DNS name of the SPIRE server | | -| `-serverPort` | Port number of the SPIRE server | | -| `-socketPath` | Location to bind the workload API socket | | +| `-serverPort` | Port number of the SPIRE server | | +| `-socketPath (-s)` | Location to bind the workload API socket | | | `-trustBundle` | Path to the SPIRE server CA bundle | | | `-trustBundleUrl` | URL to download the SPIRE server CA bundle | | | `-trustDomain` | The trust domain that this agent belongs to (should be no more than 255 characters) | | @@ -349,9 +349,9 @@ Checks SPIRE agent's health. | Command | Action | Default | |:--------------|:--------------------------------------|:---------------------------------| -| `-shallow` | Perform a less stringent health check | | +| `-shallow (-s)` | Perform a less stringent health check | | | `-socketPath` | Path to the SPIRE Agent API socket | /tmp/spire-agent/public/api.sock | -| `-verbose` | Print verbose information | | +| `-verbose (-v)` | Print verbose information | | ### `spire-agent validate` diff --git a/doc/spire_server.md b/doc/spire_server.md index e35749a816..ed567c69dc 100644 --- a/doc/spire_server.md +++ b/doc/spire_server.md @@ -334,14 +334,14 @@ Most of the configuration file above options have identical command-line counter | Command | Action | Default | |:---------------|:-------------------------------------------------------------------------------------|:------------------------| | `-bindAddress` | IP address or DNS name of the SPIRE server | | -| `-config` | Path to a SPIRE config file | conf/server/server.conf | -| `-dataDir` | Directory to store runtime data to | | +| `-config (-c)` | Path to a SPIRE config file | conf/server/server.conf | +| `-dataDir (-d)` | Directory to store runtime data to | | | `-expandEnv` | Expand environment $VARIABLES in the config file | | | `-logFile` | File to write logs to | | | `-logFormat` | Format of logs, <text|json> | | -| `-logLevel` | DEBUG, INFO, WARN or ERROR | | +| `-logLevel (-v)` | DEBUG, INFO, WARN or ERROR | | | `-serverPort` | Port number of the SPIRE server | | -| `-socketPath` | Path to bind the SPIRE Server API socket to | | +| `-socketPath (-s)` | Path to bind the SPIRE Server API socket to | | | `-trustDomain` | The trust domain that this server belongs to (should be no more than 255 characters) | | #### Running SPIRE Server as a Windows service @@ -381,18 +381,18 @@ Creates registration entries. | Command | Action | Default | |:-----------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------| -| `-admin` | If set, the SPIFFE ID in this entry will be granted access to the Server APIs | | -| `-data` | Path to a file containing registration data in JSON format (optional, if specified, other flags related with entry information must be omitted). If set to '-', read the JSON from stdin. | | +| `-admin (-a)` | If set, the SPIFFE ID in this entry will be granted access to the Server APIs | | +| `-data (-d)` | Path to a file containing registration data in JSON format (optional, if specified, other flags related with entry information must be omitted). If set to '-', read the JSON from stdin. | | | `-dns` | A DNS name that will be included in SVIDs issued based on this entry, where appropriate. Can be used more than once | | | `-downstream` | A boolean value that, when set, indicates that the entry describes a downstream SPIRE server | | | `-entryExpiry` | An expiry, from epoch in seconds, for the resulting registration entry to be pruned from the datastore. Please note that this is a data management feature and not a security feature (optional). | | -| `-entryID` | A user-specified ID for the newly created registration entry (optional). If no entry ID is provided, one will be generated during creation | | -| `-federatesWith` | A list of trust domain SPIFFE IDs representing the trust domains this registration entry federates with. A bundle for that trust domain must already exist | | -| `-node` | If set, this entry will be applied to matching nodes rather than workloads | | -| `-parentID` | The SPIFFE ID of this record's parent. | | -| `-selector` | A colon-delimited type:value selector used for attestation. This parameter can be used more than once, to specify multiple selectors that must be satisfied. | | +| `-entryID (-e)` | A user-specified ID for the newly created registration entry (optional). If no entry ID is provided, one will be generated during creation | | +| `-federatesWith (-f)` | A list of trust domain SPIFFE IDs representing the trust domains this registration entry federates with. A bundle for that trust domain must already exist | | +| `-node (-n)` | If set, this entry will be applied to matching nodes rather than workloads | | +| `-parentID (-p)` | The SPIFFE ID of this record's parent. | | +| `-selector (-l)` | A colon-delimited type:value selector used for attestation. This parameter can be used more than once, to specify multiple selectors that must be satisfied. | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | -| `-spiffeID` | The SPIFFE ID that this record represents and will be set to the SVID issued. | | +| `-spiffeID (-s)` | The SPIFFE ID that this record represents and will be set to the SVID issued. | | | `-x509SVIDTTL` | A TTL, in seconds, for any X509-SVID issued as a result of this record. | The TTL configured with `default_x509_svid_ttl` | | `-jwtSVIDTTL` | A TTL, in seconds, for any JWT-SVID issued as a result of this record. | The TTL configured with `default_jwt_svid_ttl` | | `-storeSVID` | A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin | | @@ -403,17 +403,17 @@ Updates registration entries. | Command | Action | Default | |:-----------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------| -| `-admin` | If true, the SPIFFE ID in this entry will be granted access to the Server APIs | | -| `-data` | Path to a file containing registration data in JSON format (optional, if specified, other flags related with entry information must be omitted). If set to '-', read the JSON from stdin. | | +| `-admin (-a)` | If true, the SPIFFE ID in this entry will be granted access to the Server APIs | | +| `-data (-d)` | Path to a file containing registration data in JSON format (optional, if specified, other flags related with entry information must be omitted). If set to '-', read the JSON from stdin. | | | `-dns` | A DNS name that will be included in SVIDs issued based on this entry, where appropriate. Can be used more than once | | | `-downstream` | A boolean value that, when set, indicates that the entry describes a downstream SPIRE server | | | `-entryExpiry` | An expiry, from epoch in seconds, for the resulting registration entry to be pruned | | -| `-entryID` | The Registration Entry ID of the record to update | | -| `-federatesWith` | A list of trust domain SPIFFE IDs representing the trust domains this registration entry federates with. A bundle for that trust domain must already exist | | -| `-parentID` | The SPIFFE ID of this record's parent. | | -| `-selector` | A colon-delimited type:value selector used for attestation. This parameter can be used more than once, to specify multiple selectors that must be satisfied. | | +| `-entryID (-e)` | The Registration Entry ID of the record to update | | +| `-federatesWith (-f)` | A list of trust domain SPIFFE IDs representing the trust domains this registration entry federates with. A bundle for that trust domain must already exist | | +| `-parentID (-p)` | The SPIFFE ID of this record's parent. | | +| `-selector (-l)` | A colon-delimited type:value selector used for attestation. This parameter can be used more than once, to specify multiple selectors that must be satisfied. | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | -| `-spiffeID` | The SPIFFE ID that this record represents and will be set to the SVID issued. | | +| `-spiffeID (-s)` | The SPIFFE ID that this record represents and will be set to the SVID issued. | | | `-x509SVIDTTL` | A TTL, in seconds, for any X509-SVID issued as a result of this record. | The TTL configured with `default_x509_svid_ttl` | | `-jwtSVIDTTL` | A TTL, in seconds, for any JWT-SVID issued as a result of this record. | The TTL configured with `default_jwt_svid_ttl` | | `storeSVID` | A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin | | @@ -425,11 +425,11 @@ Displays the total number of registration entries. | Command | Action | Default | |:-----------------|:-------------------------------------------------------------------------------------------------|:-----------------------------------| | `-downstream` | A boolean value that, when set, indicates that the entry describes a downstream SPIRE server | | -| `-federatesWith` | SPIFFE ID of a trust domain an entry is federate with. Can be used more than once | | -| `-parentID` | The Parent ID of the records to count. | | -| `-selector` | A colon-delimited type:value selector. Can be used more than once to specify multiple selectors. | | +| `-federatesWith (-f)` | SPIFFE ID of a trust domain an entry is federate with. Can be used more than once | | +| `-parentID (-p)` | The Parent ID of the records to count. | | +| `-selector (-l)` | A colon-delimited type:value selector. Can be used more than once to specify multiple selectors. | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | -| `-spiffeID` | The SPIFFE ID of the records to count. | | +| `-spiffeID (-s)` | The SPIFFE ID of the records to count. | | ### `spire-server entry delete` @@ -437,7 +437,7 @@ Deletes a specified registration entry. | Command | Action | Default | |:--------------|:--------------------------------------------------|:-----------------------------------| -| `-entryID` | The Registration Entry ID of the record to delete | | +| `-entryID (-e)` | The Registration Entry ID of the record to delete | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | ### `spire-server entry show` @@ -447,12 +447,12 @@ Displays configured registration entries. | Command | Action | Default | |:-----------------|:-------------------------------------------------------------------------------------------------|:-----------------------------------| | `-downstream` | A boolean value that, when set, indicates that the entry describes a downstream SPIRE server | | -| `-entryID` | The Entry ID of the record to show. | | -| `-federatesWith` | SPIFFE ID of a trust domain an entry is federate with. Can be used more than once | | -| `-parentID` | The Parent ID of the records to show. | | -| `-selector` | A colon-delimited type:value selector. Can be used more than once to specify multiple selectors. | | +| `-entryID (-e)` | The Entry ID of the record to show. | | +| `-federatesWith (-f)` | SPIFFE ID of a trust domain an entry is federate with. Can be used more than once | | +| `-parentID (-p)` | The Parent ID of the records to show. | | +| `-selector (-l)` | A colon-delimited type:value selector. Can be used more than once to specify multiple selectors. | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | -| `-spiffeID` | The SPIFFE ID of the records to show. | | +| `-spiffeID (-s)` | The SPIFFE ID of the records to show. | | ### `spire-server bundle count` @@ -468,7 +468,7 @@ Displays the bundle for the trust domain of the server. | Command | Action | Default | |:--------------|:--------------------------------------------------------|:-----------------------------------| -| `-format` | The format to show the bundle. Either `pem` or `spiffe` | pem | +| `-format (-f)` | The format to show the bundle. Either `pem` or `spiffe` | pem | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | ### `spire-server bundle list` @@ -477,8 +477,8 @@ Displays federated bundles. | Command | Action | Default | |:--------------|:----------------------------------------------------------------------------------------|:-----------------------------------| -| `-id` | The trust domain SPIFFE ID of the bundle to show. If unset, all trust bundles are shown | | -| `-format` | The format to show the federated bundles. Either `pem` or `spiffe` | pem | +| `-id (-i)` | The trust domain SPIFFE ID of the bundle to show. If unset, all trust bundles are shown | | +| `-format (-f)` | The format to show the federated bundles. Either `pem` or `spiffe` | pem | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | ### `spire-server bundle set` @@ -487,10 +487,10 @@ Creates or updates bundle data for a trust domain. This command cannot be used t | Command | Action | Default | |:--------------|:----------------------------------------------------------------------------------------|:-----------------------------------| -| `-id` | The trust domain SPIFFE ID of the bundle to set. | | -| `-path` | Path on disk to the file containing the bundle data. If unset, data is read from stdin. | | +| `-id (-i)` | The trust domain SPIFFE ID of the bundle to set. | | +| `-path (-p)` | Path on disk to the file containing the bundle data. If unset, data is read from stdin. | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | -| `-format` | The format of the bundle to set. Either `pem` or `spiffe` | pem | +| `-format (-f)` | The format of the bundle to set. Either `pem` or `spiffe` | pem | ### `spire-server bundle delete` @@ -498,9 +498,9 @@ Deletes bundle data for a trust domain. This command cannot be used to delete th | Command | Action | Default | |:--------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------| -| `-id` | The trust domain SPIFFE ID of the bundle to delete. | | +| `-id (-i)` | The trust domain SPIFFE ID of the bundle to delete. | | | `-mode` | One of: `restrict`, `dissociate`, `delete`. `restrict` prevents the bundle from being deleted if it is associated to registration entries (i.e. federated with). `dissociate` allows the bundle to be deleted and removes the association from registration entries. `delete` deletes the bundle as well as associated registration entries. | `restrict` | -| `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | +| `-socketPath (-s)` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | ### `spire-server federation create` @@ -627,9 +627,9 @@ Checks SPIRE server's health. | Command | Action | Default | |:--------------|:--------------------------------------|:-----------------------------------| -| `-shallow` | Perform a less stringent health check | | +| `-shallow (-s)` | Perform a less stringent health check | | | `-socketPath` | Path to the SPIRE Server API socket | /tmp/spire-server/private/api.sock | -| `-verbose` | Print verbose information | | +| `-verbose (-v)` | Print verbose information | | ### `spire-server validate` diff --git a/pkg/common/cli/flags.go b/pkg/common/cli/flags.go index 9770f821a2..93a9ae3fe8 100644 --- a/pkg/common/cli/flags.go +++ b/pkg/common/cli/flags.go @@ -1,6 +1,7 @@ package cli import ( + "flag" "fmt" "strings" "time" @@ -71,3 +72,43 @@ func (b *BoolFlag) Set(val string) error { *b = BoolFlagAll return nil } + +// StringVar registers a string flag with an optional shorthand. +func StringVar(f *flag.FlagSet, p *string, name, shorthand, value, usage string) { + f.StringVar(p, name, value, usage) + if shorthand != "" { + f.StringVar(p, shorthand, value, usage) + } +} + +// BoolVar registers a bool flag with an optional shorthand. +func BoolVar(f *flag.FlagSet, p *bool, name, shorthand string, value bool, usage string) { + f.BoolVar(p, name, value, usage) + if shorthand != "" { + f.BoolVar(p, shorthand, value, usage) + } +} + +// IntVar registers an int flag with an optional shorthand. +func IntVar(f *flag.FlagSet, p *int, name, shorthand string, value int, usage string) { + f.IntVar(p, name, value, usage) + if shorthand != "" { + f.IntVar(p, shorthand, value, usage) + } +} + +// Int64Var registers an int64 flag with an optional shorthand. +func Int64Var(f *flag.FlagSet, p *int64, name, shorthand string, value int64, usage string) { + f.Int64Var(p, name, value, usage) + if shorthand != "" { + f.Int64Var(p, shorthand, value, usage) + } +} + +// Var registers a flag.Value with an optional shorthand. +func Var(f *flag.FlagSet, value flag.Value, name, shorthand, usage string) { + f.Var(value, name, usage) + if shorthand != "" { + f.Var(value, shorthand, usage) + } +}