Port filtered paths changes back to OSS (#7741)

* Port filtered paths changes back to OSS

* Fix build
This commit is contained in:
Brian Kassouf 2019-10-27 13:30:38 -07:00 committed by GitHub
parent f982899f1e
commit a20e73c2da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 167 additions and 32 deletions

4
go.mod
View File

@ -29,6 +29,7 @@ require (
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c
github.com/coreos/go-semver v0.2.0
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d // indirect
github.com/denisenkom/go-mssqldb v0.0.0-20190412130859-3b1d194e553a
github.com/dnaeon/go-vcr v1.0.1 // indirect
github.com/dsnet/compress v0.0.1 // indirect
@ -47,6 +48,7 @@ require (
github.com/golang/protobuf v1.3.2
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-metrics-stackdriver v0.0.0-20190816035513-b52628e82e2a
github.com/google/go-querystring v1.0.0 // indirect
github.com/hashicorp/consul-template v0.22.0
github.com/hashicorp/consul/api v1.1.0
github.com/hashicorp/errwrap v1.0.0
@ -91,6 +93,7 @@ require (
github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869
github.com/keybase/go-crypto v0.0.0-20190403132359-d65b6b94177f
github.com/kr/pretty v0.1.0
github.com/kr/pty v1.1.3 // indirect
github.com/kr/text v0.1.0
github.com/lib/pq v1.2.0
github.com/mattn/go-colorable v0.1.2
@ -105,6 +108,7 @@ require (
github.com/ncw/swift v1.0.47
github.com/nwaples/rardecode v1.0.0 // indirect
github.com/oklog/run v1.0.0
github.com/onsi/ginkgo v1.7.0 // indirect
github.com/oracle/oci-go-sdk v7.0.0+incompatible
github.com/ory/dockertest v3.3.4+incompatible
github.com/patrickmn/go-cache v2.1.0+incompatible

View File

@ -48,7 +48,17 @@ var (
// enableCredential is used to enable a new credential backend
func (c *Core) enableCredential(ctx context.Context, entry *MountEntry) error {
return c.enableCredentialInternal(ctx, entry, MountTableUpdateStorage)
// Enable credential internally
if err := c.enableCredentialInternal(ctx, entry, MountTableUpdateStorage); err != nil {
return err
}
// Re-evaluate filtered paths
if err := runFilteredPathsEvaluation(ctx, c); err != nil {
c.logger.Error("failed to evaluate filtered paths", "error", err)
return err
}
return nil
}
// enableCredential is used to enable a new credential backend
@ -128,6 +138,12 @@ func (c *Core) enableCredentialInternal(ctx context.Context, entry *MountEntry,
viewPath := entry.ViewPath()
view := NewBarrierView(c.barrier, viewPath)
// Singleton mounts cannot be filtered on a per-secondary basis
// from replication
if strutil.StrListContains(singletonMounts, entry.Type) {
addFilterablePath(c, viewPath)
}
nilMount, err := preprocessMount(c, entry, view)
if err != nil {
return err
@ -202,8 +218,7 @@ func (c *Core) enableCredentialInternal(ctx context.Context, entry *MountEntry,
return nil
}
// disableCredential is used to disable an existing credential backend; the
// boolean indicates if it existed
// disableCredential is used to disable an existing credential backend
func (c *Core) disableCredential(ctx context.Context, path string) error {
// Ensure we end the path in a slash
if !strings.HasSuffix(path, "/") {
@ -369,6 +384,38 @@ func (c *Core) remountCredEntryForce(ctx context.Context, path string) error {
return c.enableCredential(ctx, me)
}
// remountCredEntryForceInternal takes a copy of the mount entry for the path and fully
// unmounts and remounts the backend to pick up any changes, such as filtered
// paths. This should be only used internal.
func (c *Core) remountCredEntryForceInternal(ctx context.Context, path string, updateStorage bool) error {
fullPath := credentialRoutePrefix + path
me := c.router.MatchingMountEntry(ctx, fullPath)
if me == nil {
return fmt.Errorf("cannot find mount for path %q", path)
}
me, err := me.Clone()
if err != nil {
return err
}
if err := c.disableCredentialInternal(ctx, path, updateStorage); err != nil {
return err
}
// Enable credential internally
if err := c.enableCredentialInternal(ctx, me, updateStorage); err != nil {
return err
}
// Re-evaluate filtered paths
if err := runFilteredPathsEvaluation(ctx, c); err != nil {
c.logger.Error("failed to evaluate filtered paths", "error", err)
return err
}
return nil
}
// taintCredEntry is used to mark an entry in the auth table as tainted
func (c *Core) taintCredEntry(ctx context.Context, path string, updateStorage bool) error {
c.authLock.Lock()

View File

@ -17,11 +17,11 @@ import (
"sync/atomic"
"time"
"github.com/armon/go-metrics"
metrics "github.com/armon/go-metrics"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
multierror "github.com/hashicorp/go-multierror"
uuid "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/audit"
"github.com/hashicorp/vault/command/server"
@ -42,7 +42,7 @@ import (
"github.com/hashicorp/vault/vault/cluster"
"github.com/hashicorp/vault/vault/seal"
shamirseal "github.com/hashicorp/vault/vault/seal/shamir"
"github.com/patrickmn/go-cache"
cache "github.com/patrickmn/go-cache"
"google.golang.org/grpc"
)
@ -92,16 +92,17 @@ var (
manualStepDownSleepPeriod = 10 * time.Second
// Functions only in the Enterprise version
enterprisePostUnseal = enterprisePostUnsealImpl
enterprisePreSeal = enterprisePreSealImpl
startReplication = startReplicationImpl
stopReplication = stopReplicationImpl
LastWAL = lastWALImpl
LastPerformanceWAL = lastPerformanceWALImpl
PerformanceMerkleRoot = merkleRootImpl
DRMerkleRoot = merkleRootImpl
LastRemoteWAL = lastRemoteWALImpl
WaitUntilWALShipped = waitUntilWALShippedImpl
enterprisePostUnseal = enterprisePostUnsealImpl
enterprisePreSeal = enterprisePreSealImpl
enterpriseSetupFilteredPaths = enterpriseSetupFilteredPathsImpl
startReplication = startReplicationImpl
stopReplication = stopReplicationImpl
LastWAL = lastWALImpl
LastPerformanceWAL = lastPerformanceWALImpl
PerformanceMerkleRoot = merkleRootImpl
DRMerkleRoot = merkleRootImpl
LastRemoteWAL = lastRemoteWALImpl
WaitUntilWALShipped = waitUntilWALShippedImpl
)
// NonFatalError is an error that can be returned during NewCore that should be
@ -1681,6 +1682,9 @@ func (s standardUnsealStrategy) unseal(ctx context.Context, logger log.Logger, c
if err := c.loadMounts(ctx); err != nil {
return err
}
if err := enterpriseSetupFilteredPaths(c); err != nil {
return err
}
if err := c.setupMounts(ctx); err != nil {
return err
}
@ -1696,6 +1700,9 @@ func (s standardUnsealStrategy) unseal(ctx context.Context, logger log.Logger, c
if err := c.loadCredentials(ctx); err != nil {
return err
}
if err := enterpriseSetupFilteredPaths(c); err != nil {
return err
}
if err := c.setupCredentials(ctx); err != nil {
return err
}
@ -1881,6 +1888,10 @@ func enterprisePreSealImpl(c *Core) error {
return nil
}
func enterpriseSetupFilteredPathsImpl(c *Core) error {
return nil
}
func startReplicationImpl(c *Core) error {
return nil
}

View File

@ -105,7 +105,7 @@ func (c *Core) setupReplicatedClusterPrimary(*replication.Cluster) error { retur
func (c *Core) perfStandbyCount() int { return 0 }
func (c *Core) removePrefixFromFilteredPaths(context.Context, string) error {
func (c *Core) removePathFromFilteredPaths(context.Context, string, string) error {
return nil
}

View File

@ -18,13 +18,13 @@ import (
"sync"
"time"
"github.com/hashicorp/go-multierror"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/physical/raft"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-memdb"
"github.com/hashicorp/go-uuid"
memdb "github.com/hashicorp/go-memdb"
uuid "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/hostutil"
"github.com/hashicorp/vault/helper/identity"
"github.com/hashicorp/vault/helper/metricsutil"
@ -894,7 +894,7 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
// Attempt mount
if err := b.Core.mount(ctx, me); err != nil {
b.Backend.Logger().Error("mount failed", "path", me.Path, "error", err)
b.Backend.Logger().Error("error occurred during enable mount", "path", me.Path, "error", err)
return handleError(err)
}
@ -957,7 +957,7 @@ func (b *SystemBackend) handleUnmount(ctx context.Context, req *logical.Request,
return nil, nil
}
prefix, found := b.Core.router.MatchingStoragePrefixByAPIPath(ctx, path)
_, found := b.Core.router.MatchingStoragePrefixByAPIPath(ctx, path)
if !found {
b.Backend.Logger().Error("unable to find storage for path", "path", path)
return handleError(fmt.Errorf("unable to find storage for path: %q", path))
@ -969,8 +969,14 @@ func (b *SystemBackend) handleUnmount(ctx context.Context, req *logical.Request,
return handleError(err)
}
// Get the view path if available
var viewPath string
if entry != nil {
viewPath = entry.ViewPath()
}
// Remove from filtered mounts
if err := b.Core.removePrefixFromFilteredPaths(ctx, prefix); err != nil {
if err := b.Core.removePathFromFilteredPaths(ctx, ns.Path+path, viewPath); err != nil {
b.Backend.Logger().Error("filtered path removal failed", path, "error", err)
return handleError(err)
}
@ -982,6 +988,11 @@ func (b *SystemBackend) handleUnmount(ctx context.Context, req *logical.Request,
func (b *SystemBackend) handleRemount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
repState := b.Core.ReplicationState()
ns, err := namespace.FromContext(ctx)
if err != nil {
return nil, err
}
// Get the paths
fromPath := data.Get("from").(string)
toPath := data.Get("to").(string)
@ -1005,6 +1016,18 @@ func (b *SystemBackend) handleRemount(ctx context.Context, req *logical.Request,
return handleError(err)
}
// Get the view path if available
var viewPath string
if entry != nil {
viewPath = entry.ViewPath()
}
// Remove from filtered mounts and restart evaluation process
if err := b.Core.removePathFromFilteredPaths(ctx, ns.Path+fromPath, viewPath); err != nil {
b.Backend.Logger().Error("filtered path removal failed", fromPath, "error", err)
return handleError(err)
}
return nil, nil
}
@ -1823,7 +1846,7 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
// Attempt enabling
if err := b.Core.enableCredential(ctx, me); err != nil {
b.Backend.Logger().Error("enable auth mount failed", "path", me.Path, "error", err)
b.Backend.Logger().Error("error occurred during enable credential", "path", me.Path, "error", err)
return handleError(err)
}
return nil, nil
@ -1857,7 +1880,7 @@ func (b *SystemBackend) handleDisableAuth(ctx context.Context, req *logical.Requ
return nil, nil
}
prefix, found := b.Core.router.MatchingStoragePrefixByAPIPath(ctx, fullPath)
_, found := b.Core.router.MatchingStoragePrefixByAPIPath(ctx, fullPath)
if !found {
b.Backend.Logger().Error("unable to find storage for path", "path", fullPath)
return handleError(fmt.Errorf("unable to find storage for path: %q", fullPath))
@ -1869,8 +1892,14 @@ func (b *SystemBackend) handleDisableAuth(ctx context.Context, req *logical.Requ
return handleError(err)
}
// Get the view path if available
var viewPath string
if entry != nil {
viewPath = entry.ViewPath()
}
// Remove from filtered mounts
if err := b.Core.removePrefixFromFilteredPaths(ctx, prefix); err != nil {
if err := b.Core.removePathFromFilteredPaths(ctx, fullPath, viewPath); err != nil {
b.Backend.Logger().Error("filtered path removal failed", path, "error", err)
return handleError(err)
}

View File

@ -374,7 +374,19 @@ func (c *Core) mount(ctx context.Context, entry *MountEntry) error {
return logical.CodedError(403, fmt.Sprintf("mount type of %q is not mountable", entry.Type))
}
}
return c.mountInternal(ctx, entry, MountTableUpdateStorage)
// Mount internally
if err := c.mountInternal(ctx, entry, MountTableUpdateStorage); err != nil {
return err
}
// Re-evaluate filtered paths
if err := runFilteredPathsEvaluation(ctx, c); err != nil {
c.logger.Error("failed to evaluate filtered paths", "error", err)
return err
}
return nil
}
func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStorage bool) error {
@ -443,8 +455,8 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
viewPath := entry.ViewPath()
view := NewBarrierView(c.barrier, viewPath)
// Singleton mounts cannot be filtered on a per-secondary basis
// from replication
// Singleton mounts cannot be filtered manually on a per-secondary basis
// from replication.
if strutil.StrListContains(singletonMounts, entry.Type) {
addFilterablePath(c, viewPath)
}
@ -727,6 +739,37 @@ func (c *Core) remountForce(ctx context.Context, path string) error {
return c.mount(ctx, me)
}
// remountForceInternal takes a copy of the mount entry for the path and fully unmounts
// and remounts the backend to pick up any changes, such as filtered paths.
// Should be only used for internal usage.
func (c *Core) remountForceInternal(ctx context.Context, path string, updateStorage bool) error {
me := c.router.MatchingMountEntry(ctx, path)
if me == nil {
return fmt.Errorf("cannot find mount for path %q", path)
}
me, err := me.Clone()
if err != nil {
return err
}
if err := c.unmountInternal(ctx, path, updateStorage); err != nil {
return err
}
// Mount internally
if err := c.mountInternal(ctx, me, updateStorage); err != nil {
return err
}
// Re-evaluate filtered paths
if err := runFilteredPathsEvaluation(ctx, c); err != nil {
c.logger.Error("failed to evaluate filtered paths", "error", err)
return err
}
return nil
}
// Remount is used to remount a path at a new mount point.
func (c *Core) remount(ctx context.Context, src, dst string) error {
ns, err := namespace.FromContext(ctx)
@ -1068,7 +1111,7 @@ func (c *Core) setupMounts(ctx context.Context) error {
// Create a barrier view using the UUID
view := NewBarrierView(c.barrier, barrierPath)
// Singleton mounts cannot be filtered on a per-secondary basis
// Singleton mounts cannot be filtered manually on a per-secondary basis
// from replication
if strutil.StrListContains(singletonMounts, entry.Type) {
addFilterablePath(c, barrierPath)

View File

@ -18,6 +18,7 @@ func addFilterablePath(*Core, string) {}
func preprocessMount(*Core, *MountEntry, *BarrierView) (bool, error) { return false, nil }
func clearIgnoredPaths(context.Context, *Core, logical.Backend, string) error { return nil }
func addLicenseCallback(*Core, logical.Backend) {}
func runFilteredPathsEvaluation(context.Context, *Core) error { return nil }
// ViewPath returns storage prefix for the view
func (e *MountEntry) ViewPath() string {

View File

@ -10,7 +10,7 @@ import (
metrics "github.com/armon/go-metrics"
radix "github.com/armon/go-radix"
"github.com/hashicorp/go-hclog"
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/salt"