Sync over

This commit is contained in:
Jeff Mitchell 2017-10-23 16:03:36 -04:00
parent 3c6fe40a91
commit b7ffe7ec99
5 changed files with 100 additions and 48 deletions

View File

@ -51,6 +51,10 @@ const (
// the currently elected leader.
coreLeaderPrefix = "core/leader/"
// knownPrimaryAddrsPrefix is used to store last-known cluster address
// information for primaries
knownPrimaryAddrsPrefix = "core/primary-addrs/"
// lockRetryInterval is the interval we re-attempt to acquire the
// HA lock if an error is encountered
lockRetryInterval = 10 * time.Second
@ -104,6 +108,9 @@ var (
startReplication = startReplicationImpl
stopReplication = stopReplicationImpl
LastRemoteWAL = lastRemoteWALImpl
// A package-available logger function, mainly to have access in ACL for
// error conditions
vlogger log.Logger
)
// NonFatalError is an error that can be returned during NewCore that should be
@ -344,6 +351,11 @@ type Core struct {
// CORS Information
corsConfig *CORSConfig
// The active set of upstream cluster addresses; stored via the Echo
// mechanism, loaded by the balancer
atomicPrimaryClusterAddrs *atomic.Value
atomicPrimaryFailoverAddrs *atomic.Value
// replicationState keeps the current replication state cached for quick
// lookup
replicationState consts.ReplicationState
@ -455,6 +467,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
if conf.Logger == nil {
conf.Logger = logformat.NewVaultLogger(log.LevelTrace)
}
vlogger = conf.Logger
// Setup the core
c := &Core{
@ -476,6 +489,8 @@ func NewCore(conf *CoreConfig) (*Core, error) {
clusterPeerClusterAddrsCache: cache.New(3*heartbeatInterval, time.Second),
enableMlock: !conf.DisableMlock,
rawEnabled: conf.EnableRaw,
atomicPrimaryClusterAddrs: new(atomic.Value),
atomicPrimaryFailoverAddrs: new(atomic.Value),
}
if conf.ClusterCipherSuites != "" {
@ -486,18 +501,27 @@ func NewCore(conf *CoreConfig) (*Core, error) {
c.clusterCipherSuites = suites
}
c.corsConfig = &CORSConfig{core: c}
// Load CORS config and provide a value for the core field.
c.corsConfig = &CORSConfig{core: c}
phys := conf.Physical
_, txnOK := conf.Physical.(physical.Transactional)
// Wrap the physical backend in a cache layer if enabled and not already wrapped
if _, isCache := conf.Physical.(*physical.Cache); !conf.DisableCache && !isCache {
if c.seal == nil {
c.seal = &DefaultSeal{}
}
c.seal.SetCore(c)
var ok bool
// Wrap the physical backend in a cache layer if enabled
if !conf.DisableCache {
if txnOK {
c.physical = physical.NewTransactionalCache(conf.Physical, conf.CacheSize, conf.Logger)
c.physical = physical.NewTransactionalCache(phys, conf.CacheSize, conf.Logger)
} else {
c.physical = physical.NewCache(conf.Physical, conf.CacheSize, conf.Logger)
c.physical = physical.NewCache(phys, conf.CacheSize, conf.Logger)
}
}
}
if !conf.DisableMlock {
// Ensure our memory usage is locked into physical RAM
@ -546,7 +570,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
for k, f := range conf.LogicalBackends {
logicalBackends[k] = f
}
_, ok := logicalBackends["kv"]
_, ok = logicalBackends["kv"]
if !ok {
logicalBackends["kv"] = PassthroughBackendFactory
}
@ -580,16 +604,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
}
c.auditBackends = auditBackends
if c.seal == nil {
c.seal = &DefaultSeal{}
}
c.seal.SetCore(c)
// Attempt unsealing with stored keys; if there are no stored keys this
// returns nil, otherwise returns nil or an error
storedKeyErr := c.UnsealWithStoredKeys()
return c, storedKeyErr
return c, nil
}
// Shutdown is invoked when the Vault instance is about to be terminated. It
@ -724,17 +739,34 @@ func (c *Core) fetchACLTokenEntryAndEntity(clientToken string) (*ACL, *TokenEntr
return acl, te, entity, nil
}
func (c *Core) checkToken(req *logical.Request) (*logical.Auth, *TokenEntry, error) {
func (c *Core) checkToken(req *logical.Request, unauth bool) (*logical.Auth, *TokenEntry, error) {
defer metrics.MeasureSince([]string{"core", "check_token"}, time.Now())
acl, te, _, err := c.fetchACLTokenEntryAndEntity(req.ClientToken)
if err != nil {
return nil, te, err
var acl *ACL
var te *TokenEntry
var entity *identity.Entity
var err error
// Even if unauth, if a token is provided, there's little reason not to
// gather as much info as possible for the audit log and to e.g. control
// trace mode for EGPs.
if !unauth || (unauth && req.ClientToken != "") {
acl, te, entity, err = c.fetchACLTokenEntryAndEntity(req.ClientToken)
// In the unauth case we don't want to fail the command, since it's
// unauth, we just have no information to attach to the request, so
// ignore errors...this was best-effort anyways
if err != nil && !unauth {
return nil, te, err
}
}
// Check if this is a root protected path
rootPath := c.router.RootPath(req.Path)
if rootPath && unauth {
return nil, nil, errors.New("cannot access root path in unauthenticated request")
}
// When we receive a write of either type, rather than require clients to
// PUT/POST and trust the operation, we ask the backend to give us the real
// skinny -- if the backend implements an existence check, it can tell us
@ -788,12 +820,14 @@ func (c *Core) checkToken(req *logical.Request) (*logical.Auth, *TokenEntry, err
// Check the standard non-root ACLs. Return the token entry if it's not
// allowed so we can decrement the use count.
allowed, rootPrivs := acl.AllowOperation(req)
if !allowed {
// Return auth for audit logging even if not allowed
return auth, te, logical.ErrPermissionDenied
authResults := c.performPolicyChecks(acl, te, req, entity, &PolicyCheckOpts{
Unauth: unauth,
RootPrivsRequired: rootPath,
})
if authResults.Error.ErrorOrNil() != nil {
return auth, te, authResults.Error
}
if rootPath && !rootPrivs {
if !authResults.Allowed {
// Return auth for audit logging even if not allowed
return auth, te, logical.ErrPermissionDenied
}
@ -1147,7 +1181,7 @@ func (c *Core) sealInitCommon(req *logical.Request) (retErr error) {
}
// Validate the token is a root token
acl, te, _, err := c.fetchACLTokenEntryAndEntity(req.ClientToken)
acl, te, entity, err := c.fetchACLTokenEntryAndEntity(req.ClientToken)
if err != nil {
// Since there is no token store in standby nodes, sealing cannot
// be done. Ideally, the request has to be forwarded to leader node
@ -1210,15 +1244,15 @@ func (c *Core) sealInitCommon(req *logical.Request) (retErr error) {
}
// Verify that this operation is allowed
allowed, rootPrivs := acl.AllowOperation(req)
if !allowed {
retErr = multierror.Append(retErr, logical.ErrPermissionDenied)
authResults := c.performPolicyChecks(acl, te, req, entity, &PolicyCheckOpts{
RootPrivsRequired: true,
})
if authResults.Error.ErrorOrNil() != nil {
retErr = multierror.Append(retErr, authResults.Error)
c.stateLock.RUnlock()
return retErr
}
// We always require root privileges for this operation
if !rootPrivs {
if !authResults.Allowed {
retErr = multierror.Append(retErr, logical.ErrPermissionDenied)
c.stateLock.RUnlock()
return retErr
@ -1266,7 +1300,7 @@ func (c *Core) StepDown(req *logical.Request) (retErr error) {
return nil
}
acl, te, _, err := c.fetchACLTokenEntryAndEntity(req.ClientToken)
acl, te, entity, err := c.fetchACLTokenEntryAndEntity(req.ClientToken)
if err != nil {
retErr = multierror.Append(retErr, err)
return retErr
@ -1313,14 +1347,14 @@ func (c *Core) StepDown(req *logical.Request) (retErr error) {
}
// Verify that this operation is allowed
allowed, rootPrivs := acl.AllowOperation(req)
if !allowed {
retErr = multierror.Append(retErr, logical.ErrPermissionDenied)
authResults := c.performPolicyChecks(acl, te, req, entity, &PolicyCheckOpts{
RootPrivsRequired: true,
})
if authResults.Error.ErrorOrNil() != nil {
retErr = multierror.Append(retErr, authResults.Error)
return retErr
}
// We always require root privileges for this operation
if !rootPrivs {
if !authResults.Allowed {
retErr = multierror.Append(retErr, logical.ErrPermissionDenied)
return retErr
}
@ -1463,6 +1497,9 @@ func (c *Core) postUnseal() (retErr error) {
if err := c.setupAudits(); err != nil {
return err
}
if err := c.loadIdentityStoreArtifacts(); err != nil {
return err
}
if err := c.setupAuditedHeadersConfig(); err != nil {
return err
}
@ -1967,9 +2004,7 @@ func (c *Core) ReplicationState() consts.ReplicationState {
}
func (c *Core) SealAccess() *SealAccess {
sa := &SealAccess{}
sa.SetSeal(c.seal)
return sa
return NewSealAccess(c.seal)
}
func (c *Core) Logger() log.Logger {
@ -1989,3 +2024,15 @@ func (c *Core) AuditedHeadersConfig() *AuditedHeadersConfig {
func lastRemoteWALImpl(c *Core) uint64 {
return 0
}
func (c *Core) BarrierEncryptorAccess() *BarrierEncryptorAccess {
return NewBarrierEncryptorAccess(c.barrier)
}
func (c *Core) PhysicalAccess() *physical.PhysicalAccess {
return physical.NewPhysicalAccess(c.physical)
}
func (c *Core) RouterAccess() *RouterAccess {
return NewRouterAccess(c)
}

View File

@ -488,7 +488,7 @@ func TestCore_HandleRequest_RootPath_WithSudo(t *testing.T) {
if err != nil {
t.Fatalf("err: %v", err)
}
if resp != nil {
if resp != nil && (resp.IsError() || len(resp.Data) > 0) {
t.Fatalf("bad: %#v", resp)
}
@ -546,7 +546,7 @@ func TestCore_HandleRequest_PermissionAllowed(t *testing.T) {
if err != nil {
t.Fatalf("err: %v", err)
}
if resp != nil {
if resp != nil && (resp.IsError() || len(resp.Data) > 0) {
t.Fatalf("bad: %#v", resp)
}
@ -873,6 +873,9 @@ func TestCore_HandleRequest_CreateToken_Lease(t *testing.T) {
}
// Ensure we got a new client token back
if resp.IsError() {
t.Fatalf("err: %v %v", err, *resp)
}
clientToken := resp.Auth.ClientToken
if clientToken == "" {
t.Fatalf("bad: %#v", resp)
@ -1927,7 +1930,7 @@ path "secret/*" {
`
ps := c.policyStore
policy, _ := Parse(secretWritingPolicy)
policy, _ := ParseACLPolicy(secretWritingPolicy)
if err := ps.SetPolicy(policy); err != nil {
t.Fatal(err)
}

View File

@ -24,6 +24,7 @@ var StdAllowedHeaders = []string{
"X-Vault-Token",
"X-Vault-Wrap-Format",
"X-Vault-Wrap-TTL",
"X-Vault-Policy-Override",
}
// CORSConfig stores the state of the CORS configuration.

View File

@ -54,8 +54,8 @@ func (d dynamicSystemView) SudoPrivilege(path string, token string) bool {
req := new(logical.Request)
req.Operation = logical.ReadOperation
req.Path = path
_, rootPrivs := acl.AllowOperation(req)
return rootPrivs
authResults := acl.AllowOperation(req)
return authResults.RootPrivs
}
// TTLsByPath returns the default and max TTLs corresponding to a particular

View File

@ -251,6 +251,7 @@ func (c *Core) Initialize(initParams *InitParams) (*InitResult, error) {
return results, nil
}
// UnsealWithStoredKeys performs auto-unseal using stored keys.
func (c *Core) UnsealWithStoredKeys() error {
if !c.seal.StoredKeysSupported() {
return nil
@ -297,6 +298,6 @@ func (c *Core) UnsealWithStoredKeys() error {
}
}
}
return nil
}