Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - Transactional storage #292

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

cipherboy
Copy link
Contributor

@cipherboy cipherboy commented Apr 13, 2024

This adds support for interactive transactions across the backend, physical, and plugin storage levels. This will ultimately allow for greater assurance in secrets management operations built on top of OpenBao.

See the RFC in #296 for more detailed information about the design of this change.


TODO:

  • Resolve unanswered questions.
  • Benchmark subsystem performance when using transactions.
  • Implement support for GRPC connected plugins.
  • Expand randomized testing to logical.Storage, finish adding remaining layers to the cross-test.
  • Obey error handling discussed in RFC.
  • Add transaction concurrency limiting to InMem as well.
  • Expand physical's testing.go to support basic testing of transactions.
  • Split off removal of one-shot transactional interface.
  • Add support disabling transactional storage from the configuration.
  • Update inmem-ha, sdk/physical/latency.go, and sdk/physical/errors.go to be transactional?
  • Split seal unwrapper removal into separate PR.
  • Think about separate raft limit size of transactions.

@cipherboy cipherboy marked this pull request as draft April 13, 2024 19:16
When a non-empty path is given that ends in a slash and after=., the
resulting seek prefix from joining the path and the period has the
slash trimmed off. This results in no list results, because this seek
prefix lacks the trailing slash and is thus not prefixed by the expected
prefix. E.g., for foo/ and after=., we end up with seekPrefix=foo, which
doesn't start with our prefix (foo/).

Correctly handle this edge case. This was caught by randomized testing
across multiple storage backends.

Signed-off-by: Alexander Scheel <[email protected]>
This removes the legacy one-shot transaction interface and its various
implementers, including in the File, InMem, and Raft backends. In the
former's case (file), this might not have truly had the strict
consistency guarantees one would expect from a transaction
implementation.

Signed-off-by: Alexander Scheel <[email protected]>
physical/raft/raft.go Outdated Show resolved Hide resolved
verifyReadOp
verifyListOp
beginTxOp
commitTxOp
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

beginTxOp / commitTxOp are mostly transaction sentinels for the time being. However, when implementing the single hash method (number 3), we can send the hash type in beginTxOp and the final hash in commitTxOp. We'll need verifyReadOp because while we can re-order any un-modified reads to occur at the end (sending them along in the commitTxOp if we wanted fewer operations in the log), we can't avoid sending reads before writes. We'll need verifyListOp, because its results can be impacted by writes and we won't necessarily know to compact (or not compact) them, so we'd prefer to keep them in execution order.

physical/raft/fsm.go Outdated Show resolved Hide resolved
// SecurityBarrier must provide the encryption APIs
BarrierEncryptor
}

// BarrierStorage is the storage only interface required for a Barrier.
type BarrierStorage interface {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BarrierStorage was unused and conformed to logical.Storage.

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package vault
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removal could be a separate PR as well.

Signed-off-by: Alexander Scheel <[email protected]>
This converts StorageView to an interface, aligning with the Storage
interface. The only consumer, as far as I can tell, is the BarrierView,
which was easy enough to convert to an interface user, and will itself
need to be made transactional in a future commit.

Signed-off-by: Alexander Scheel <[email protected]>
This converts BarrierView to an interface, updating definitions
everywhere to use it as such. This lets us replace it with two different
structs (barrierView and transacitonalBarrierView).

Signed-off-by: Alexander Scheel <[email protected]>
This extends SecurityBarrier into a TransactionalSecurityBarrier
variant, in which access to the underlying storage (but not the barrier
itself!) can be modified in a transaction-aware way.

Signed-off-by: Alexander Scheel <[email protected]>
Signed-off-by: Alexander Scheel <[email protected]>
SealUnwrapper exists to err about storage which was at one point in time
seal wrapped. This only exists on Vault Enterprise, and would require a
migration from Vault Enterprise -> OpenBao to trigger. As we likely
won't support this (as we have no way of unsealing the underlying
storage as we don't have the seal wrap subsystem in OSS), and thus
would require it to have been completely unseal wrapped manually
prior to migration, we can safely remove this and assume that other
failures would instead catch this unlikely event.

This is also one less layer to add transactional storage to.

Signed-off-by: Alexander Scheel <[email protected]>
This adds a cross-storage backend testing interface, suitable for
testing all physical backends at various levels of indirection (from
direct access to caches to error interposers). This will eventually
include testing logical.Storage interfaces as well, to ensure various
combinations of layers work together nicely (physical + barrier +
views) and match interface expectations.

Signed-off-by: Alexander Scheel <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants