ansible-collections / community.general

Ansible Community General Collection
https://galaxy.ansible.com/ui/repo/published/community/general/
GNU General Public License v3.0
820 stars 1.5k forks source link

java_cert: module fails if pkcs12_alias omitted #6010

Open jlm0x017 opened 1 year ago

jlm0x017 commented 1 year ago

Summary

I attempted to use the community.general.java_cert module to import a pkcs12 module into a keystore. I did not specify a pkcs12_alias.

The call fails.

The module constructs the command to keytool, but the absent alias the command gets misinterpreted. Specifically, this is generaged: ... -alias -storetype pkcs12 .... -storetype is interpreted as the alias, and keytool wants to read pkcs12 as a command, rather than as the storetype.

At its simplest, the documentation could list pkcs12_alias as mandatory. But that's not the best answer.

If we only ever use keytool generated pkcs12 certificates, then the alias will likely be there (I didn't dig into its source). However, 'alias' is not part of the standard. Openssl-generated pkcs12 certificates will not have this attribute (as I found out much to my chagrin, having started with community.crypto.openssl_pkcs12).

The better answer is to handle the lack of alias in the command line generation; however, this means validating that keytool will do the right thing. I've not investigated that directly.

Should the simple solution of making pkcs12_alias mandatory, please amend the header synopsis to discuss the modules bias towards keytool generated keys.

Issue Type

Bug Report

Component Name

java_cert

Ansible Version

$ ansible --version
ansible [core 2.14.2]
  config file = /Users/xxx/Workspace/ansible.20221219/ansible.cfg
  configured module search path = ['/Users/xxx/Workspace/ansible.20221219/library']
  ansible python module location = /opt/homebrew/Cellar/ansible/7.2.0/libexec/lib/python3.11/site-packages/ansible
  ansible collection location = /Users/xxx/.ansible/collections:/usr/share/ansible/collections
  executable location = /opt/homebrew/bin/ansible
  python version = 3.11.1 (main, Dec 23 2022, 09:25:23) [Clang 14.0.0 (clang-1400.0.29.202)] (/opt/homebrew/Cellar/ansible/7.2.0/libexec/bin/python3.11)
  jinja version = 3.1.2
  libyaml = True

Community.general Version

$ ansible-galaxy collection list community.general

# /opt/homebrew/Cellar/ansible/7.2.0/libexec/lib/python3.11/site-packages/ansible_collections
Collection        Version
----------------- -------
community.general 6.3.0  

Configuration

$ ansible-config dump --only-changed
CONFIG_FILE() = /Users/xxx/Workspace/ansible.20221219/ansible.cfg
DEFAULT_FORKS(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = 20
DEFAULT_HOST_LIST(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = ['/Users/xxx/Workspace/ansible.20221219/hosts']
DEFAULT_MODULE_PATH(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = ['/Users/xxx/Workspace/ansible.20221219/library']
DEFAULT_ROLES_PATH(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = ['/Users/xxx/Workspace/ansible.20221219/roles']
DEFAULT_VAULT_PASSWORD_FILE(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = /Users/xxx/.vault-pass
HOST_KEY_CHECKING(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = False
RETRY_FILES_ENABLED(/Users/xxx/Workspace/ansible.20221219/ansible.cfg) = False

OS / Environment

source machine: macOS version 12.6.2

remote machine:

# cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"

Steps to Reproduce

---
- hosts: i-0704cf1dfb27fcea1

  tasks:
    - community.general.java_cert:
        pkcs12_path: "/opt/sample/nonexistant.p12"
        pkcs12_password: "foobarbaz"
        cert_alias: "tomcat"
        keystore_path: "/opt/sample/never_gets_created.jks"
        keystore_type: "jks"
        keystore_pass: "onetwothree"
        keystore_create: true
        state: present

Expected Results

I would expect key_tool to attempt to import the cert; instead, it fails because the keytool command is getting corrupted.

Actual Results

<elided>
fatal: [i-0704cf1dfb27fcea1]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "cert_alias": "tomcat",
            "cert_path": null,
            "cert_port": 443,
            "cert_url": null,
            "executable": "keytool",
            "keystore_create": true,
            "keystore_pass": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "keystore_path": "/opt/sample/never_gets_created.jks",
            "keystore_type": "jks",
            "pkcs12_alias": null,
            "pkcs12_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "pkcs12_path": "/opt/sample/nonexistant.p12",
            "state": "present",
            "trust_cacert": false
        }
    },
    "msg": "Internal module failure, cannot extract public certificate from PKCS12, message: ",
    "rc": 1,
    "stderr": "Illegal option:  pkcs12\nkeytool -list [OPTION]...\n\nLists entries in a keystore\n\nOptions:\n\n -rfc                    output in RFC style\n -alias <alias>          alias name of the entry to process\n -keystore <keystore>    keystore name\n -cacerts                access the cacerts keystore\n -storepass <arg>        keystore password\n -storetype <type>       keystore type\n -providername <name>    provider name\n -addprovider <name>     add security provider by name (e.g. SunPKCS11)\n   [-providerarg <arg>]    configure argument for -addprovider\n -providerclass <class>  add security provider by fully-qualified class name\n   [-providerarg <arg>]    configure argument for -providerclass\n -providerpath <list>    provider classpath\n -v                      verbose output\n -protected              password through protected mechanism\n\nUse \"keytool -?, -h, or --help\" for this help message\n",
    "stderr_lines": [
        "Illegal option:  pkcs12",
        "keytool -list [OPTION]...",
        "",
        "Lists entries in a keystore",
        "",
        "Options:",
        "",
        " -rfc                    output in RFC style",
        " -alias <alias>          alias name of the entry to process",
        " -keystore <keystore>    keystore name",
        " -cacerts                access the cacerts keystore",
        " -storepass <arg>        keystore password",
        " -storetype <type>       keystore type",
        " -providername <name>    provider name",
        " -addprovider <name>     add security provider by name (e.g. SunPKCS11)",
        "   [-providerarg <arg>]    configure argument for -addprovider",
        " -providerclass <class>  add security provider by fully-qualified class name",
        "   [-providerarg <arg>]    configure argument for -providerclass",
        " -providerpath <list>    provider classpath",
        " -v                      verbose output",
        " -protected              password through protected mechanism",
        "",
        "Use \"keytool -?, -h, or --help\" for this help message"
    ]
}

PLAY RECAP *********************************************************************
i-0704cf1dfb27fcea1        : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

Code of Conduct

ansibullbot commented 1 year ago

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot commented 1 year ago

cc @absynth76 @haad click here for bot help

felixfontein commented 1 year ago

I guess '-alias' should only be added to the list if alias is not None. Not sure whether there is some more dependence on alias being present in the module's logic though.