Package: ahvl
ahvlBase libraries for the Ansible HashiCorp Vault Lookup (AHVL) Plugin by NetsonContentsIntroductionSecretsOutput filtersRequirementsInstallationStorage structureExamplesPasswordsConfiguration optionsahvl Lookup Password optionsahvl Lookup SSH Key optionsahvl Lookup SSH Hostkey optionsahvl Lookup GPG Key optionsahvl Lookup Credential optionsahvl Generate Password optionsahvl Generate SSH Key optionsahvl Generate SSH Hostkey optionsahvl Generate GPG Key optionsahvl Generate Salt optionsIntroductionShort versionA set of lookup plugins which retrieves secrets from HashiCorp Vault, and generates them automatically if they don't exist. It support generating passwords, SSH keys, SSH hostkeys and GPG keys. Keys are generated and converted to various formats to support a wide range of applications. All aspects of the various keys are stored in vault and accessible. Each secret can be passed through an output filter or hash function so no further processing is necessary. Hash functions which require a salt will store the salt in Vault as well to maintain idempotence.TL;DRManaging secrets properly is tough. Even though there are great tools available which help you manage, rotate and audit your secrets properly, it still requires a significant effort. These ansible lookup plugins aim to make that process easier. When managing many servers with Ansible, the number of secrets you need to manage just keeps growing and even though Ansible provides its own Ansible Vault as a means to store these secrets in an encrypted form, I still found the process to be quite cumbersome and I wanted to keep all my secrets out of version control entirely, encrypted or not.My first attempt at using a different secrets store, other than Ansible Vault, was built on KeePass which I have used successfully and happily for over 10 years now. After spending a good amount of time developing a lookup plugin for keepass I ran into a major issue: performance! For each lookup, the KeePass database had to be unlocked, decrypted, searched, encrypted and closed again. For a few lookups, this was not an issue, but since we're talking seconds per lookup, this didn't seem like a scalable solution. Enter HashiCorp Vault. HashiCorp Vault was built specifically for the purpose of managing secrets and provided important features straight out of the box: auditing, fine-grained access control, versioning, etc.The next major issue I have is with generating secrets; when creating user accounts, when setting up databases, when generating SSH keys and potentially having to convert them because your end user uses Putty on a windows system, when generating GPG keys to protect automated backups etc. etc. Generating the secrets is one thing, but then you need to store these secrets in vault in order to be able to retrieve them in your playbooks. Again, quite a time consuming process, not to mention the risk of generating insecure secrets due to missing parameters, insecure system defaults, poorly configured tools, or simply a lack of sleep!Then another issue I had with the manual secret managing process, is that often you need secrets in a particular format for a specific purpose. I already mentioned the SSH key that needs to be converted to the Putty format, but when creating a user account, you may need the password to be hashed as a sha256crypt hash or a particular application hash such as the MySQL41 hash.Previously I had a bunch of bash scripts to help me generate and convert all these secrets, but storing them safely was always cumbersome. These lookup plugins attempt to solve all these issues at once! Keep all secrets out of version control, store them securly in HashiCorp Vault, and when you request a secret which does not exist (yet), it will simply generate it for you on the fly and store it in Vault! Last but not least, you can request the specific output that you need and the plugin will return the converted secret!SecretsVarious types of secrets are supported, seperated into seperate lookup plugins. For all lookup plugins sane and secure defaults have been set, but you can manipulate almost all aspects of the secret generating process using variables to match your needs.TypeDescriptionPasswordsThis lookup plugin will return straight forward passwords. It uses the python library Passlib to generate secure secrets.SSH keysThis lookup plugin allows you to fetch every aspect of an SSH key: private key in various formats (OpenSSH, Putty, SSHCOM, PKCS8), public key in various formats (OpenSSH, PEM, PKCS8, RFC4716), but also the MD5 and SHA256 fingerprints, the key art and bubblebabble and of course the password!SSH hostkeysThis lookup plugin will generate a set of SSH hostkeys in 2 formats (RSA and Ed25519), the matching DNS entries, fingerprints and bubblebabble. Never again do you have an excuse to not have you knownhosts file out of date or to support the older, insecure hostkey formats.GPG keysThis lookup plugin allows you to generate 2 sets of keys on the fly. The 'regular' setting will generate a single master key (cert only) and 3 subkeys, each with a single responsibility (sign, encr or auth). All aspects of the generated key can be retrieved, from the KeyID, fingerprint and keygrip to the expiration date, private key (armored) and of course the password. The 'backup' setting will generate 2 master keys, each with a single subkey. One will be used for signing only, the other for encryption only. The encryption key will be signed by the signing key. Again, all aspects of each key will be stored in vault and can be retrieved.CredentialsCredentials are similar to passwords, however, they differ on 1 main aspect: credentials are never automatically generated. I use these to store my AWS, GCP, API keys and other sorts of external credentials which are needed by various playbooks.Output filtersEach of the above secrets can be run through an output filter before being returned to your playbook. If you select a hashing algorithm which requires a salt, the lookup plugin will automatically generate a unique salt for you and store this salt in Vault as well, to make sure that each subsequent playbook run maintains idempotence. For each combination of secret, hostname and hashing algorithm, a unique salt is generated and stored next to the requested secret so they can be easily found and salt reuse is limited as much as possible accross hosts and services. The following output filters are supported:Filter/OutDescriptionplaintextReturns the plaintext versionhexsha256Returns the sha256 hashed versionhexsha512Returns the sha512 hashed versionsha256cryptReturn the Crypt hashed and salted SHA-256 versionsha512cryptReturns the Crypt hashed and salted SHA-512 versionpbkdf2sha256Return the PBKDF2 hashed and salted SHA-256 versionpbkdf2sha512Return the PBKDF2 hashed and salted SHA-512 versiongrubpbkdf2sha512Return the GRUB specific PBKDF2 hashed and salted SHA-512 versionphpassReturns the PHPass hashed and salted versionmysql41Returns the MySQL41 hashed versionpostgresmd5Returns the PostgreSQL hashed version (uses the 'in' parameter as usernameargon2Returns the Argon2 hashed and salted versionRequirementsThese lookup plugins depend on the following software packages:NameMin. versionCommentsAnsible2.7Doesn't really need an introduction hereHashiCorp Vault1.1.3Only KV storage engine version 2 is supportedGnuPG2.1.17To generate GPG KeysLibgcrypt1.8.1Required by GnuPGOpenSSL1.1.1To generate SSH Keys and SSH Hostkeysputty-tools0.7.2To convert SSH keys to various formatsPython3.6May work with other versions, but is untestedAdditionally, the following python packages are required. These should be installed automatically or be part of the default python distribution.Python packagedistutilstimepasslibshutilsubprocessreoshvacrandompackagingargon2-cffiInstallationInstall packagepipinstallahvlPackage will most likely be installed in/usr/local/lib/pythonX.X/dist-packages/ahvlon ubuntu systemsUpgrade packagepipinstall--upgradeahvlStorage structureThese lookup plugins, by default, store different secrets at different paths in Vault.The default paths are as follows:Secret typeDefault pathCommentspasswordhosts/{hostname}/{find}Regular passwords are stored per host, so having the same 'find' on different hosts will lead to different passwordssshkeysshkeys/{find}SSH keys are usually per user, and are not usually unique per hostsshhostkeyhosts/{hostname}/sshhostkeysHostkeys are, obviously, different per host, so are stored under hostsgpgkeygpgkeys/{find}GPG keys are usually per user, and are not usually unique per hostcredentialcredentials/{find}Credentials (AWS, API keys, etc) are stored seperatelysaltAlways at the same path as the secretIf a salt is generated it will always be stored in vault to ensure idempotence across runs. The path for the salt will be based on the path of the secret, will have the same 'in', but appended with the hostname, hashtype and the fixed string 'salt' at the endThe optionpathdoes not need to be provided to the lookup plugin, instead it will be calculated. However, if you wish to have a different storage structure, you can simply change the base values as you see fit. You can use the variables{find}and{hostname}in your paths. Please be aware of any conflicting paths though. A specific path for salts cannot be set and will always follow the rules above.Using the default settings, you will end up with a structure that looks similar to the one below. The lowest levels will contain the key/value combinations.+-secret/
  +-credentials/
    +-aws/
    +-gcp/
  +-hosts/
    +-srv1.example.com/
      +-sshhostkeys/
        +-ed25519/
        +-rsa/
      +-mariadb/
  +-sshkeys/
    +-myuser/
  +-gpgkeys/
    +-someusr/ExamplesHashiCorp Vault connection# ansible.cfg...# connection details for HashiVault lookup plugin[ahvl_connection]ahvl_url=https://192.168.1.100:8200ahvl_auth_method=tokenahvl_validate_certs=Trueahvl_cacert=/usr/local/share/ca-certificates/Netson_CA.crt# /etc/environment...AHVL_CONNECTION_AHVL_TOKEN=<myvaulttoken>PASSLIB_MAX_PASSWORD_SIZE=16384# to prevent error when using the hash function on (very) large passwords or keysPasswords---# playbook to demonstrate ahvl_password-hosts:localhostgather_facts:novars:output_filters:-plaintext-hexsha256-hexsha512-sha256crypt-sha512crypt-phpass-mysql41-postgresmd5-pbkdf2sha256-pbkdf2sha512-argon2-grubpbkdf2sha512tasks:# the path in vault which will be searched is [hosts/localhost/mariadb] on the default mountpoint-name:'ahvl_password:getpasswordforMariaDBaccountwithusernamemyuserandshowalloutputs'debug:msg:"{{lookup('ahvl_password',find='mariadb',in='myuser',out=item)}}"loop:"{{output_filters}}"-name:'ahvl_password:getpassword(length=8,type=phrase-willresultin8words)forMariaDBaccountwithusernameanotheruserandoutputthemysql41hash'debug:msg:"{{lookup('ahvl_password',find='mariadb',in='anotheruser',out='mysql41',pwd_length=8,pwd_type='phrase')}}"Additionally, passwords can be set with a value from your playbook. This can be useful to store secrets which you receive from an API or similar. For example, when creating IAM users on Amazon AWS, you could use the following example to store the returned access key in Vault:---
