From 12c00b97eff288286334bc1785a6fe11b75dbbb8 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 22 Jan 2016 17:01:22 -0500 Subject: [PATCH] Allow backends to see taint status. This can be seen via System(). In the PKI backend, if the CA is reconfigured but not fully (e.g. an intermediate CSR is generated but no corresponding cert set) and there are already leases (issued certs), the CRL is unable to be built. As a result revocation fails. But in this case we don't actually need revocation to be successful since the CRL is useless after unmounting. By checking taint status we know if we can simply fast-path out of revocation with a success in this case. Fixes #946 --- builtin/logical/pki/crl_util.go | 9 +++++++++ logical/system_view.go | 15 +++++++++++++++ vault/dynamic_system_view.go | 5 +++++ 3 files changed, 29 insertions(+) diff --git a/builtin/logical/pki/crl_util.go b/builtin/logical/pki/crl_util.go index b433e2512..45624aca0 100644 --- a/builtin/logical/pki/crl_util.go +++ b/builtin/logical/pki/crl_util.go @@ -18,6 +18,15 @@ type revocationInfo struct { // Revokes a cert, and tries to be smart about error recovery func revokeCert(b *backend, req *logical.Request, serial string) (*logical.Response, error) { + // As this backend is self-contained and this function does not hook into + // third parties to manage users or resources, if the mount is tainted, + // revocation doesn't matter anyways -- the CRL that would be written will + // be immediately blown away by the view being cleared. So we can simply + // fast path a successful exit. + if b.System().Tainted() { + return nil, nil + } + alreadyRevoked := false var revInfo revocationInfo diff --git a/logical/system_view.go b/logical/system_view.go index cf3e10457..33dd01a41 100644 --- a/logical/system_view.go +++ b/logical/system_view.go @@ -16,12 +16,23 @@ type SystemView interface { // SudoPrivilege returns true if given path has sudo privileges // for the given client token SudoPrivilege(path string, token string) bool + + // Returns true if the mount is tainted. A mount is tainted if it is in the + // process of being unmounted. This should only be used in special + // circumstances; a primary use-case is as a guard in revocation functions. + // If revocation of a backend's leases fails it can keep the unmounting + // process from being successful. If the reason for this failure is not + // relevant when the mount is tainted (for instance, saving a CRL to disk + // when the stored CRL will be removed during the unmounting process + // anyways), we can ignore the errors to allow unmounting to complete. + Tainted() bool } type StaticSystemView struct { DefaultLeaseTTLVal time.Duration MaxLeaseTTLVal time.Duration SudoPrivilegeVal bool + TaintedVal bool } func (d StaticSystemView) DefaultLeaseTTL() time.Duration { @@ -35,3 +46,7 @@ func (d StaticSystemView) MaxLeaseTTL() time.Duration { func (d StaticSystemView) SudoPrivilege(path string, token string) bool { return d.SudoPrivilegeVal } + +func (d StaticSystemView) Tainted() bool { + return d.TaintedVal +} diff --git a/vault/dynamic_system_view.go b/vault/dynamic_system_view.go index 13a3166a3..9c9340ac9 100644 --- a/vault/dynamic_system_view.go +++ b/vault/dynamic_system_view.go @@ -64,3 +64,8 @@ func (d dynamicSystemView) fetchTTLs() (def, max time.Duration) { return } + +// Tainted indicates that the mount is in the process of being removed +func (d dynamicSystemView) Tainted() bool { + return d.mountEntry.Tainted +}