some more auth stuff and documentation
This commit is contained in:
parent
e23ef97057
commit
feb032b84f
341
docs/README.adoc
Normal file
341
docs/README.adoc
Normal file
@ -0,0 +1,341 @@
|
||||
= VaultPass User Manual
|
||||
Brent Saner <bts@square-r00t.net>
|
||||
v1.0, 2020-03-28
|
||||
:doctype: book
|
||||
:data-uri:
|
||||
:imagesdir: images
|
||||
:sectlinks:
|
||||
:toc: preamble
|
||||
:toc2: left
|
||||
:idprefix:
|
||||
:toclevels: 7
|
||||
:source-highlighter: highlightjs
|
||||
|
||||
== Preface
|
||||
=== What is Vault?
|
||||
https://www.vaultproject.io/[Vault by HashiCorp^] is a "secrets manager" - it securely protects various secrets with a
|
||||
very robust system of authentication and authorization.
|
||||
|
||||
It also provides an https://en.wikipedia.org/wiki/X.509[X.509^] https://en.wikipedia.org/wiki/Public_key_infrastructure[PKI^]
|
||||
system for certificates generation and a token/OTP generator.
|
||||
|
||||
=== What is Pass?
|
||||
https://www.passwordstore.org/[Pass^] ("The standard Unix password manager") is a password manager written entirely in
|
||||
bash and backed by GPG. It's fairly barebones in terms of technology but does a decent enough job.
|
||||
|
||||
=== What is VaultPass?
|
||||
VaultPass attempts to bridge the gap between the two. It aims to be a drop-in replacement for the pass CLI utility via
|
||||
subcommands and other operations, but obviously with Vault as a backend instead of GPG-encrypted flatfile hierarchy.
|
||||
|
||||
Obviously since the backends are vastly different, total parity is going to be impossible. But I try to get it pretty close.
|
||||
|
||||
|
||||
== Configuration
|
||||
Unlike Pass, PassVault requires a persistent configuration. At the very **least**, the authentication method needs to be
|
||||
specified.
|
||||
|
||||
The default location for the configuration file is `~/.config/vaultpass.xml`. It's an XML document formatted with the
|
||||
following structure:
|
||||
|
||||
. The https://www.w3.org/TR/xml/#sec-prolog-dtd[XML prolog^], specifying the character encoding of the document and
|
||||
XML version.footnote:confheader[These aren't **strictly** necessary, but will make cross-parsing and validation MUCH
|
||||
easier. It's *highly* recommended to use them.]
|
||||
. The root element (`vaultpass`).
|
||||
This element contains attributes describing parsing/validation specifics as well, such as the
|
||||
https://www.w3.org/TR/xml-names/[namespace definitions^] and https://www.w3.org/TR/xmlschema11-1/#xsi_schemaLocation[schema location^].footnote:confheader[]
|
||||
.. The `server` element.footnote:optelem[This element/attribute/text content is *optional*. See the item's description
|
||||
for how default values/behaviour are determined.] This element is a container for connection and management of the
|
||||
Vault server. This consists of:
|
||||
... A single `uri` element.footnote:optelem[] It should be the same as the **base** URL for your Vault server.
|
||||
The default (if not specified) is to first check for a **`VAULT_SERVER`** environment variable and, if not found, to use
|
||||
`http://localhost:8000/`.
|
||||
... An unseal directive, which can be used to (attempt to) automatically unseal the server if it is sealed.
|
||||
This isn't required, but can assist in automatic operation.
|
||||
One of either:footnote:optelem[]
|
||||
.... `unseal`, the unseal key shard (a Base64 string), or
|
||||
.... `unsealGpg`, the unseal key shard encrypted with GPG. See the section on <<GPG-Encrypted Elements>>.
|
||||
... A required authentication directive which specifies how we should authenticate to Vault. It should be comprised of
|
||||
one of either:
|
||||
.... `auth` (see <<Auth>> section below), or
|
||||
.... `authGpg`, an <<Auth>> config snippet encrypted with GPG. See the section on <<GPG-Encrypted Elements>>.
|
||||
|
||||
Let's look at an example configuration.
|
||||
|
||||
=== Example Configuration
|
||||
|
||||
.`~/.config/vaultpass.xml` example:
|
||||
[source,xml]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<vaultpass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://git.square-r00t.net/VaultPass/"
|
||||
xsi:schemaLocation="https://git.square-r00t.net/VaultPass/ http://schema.xml.r00t2.io/projects/vaultpass.xsd">
|
||||
|
||||
<server>
|
||||
<uri>http://localhost:8000/</uri>
|
||||
<unseal>YOUR_UNSEAL_SHARD</unseal>
|
||||
</server>
|
||||
<auth>
|
||||
<token/>
|
||||
</auth>
|
||||
|
||||
</vaultpass>
|
||||
----
|
||||
|
||||
In the above, we can see that it would use the vault server at `http://localhost:8000/` using whatever token is either
|
||||
in the **`VAULT_TOKEN`** environment variable or, if empty, the `~/.vault-token` file. Because an unseal shard was
|
||||
provided, it will be able to attempt to automatically unseal the Vault (assuming its shard will complete the threshold
|
||||
needed).
|
||||
|
||||
=== Auth
|
||||
Vault itself supports a https://www.vaultproject.io/docs/auth/[large number of authentication methods^]. However, in
|
||||
the interest if maintainability, this project has limited support to only the most common authentication methods. More
|
||||
authentication methods may be added in the future upon request.
|
||||
|
||||
NOTE: All of these (except for <<token>>) **require** configuration in Vault first. Configuration of those
|
||||
authentication methods is out of scope for this document and project. Please ensure that your authentication works as
|
||||
expected in the https://www.vaultproject.io/downloads/[Vault CLI utility^] or via the
|
||||
https://www.vaultproject.io/api-docs/auth/[Vault API^] first before submitting a bug report in VaultPass.
|
||||
|
||||
==== AppRole
|
||||
AppRole takes two required children elements:
|
||||
|
||||
. `appRole` (the container element)
|
||||
.. `role`, the AppRole's RoleID, and
|
||||
.. `secret`, the AppRole's SecretID.
|
||||
|
||||
===== Example Snippet
|
||||
[source,xml]
|
||||
----
|
||||
<!-- SNIP -->
|
||||
<auth>
|
||||
<appRole>
|
||||
<role>my-role</role>
|
||||
<secret>37b74931-c4cd-d49a-9246-ccc62d682a25</secret>
|
||||
</appRole>
|
||||
</auth>
|
||||
<!-- SNIP -->
|
||||
----
|
||||
|
||||
==== LDAP
|
||||
LDAP takes two required children elements and one optional child element:
|
||||
|
||||
. `ldap` (the container element)
|
||||
.. `username`, the username (as according to the *`userdn`* and *`userattr`* settings
|
||||
https://www.vaultproject.io/docs/auth/ldap/#binding-parameters[in the configuration^])
|
||||
.. `password`, the password for the account object.
|
||||
.. `mountPoint` footnote:optelem[], the https://www.vaultproject.io/api-docs/system/mounts/[mount point^] for the LDAP authentication in
|
||||
Vault. The default, if not provided, is `ldap`.
|
||||
|
||||
===== Example Snippet
|
||||
[source,xml]
|
||||
----
|
||||
<!-- SNIP -->
|
||||
<auth>
|
||||
<ldap>
|
||||
<username>mitchellh</username>
|
||||
<password>MyPassword1</password>
|
||||
<mountPoint>ldap</mountPoint>
|
||||
</ldap>
|
||||
</auth>
|
||||
<!-- SNIP -->
|
||||
----
|
||||
|
||||
==== Token
|
||||
Token auth is the most basic supported authentication in Vault and can be used without any further configuration.
|
||||
|
||||
It consists of, at its most basic (and "automagic") configuration, a single element -- but this can be configured more
|
||||
in-depth/explicitly.
|
||||
|
||||
. `token` (the container element)
|
||||
.. The token itself or content/source of the token.footnote:optelem[]
|
||||
|
||||
It has one optional attribute: `source`.footnote:optelem[]. It can be one of the following:
|
||||
|
||||
* `env:MY_TOKEN_VAR`, in which environmental token **`MY_TOKEN_VAR`** will be sourced.
|
||||
* A filesystem path, in which the file is assumed to contain the token (and ONLY the token).
|
||||
|
||||
To determine the behaviour of how this behaves, please refer to the below table.
|
||||
|
||||
.Determining `token` behaviour
|
||||
[cols="^1,5,10"]
|
||||
|===
|
||||
|No. |If... |Then...
|
||||
|
||||
| 1 |self-enclosed, no `source` |The **`VAULT_TOKEN`** environment variable is checked. If not defined, the file
|
||||
`~/.vault-token` will be checked. If that file doesn't exist, a `RuntimeError` will be raised.
|
||||
| 2 |self-enclosed, `source` given| The `source` is assumed to be the *only* source and no automatic detection will occur.
|
||||
| 3 |token contained in tags, no `source`| The specified token will be used and no automatic detection will occur.
|
||||
| 4 |token contained in tags, `source` given |Same as **3**; `source` is ignored.
|
||||
|===
|
||||
|
||||
===== Example Snippet
|
||||
[source,xml]
|
||||
----
|
||||
<!-- SNIP -->
|
||||
<auth>
|
||||
<!-- "Automagic" (#1).
|
||||
First $VAULT_TOKEN environment variable is checked, then ~/.vault-token is checked. -->
|
||||
<token/>
|
||||
|
||||
<!-- Source is considered the only place to fetch token from (#2). -->
|
||||
<!-- This would check the environment variable $SOMEVAR -->
|
||||
<!-- <token source="env:SOMEVAR"/> -->
|
||||
<!-- This would use the contents of ~/.vault-token.alt -->
|
||||
<!-- <token source="~/.vault-token.alt"/> -->
|
||||
|
||||
<!-- Token explicitly given is the only one used. -->
|
||||
<!-- <token>s.Lp4ix1CKBtJOfA46Ks4b4cs6</token> -->
|
||||
|
||||
<!-- Token explicitly given is the only one used; source attribute is ignored. -->
|
||||
<!-- <token source="env:THIS_IS_IGNORED">s.Lp4ix1CKBtJOfA46Ks4b4cs6</token> -->
|
||||
</auth>
|
||||
<!-- SNIP -->
|
||||
----
|
||||
|
||||
==== User/Password
|
||||
Vault's https://www.vaultproject.io/docs/auth/userpass/[userpass authentication method^] must be
|
||||
https://www.vaultproject.io/docs/auth/userpass/#configuration[configured^] beforehand, but it's a relatively simple
|
||||
configuration.
|
||||
|
||||
VaultPass user/password authentication takes two required children elements and one optional element.
|
||||
|
||||
. `userpass` (the container element)
|
||||
.. `username`, the username of the account.
|
||||
.. `password`, the password for the account.
|
||||
.. `mountPoint` footnote:optelem[], the https://www.vaultproject.io/api-docs/system/mounts/[mount point^] for the auth.
|
||||
If not specified, the default is `userpass`.
|
||||
|
||||
===== Example Snippet
|
||||
[source,xml]
|
||||
----
|
||||
<!-- SNIP -->
|
||||
<auth>
|
||||
<userpass>
|
||||
<username>mitchellh</username>
|
||||
<password>foo</password>
|
||||
<mountPoint>userpass</mountPoint>
|
||||
</userpass>
|
||||
</auth>
|
||||
<!-- SNIP -->
|
||||
----
|
||||
|
||||
=== GPG-Encrypted Elements
|
||||
Understandably, in order to have a persistent configuration, that means storing on disk. That also means that they need
|
||||
to be able to be accessed with no or minimal user interruption. Pass used GPG natively, so it didn't have an issue with
|
||||
this; since https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html[gpg-agent^] is typically
|
||||
spawned on first use of a https://www.gnupg.org/gph/en/manual/r1616.html[GPG homedir^] (usually `~/.gnupg/` by default)
|
||||
and keeps an authenticated session open for 10 minutes
|
||||
(https://superuser.com/questions/624343/keep-gnupg-credentials-cached-for-entire-user-session[by default^]).
|
||||
|
||||
To get around needing to store plaintext credentials on-disk in any form, VaultPass has `unsealGpg` and `authGpg`
|
||||
elements. These elements are of the same composition (described <<gpg_elements, below>>) and allow you to use GPG to
|
||||
encrypt that sensitive information.
|
||||
|
||||
Note that while this does increase security, it breaks compatibility with other XML parsers - they won't be able to
|
||||
decrypt and parse the encrypted snippet unless explicitly coded to do so.
|
||||
|
||||
==== `*Gpg` elements
|
||||
`*Gpg` elements (`authGpg`, `unsealGpg`) have the same structure:
|
||||
|
||||
. `unsealGpg`/`authGpg`, the container element.
|
||||
.. The path to the encrypted file as the contained text.
|
||||
|
||||
It has some optional attributes as well:
|
||||
|
||||
.`*Gpg` element attributes
|
||||
|===
|
||||
|Attribute |Content
|
||||
|
||||
|`keyFPR` footnote:optelem[] | The GPG key to use to decrypt the file. It accepts multiple key ID formats, but it's *highly* recommended to
|
||||
use the full 40-character (without spaces) key fingerprint. If not specified, VaultPass will use the first private key
|
||||
it finds in the keyring.
|
||||
|`gpgHome` footnote:optelem[] | The GPG home directory. If not specified, VaultPass will first check the **`GNUPGHOME`** environment
|
||||
variable. If that's empty, we'll default to `~/.gnupg/`.
|
||||
|===
|
||||
|
||||
The contents of the encrypted file should match the **unencrypted** XML content it's replacing.
|
||||
|
||||
CAUTION: Note that if you use namespaces in your `vaultpass.xml` config file, you **MUST** use matching declarations in
|
||||
your encrypted file.
|
||||
|
||||
Let's look at an example of GPG-encrypted elements.
|
||||
|
||||
==== GPG-Encrypted Elements Example
|
||||
|
||||
.`~/.config/vaultpass.xml` snippet:
|
||||
[source,xml]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<vaultpass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://git.square-r00t.net/VaultPass/"
|
||||
xsi:schemaLocation="https://git.square-r00t.net/VaultPass/ http://schema.xml.r00t2.io/projects/vaultpass.xsd">
|
||||
|
||||
<server>
|
||||
<uri>http://localhost:8000/</uri>
|
||||
<unsealGpg keyFPR="D34DB33FD34DB33FD34DB33FD34DB33FD34DB33F"
|
||||
gpgHome="~/.gnupg">~/.private/vaultpass/unseal.asc</unsealGpg>
|
||||
</server>
|
||||
<authGpg keyFPR="D34DB33FD34DB33FD34DB33FD34DB33FD34DB33F"
|
||||
gpgHome="~/.gnupg">~/.private/vaultpass/auth.gpg</unsealGpg>
|
||||
</vaultpass>
|
||||
----
|
||||
|
||||
As shown, it supports both <<ascii_armored>> and <<binary>> encryption formats.
|
||||
|
||||
==== ASCII-Armored
|
||||
===== Encrypted
|
||||
.`~/.private/vaultpass/unseal.asc` contents:
|
||||
[source]
|
||||
----
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA7QuYg9nGdZdAQ//eHvEZ7vpLvygM2ofIiT2uW7cWYQaYm/09li7s0+0ZqTu
|
||||
hNki7oIQ1Ip+k6ds45eEXPG6hXwZ7+mtIDG8VcYpo0PdwpvcJ9qqAgvnFAynvjgH
|
||||
pRkeIw4VUfGxxhs8oZMvdrXuYtwzaXIhn0UuZv+cIS1Jj6IfG0xSpRvd+M0MW+Wk
|
||||
IWSIyUcY6fkP7MFEiId7sQwm6htHXJDqiVAmwn4lqk2CnIhtsTd5HUyRzGg5gZs+
|
||||
sFAssa7QjoBKJMkTDVH4EIC4GcgNtTB/rg7XBoX1k36CHZAwB/boZ5arMYswwkYp
|
||||
VFv9At13vkkRMf23bb7siq7U0Vbvs0PGsFJS/1ivS1IyzFGFZGHaTz7ndk2q2iyY
|
||||
tMjMe+z+i2VAGvtfdE7H4K4TrqrM9OZ81vyJkEjRBrkSfR9sWOgv5yBFDvoeVkZl
|
||||
k1gRXLkrF/7eZn8vD17oOew/zr+um7s/rTtLp5GEknOsKzb1NOMBHP44dXdxNreT
|
||||
HdRlNDLgOp2KffXgNSm/A026tMSA0nf0kpJmR1yLjucKPoy6wVrTMh+sLNubgxmZ
|
||||
BCz64myu8dfWtHQfPSis1kjrs15mfQoOu9Cl9st8gTs50sKWTa+dGdajZEcz8rcX
|
||||
OMBLwiTQodP/0uRHf8YofIFk86QXbYALd4WsC/KvDQBiaz8HRcfkccDQCHQvdLrS
|
||||
wEkBuhCZj1OqUnTXg0qggMD0Hp2pO0CqD4uZ3RHvIt49W+7oUr22Y4VarRNeP06x
|
||||
JhYC3Sr0RXv/Vi21DMiUUUAXYeYKP82HpP0zSZhCcwVZZje1dXwq85SH04u9pT+n
|
||||
f2JqgATxmAaepQZCANxAluknfSluuCBi0hmhagYY2IsgKmJcSsksm0AWfGyzgoeV
|
||||
ZypDlE3MuERVLJSDBjZtfnScy3CeTWWj5vw7Nfm5XEqOuIIbZaTV/qb6i6y4rc6k
|
||||
Yx5xYKHeuXJGbrQdVJemcXyDIV5tDw5RtLpO57EwL+uEYgSbN9rO/N2B83QjB7D5
|
||||
lCmbJtQcjxG/eJ/SrB2oS47YdEKRy+cH0Xx+
|
||||
=scGv
|
||||
-----END PGP MESSAGE-----
|
||||
----
|
||||
|
||||
===== Decrypted
|
||||
[source,xml]
|
||||
----
|
||||
<unseal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://git.square-r00t.net/VaultPass/"
|
||||
xsi:schemaLocation="https://git.square-r00t.net/VaultPass/ http://schema.xml.r00t2.io/projects/vaultpass.xsd">1fs1tV46ebb6awF6edtuzsoEawZlBARFp5rSaED+EJI=</unseal>
|
||||
----
|
||||
|
||||
==== Binary
|
||||
===== Encrypted
|
||||
.`~/.private/vaultpass/auth.gpg` contents:
|
||||
[source]
|
||||
----
|
||||
<BINARY DATA>
|
||||
----
|
||||
|
||||
|
||||
===== Decrypted
|
||||
[source,xml]
|
||||
----
|
||||
<auth xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://git.square-r00t.net/VaultPass/"
|
||||
xsi:schemaLocation="https://git.square-r00t.net/VaultPass/ http://schema.xml.r00t2.io/projects/vaultpass.xsd">
|
||||
|
||||
<token>s.Lp4ix1CKBtJOfA46Ks4b4cs6</token>
|
||||
|
||||
</auth>
|
||||
----
|
3
docs/gendocs.sh
Executable file
3
docs/gendocs.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
asciidoctor README.adoc -o ./README.html
|
@ -29,7 +29,7 @@ class PassMan(object):
|
||||
def getClient(self):
|
||||
# This may need to be re-tooled in the future.
|
||||
auth_xml = self.cfg.xml.find('auth')
|
||||
authmethod_xml = auth_xml.getchildren()[0]\
|
||||
authmethod_xml = auth_xml.getchildren()[0]
|
||||
for a in dir(auth):
|
||||
if a.startswith('_'):
|
||||
continue
|
||||
|
@ -128,3 +128,6 @@ class Token(_AuthBase):
|
||||
self.token = self._getEnv(e)
|
||||
else:
|
||||
self.token = self._getFile(a)
|
||||
self.client.token = self.token
|
||||
self.authCheck()
|
||||
return(None)
|
||||
|
16
vaultpass/gpgauth.py
Normal file
16
vaultpass/gpgauth.py
Normal file
@ -0,0 +1,16 @@
|
||||
import os
|
||||
import logging
|
||||
##
|
||||
import gpg
|
||||
|
||||
|
||||
# Special shoutout to Jthan for ruining my life.
|
||||
|
||||
|
||||
_logger = logging.getLogger()
|
||||
|
||||
|
||||
class GPGAuth(object):
|
||||
def __init__(self, gpgauth_xml):
|
||||
pass
|
||||
|
Reference in New Issue
Block a user