From 36f1aa9b3e1b1f21e8e0e3e15ba7f0538afadf5b Mon Sep 17 00:00:00 2001 From: abellotti Date: Wed, 13 May 2026 13:58:49 -0400 Subject: [PATCH 1/3] fix: add support for vault_key - When creating or updating credentials with HashiCorp vault secrets, require the vault_key when users specify the vault_secret_path. --- docs/_build/QPC_VAR_PROGRAM_NAME.1 | 15 +++++++--- docs/_build/man-qpc.rst | 12 +++++--- docs/_build/qpc.1 | 17 +++++++---- docs/source/man-template.rst | 12 +++++--- qpc/cred/add.py | 7 +++++ qpc/cred/edit.py | 9 ++++++ qpc/cred/utils.py | 8 ++++++ qpc/messages.py | 7 +++++ qpc/tests/cred/test_vault_cred_add.py | 29 +++++++++++++++++++ qpc/tests/cred/test_vault_cred_edit.py | 39 ++++++++++++++++++++++++++ 10 files changed, 138 insertions(+), 17 deletions(-) diff --git a/docs/_build/QPC_VAR_PROGRAM_NAME.1 b/docs/_build/QPC_VAR_PROGRAM_NAME.1 index fc174e0b..b74269eb 100644 --- a/docs/_build/QPC_VAR_PROGRAM_NAME.1 +++ b/docs/_build/QPC_VAR_PROGRAM_NAME.1 @@ -160,7 +160,7 @@ When a scan runs, it uses a source that contains information such as the host na .sp To create a credential, supply the type of credential and supply SSH credentials as either a username\-password pair, a username\-key pair, or an access token. The QPC_VAR_PROJECT tool stores each set of credentials in a separate credential entry. .sp -\fBQPC_VAR_PROGRAM_NAME cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP +\fBQPC_VAR_PROGRAM_NAME cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP \fB\-\-vault\-key=\fP \fIkey\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP .sp \fB\-\-name=name\fP .INDENT 0.0 @@ -235,7 +235,14 @@ Prompts for the access token for authentication. Mutually exclusive with the \fB \fB\-\-vault\-secret\-path=path\fP .INDENT 0.0 .INDENT 3.5 -Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. +Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. Requires \fB\-\-vault\-key\fP\&. +.UNINDENT +.UNINDENT +.sp +\fB\-\-vault\-key=key\fP +.INDENT 0.0 +.INDENT 3.5 +Required when \fB\-\-vault\-secret\-path\fP is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. .UNINDENT .UNINDENT .sp @@ -248,7 +255,7 @@ Sets the HashiCorp Vault mount point. Only valid when \fB\-\-vault\-secret\-path .sp The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the \fBQPC_VAR_PROGRAM_NAME cred edit\fP command to change credential information. The parameters for \fBQPC_VAR_PROGRAM_NAME cred edit\fP are the same as those for \fBQPC_VAR_PROGRAM_NAME cred add\fP\&. .sp -\fBQPC_VAR_PROGRAM_NAME cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP +\fBQPC_VAR_PROGRAM_NAME cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP \fB\-\-vault\-key\fP \fIkey\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP .SS Listing and Showing Credentials .sp The \fBQPC_VAR_PROGRAM_NAME cred list\fP command returns the details for every credential that is configured for QPC_VAR_PROJECT. This output includes the name and username for each entry. Secret values such as passwords and tokens are never displated in the output. @@ -1020,7 +1027,7 @@ Creating a new openshift type credential with a password .IP \(bu 2 Creating a new openshift type credential using a HashiCorp Vault secret .sp -\fBQPC_VAR_PROGRAM_NAME cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret\fP +\fBQPC_VAR_PROGRAM_NAME cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret \-\-vault\-key ocp3_key\fP .IP \(bu 2 Creating a new vcenter type credential .sp diff --git a/docs/_build/man-qpc.rst b/docs/_build/man-qpc.rst index 46c68658..9f5037ba 100644 --- a/docs/_build/man-qpc.rst +++ b/docs/_build/man-qpc.rst @@ -143,7 +143,7 @@ Creating and Editing Credentials To create a credential, supply the type of credential and supply SSH credentials as either a username-password pair, a username-key pair, or an access token. The Quipucords tool stores each set of credentials in a separate credential entry. -**qpc cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** +**qpc cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* **--vault-key=** *key* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** ``--name=name`` @@ -188,7 +188,11 @@ To create a credential, supply the type of credential and supply SSH credentials ``--vault-secret-path=path`` - Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. + Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. Requires ``--vault-key``. + +``--vault-key=key`` + + Required when ``--vault-secret-path`` is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. ``--vault-mount-point=mount_point`` @@ -196,7 +200,7 @@ To create a credential, supply the type of credential and supply SSH credentials The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the ``qpc cred edit`` command to change credential information. The parameters for ``qpc cred edit`` are the same as those for ``qpc cred add``. -**qpc cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** +**qpc cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path* **--vault-key** *key*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** Listing and Showing Credentials ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -823,7 +827,7 @@ Examples * Creating a new openshift type credential using a HashiCorp Vault secret - ``qpc cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret`` + ``qpc cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret --vault-key ocp3_key`` * Creating a new vcenter type credential diff --git a/docs/_build/qpc.1 b/docs/_build/qpc.1 index a3a8e5ba..25fc2283 100644 --- a/docs/_build/qpc.1 +++ b/docs/_build/qpc.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "qpc" "1" "April 27, 2026" "" "qpc" +.TH "qpc" "1" "May 13, 2026" "" "qpc" .SH NAME .sp qpc \- Inspect and report on product entitlement metadata from various sources, including networks and systems management solutions. @@ -160,7 +160,7 @@ When a scan runs, it uses a source that contains information such as the host na .sp To create a credential, supply the type of credential and supply SSH credentials as either a username\-password pair, a username\-key pair, or an access token. The Quipucords tool stores each set of credentials in a separate credential entry. .sp -\fBqpc cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP +\fBqpc cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP \fB\-\-vault\-key=\fP \fIkey\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP .sp \fB\-\-name=name\fP .INDENT 0.0 @@ -235,7 +235,14 @@ Prompts for the access token for authentication. Mutually exclusive with the \fB \fB\-\-vault\-secret\-path=path\fP .INDENT 0.0 .INDENT 3.5 -Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. +Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. Requires \fB\-\-vault\-key\fP\&. +.UNINDENT +.UNINDENT +.sp +\fB\-\-vault\-key=key\fP +.INDENT 0.0 +.INDENT 3.5 +Required when \fB\-\-vault\-secret\-path\fP is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. .UNINDENT .UNINDENT .sp @@ -248,7 +255,7 @@ Sets the HashiCorp Vault mount point. Only valid when \fB\-\-vault\-secret\-path .sp The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the \fBqpc cred edit\fP command to change credential information. The parameters for \fBqpc cred edit\fP are the same as those for \fBqpc cred add\fP\&. .sp -\fBqpc cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP +\fBqpc cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP \fB\-\-vault\-key\fP \fIkey\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP .SS Listing and Showing Credentials .sp The \fBqpc cred list\fP command returns the details for every credential that is configured for Quipucords. This output includes the name and username for each entry. Secret values such as passwords and tokens are never displated in the output. @@ -1020,7 +1027,7 @@ Creating a new openshift type credential with a password .IP \(bu 2 Creating a new openshift type credential using a HashiCorp Vault secret .sp -\fBqpc cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret\fP +\fBqpc cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret \-\-vault\-key ocp3_key\fP .IP \(bu 2 Creating a new vcenter type credential .sp diff --git a/docs/source/man-template.rst b/docs/source/man-template.rst index e9f08532..40ea703c 100644 --- a/docs/source/man-template.rst +++ b/docs/source/man-template.rst @@ -143,7 +143,7 @@ Creating and Editing Credentials To create a credential, supply the type of credential and supply SSH credentials as either a username-password pair, a username-key pair, or an access token. The QPC_VAR_PROJECT tool stores each set of credentials in a separate credential entry. -**QPC_VAR_PROGRAM_NAME cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** +**QPC_VAR_PROGRAM_NAME cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* **--vault-key=** *key* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** ``--name=name`` @@ -188,7 +188,11 @@ To create a credential, supply the type of credential and supply SSH credentials ``--vault-secret-path=path`` - Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. + Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. Requires ``--vault-key``. + +``--vault-key=key`` + + Required when ``--vault-secret-path`` is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. ``--vault-mount-point=mount_point`` @@ -196,7 +200,7 @@ To create a credential, supply the type of credential and supply SSH credentials The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the ``QPC_VAR_PROGRAM_NAME cred edit`` command to change credential information. The parameters for ``QPC_VAR_PROGRAM_NAME cred edit`` are the same as those for ``QPC_VAR_PROGRAM_NAME cred add``. -**QPC_VAR_PROGRAM_NAME cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** +**QPC_VAR_PROGRAM_NAME cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path* **--vault-key** *key*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** Listing and Showing Credentials ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -823,7 +827,7 @@ Examples * Creating a new openshift type credential using a HashiCorp Vault secret - ``QPC_VAR_PROGRAM_NAME cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret`` + ``QPC_VAR_PROGRAM_NAME cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret --vault-key ocp3_key`` * Creating a new vcenter type credential diff --git a/qpc/cred/add.py b/qpc/cred/add.py index 815c9716..3c1906e1 100644 --- a/qpc/cred/add.py +++ b/qpc/cred/add.py @@ -85,6 +85,13 @@ def __init__(self, subparsers): metavar="VAULT_SECRET_PATH", help=_(messages.CRED_VAULT_SECRET_PATH_HELP), ) + self.parser.add_argument( + "--vault-key", + dest="vault_key", + metavar="VAULT_KEY", + help=_(messages.CRED_VAULT_KEY_HELP), + required=False, + ) self.parser.add_argument( "--vault-mount-point", dest="vault_mount_point", diff --git a/qpc/cred/edit.py b/qpc/cred/edit.py index a6edcd66..c1d0da12 100644 --- a/qpc/cred/edit.py +++ b/qpc/cred/edit.py @@ -69,6 +69,13 @@ def __init__(self, subparsers): metavar="VAULT_SECRET_PATH", help=_(messages.CRED_VAULT_SECRET_PATH_HELP), ) + self.parser.add_argument( + "--vault-key", + dest="vault_key", + metavar="VAULT_KEY", + help=_(messages.CRED_VAULT_KEY_HELP), + required=False, + ) self.parser.add_argument( "--vault-mount-point", dest="vault_mount_point", @@ -114,6 +121,7 @@ def _validate_args(self): # Get vault options (use getattr for legacy test compatibility) vault_secret_path = getattr(self.args, "vault_secret_path", None) + vault_key = getattr(self.args, "vault_key", None) vault_mount_point = getattr(self.args, "vault_mount_point", None) if not ( @@ -126,6 +134,7 @@ def _validate_args(self): or self.args.become_password or self.args.token or vault_secret_path + or vault_key or vault_mount_point ): logger.error(_(messages.CRED_EDIT_NO_ARGS), self.args.name) diff --git a/qpc/cred/utils.py b/qpc/cred/utils.py index a0688633..46d23b6c 100644 --- a/qpc/cred/utils.py +++ b/qpc/cred/utils.py @@ -129,6 +129,8 @@ def build_credential_payload(args, cred_type, add_none=True): req_payload["become_user"] = args.become_user if "vault_secret_path" in args and args.vault_secret_path: req_payload["vault_secret_path"] = args.vault_secret_path + if "vault_key" in args and args.vault_key: + req_payload["vault_key"] = args.vault_key if "vault_mount_point" in args and args.vault_mount_point: req_payload["vault_mount_point"] = args.vault_mount_point @@ -170,6 +172,7 @@ def validate_vault_args(args, cred_type=None): """ # Get vault options (use getattr for legacy test compatibility) vault_secret_path = getattr(args, "vault_secret_path", None) + vault_key = getattr(args, "vault_key", None) vault_mount_point = getattr(args, "vault_mount_point", None) if vault_secret_path: @@ -191,6 +194,11 @@ def validate_vault_args(args, cred_type=None): logger.error(_(messages.CRED_VAULT_EXCLUSIVE_WITH_CREDS)) sys.exit(1) + # vault_key is required when vault_secret_path is specified + if not vault_key: + logger.error(_(messages.CRED_VAULT_KEY_REQUIRED)) + sys.exit(1) + # vault_mount_point can only be specified if vault_secret_path is specified if vault_mount_point and not vault_secret_path: logger.error(_(messages.CRED_VAULT_MOUNT_REQUIRES_PATH)) diff --git a/qpc/messages.py b/qpc/messages.py index 7d7a0a9e..7f600cf1 100644 --- a/qpc/messages.py +++ b/qpc/messages.py @@ -63,6 +63,10 @@ "Only valid for openshift and ansible credential types. " "Cannot be used with --username, --password, --sshkeyfile, or --token." ) +CRED_VAULT_KEY_HELP = ( + "HashiCorp Vault key within the secret. " + "Required when --vault-secret-path is specified." +) CRED_VAULT_MOUNT_POINT_HELP = ( "Optional HashiCorp Vault mount point. " "Only valid when --vault-secret-path is specified." @@ -79,6 +83,9 @@ "The --vault-mount-point option can only be specified " "when --vault-secret-path is also specified." ) +CRED_VAULT_KEY_REQUIRED = ( + "The --vault-key option is required when --vault-secret-path is specified." +) SOURCE_NAME_HELP = "Source name." SOURCES_NAME_HELP = "List of source names." diff --git a/qpc/tests/cred/test_vault_cred_add.py b/qpc/tests/cred/test_vault_cred_add.py index 829e25ee..0e6fd413 100644 --- a/qpc/tests/cred/test_vault_cred_add.py +++ b/qpc/tests/cred/test_vault_cred_add.py @@ -37,6 +37,8 @@ def test_add_vault_openshift_green_path( OPENSHIFT_CRED_TYPE, "--vault-secret-path", "secret/data/my-creds", + "--vault-key", + "my-key", ] CLI().main() assert caplog.messages[-1] == messages.CRED_ADDED % "openshift_vault_credential" @@ -63,6 +65,8 @@ def test_add_vault_ansible_green_path( ANSIBLE_SOURCE_TYPE, "--vault-secret-path", "secret/data/my-creds", + "--vault-key", + "my-key", ] CLI().main() assert caplog.messages[-1] == messages.CRED_ADDED % "ansible_vault_credential" @@ -70,6 +74,7 @@ def test_add_vault_ansible_green_path( # Validate outgoing request payload payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" + assert payload["vault_key"] == "my-key" # Mount point should not be present when not provided assert "vault_mount_point" not in payload @@ -95,6 +100,8 @@ def test_add_vault_with_mount_point( OPENSHIFT_CRED_TYPE, "--vault-secret-path", "secret/data/my-creds", + "--vault-key", + "my-key", "--vault-mount-point", "custom-mount", ] @@ -104,6 +111,7 @@ def test_add_vault_with_mount_point( # Validate outgoing request payload includes mount point when provided payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" + assert payload["vault_key"] == "my-key" assert payload["vault_mount_point"] == "custom-mount" def test_add_vault_invalid_type( @@ -127,6 +135,27 @@ def test_add_vault_invalid_type( out, err = capsys.readouterr() assert messages.CRED_VAULT_INVALID_TYPE in err + def test_add_vault_missing_key( + self, + capsys, + ): + """Test that vault secret path without vault key fails.""" + sys.argv = [ + "/bin/qpc", + "cred", + "add", + "--name", + "openshift_vault_credential", + "--type", + OPENSHIFT_CRED_TYPE, + "--vault-secret-path", + "secret/data/my-creds", + ] + with pytest.raises(SystemExit): + CLI().main() + out, err = capsys.readouterr() + assert messages.CRED_VAULT_KEY_REQUIRED in err + @patch("sys.stdin.isatty") def test_add_vault_with_username( self, diff --git a/qpc/tests/cred/test_vault_cred_edit.py b/qpc/tests/cred/test_vault_cred_edit.py index b5551bc4..b9019267 100644 --- a/qpc/tests/cred/test_vault_cred_edit.py +++ b/qpc/tests/cred/test_vault_cred_edit.py @@ -46,6 +46,8 @@ def test_edit_vault_openshift_green_path( "openshift_cred", "--vault-secret-path", "secret/data/my-creds", + "--vault-key", + "my-key", ] CLI().main() assert caplog.messages[-1] == messages.CRED_UPDATED % "openshift_cred" @@ -80,6 +82,8 @@ def test_edit_vault_ansible_green_path( "ansible_cred", "--vault-secret-path", "secret/data/my-creds", + "--vault-key", + "my-key", ] CLI().main() assert caplog.messages[-1] == messages.CRED_UPDATED % "ansible_cred" @@ -87,6 +91,7 @@ def test_edit_vault_ansible_green_path( # Validate outgoing request payload payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" + assert payload["vault_key"] == "my-key" # Mount point should not be present when not provided assert "vault_mount_point" not in payload @@ -122,6 +127,8 @@ def test_edit_vault_with_mount_point( "openshift_cred", "--vault-secret-path", "secret/data/my-creds", + "--vault-key", + "my-key", "--vault-mount-point", "custom-mount", ] @@ -131,8 +138,40 @@ def test_edit_vault_with_mount_point( # Validate outgoing request payload includes mount point when provided payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" + assert payload["vault_key"] == "my-key" assert payload["vault_mount_point"] == "custom-mount" + def test_edit_vault_missing_key( + self, + capsys, + requests_mock, + ): + """Test that vault secret path without vault key fails.""" + url = get_server_location() + CREDENTIAL_URI + requests_mock.get( + url, + status_code=200, + json={ + "count": 1, + "results": [ + {"id": 1, "name": "openshift_cred", "cred_type": "openshift"} + ], + }, + ) + sys.argv = [ + "/bin/qpc", + "cred", + "edit", + "--name", + "openshift_cred", + "--vault-secret-path", + "secret/data/my-creds", + ] + with pytest.raises(SystemExit): + CLI().main() + out, err = capsys.readouterr() + assert messages.CRED_VAULT_KEY_REQUIRED in err + def test_edit_vault_invalid_type( self, capsys, From fd8e3c421b37433886fd38ed9a0f7b082d9a4f25 Mon Sep 17 00:00:00 2001 From: abellotti Date: Wed, 13 May 2026 14:14:57 -0400 Subject: [PATCH 2/3] fix: catch case where vault_key is specified without the path - Make sure we catch the case where vault_key is specified without having secified the vault_secret_path. --- qpc/cred/utils.py | 5 +++++ qpc/messages.py | 4 ++++ qpc/tests/cred/test_vault_cred_add.py | 22 ++++++++++++++++++ qpc/tests/cred/test_vault_cred_edit.py | 31 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) diff --git a/qpc/cred/utils.py b/qpc/cred/utils.py index 46d23b6c..2b247bfd 100644 --- a/qpc/cred/utils.py +++ b/qpc/cred/utils.py @@ -199,6 +199,11 @@ def validate_vault_args(args, cred_type=None): logger.error(_(messages.CRED_VAULT_KEY_REQUIRED)) sys.exit(1) + # vault_key can only be specified if vault_secret_path is specified + if vault_key and not vault_secret_path: + logger.error(_(messages.CRED_VAULT_KEY_REQUIRES_PATH)) + sys.exit(1) + # vault_mount_point can only be specified if vault_secret_path is specified if vault_mount_point and not vault_secret_path: logger.error(_(messages.CRED_VAULT_MOUNT_REQUIRES_PATH)) diff --git a/qpc/messages.py b/qpc/messages.py index 7f600cf1..f9ee282a 100644 --- a/qpc/messages.py +++ b/qpc/messages.py @@ -86,6 +86,10 @@ CRED_VAULT_KEY_REQUIRED = ( "The --vault-key option is required when --vault-secret-path is specified." ) +CRED_VAULT_KEY_REQUIRES_PATH = ( + "The --vault-key option can only be specified " + "when --vault-secret-path is also specified." +) SOURCE_NAME_HELP = "Source name." SOURCES_NAME_HELP = "List of source names." diff --git a/qpc/tests/cred/test_vault_cred_add.py b/qpc/tests/cred/test_vault_cred_add.py index 0e6fd413..8f279104 100644 --- a/qpc/tests/cred/test_vault_cred_add.py +++ b/qpc/tests/cred/test_vault_cred_add.py @@ -185,6 +185,28 @@ def test_add_vault_with_username( out, err = capsys.readouterr() assert messages.CRED_VAULT_EXCLUSIVE_WITH_CREDS in err + def test_add_vault_key_without_path( + self, + capsys, + ): + """Test that vault key without vault secret path fails.""" + sys.argv = [ + "/bin/qpc", + "cred", + "add", + "--name", + "openshift_vault_credential", + "--type", + OPENSHIFT_CRED_TYPE, + "--password", + "--vault-key", + "my-key", + ] + with pytest.raises(SystemExit): + CLI().main() + out, err = capsys.readouterr() + assert messages.CRED_VAULT_KEY_REQUIRES_PATH in err + @patch("sys.stdin.isatty") def test_add_vault_mount_without_path( self, diff --git a/qpc/tests/cred/test_vault_cred_edit.py b/qpc/tests/cred/test_vault_cred_edit.py index b9019267..e4aed6b7 100644 --- a/qpc/tests/cred/test_vault_cred_edit.py +++ b/qpc/tests/cred/test_vault_cred_edit.py @@ -300,3 +300,34 @@ def test_edit_vault_mount_without_path( CLI().main() out, err = capsys.readouterr() assert messages.CRED_VAULT_MOUNT_REQUIRES_PATH in err + + def test_edit_vault_key_without_path( + self, + capsys, + requests_mock, + ): + """Test that vault key without vault secret path fails.""" + url = get_server_location() + CREDENTIAL_URI + requests_mock.get( + url, + status_code=200, + json={ + "count": 1, + "results": [ + {"id": 1, "name": "openshift_cred", "cred_type": "openshift"} + ], + }, + ) + sys.argv = [ + "/bin/qpc", + "cred", + "edit", + "--name", + "openshift_cred", + "--vault-key", + "my-key", + ] + with pytest.raises(SystemExit): + CLI().main() + out, err = capsys.readouterr() + assert messages.CRED_VAULT_KEY_REQUIRES_PATH in err From 1b4890f21e64b1c5c02285a3a58ad77728331bd2 Mon Sep 17 00:00:00 2001 From: abellotti Date: Wed, 13 May 2026 16:45:07 -0400 Subject: [PATCH 3/3] refactor: prerring to use vault_secret_key instead of vault_key - Preferring to use vault_secret_key instead of vault_key as to not confuse with keys uses to authenticate to the vault itself. --- docs/_build/QPC_VAR_PROGRAM_NAME.1 | 10 +++++----- docs/_build/man-qpc.rst | 10 +++++----- docs/_build/qpc.1 | 10 +++++----- docs/source/man-template.rst | 10 +++++----- qpc/cred/add.py | 8 ++++---- qpc/cred/edit.py | 12 ++++++------ qpc/cred/utils.py | 18 +++++++++--------- qpc/messages.py | 10 +++++----- qpc/tests/cred/test_vault_cred_add.py | 18 +++++++++--------- qpc/tests/cred/test_vault_cred_edit.py | 18 +++++++++--------- 10 files changed, 62 insertions(+), 62 deletions(-) diff --git a/docs/_build/QPC_VAR_PROGRAM_NAME.1 b/docs/_build/QPC_VAR_PROGRAM_NAME.1 index b74269eb..7e2ba693 100644 --- a/docs/_build/QPC_VAR_PROGRAM_NAME.1 +++ b/docs/_build/QPC_VAR_PROGRAM_NAME.1 @@ -160,7 +160,7 @@ When a scan runs, it uses a source that contains information such as the host na .sp To create a credential, supply the type of credential and supply SSH credentials as either a username\-password pair, a username\-key pair, or an access token. The QPC_VAR_PROJECT tool stores each set of credentials in a separate credential entry. .sp -\fBQPC_VAR_PROGRAM_NAME cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP \fB\-\-vault\-key=\fP \fIkey\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP +\fBQPC_VAR_PROGRAM_NAME cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP \fB\-\-vault\-secret\-key=\fP \fIkey\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP .sp \fB\-\-name=name\fP .INDENT 0.0 @@ -235,11 +235,11 @@ Prompts for the access token for authentication. Mutually exclusive with the \fB \fB\-\-vault\-secret\-path=path\fP .INDENT 0.0 .INDENT 3.5 -Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. Requires \fB\-\-vault\-key\fP\&. +Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. Requires \fB\-\-vault\-secret\-key\fP\&. .UNINDENT .UNINDENT .sp -\fB\-\-vault\-key=key\fP +\fB\-\-vault\-secret\-key=key\fP .INDENT 0.0 .INDENT 3.5 Required when \fB\-\-vault\-secret\-path\fP is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. @@ -255,7 +255,7 @@ Sets the HashiCorp Vault mount point. Only valid when \fB\-\-vault\-secret\-path .sp The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the \fBQPC_VAR_PROGRAM_NAME cred edit\fP command to change credential information. The parameters for \fBQPC_VAR_PROGRAM_NAME cred edit\fP are the same as those for \fBQPC_VAR_PROGRAM_NAME cred add\fP\&. .sp -\fBQPC_VAR_PROGRAM_NAME cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP \fB\-\-vault\-key\fP \fIkey\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP +\fBQPC_VAR_PROGRAM_NAME cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP \fB\-\-vault\-secret\-key\fP \fIkey\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP .SS Listing and Showing Credentials .sp The \fBQPC_VAR_PROGRAM_NAME cred list\fP command returns the details for every credential that is configured for QPC_VAR_PROJECT. This output includes the name and username for each entry. Secret values such as passwords and tokens are never displated in the output. @@ -1027,7 +1027,7 @@ Creating a new openshift type credential with a password .IP \(bu 2 Creating a new openshift type credential using a HashiCorp Vault secret .sp -\fBQPC_VAR_PROGRAM_NAME cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret \-\-vault\-key ocp3_key\fP +\fBQPC_VAR_PROGRAM_NAME cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret \-\-vault\-secret\-key ocp3_key\fP .IP \(bu 2 Creating a new vcenter type credential .sp diff --git a/docs/_build/man-qpc.rst b/docs/_build/man-qpc.rst index 9f5037ba..64308c34 100644 --- a/docs/_build/man-qpc.rst +++ b/docs/_build/man-qpc.rst @@ -143,7 +143,7 @@ Creating and Editing Credentials To create a credential, supply the type of credential and supply SSH credentials as either a username-password pair, a username-key pair, or an access token. The Quipucords tool stores each set of credentials in a separate credential entry. -**qpc cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* **--vault-key=** *key* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** +**qpc cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* **--vault-secret-key=** *key* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** ``--name=name`` @@ -188,9 +188,9 @@ To create a credential, supply the type of credential and supply SSH credentials ``--vault-secret-path=path`` - Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. Requires ``--vault-key``. + Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. Requires ``--vault-secret-key``. -``--vault-key=key`` +``--vault-secret-key=key`` Required when ``--vault-secret-path`` is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. @@ -200,7 +200,7 @@ To create a credential, supply the type of credential and supply SSH credentials The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the ``qpc cred edit`` command to change credential information. The parameters for ``qpc cred edit`` are the same as those for ``qpc cred add``. -**qpc cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path* **--vault-key** *key*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** +**qpc cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path* **--vault-secret-key** *key*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** Listing and Showing Credentials ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -827,7 +827,7 @@ Examples * Creating a new openshift type credential using a HashiCorp Vault secret - ``qpc cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret --vault-key ocp3_key`` + ``qpc cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret --vault-secret-key ocp3_key`` * Creating a new vcenter type credential diff --git a/docs/_build/qpc.1 b/docs/_build/qpc.1 index 25fc2283..4c44764a 100644 --- a/docs/_build/qpc.1 +++ b/docs/_build/qpc.1 @@ -160,7 +160,7 @@ When a scan runs, it uses a source that contains information such as the host na .sp To create a credential, supply the type of credential and supply SSH credentials as either a username\-password pair, a username\-key pair, or an access token. The Quipucords tool stores each set of credentials in a separate credential entry. .sp -\fBqpc cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP \fB\-\-vault\-key=\fP \fIkey\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP +\fBqpc cred add \-\-name=\fP \fIname\fP \fB\-\-type=\fP \fI(network | vcenter | satellite | openshift | rhacs | ansible)\fP { \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP | \fB\-\-token\fP) | \fB\-\-vault\-secret\-path=\fP \fIpath\fP \fB\-\-vault\-secret\-key=\fP \fIkey\fP [\fB\-\-vault\-mount\-point=\fP \fImount_point\fP] } \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP .sp \fB\-\-name=name\fP .INDENT 0.0 @@ -235,11 +235,11 @@ Prompts for the access token for authentication. Mutually exclusive with the \fB \fB\-\-vault\-secret\-path=path\fP .INDENT 0.0 .INDENT 3.5 -Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. Requires \fB\-\-vault\-key\fP\&. +Sets the HashiCorp Vault secret path for credential storage. Only valid for \fBopenshift\fP and \fBansible\fP credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the \fB\-\-username\fP, \fB\-\-password\fP, \fB\-\-sshkeyfile\fP, and \fB\-\-token\fP options. Requires \fB\-\-vault\-secret\-key\fP\&. .UNINDENT .UNINDENT .sp -\fB\-\-vault\-key=key\fP +\fB\-\-vault\-secret\-key=key\fP .INDENT 0.0 .INDENT 3.5 Required when \fB\-\-vault\-secret\-path\fP is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. @@ -255,7 +255,7 @@ Sets the HashiCorp Vault mount point. Only valid when \fB\-\-vault\-secret\-path .sp The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the \fBqpc cred edit\fP command to change credential information. The parameters for \fBqpc cred edit\fP are the same as those for \fBqpc cred add\fP\&. .sp -\fBqpc cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP \fB\-\-vault\-key\fP \fIkey\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP +\fBqpc cred edit \-\-name=\fP \fIname\fP \fB\-\-username=\fP \fIusername\fP (\fB\-\-password\fP | \fB\-\-sshkeyfile\fP \fI(ssh_keyfile | \-)\fP \fB| \-\-token | \-\-vault\-secret\-path\fP \fIpath\fP \fB\-\-vault\-secret\-key\fP \fIkey\fP) \fB[\-\-sshpassphrase]\fP \fB\-\-become\-method=\fP \fI(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )\fP \fB\-\-become\-user=\fP \fIuser\fP \fB[\-\-become\-password]\fP \fB[\-\-vault\-mount\-point\fP \fImount_point\fP \fB]\fP .SS Listing and Showing Credentials .sp The \fBqpc cred list\fP command returns the details for every credential that is configured for Quipucords. This output includes the name and username for each entry. Secret values such as passwords and tokens are never displated in the output. @@ -1027,7 +1027,7 @@ Creating a new openshift type credential with a password .IP \(bu 2 Creating a new openshift type credential using a HashiCorp Vault secret .sp -\fBqpc cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret \-\-vault\-key ocp3_key\fP +\fBqpc cred add \-\-name ocp_cred3 \-\-type openshift \-\-vault\-secret\-path ocp3_secret \-\-vault\-secret\-key ocp3_key\fP .IP \(bu 2 Creating a new vcenter type credential .sp diff --git a/docs/source/man-template.rst b/docs/source/man-template.rst index 40ea703c..987cfe21 100644 --- a/docs/source/man-template.rst +++ b/docs/source/man-template.rst @@ -143,7 +143,7 @@ Creating and Editing Credentials To create a credential, supply the type of credential and supply SSH credentials as either a username-password pair, a username-key pair, or an access token. The QPC_VAR_PROJECT tool stores each set of credentials in a separate credential entry. -**QPC_VAR_PROGRAM_NAME cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* **--vault-key=** *key* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** +**QPC_VAR_PROGRAM_NAME cred add --name=** *name* **--type=** *(network | vcenter | satellite | openshift | rhacs | ansible)* { **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* | **--token**) | **--vault-secret-path=** *path* **--vault-secret-key=** *key* [**--vault-mount-point=** *mount_point*] } **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** ``--name=name`` @@ -188,9 +188,9 @@ To create a credential, supply the type of credential and supply SSH credentials ``--vault-secret-path=path`` - Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. Requires ``--vault-key``. + Sets the HashiCorp Vault secret path for credential storage. Only valid for ``openshift`` and ``ansible`` credential types. When this option is used, credentials are retrieved from the configured HashiCorp Vault server instead of being stored in the QPC database. Mutually exclusive with the ``--username``, ``--password``, ``--sshkeyfile``, and ``--token`` options. Requires ``--vault-secret-key``. -``--vault-key=key`` +``--vault-secret-key=key`` Required when ``--vault-secret-path`` is specified. Sets the key within the HashiCorp Vault secret from which the credential value is retrieved. @@ -200,7 +200,7 @@ To create a credential, supply the type of credential and supply SSH credentials The information in a credential might change, including passwords, become passwords, SSH keys, the become_method, tokens or even the username. For example, your local security policies might require you to change passwords periodically. Use the ``QPC_VAR_PROGRAM_NAME cred edit`` command to change credential information. The parameters for ``QPC_VAR_PROGRAM_NAME cred edit`` are the same as those for ``QPC_VAR_PROGRAM_NAME cred add``. -**QPC_VAR_PROGRAM_NAME cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path* **--vault-key** *key*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** +**QPC_VAR_PROGRAM_NAME cred edit --name=** *name* **--username=** *username* (**--password** | **--sshkeyfile** *(ssh_keyfile | -)* **| --token | --vault-secret-path** *path* **--vault-secret-key** *key*) **[--sshpassphrase]** **--become-method=** *(sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas )* **--become-user=** *user* **[--become-password]** **[--vault-mount-point** *mount_point* **]** Listing and Showing Credentials ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -827,7 +827,7 @@ Examples * Creating a new openshift type credential using a HashiCorp Vault secret - ``QPC_VAR_PROGRAM_NAME cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret --vault-key ocp3_key`` + ``QPC_VAR_PROGRAM_NAME cred add --name ocp_cred3 --type openshift --vault-secret-path ocp3_secret --vault-secret-key ocp3_key`` * Creating a new vcenter type credential diff --git a/qpc/cred/add.py b/qpc/cred/add.py index 3c1906e1..8f703402 100644 --- a/qpc/cred/add.py +++ b/qpc/cred/add.py @@ -86,10 +86,10 @@ def __init__(self, subparsers): help=_(messages.CRED_VAULT_SECRET_PATH_HELP), ) self.parser.add_argument( - "--vault-key", - dest="vault_key", - metavar="VAULT_KEY", - help=_(messages.CRED_VAULT_KEY_HELP), + "--vault-secret-key", + dest="vault_secret_key", + metavar="VAULT_SECRET_KEY", + help=_(messages.CRED_VAULT_SECRET_KEY_HELP), required=False, ) self.parser.add_argument( diff --git a/qpc/cred/edit.py b/qpc/cred/edit.py index c1d0da12..89d589d0 100644 --- a/qpc/cred/edit.py +++ b/qpc/cred/edit.py @@ -70,10 +70,10 @@ def __init__(self, subparsers): help=_(messages.CRED_VAULT_SECRET_PATH_HELP), ) self.parser.add_argument( - "--vault-key", - dest="vault_key", - metavar="VAULT_KEY", - help=_(messages.CRED_VAULT_KEY_HELP), + "--vault-secret-key", + dest="vault_secret_key", + metavar="VAULT_SECRET_KEY", + help=_(messages.CRED_VAULT_SECRET_KEY_HELP), required=False, ) self.parser.add_argument( @@ -121,7 +121,7 @@ def _validate_args(self): # Get vault options (use getattr for legacy test compatibility) vault_secret_path = getattr(self.args, "vault_secret_path", None) - vault_key = getattr(self.args, "vault_key", None) + vault_secret_key = getattr(self.args, "vault_secret_key", None) vault_mount_point = getattr(self.args, "vault_mount_point", None) if not ( @@ -134,7 +134,7 @@ def _validate_args(self): or self.args.become_password or self.args.token or vault_secret_path - or vault_key + or vault_secret_key or vault_mount_point ): logger.error(_(messages.CRED_EDIT_NO_ARGS), self.args.name) diff --git a/qpc/cred/utils.py b/qpc/cred/utils.py index 2b247bfd..39ccf2d9 100644 --- a/qpc/cred/utils.py +++ b/qpc/cred/utils.py @@ -129,8 +129,8 @@ def build_credential_payload(args, cred_type, add_none=True): req_payload["become_user"] = args.become_user if "vault_secret_path" in args and args.vault_secret_path: req_payload["vault_secret_path"] = args.vault_secret_path - if "vault_key" in args and args.vault_key: - req_payload["vault_key"] = args.vault_key + if "vault_secret_key" in args and args.vault_secret_key: + req_payload["vault_secret_key"] = args.vault_secret_key if "vault_mount_point" in args and args.vault_mount_point: req_payload["vault_mount_point"] = args.vault_mount_point @@ -172,7 +172,7 @@ def validate_vault_args(args, cred_type=None): """ # Get vault options (use getattr for legacy test compatibility) vault_secret_path = getattr(args, "vault_secret_path", None) - vault_key = getattr(args, "vault_key", None) + vault_secret_key = getattr(args, "vault_secret_key", None) vault_mount_point = getattr(args, "vault_mount_point", None) if vault_secret_path: @@ -194,14 +194,14 @@ def validate_vault_args(args, cred_type=None): logger.error(_(messages.CRED_VAULT_EXCLUSIVE_WITH_CREDS)) sys.exit(1) - # vault_key is required when vault_secret_path is specified - if not vault_key: - logger.error(_(messages.CRED_VAULT_KEY_REQUIRED)) + # vault_secret_key is required when vault_secret_path is specified + if not vault_secret_key: + logger.error(_(messages.CRED_VAULT_SECRET_KEY_REQUIRED)) sys.exit(1) - # vault_key can only be specified if vault_secret_path is specified - if vault_key and not vault_secret_path: - logger.error(_(messages.CRED_VAULT_KEY_REQUIRES_PATH)) + # vault_secret_key can only be specified if vault_secret_path is specified + if vault_secret_key and not vault_secret_path: + logger.error(_(messages.CRED_VAULT_SECRET_KEY_REQUIRES_PATH)) sys.exit(1) # vault_mount_point can only be specified if vault_secret_path is specified diff --git a/qpc/messages.py b/qpc/messages.py index f9ee282a..8f17da66 100644 --- a/qpc/messages.py +++ b/qpc/messages.py @@ -63,7 +63,7 @@ "Only valid for openshift and ansible credential types. " "Cannot be used with --username, --password, --sshkeyfile, or --token." ) -CRED_VAULT_KEY_HELP = ( +CRED_VAULT_SECRET_KEY_HELP = ( "HashiCorp Vault key within the secret. " "Required when --vault-secret-path is specified." ) @@ -83,11 +83,11 @@ "The --vault-mount-point option can only be specified " "when --vault-secret-path is also specified." ) -CRED_VAULT_KEY_REQUIRED = ( - "The --vault-key option is required when --vault-secret-path is specified." +CRED_VAULT_SECRET_KEY_REQUIRED = ( + "The --vault-secret-key option is required when --vault-secret-path is specified." ) -CRED_VAULT_KEY_REQUIRES_PATH = ( - "The --vault-key option can only be specified " +CRED_VAULT_SECRET_KEY_REQUIRES_PATH = ( + "The --vault-secret-key option can only be specified " "when --vault-secret-path is also specified." ) diff --git a/qpc/tests/cred/test_vault_cred_add.py b/qpc/tests/cred/test_vault_cred_add.py index 8f279104..927c7c29 100644 --- a/qpc/tests/cred/test_vault_cred_add.py +++ b/qpc/tests/cred/test_vault_cred_add.py @@ -37,7 +37,7 @@ def test_add_vault_openshift_green_path( OPENSHIFT_CRED_TYPE, "--vault-secret-path", "secret/data/my-creds", - "--vault-key", + "--vault-secret-key", "my-key", ] CLI().main() @@ -65,7 +65,7 @@ def test_add_vault_ansible_green_path( ANSIBLE_SOURCE_TYPE, "--vault-secret-path", "secret/data/my-creds", - "--vault-key", + "--vault-secret-key", "my-key", ] CLI().main() @@ -74,7 +74,7 @@ def test_add_vault_ansible_green_path( # Validate outgoing request payload payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" - assert payload["vault_key"] == "my-key" + assert payload["vault_secret_key"] == "my-key" # Mount point should not be present when not provided assert "vault_mount_point" not in payload @@ -100,7 +100,7 @@ def test_add_vault_with_mount_point( OPENSHIFT_CRED_TYPE, "--vault-secret-path", "secret/data/my-creds", - "--vault-key", + "--vault-secret-key", "my-key", "--vault-mount-point", "custom-mount", @@ -111,7 +111,7 @@ def test_add_vault_with_mount_point( # Validate outgoing request payload includes mount point when provided payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" - assert payload["vault_key"] == "my-key" + assert payload["vault_secret_key"] == "my-key" assert payload["vault_mount_point"] == "custom-mount" def test_add_vault_invalid_type( @@ -154,7 +154,7 @@ def test_add_vault_missing_key( with pytest.raises(SystemExit): CLI().main() out, err = capsys.readouterr() - assert messages.CRED_VAULT_KEY_REQUIRED in err + assert messages.CRED_VAULT_SECRET_KEY_REQUIRED in err @patch("sys.stdin.isatty") def test_add_vault_with_username( @@ -185,7 +185,7 @@ def test_add_vault_with_username( out, err = capsys.readouterr() assert messages.CRED_VAULT_EXCLUSIVE_WITH_CREDS in err - def test_add_vault_key_without_path( + def test_add_vault_secret_key_without_path( self, capsys, ): @@ -199,13 +199,13 @@ def test_add_vault_key_without_path( "--type", OPENSHIFT_CRED_TYPE, "--password", - "--vault-key", + "--vault-secret-key", "my-key", ] with pytest.raises(SystemExit): CLI().main() out, err = capsys.readouterr() - assert messages.CRED_VAULT_KEY_REQUIRES_PATH in err + assert messages.CRED_VAULT_SECRET_KEY_REQUIRES_PATH in err @patch("sys.stdin.isatty") def test_add_vault_mount_without_path( diff --git a/qpc/tests/cred/test_vault_cred_edit.py b/qpc/tests/cred/test_vault_cred_edit.py index e4aed6b7..a90d60c6 100644 --- a/qpc/tests/cred/test_vault_cred_edit.py +++ b/qpc/tests/cred/test_vault_cred_edit.py @@ -46,7 +46,7 @@ def test_edit_vault_openshift_green_path( "openshift_cred", "--vault-secret-path", "secret/data/my-creds", - "--vault-key", + "--vault-secret-key", "my-key", ] CLI().main() @@ -82,7 +82,7 @@ def test_edit_vault_ansible_green_path( "ansible_cred", "--vault-secret-path", "secret/data/my-creds", - "--vault-key", + "--vault-secret-key", "my-key", ] CLI().main() @@ -91,7 +91,7 @@ def test_edit_vault_ansible_green_path( # Validate outgoing request payload payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" - assert payload["vault_key"] == "my-key" + assert payload["vault_secret_key"] == "my-key" # Mount point should not be present when not provided assert "vault_mount_point" not in payload @@ -127,7 +127,7 @@ def test_edit_vault_with_mount_point( "openshift_cred", "--vault-secret-path", "secret/data/my-creds", - "--vault-key", + "--vault-secret-key", "my-key", "--vault-mount-point", "custom-mount", @@ -138,7 +138,7 @@ def test_edit_vault_with_mount_point( # Validate outgoing request payload includes mount point when provided payload = requests_mock.last_request.json() assert payload["vault_secret_path"] == "secret/data/my-creds" - assert payload["vault_key"] == "my-key" + assert payload["vault_secret_key"] == "my-key" assert payload["vault_mount_point"] == "custom-mount" def test_edit_vault_missing_key( @@ -170,7 +170,7 @@ def test_edit_vault_missing_key( with pytest.raises(SystemExit): CLI().main() out, err = capsys.readouterr() - assert messages.CRED_VAULT_KEY_REQUIRED in err + assert messages.CRED_VAULT_SECRET_KEY_REQUIRED in err def test_edit_vault_invalid_type( self, @@ -301,7 +301,7 @@ def test_edit_vault_mount_without_path( out, err = capsys.readouterr() assert messages.CRED_VAULT_MOUNT_REQUIRES_PATH in err - def test_edit_vault_key_without_path( + def test_edit_vault_secret_key_without_path( self, capsys, requests_mock, @@ -324,10 +324,10 @@ def test_edit_vault_key_without_path( "edit", "--name", "openshift_cred", - "--vault-key", + "--vault-secret-key", "my-key", ] with pytest.raises(SystemExit): CLI().main() out, err = capsys.readouterr() - assert messages.CRED_VAULT_KEY_REQUIRES_PATH in err + assert messages.CRED_VAULT_SECRET_KEY_REQUIRES_PATH in err