# playbook to demonstrate ahvl_set_password

- hosts: localhost
  gather_facts: no

  tasks:

  # the path in vault which will be set is [hosts/localhost/awstestusr] on the default mountpoint
  - name: 'ahvl_set_password : set password for aws user, created via ansible'
    debug:
      msg: "{{ lookup('ahvl_set_password', find='awstestusr', in='myawsuser', pwd='mypasswd') }}"SSH keys---# playbook to demonstrate ahvl_sshkey-hosts:localhostgather_facts:novars:ahvl_generate_sshkey:sshkey_pkcs8_enabled:yes# requires openssl 6.5+sshkey_putty_enabled:yes# requires puttygen 0.72+# PCKS8 and SSHCOM do not support Ed25519 keyssshkey_ed25519_in:-password-private-private_keybits-private_keytype-private_openssh-private_putty-public-public_rfc4716-fingerprint_sha256-fingerprint_sha256_clean-fingerprint_sha256_art-fingerprint_md5-fingerprint_md5_clean-fingerprint_md5_art-fingerprint_bubblebabble-fingerprint_bubblebabble_clean-fingerprint_puttysshkey_rsa_in:-password-private-private_keybits-private_keytype-private_pkcs8-private_openssh-private_putty-private_sshcom-public-public_pem-public_pkcs8-public_rfc4716-fingerprint_sha256-fingerprint_sha256_clean-fingerprint_sha256_art-fingerprint_md5-fingerprint_md5_clean-fingerprint_md5_art-fingerprint_bubblebabble-fingerprint_bubblebabble_clean-fingerprint_puttytasks:-name:'ahvl_sshkey:fetch/generateSSHkeyoftypeEd25519andoutputallinformationpieces'debug:msg:"{{lookup('ahvl_sshkey',find='myusername',in=item,out='plaintext')}}"loop:"{{sshkey_ed25519_in}}"-name:'ahvl_sshkey:rsa'debug:msg:"{{lookup('ahvl_sshkey',find='anotherusername',sshkey_type='rsa',in=item,out='plaintext')}}"loop:"{{sshkey_rsa_in}}"SSH hostkeys---# playbook to demonstrate ahvl_sshhostkey-hosts:localhostgather_facts:novars:sshhostkey_ins:-private-public-fingerprint_sha256-fingerprint_sha256_clean-fingerprint_sha256_art-fingerprint_md5-fingerprint_md5_clean-fingerprint_md5_art-fingerprint_bubblebabble-fingerprint_bubblebabble_clean-dns_sha1-dns_sha1_clean-dns_sha256-dns_sha256_cleantasks:# search path used for vault will be [hosts/localhost/sshhostkeys/rsa]-name:'ahvl_sshhostkey:lookupRSAhostkeyandoutputallpieces'debug:msg:"{{lookup('ahvl_sshhostkey',find='rsa',in=item,out='plaintext')}}"loop:"{{sshhostkey_ins}}"# search path used for vault will be [hosts/localhost/sshhostkeys/ed25519]-name:'ahvl_sshhostkey:lookupEd25519hostkeyandoutputallpieces'debug:msg:"{{lookup('ahvl_sshhostkey',find='ed25519',in=item,out='plaintext')}}"loop:"{{sshhostkey_ins}}"# search path used for vault will be [hosts/myhost2.local/sshhostkeys/rsa]-name:'ahvl_sshhostkey:lookupRSAforanotherhostandoutputallpieces'debug:msg:"{{lookup('ahvl_sshhostkey',find='rsa',in=item,sshhostkey_type='rsa',out='plaintext',hostname='myhost2.local')}}"loop:"{{sshhostkey_ins}}"GPG keys---# playbook to demonstrate ahvl_gpgkey-hosts:localhostgather_facts:novars:gpgkey_regular_ins:-master_cert_pub_key_armored-master_cert_sec_key_armored-master_cert_sec_keytype-master_cert_sec_keyuid-master_cert_sec_password-master_cert_sec_fingerprint-master_cert_sec_keycurve-master_cert_sec_keygrip-master_cert_sec_keybits-master_cert_sec_creationdate-master_cert_sec_keyid-master_cert_sec_expirationdate-subkey_sign_sec_key_armored-subkey_sign_sec_fingerprint-subkey_sign_sec_keycurve-subkey_sign_sec_keygrip-subkey_sign_sec_keybits-subkey_sign_sec_creationdate-subkey_sign_sec_keyid-subkey_sign_sec_expirationdate-subkey_encr_sec_key_armored-subkey_encr_sec_fingerprint-subkey_encr_sec_keycurve-subkey_encr_sec_keygrip-subkey_encr_sec_keybits-subkey_encr_sec_creationdate-subkey_encr_sec_keyid-subkey_encr_sec_expirationdate-subkey_auth_sec_key_armored-subkey_auth_sec_fingerprint-subkey_auth_sec_keycurve-subkey_auth_sec_keygrip-subkey_auth_sec_keybits-subkey_auth_sec_creationdate-subkey_auth_sec_keyid-subkey_auth_sec_expirationdategpgkey_backup_ins:-sign_master_cert_pub_key_armored-sign_master_cert_sec_key_armored-sign_master_cert_sec_keytype-sign_master_cert_sec_keyuid-sign_master_cert_sec_password-sign_master_cert_sec_fingerprint-sign_master_cert_sec_keycurve-sign_master_cert_sec_keygrip-sign_master_cert_sec_keybits-sign_master_cert_sec_creationdate-sign_master_cert_sec_keyid-sign_master_cert_sec_expirationdate-sign_subkey_sign_sec_key_armored-sign_subkey_sign_sec_fingerprint-sign_subkey_sign_sec_keycurve-sign_subkey_sign_sec_keygrip-sign_subkey_sign_sec_keybits-sign_subkey_sign_sec_creationdate-sign_subkey_sign_sec_keyid-sign_subkey_sign_sec_expirationdate-encr_master_cert_pub_key_armored-encr_master_cert_sec_key_armored-encr_master_cert_sec_keytype-encr_master_cert_sec_keyuid-encr_master_cert_sec_password-encr_master_cert_sec_fingerprint-encr_master_cert_sec_keycurve-encr_master_cert_sec_keygrip-encr_master_cert_sec_keybits-encr_master_cert_sec_creationdate-encr_master_cert_sec_keyid-encr_master_cert_sec_expirationdate-encr_subkey_encr_sec_key_armored-encr_subkey_encr_sec_fingerprint-encr_subkey_encr_sec_keycurve-encr_subkey_encr_sec_keygrip-encr_subkey_encr_sec_keybits-encr_subkey_encr_sec_creationdate-encr_subkey_encr_sec_keyid-encr_subkey_encr_sec_expirationdatetasks:# search path used for vault will be [gpgkeys/name_ed25519_localhost_myemail]-name:'ahvl_gpgkey:fetch/generateregulared25519keyandoutputallpieces'debug:msg:"{{lookup('ahvl_gpgkey',gpgkey_fullname='name_ed25519',gpgkey_email='myemail',in=item,out='plaintext')}}"loop:"{{gpgkey_regular_ins}}"# search path used for vault will be [gpgkeys/name_rsa_localhost_myemail]-name:'ahvl_gpgkey:fetchgenerateregularRSAkeyandoutputallpieces'debug:msg:"{{lookup('ahvl_gpgkey',gpgkey_type='rsa',gpgkey_fullname='name_rsa',gpgkey_email='myemail',in=item,out='plaintext')}}"loop:"{{gpgkey_regular_ins}}"# search path used for vault will be [gpgkeys/bckp_ed25519_localhost_myemail]-name:'ahvl_gpgkey:fetch/generatebackuped25519keyandoutputallpieces'debug:msg:"{{lookup('ahvl_gpgkey',gpgkey_keyset='backup',gpgkey_fullname='bckp_ed25519',gpgkey_email='myemail',gpgkey_comment=inventory_hostname,in=item,out='plaintext')}}"loop:"{{gpgkey_backup_ins}}"# search path used for vault will be [gpgkeys/bckp_rsa_localhost_myemail]-name:'ahvl_gpgkey:fetch/generatebackupRSAkeyandoutputallpieces'debug:msg:"{{lookup('ahvl_gpgkey',gpgkey_keyset='backup',gpgkey_type='rsa',gpgkey_fullname='bckp_rsa',gpgkey_email='myemail',gpgkey_comment=inventory_hostname,in=item,out='plaintext')}}"loop:"{{gpgkey_backup_ins}}"Credentials---# playbook to demonstrate ahvl_credential-hosts:localhostgather_facts:novars:credential_outs:-plaintext-hexsha256-hexsha512-sha256crypt-sha512crypt-phpass-mysql41-postgresmd5-pbkdf2sha256-pbkdf2sha512-argon2-grubpbkdf2sha512tasks:# search path used for vault will be [credentials/transip]-name:'ahvl_password:findcredential;willfailifitdoesnotexist'debug:msg:"{{lookup('ahvl_credential',find='transip',in='apikeyxyz',out=item)}}"loop:"{{credential_outs}}"Configuration OptionsTo give you maximum flexibility in configuring the behaviour of these lookup plugins, there are several ways you can set the option values, one taking precedence over the other. The order in which they are processed is as follows. The lowest number will have the highest priority. Obviously, the variable precedence as defined in Ansible also applies. Consult theAnsible docsfor more information.PriorityMethodExampleComments1Lookup argumentslookup('ahvl_password', find='mysql' in='myuser', out='mysql41')2Environment variablesAHVL_CONNECTION_AHVL_TOKEN=http://localhost:82003Prefixed variablesahvl_connection_ahvl_url:'http://localhost:8200'4Nested variablesahvl_connection:ahvl_url: 'http://localhost:8200'5ansible.cfg[ahvl_connection]ahvl_token: 'yourtoken'Only supported for AHVL Connection details6DefaultsNoneHardcoded in the lookup pluginahvl Vault connection optionsEvery lookup will generate at least a single request to the HashiCorp Vault. In case a new secret has been generated, or a search path doesn't exist yet, more than one request will be made. The following connection details can be set:Option nameRequiredValue typePossible valuesDefault valueCommentahvl_urlyesstringprotocol://fqdn:porthttp://localhost:8200ahvl_auth_methodyesstringtoken/userpass/ldap/approletokenvault authentication methodahvl_namespacenostringNonevault secret namespaceahvl_validate_certsnobooleanTrue/FalseTruevalidate vault certificates; set to False if not using an https connection; if you're using self-signed certificates provide the root certificate in ahvl_cacert insteadahvl_mount_pointnostringsecretvault secret mount pointahvl_cacertnopath/fullpath/to/file.crtNone(self-signed) certificate to verify https connectionahvl_usernamenostringNonevault login username; required if auth_method is userpass/ldapahvl_passwordnostringNonevault login password; required if auth_method is userpass/ldap; it is strongly recommended to only set the password using the environment variable AHVL_CONNECTION_AHVL_PASSWORDahvl_role_idnostringNonevault login role id; required if auth_method is approleahvl_secret_idnostringNonevault login secret id; required if auth_method is approleahvl_tokennostringNonevault token; required if auth_method is token; it is strongly recommended to only set the token using the environment variable AHVL_CONNECTION_AHVL_TOKEN!ahvl General optionsThese options apply to all lookup plugins and can (or sometimes must) be set for each lookup. With the exception of the ahvl_tmppath, these options cannot be set globally.Option nameRequiredValue typePossible valuesDefault valueCommenthostnameyesfqdninventory_hostnameThe hostname can/will be used as part of the search pathahvl_tmppathnopath/fullpath/to/tmpdiransible generated tmp pathBEWARE:The tmppathWILL BE DELETED AT THE END OF EACH LOOKUP! To be safe, leave this setting empty; ansible will provide a random temporary folder which can be safely deleted.findyesstringNoneThe find parameter is used as part of the search pathinyesstringdepends on lookup pluginNoneAt the given search path, determine which key to look foroutyesstringplaintext/hexsha256/hexsha512/sha256crypt/sha512crypt/grubpbkdf2sha512/phpass/mysql41/postgresmd5/pbkdf2sha256/pbkdf2sha512/argon2hexsha512The format in which the secret will be returned. The hex*, mysql41 and postgresmd5 formats provide a hash, the sha* and phpass functions will give you a salted hash. Each hostname/secret/hash combination will have a unique salt and the salt will also be stored in vault to make sure each subsequent playbook run will not generate a new salt and thus result in a 'changed' state. For each hash function the correct salt is determined automatically based on best practices.pathnostring{find}/{hostname}depends on lookup pluginThe actual search path used to find secret in vault. If not specified, it will be determined by the lookup plugin. When setting the path directly, you can use the variables {find} and {hostname} which will be replaced by the correct values prior to querying vault.autogeneratenobooleanTrue/FalseTrueWhether or not to automatically generate new secrets when they could not be found in vault or when the latest version of the secret has been deletedrenewnobooleanTrue/FalseFalseForces renewal of the secret, regardless of whether it already exists or not; will not change the behaviour of the autogenerate option. Be careful when using this, as it will be triggered for each and every lookup where this option is True, particularly in loops!pwdnostringany stringNoneRequired only when using the set_password functionahvl Lookup Password optionsGeneral optionsOption nameDefault valueAvailable optionspathhosts/{hostname}/{find}Lookup optionsNo additional options available, however, check theahvl Generate Password optionssection as well!ahvl Set Password optionsGeneral optionsOption nameDefault valueAvailable optionspathhosts/{hostname}/{find}pwdNoneahvl Lookup SSH Key optionsGeneral optionsOption nameDefault valueAvailable optionspathsshkeys/{find}inNoneprivate/password/private_keybits/private_keytype/private_pkcs8/private_openssh/private_putty/private_sshcom/public/public_pem/public_pkcs8/public_rfc4716/fingerprint_sha256/fingerprint_sha256_clean/fingerprint_sha256_art/fingerprint_md5/fingerprint_md5_clean/fingerprint_md5_art/fingerprint_putty/fingerprint_bubblebabble/fingerprint_bubblebabble_cleanLookup optionsNo additional options available, however, check theahvl Generate SSH Key optionssection as well!ahvl Lookup SSH Hostkey optionsGeneral optionsOption nameDefault valueAvailable optionspathhosts/{hostname}/sshhostkeys/{find}findNoneed25519/rsainNoneprivate/private_keybits/private_keytype/fingerprint_sha256/fingerprint_sha256_clean/fingerprint_sha256_art/fingerprint_md5/fingerprint_md5_clean/fingerprint_md5_art/fingerprint_bubblebabble/fingerprint_bubblebabble_clean/dns_sha1/dns_sha1_clean/dns_sha256/dns_sha256_clean/publicLookup optionsNo additional options available, however, check theahvl Generate SSH Hostkey optionssection as well!ahvl Lookup GPG Key optionsGeneral optionsOption nameDefault valueAvailable optionspathgpgkeys/{find}findNonewhengpgkey_keyset=backup:ed25519/rsainNonewhengpgkey_keyset=regular:master_cert_pub_key_armored/master_cert_sec_key_armored/master_cert_sec_keytype/master_cert_sec_keyuid/master_cert_sec_password/master_cert_sec_fingerprint/master_cert_sec_keycurve/master_cert_sec_keygrip/master_cert_sec_keybits/master_cert_sec_creationdate/master_cert_sec_keyid/master_cert_sec_expirationdate/subkey_sign_sec_key_armored/subkey_sign_sec_fingerprint/subkey_sign_sec_keycurve/subkey_sign_sec_keygrip/subkey_sign_sec_keybits/subkey_sign_sec_creationdate/subkey_sign_sec_keyid/subkey_sign_sec_expirationdate/subkey_encr_sec_key_armored/subkey_encr_sec_fingerprint/subkey_encr_sec_keycurve/subkey_encr_sec_keygrip/subkey_encr_sec_keybits/subkey_encr_sec_creationdate/subkey_encr_sec_keyid/subkey_encr_sec_expirationdate/subkey_auth_sec_key_armored/subkey_auth_sec_fingerprint/subkey_auth_sec_keycurve/subkey_auth_sec_keygrip/subkey_auth_sec_keybits/subkey_auth_sec_creationdate/subkey_auth_sec_keyid/subkey_auth_sec_expirationdatewhengpgkey_keyset=backup:sign_master_cert_pub_key_armored/sign_master_cert_sec_key_armored/sign_master_cert_sec_keytype/sign_master_cert_sec_keyuid/sign_master_cert_sec_password/sign_master_cert_sec_fingerprint/sign_master_cert_sec_keycurve/sign_master_cert_sec_keygrip/sign_master_cert_sec_keybits/sign_master_cert_sec_creationdate/sign_master_cert_sec_keyid/sign_master_cert_sec_expirationdate/sign_subkey_sign_sec_key_armored/sign_subkey_sign_sec_fingerprint/sign_subkey_sign_sec_keycurve/sign_subkey_sign_sec_keygrip/sign_subkey_sign_sec_keybits/sign_subkey_sign_sec_creationdate/sign_subkey_sign_sec_keyid/sign_subkey_sign_sec_expirationdate/encr_master_cert_pub_key_armored/encr_master_cert_sec_key_armored/encr_master_cert_sec_keytype/encr_master_cert_sec_keyuid/encr_master_cert_sec_password/encr_master_cert_sec_fingerprint/encr_master_cert_sec_keycurve/encr_master_cert_sec_keygrip/encr_master_cert_sec_keybits/encr_master_cert_sec_creationdate/encr_master_cert_sec_keyid/encr_master_cert_sec_expirationdate/encr_subkey_encr_sec_key_armored/encr_subkey_encr_sec_fingerprint/encr_subkey_encr_sec_keycurve/encr_subkey_encr_sec_keygrip/encr_subkey_encr_sec_keybits/encr_subkey_encr_sec_creationdate/encr_subkey_encr_sec_keyid/encr_subkey_encr_sec_expirationdateLookup optionsOption nameRequiredValue typePossible valuesDefault valueCommentgpgkey_fullnameyesstringNonefull name for keygpgkey_emailyesstringNoneemail for keygpgkey_commentnostringNonecomment for key; if not provided will default tohostnamegpgkey_uidnostringNoneuid for key; if not provided will default to<gpgkey_fullname>_<gpgkey_comment>_<gpgkey_email>gpgkey_keysetyesstringregular/backupregularkeyset to generateNo additional options available, however, check theahvl Generate GPG Key optionssection as well!ahvl Lookup Credential optionsGeneral optionsOption nameDefault valueAvailable optionspathcredentials/{find}Lookup optionsNo additional options available.ahvl Generate Password optionsOption nameRequiredValue typePossible valuesDefault valueCommentpwd_typeyesstringword/phrasewordtype of password to generate; word or phrasepwd_entropyyesstringweak/fair/strong/securesecurestrength of password; check passlib docs for allowed valuespwd_lengthnointeger32length of password; if omitted is auto calculated based on entropypwd_charsnostringNonespecific string of characters to use when generating passwordspwd_charsetnostringascii_62/ascii_50/ascii_72/hexascii_72specific charset to use when generating passwordspwd_wordsnostringNonelist of words to use when generating passphrasepwd_wordsetnostringeff_long/eff_short/eff_prefixed/bip39eff_longpredefined list of words to use when generating passphrase; check passlib docs for allowed valuespwd_sepnostringword separator for passphraseahvl Generate SSH Key optionsOption nameRequiredValue typePossible valuesDefault valueCommentsshkey_typeyesstringed25519/rsaed25519type of ssh key to generatesshkey_bitsyesinteger4096number of bits for ssh keysshkey_usernamenostringNonessh key username; defaults tofindif not providedsshkey_commentnostringNonesshkey comment; defaults tousernameif not providedsshkey_bin_keygenyespathNonefull path to ssh-keygen binary; attempts to findssh-keygenif not providedsshkey_bin_opensslnopathNonefull path to puttygen binary, for pkcs8 key format; attempts to findopensslif not providedsshkey_bin_puttygennopathNonefull path to puttygen binary; attempts to findputtygenwhen not providedsshkey_pkcs8_enablednobooleanFalseuse openssl to convert keys to pkcs8 compatible keyssshkey_putty_enablednobooleanFalseuse puttygen to convert keys to putty/sshcom compatible keysahvl Generate SSH Hostkey optionsOption nameRequiredValue typePossible valuesDefault valueCommentsshhostkey_typeyesstringed25519/rsaNonetype of keys to generate when generating hostkeyssshhostkey_strengthyesstringmedium/strongstronghostkey strength; see gen_sshhostkey function for actual valuessshhostkey_commentnostringNonesshhostkey commentsshhostkey_bin_keygenyespathNonefull path to ssh-keygen binary; attempts to findssh-keygenif not providedahvl Generate GPG Key optionsOption nameRequiredValue typePossible valuesDefault valueCommentgpgkey_confnolistdescribed in gpg manpage['keyid-format 0xlong', 'with-fingerprint', 'personal-cipher-preferences AES256', 'personal-digest-preferences SHA512', 'cert-digest-algo SHA512']Contains the options which will be written to gpg.conf when manipulating keys. It will always be appended with the key preferences as defined ingpgkey_prefgpgkey_prefyeslistdescribed in gpg manpage['SHA512', 'SHA384', 'SHA256', 'SHA224', 'AES256', 'AES192', 'ZLIB', 'BZIP2', 'ZIP', 'Uncompressed']Preferences regarding ciphers, digests and algorithmsgpgkey_digestnostringSHA512used with gpg option --digest-algogpgkey_s2k_ciphernostringAES256used with gpg option --s2k-cipher-algogpgkey_s2k_digestnostringSHA512used with gpg option --s2k-digest-algogpgkey_s2k_modenointeger3used with gpg option --s2k-modegpgkey_s2k_countnointeger65011712used with gpg option --s2k-count; must be between 1024-65011712 inclusivegpgkey_fullnameyesstringNoneconcatenated into a uid like; fullname (comment)gpgkey_emailyesstringNoneconcatenated into a uid like; fullname (comment)gpgkey_commentnostringNoneconcatenated into a uid like; fullname (comment)gpgkey_uidyesstringNonethe uidgpgkey_expirationdateyesstring0key expiration date in the format of [YYYY-MM-DD], [YYYYMMDDThhmmss], seconds=(int)gpgkey_bitsyesinteger4096key length; only used by RSA keys; will be added to the gpgkey_algo variable for RSA keysgpgkey_typeyesstringed25519/rsaed25519main key type to use for all 4 keys (master + 3 subkeys); supported are rsagpgkey_binyespathNonefull path to gpg binarygpgkey_keysetyesstringregular/backupregularset of keys to generate; regular or backup (i.e. for duplicity)ahvl Generate Salt optionsOption nameRequiredValue typePossible valuesDefault valueCommentsalt_charsyesstringitoa64/alnumitoa64Set of characters to use when generating salts; alnum is Alpha-numeric. while itoa64 adds the.and/characters to thealnumsetUpdate ahvl package instructionscreate a working directorymkdir /opt/ahvl && cd /opt/ahvlmake sure twine is installedpip install twinemake sure your github SSH key is availablelogin to githubssh -T git@github.comclone repositorygit clone git://github.com/netson/ahvlset remote origingit remote set-url origin git@github.com:netson/ahvl.gitmake changes as neededremove any dist folder that may existrm -rf ./dist && rm MANIFESTdetermine next PyPi package version number, look athttps://github.com/netson/ahvl/releaseschange theversionanddownload_urlinsetup.pycommit changes to gitgit add . && git commit -m "commit message"push to mastergit push origin mastercreate a new release on github with the same version number as indownload_urlcreate PyPi source distributionpython setup.py sdisttest package upload using twinetwine upload --repository-url https://test.pypi.org/legacy/ dist/*verify test results onhttps://test.pypi.org/manage/projects/upload package to PyPi using twinetwine upload dist/*enter yourusernameandpasswordDONE! :-)