mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-11-01 02:57:59 +00:00 
			
		
		
		
	Port over bits (#3575)
This commit is contained in:
		| @@ -40,6 +40,7 @@ type Secret struct { | ||||
| // available in WrappedAccessor. | ||||
| type SecretWrapInfo struct { | ||||
| 	Token           string    `json:"token"` | ||||
| 	Accessor        string    `json:"accessor"` | ||||
| 	TTL             int       `json:"ttl"` | ||||
| 	CreationTime    time.Time `json:"creation_time"` | ||||
| 	CreationPath    string    `json:"creation_path"` | ||||
|   | ||||
| @@ -21,6 +21,7 @@ func TestParseSecret(t *testing.T) { | ||||
| 	], | ||||
| 	"wrap_info": { | ||||
| 		"token": "token", | ||||
| 		"accessor": "accessor", | ||||
| 		"ttl": 60, | ||||
| 		"creation_time": "2016-06-07T15:52:10-04:00", | ||||
| 		"wrapped_accessor": "abcd1234" | ||||
| @@ -46,6 +47,7 @@ func TestParseSecret(t *testing.T) { | ||||
| 		}, | ||||
| 		WrapInfo: &SecretWrapInfo{ | ||||
| 			Token:           "token", | ||||
| 			Accessor:        "accessor", | ||||
| 			TTL:             60, | ||||
| 			CreationTime:    rawTime, | ||||
| 			WrappedAccessor: "abcd1234", | ||||
|   | ||||
| @@ -242,12 +242,13 @@ func (f *AuditFormatter) FormatResponse( | ||||
|  | ||||
| 		// Cache and restore accessor in the response | ||||
| 		if resp != nil { | ||||
| 			var accessor, wrappedAccessor string | ||||
| 			var accessor, wrappedAccessor, wrappingAccessor string | ||||
| 			if !config.HMACAccessor && resp != nil && resp.Auth != nil && resp.Auth.Accessor != "" { | ||||
| 				accessor = resp.Auth.Accessor | ||||
| 			} | ||||
| 			if !config.HMACAccessor && resp != nil && resp.WrapInfo != nil && resp.WrapInfo.WrappedAccessor != "" { | ||||
| 				wrappedAccessor = resp.WrapInfo.WrappedAccessor | ||||
| 				wrappingAccessor = resp.WrapInfo.Accessor | ||||
| 			} | ||||
| 			if err := Hash(salt, resp); err != nil { | ||||
| 				return err | ||||
| @@ -258,6 +259,9 @@ func (f *AuditFormatter) FormatResponse( | ||||
| 			if wrappedAccessor != "" { | ||||
| 				resp.WrapInfo.WrappedAccessor = wrappedAccessor | ||||
| 			} | ||||
| 			if wrappingAccessor != "" { | ||||
| 				resp.WrapInfo.Accessor = wrappingAccessor | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -301,6 +305,7 @@ func (f *AuditFormatter) FormatResponse( | ||||
| 		respWrapInfo = &AuditResponseWrapInfo{ | ||||
| 			TTL:             int(resp.WrapInfo.TTL / time.Second), | ||||
| 			Token:           token, | ||||
| 			Accessor:        resp.WrapInfo.Accessor, | ||||
| 			CreationTime:    resp.WrapInfo.CreationTime.Format(time.RFC3339Nano), | ||||
| 			CreationPath:    resp.WrapInfo.CreationPath, | ||||
| 			WrappedAccessor: resp.WrapInfo.WrappedAccessor, | ||||
| @@ -412,6 +417,7 @@ type AuditSecret struct { | ||||
| type AuditResponseWrapInfo struct { | ||||
| 	TTL             int    `json:"ttl"` | ||||
| 	Token           string `json:"token"` | ||||
| 	Accessor        string `json:"accessor"` | ||||
| 	CreationTime    string `json:"creation_time"` | ||||
| 	CreationPath    string `json:"creation_path"` | ||||
| 	WrappedAccessor string `json:"wrapped_accessor,omitempty"` | ||||
|   | ||||
| @@ -93,6 +93,7 @@ func Hash(salter *salt.Salt, raw interface{}) error { | ||||
| 		} | ||||
|  | ||||
| 		s.Token = fn(s.Token) | ||||
| 		s.Accessor = fn(s.Accessor) | ||||
|  | ||||
| 		if s.WrappedAccessor != "" { | ||||
| 			s.WrappedAccessor = fn(s.WrappedAccessor) | ||||
|   | ||||
| @@ -148,6 +148,7 @@ func TestHash(t *testing.T) { | ||||
| 				WrapInfo: &wrapping.ResponseWrapInfo{ | ||||
| 					TTL:             60, | ||||
| 					Token:           "bar", | ||||
| 					Accessor:        "flimflam", | ||||
| 					CreationTime:    now, | ||||
| 					WrappedAccessor: "bar", | ||||
| 				}, | ||||
| @@ -160,6 +161,7 @@ func TestHash(t *testing.T) { | ||||
| 				WrapInfo: &wrapping.ResponseWrapInfo{ | ||||
| 					TTL:             60, | ||||
| 					Token:           "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", | ||||
| 					Accessor:        "hmac-sha256:7c9c6fe666d0af73b3ebcfbfabe6885015558213208e6635ba104047b22f6390", | ||||
| 					CreationTime:    now, | ||||
| 					WrappedAccessor: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", | ||||
| 				}, | ||||
| @@ -206,6 +208,11 @@ func TestHash(t *testing.T) { | ||||
| 		if err := Hash(localSalt, tc.Input); err != nil { | ||||
| 			t.Fatalf("err: %s\n\n%s", err, input) | ||||
| 		} | ||||
| 		if _, ok := tc.Input.(*logical.Response); ok { | ||||
| 			if !reflect.DeepEqual(tc.Input.(*logical.Response).WrapInfo, tc.Output.(*logical.Response).WrapInfo) { | ||||
| 				t.Fatalf("bad:\nInput:\n%s\nTest case input:\n%#v\nTest case output\n%#v", input, tc.Input.(*logical.Response).WrapInfo, tc.Output.(*logical.Response).WrapInfo) | ||||
| 			} | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(tc.Input, tc.Output) { | ||||
| 			t.Fatalf("bad:\nInput:\n%s\nTest case input:\n%#v\nTest case output\n%#v", input, tc.Input, tc.Output) | ||||
| 		} | ||||
|   | ||||
| @@ -182,6 +182,7 @@ func (t TableFormatter) OutputSecret(ui cli.Ui, secret, s *api.Secret) error { | ||||
| 	if s.WrapInfo != nil { | ||||
| 		onceHeader.Do(headerFunc) | ||||
| 		input = append(input, fmt.Sprintf("wrapping_token: %s %s", config.Delim, s.WrapInfo.Token)) | ||||
| 		input = append(input, fmt.Sprintf("wrapping_accessor: %s %s", config.Delim, s.WrapInfo.Accessor)) | ||||
| 		input = append(input, fmt.Sprintf("wrapping_token_ttl: %s %s", config.Delim, (time.Second*time.Duration(s.WrapInfo.TTL)).String())) | ||||
| 		input = append(input, fmt.Sprintf("wrapping_token_creation_time: %s %s", config.Delim, s.WrapInfo.CreationTime.String())) | ||||
| 		input = append(input, fmt.Sprintf("wrapping_token_creation_path: %s %s", config.Delim, s.WrapInfo.CreationPath)) | ||||
|   | ||||
| @@ -53,6 +53,8 @@ func PrintRawField(ui cli.Ui, secret *api.Secret, field string) int { | ||||
| 		switch field { | ||||
| 		case "wrapping_token": | ||||
| 			val = secret.WrapInfo.Token | ||||
| 		case "wrapping_accessor": | ||||
| 			val = secret.WrapInfo.Accessor | ||||
| 		case "wrapping_token_ttl": | ||||
| 			val = secret.WrapInfo.TTL | ||||
| 		case "wrapping_token_creation_time": | ||||
|   | ||||
| @@ -28,6 +28,20 @@ func (e *Entity) SentinelGet(key string) (interface{}, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (e *Entity) SentinelKeys() []string { | ||||
| 	return []string{ | ||||
| 		"id", | ||||
| 		"aliases", | ||||
| 		"metadata", | ||||
| 		"meta", | ||||
| 		"name", | ||||
| 		"creation_time", | ||||
| 		"last_update_time", | ||||
| 		"merged_entity_ids", | ||||
| 		"policies", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *Alias) SentinelGet(key string) (interface{}, error) { | ||||
| 	if p == nil { | ||||
| 		return nil, nil | ||||
| @@ -56,6 +70,20 @@ func (p *Alias) SentinelGet(key string) (interface{}, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (a *Alias) SentinelKeys() []string { | ||||
| 	return []string{ | ||||
| 		"id", | ||||
| 		"mount_type", | ||||
| 		"mount_path", | ||||
| 		"meta", | ||||
| 		"metadata", | ||||
| 		"name", | ||||
| 		"creation_time", | ||||
| 		"last_update_time", | ||||
| 		"merged_from_entity_ids", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (g *Group) SentinelGet(key string) (interface{}, error) { | ||||
| 	if g == nil { | ||||
| 		return nil, nil | ||||
| @@ -81,3 +109,17 @@ func (g *Group) SentinelGet(key string) (interface{}, error) { | ||||
|  | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (g *Group) SentinelKeys() []string { | ||||
| 	return []string{ | ||||
| 		"id", | ||||
| 		"name", | ||||
| 		"policies", | ||||
| 		"parent_group_ids", | ||||
| 		"member_entity_ids", | ||||
| 		"metadata", | ||||
| 		"meta", | ||||
| 		"creation_time", | ||||
| 		"last_update_time", | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,9 @@ type ResponseWrapInfo struct { | ||||
| 	// The token containing the wrapped response | ||||
| 	Token string `json:"token" structs:"token" mapstructure:"token" sentinel:""` | ||||
|  | ||||
| 	// The token accessor for the wrapped response token | ||||
| 	Accessor string `json:"accessor" structs:"accessor" mapstructure:"accessor"` | ||||
|  | ||||
| 	// The creation time. This can be used with the TTL to figure out an | ||||
| 	// expected expiration. | ||||
| 	CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"creation_time" sentinel:""` | ||||
|   | ||||
| @@ -325,6 +325,12 @@ func TestSysMounts_headerAuth_Wrapped(t *testing.T) { | ||||
| 	} | ||||
| 	expected["wrap_info"].(map[string]interface{})["creation_path"] = actualCreationPath | ||||
|  | ||||
| 	actualAccessor, ok := actual["wrap_info"].(map[string]interface{})["accessor"] | ||||
| 	if !ok || actualAccessor == "" { | ||||
| 		t.Fatal("accessor missing in wrap info") | ||||
| 	} | ||||
| 	expected["wrap_info"].(map[string]interface{})["accessor"] = actualAccessor | ||||
|  | ||||
| 	if !reflect.DeepEqual(actual, expected) { | ||||
| 		t.Fatalf("bad:\nExpected: %#v\nActual: %#v\n%T %T", expected, actual, actual["warnings"], actual["data"]) | ||||
| 	} | ||||
|   | ||||
| @@ -151,6 +151,7 @@ func respondLogical(w http.ResponseWriter, r *http.Request, req *logical.Request | ||||
| 			httpResp = &logical.HTTPResponse{ | ||||
| 				WrapInfo: &logical.HTTPWrapInfo{ | ||||
| 					Token:           resp.WrapInfo.Token, | ||||
| 					Accessor:        resp.WrapInfo.Accessor, | ||||
| 					TTL:             int(resp.WrapInfo.TTL.Seconds()), | ||||
| 					CreationTime:    resp.WrapInfo.CreationTime.Format(time.RFC3339Nano), | ||||
| 					CreationPath:    resp.WrapInfo.CreationPath, | ||||
|   | ||||
| @@ -37,6 +37,13 @@ func (r *RequestWrapInfo) SentinelGet(key string) (interface{}, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (r *RequestWrapInfo) SentinelKeys() []string { | ||||
| 	return []string{ | ||||
| 		"ttl", | ||||
| 		"ttl_seconds", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Request is a struct that stores the parameters and context of a request | ||||
| // being made to Vault. It is used to abstract the details of the higher level | ||||
| // request protocol from the handlers. | ||||
| @@ -176,6 +183,14 @@ func (r *Request) SentinelGet(key string) (interface{}, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (r *Request) SentinelKeys() []string { | ||||
| 	return []string{ | ||||
| 		"path", | ||||
| 		"wrapping", | ||||
| 		"wrap_info", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (r *Request) LastRemoteWAL() uint64 { | ||||
| 	return r.lastRemoteWAL | ||||
| } | ||||
| @@ -260,4 +275,8 @@ var ( | ||||
|  | ||||
| 	// ErrPermissionDenied is returned if the client is not authorized | ||||
| 	ErrPermissionDenied = errors.New("permission denied") | ||||
|  | ||||
| 	// ErrMultiAuthzPending is returned if the the request needs more | ||||
| 	// authorizations | ||||
| 	ErrMultiAuthzPending = errors.New("request needs further approval") | ||||
| ) | ||||
|   | ||||
| @@ -92,6 +92,7 @@ type HTTPAuth struct { | ||||
|  | ||||
| type HTTPWrapInfo struct { | ||||
| 	Token           string `json:"token"` | ||||
| 	Accessor        string `json:"accessor"` | ||||
| 	TTL             int    `json:"ttl"` | ||||
| 	CreationTime    string `json:"creation_time"` | ||||
| 	CreationPath    string `json:"creation_path"` | ||||
|   | ||||
| @@ -221,18 +221,29 @@ func testCoreWithIdentityTokenGithub(t *testing.T) (*Core, *IdentityStore, *Toke | ||||
| 	return core, is, ts, ghAccessor | ||||
| } | ||||
|  | ||||
| func testCoreWithIdentityTokenGithubRoot(t *testing.T) (*Core, *IdentityStore, *TokenStore, string, string) { | ||||
| 	is, ghAccessor, core, root := testIdentityStoreWithGithubAuthRoot(t) | ||||
| 	ts := testTokenStore(t, core) | ||||
| 	return core, is, ts, ghAccessor, root | ||||
| } | ||||
|  | ||||
| func testIdentityStoreWithGithubAuth(t *testing.T) (*IdentityStore, string, *Core) { | ||||
| 	is, ghA, c, _ := testIdentityStoreWithGithubAuthRoot(t) | ||||
| 	return is, ghA, c | ||||
| } | ||||
|  | ||||
| // testIdentityStoreWithGithubAuth returns an instance of identity store which | ||||
| // is mounted by default. This function also enables the github auth backend to | ||||
| // assist with testing aliases and entities that require an valid mount | ||||
| // accessor of an auth backend. | ||||
| func testIdentityStoreWithGithubAuth(t *testing.T) (*IdentityStore, string, *Core) { | ||||
| func testIdentityStoreWithGithubAuthRoot(t *testing.T) (*IdentityStore, string, *Core, string) { | ||||
| 	// Add github credential factory to core config | ||||
| 	err := AddTestCredentialBackend("github", credGithub.Factory) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	c, _, _ := TestCoreUnsealed(t) | ||||
| 	c, _, root := TestCoreUnsealed(t) | ||||
|  | ||||
| 	meGH := &MountEntry{ | ||||
| 		Table:       credentialTableType, | ||||
| @@ -252,7 +263,7 @@ func testIdentityStoreWithGithubAuth(t *testing.T) (*IdentityStore, string, *Cor | ||||
| 		t.Fatalf("failed to fetch identity store from router") | ||||
| 	} | ||||
|  | ||||
| 	return identitystore.(*IdentityStore), meGH.Accessor, c | ||||
| 	return identitystore.(*IdentityStore), meGH.Accessor, c, root | ||||
| } | ||||
|  | ||||
| func TestIdentityStore_MetadataKeyRegex(t *testing.T) { | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
| 	"encoding/base64" | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"hash" | ||||
| 	"strconv" | ||||
| @@ -2507,42 +2508,36 @@ func (b *SystemBackend) handleWrappingUnwrap( | ||||
| 		token = req.ClientToken | ||||
| 	} | ||||
|  | ||||
| 	if thirdParty { | ||||
| 		// Use the token to decrement the use count to avoid a second operation on the token. | ||||
| 		_, err := b.Core.tokenStore.UseTokenByID(token) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("error decrementing wrapping token's use-count: %v", err) | ||||
| 	// Get the policies so we can determine if this is a normal response | ||||
| 	// wrapping request or a control group token. | ||||
| 	// | ||||
| 	// We use lookupTainted here because the token might have already been used | ||||
| 	// by handleRequest(), this happens when it's a normal response wrapping | ||||
| 	// request and the token was provided "first party". We want to inspect the | ||||
| 	// token policies but will not use this token entry for anything else. | ||||
| 	te, err := b.Core.tokenStore.lookupTainted(token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if te == nil { | ||||
| 		return nil, errors.New("could not find token") | ||||
| 	} | ||||
| 	if len(te.Policies) != 1 { | ||||
| 		return nil, errors.New("token is not a valid unwrap token") | ||||
| 	} | ||||
|  | ||||
| 	var response string | ||||
| 	switch te.Policies[0] { | ||||
| 	case responseWrappingPolicyName: | ||||
| 		response, err = b.responseWrappingUnwrap(token, thirdParty) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		var respErr *logical.Response | ||||
| 		if len(response) > 0 { | ||||
| 			respErr = logical.ErrorResponse(response) | ||||
| 		} | ||||
|  | ||||
| 		defer b.Core.tokenStore.Revoke(token) | ||||
| 	} | ||||
|  | ||||
| 	cubbyReq := &logical.Request{ | ||||
| 		Operation:   logical.ReadOperation, | ||||
| 		Path:        "cubbyhole/response", | ||||
| 		ClientToken: token, | ||||
| 	} | ||||
| 	cubbyResp, err := b.Core.router.Route(cubbyReq) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error looking up wrapping information: %v", err) | ||||
| 	} | ||||
| 	if cubbyResp == nil { | ||||
| 		return logical.ErrorResponse("no information found; wrapping token may be from a previous Vault version"), nil | ||||
| 	} | ||||
| 	if cubbyResp != nil && cubbyResp.IsError() { | ||||
| 		return cubbyResp, nil | ||||
| 	} | ||||
| 	if cubbyResp.Data == nil { | ||||
| 		return logical.ErrorResponse("wrapping information was nil; wrapping token may be from a previous Vault version"), nil | ||||
| 	} | ||||
|  | ||||
| 	responseRaw := cubbyResp.Data["response"] | ||||
| 	if responseRaw == nil { | ||||
| 		return nil, fmt.Errorf("no response found inside the cubbyhole") | ||||
| 	} | ||||
| 	response, ok := responseRaw.(string) | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("could not decode response inside the cubbyhole") | ||||
| 		return respErr, err | ||||
| 	} | ||||
|  | ||||
| 	resp := &logical.Response{ | ||||
| @@ -2559,6 +2554,50 @@ func (b *SystemBackend) handleWrappingUnwrap( | ||||
| 	return resp, nil | ||||
| } | ||||
|  | ||||
| // responseWrappingUnwrap will read the stored response in the cubbyhole and | ||||
| // return the raw HTTP response. | ||||
| func (b *SystemBackend) responseWrappingUnwrap(token string, thirdParty bool) (string, error) { | ||||
| 	if thirdParty { | ||||
| 		// Use the token to decrement the use count to avoid a second operation on the token. | ||||
| 		_, err := b.Core.tokenStore.UseTokenByID(token) | ||||
| 		if err != nil { | ||||
| 			return "", fmt.Errorf("error decrementing wrapping token's use-count: %v", err) | ||||
| 		} | ||||
|  | ||||
| 		defer b.Core.tokenStore.Revoke(token) | ||||
| 	} | ||||
|  | ||||
| 	cubbyReq := &logical.Request{ | ||||
| 		Operation:   logical.ReadOperation, | ||||
| 		Path:        "cubbyhole/response", | ||||
| 		ClientToken: token, | ||||
| 	} | ||||
| 	cubbyResp, err := b.Core.router.Route(cubbyReq) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("error looking up wrapping information: %v", err) | ||||
| 	} | ||||
| 	if cubbyResp == nil { | ||||
| 		return "no information found; wrapping token may be from a previous Vault version", ErrInternalError | ||||
| 	} | ||||
| 	if cubbyResp != nil && cubbyResp.IsError() { | ||||
| 		return cubbyResp.Error().Error(), nil | ||||
| 	} | ||||
| 	if cubbyResp.Data == nil { | ||||
| 		return "wrapping information was nil; wrapping token may be from a previous Vault version", ErrInternalError | ||||
| 	} | ||||
|  | ||||
| 	responseRaw := cubbyResp.Data["response"] | ||||
| 	if responseRaw == nil { | ||||
| 		return "", fmt.Errorf("no response found inside the cubbyhole") | ||||
| 	} | ||||
| 	response, ok := responseRaw.(string) | ||||
| 	if !ok { | ||||
| 		return "", fmt.Errorf("could not decode response inside the cubbyhole") | ||||
| 	} | ||||
|  | ||||
| 	return response, nil | ||||
| } | ||||
|  | ||||
| func (b *SystemBackend) handleWrappingLookup( | ||||
| 	req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||||
| 	// This ordering of lookups has been validated already in the wrapping | ||||
|   | ||||
| @@ -22,9 +22,16 @@ const ( | ||||
| 	// policyCacheSize is the number of policies that are kept cached | ||||
| 	policyCacheSize = 1024 | ||||
|  | ||||
| 	// defaultPolicyName is the name of the default policy | ||||
| 	defaultPolicyName = "default" | ||||
|  | ||||
| 	// responseWrappingPolicyName is the name of the fixed policy | ||||
| 	responseWrappingPolicyName = "response-wrapping" | ||||
|  | ||||
| 	// controlGroupPolicyName is the name of the fixed policy for control group | ||||
| 	// tokens | ||||
| 	controlGroupPolicyName = "control-group" | ||||
|  | ||||
| 	// responseWrappingPolicy is the policy that ensures cubbyhole response | ||||
| 	// wrapping can always succeed. | ||||
| 	responseWrappingPolicy = ` | ||||
| @@ -117,9 +124,11 @@ var ( | ||||
| 	immutablePolicies = []string{ | ||||
| 		"root", | ||||
| 		responseWrappingPolicyName, | ||||
| 		controlGroupPolicyName, | ||||
| 	} | ||||
| 	nonAssignablePolicies = []string{ | ||||
| 		responseWrappingPolicyName, | ||||
| 		controlGroupPolicyName, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| @@ -181,27 +190,12 @@ func (c *Core) setupPolicyStore() error { | ||||
| 	} | ||||
|  | ||||
| 	// Ensure that the default policy exists, and if not, create it | ||||
| 	policy, err := c.policyStore.GetPolicy("default", PolicyTypeACL) | ||||
| 	if err != nil { | ||||
| 		return errwrap.Wrapf("error fetching default policy from store: {{err}}", err) | ||||
| 	if err := c.policyStore.loadACLPolicy(defaultPolicyName, defaultPolicy); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if policy == nil { | ||||
| 		err := c.policyStore.createDefaultPolicy() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Ensure that the cubbyhole response wrapping policy exists | ||||
| 	policy, err = c.policyStore.GetPolicy(responseWrappingPolicyName, PolicyTypeACL) | ||||
| 	if err != nil { | ||||
| 		return errwrap.Wrapf("error fetching response-wrapping policy from store: {{err}}", err) | ||||
| 	} | ||||
| 	if policy == nil || policy.Raw != responseWrappingPolicy { | ||||
| 		err := c.policyStore.createResponseWrappingPolicy() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	// Ensure that the response wrapping policy exists | ||||
| 	if err := c.policyStore.loadACLPolicy(responseWrappingPolicyName, responseWrappingPolicy); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| @@ -478,32 +472,30 @@ func (ps *PolicyStore) ACL(names ...string) (*ACL, error) { | ||||
| 	return acl, nil | ||||
| } | ||||
|  | ||||
| func (ps *PolicyStore) createDefaultPolicy() error { | ||||
| 	policy, err := ParseACLPolicy(defaultPolicy) | ||||
| func (ps *PolicyStore) loadACLPolicy(policyName, policyText string) error { | ||||
| 	// Check if the policy already exists | ||||
| 	policy, err := ps.GetPolicy(policyName, PolicyTypeACL) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return errwrap.Wrapf("error parsing default policy: {{err}}", err) | ||||
| 		return errwrap.Wrapf(fmt.Sprintf("error fetching %s policy from store: {{err}}", policyName), err) | ||||
| 	} | ||||
|  | ||||
| 	if policy != nil { | ||||
| 		if !strutil.StrListContains(immutablePolicies, policyName) || policyText == policy.Raw { | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	policy, err = ParseACLPolicy(policyText) | ||||
| 	if err != nil { | ||||
| 		return errwrap.Wrapf(fmt.Sprintf("error parsing %s policy: {{err}}", policyName), err) | ||||
| 	} | ||||
|  | ||||
| 	if policy == nil { | ||||
| 		return fmt.Errorf("parsing default policy resulted in nil policy") | ||||
| 		return fmt.Errorf("parsing %s policy resulted in nil policy", policyName) | ||||
| 	} | ||||
|  | ||||
| 	policy.Name = "default" | ||||
| 	policy.Type = PolicyTypeACL | ||||
| 	return ps.setPolicyInternal(policy) | ||||
| } | ||||
|  | ||||
| func (ps *PolicyStore) createResponseWrappingPolicy() error { | ||||
| 	policy, err := ParseACLPolicy(responseWrappingPolicy) | ||||
| 	if err != nil { | ||||
| 		return errwrap.Wrapf(fmt.Sprintf("error parsing %s policy: {{err}}", responseWrappingPolicyName), err) | ||||
| 	} | ||||
|  | ||||
| 	if policy == nil { | ||||
| 		return fmt.Errorf("parsing %s policy resulted in nil policy", responseWrappingPolicyName) | ||||
| 	} | ||||
|  | ||||
| 	policy.Name = responseWrappingPolicyName | ||||
| 	policy.Name = policyName | ||||
| 	policy.Type = PolicyTypeACL | ||||
| 	return ps.setPolicyInternal(policy) | ||||
| } | ||||
|   | ||||
| @@ -68,7 +68,8 @@ func (c *Core) HandleRequest(req *logical.Request) (resp *logical.Response, err | ||||
| 		err == nil && | ||||
| 		!resp.IsError() && | ||||
| 		resp.WrapInfo != nil && | ||||
| 		resp.WrapInfo.TTL != 0 | ||||
| 		resp.WrapInfo.TTL != 0 && | ||||
| 		resp.WrapInfo.Token == "" | ||||
|  | ||||
| 	if wrapping { | ||||
| 		cubbyResp, cubbyErr := c.wrapInCubbyhole(req, resp, auth) | ||||
| @@ -161,12 +162,10 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r | ||||
| 	if ctErr != nil { | ||||
| 		// If it is an internal error we return that, otherwise we | ||||
| 		// return invalid request so that the status codes can be correct | ||||
| 		var errType error | ||||
| 		errType := logical.ErrInvalidRequest | ||||
| 		switch ctErr { | ||||
| 		case ErrInternalError, logical.ErrPermissionDenied: | ||||
| 			errType = ctErr | ||||
| 		default: | ||||
| 			errType = logical.ErrInvalidRequest | ||||
| 		} | ||||
|  | ||||
| 		if err := c.auditBroker.LogRequest(auth, req, c.auditedHeaders, ctErr); err != nil { | ||||
|   | ||||
| @@ -623,6 +623,21 @@ func (te *TokenEntry) SentinelGet(key string) (interface{}, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (te *TokenEntry) SentinelKeys() []string { | ||||
| 	return []string{ | ||||
| 		"period", | ||||
| 		"period_seconds", | ||||
| 		"explicit_max_ttl", | ||||
| 		"explicit_max_ttl_seconds", | ||||
| 		"creation_ttl", | ||||
| 		"creation_ttl_seconds", | ||||
| 		"creation_time", | ||||
| 		"creation_time_unix", | ||||
| 		"meta", | ||||
| 		"metadata", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // tsRoleEntry contains token store role information | ||||
| type tsRoleEntry struct { | ||||
| 	// The name of the role. Embedded so it can be used for pathing | ||||
| @@ -865,6 +880,12 @@ func (ts *TokenStore) UseToken(te *TokenEntry) (*TokenEntry, error) { | ||||
| 		return te, nil | ||||
| 	} | ||||
|  | ||||
| 	// If we are attempting to unwrap a control group request, don't use the token. | ||||
| 	// It will be manually revoked by the handler. | ||||
| 	if len(te.Policies) == 1 && te.Policies[0] == controlGroupPolicyName { | ||||
| 		return te, nil | ||||
| 	} | ||||
|  | ||||
| 	lock := locksutil.LockForKey(ts.tokenLocks, te.ID) | ||||
| 	lock.Lock() | ||||
| 	defer lock.Unlock() | ||||
| @@ -934,6 +955,25 @@ func (ts *TokenStore) Lookup(id string) (*TokenEntry, error) { | ||||
| 	return ts.lookupSalted(saltedID, false) | ||||
| } | ||||
|  | ||||
| // lookupTainted is used to find a token that may or maynot be tainted given its | ||||
| // ID. It acquires a read lock, then calls lookupSalted. | ||||
| func (ts *TokenStore) lookupTainted(id string) (*TokenEntry, error) { | ||||
| 	defer metrics.MeasureSince([]string{"token", "lookup"}, time.Now()) | ||||
| 	if id == "" { | ||||
| 		return nil, fmt.Errorf("cannot lookup blank token") | ||||
| 	} | ||||
|  | ||||
| 	lock := locksutil.LockForKey(ts.tokenLocks, id) | ||||
| 	lock.RLock() | ||||
| 	defer lock.RUnlock() | ||||
|  | ||||
| 	saltedID, err := ts.SaltID(id) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ts.lookupSalted(saltedID, true) | ||||
| } | ||||
|  | ||||
| // lookupSalted is used to find a token given its salted ID. If tainted is | ||||
| // true, entries that are in some revocation state (currently, indicated by num | ||||
| // uses < 0), the entry will be returned anyways | ||||
|   | ||||
| @@ -115,6 +115,7 @@ func (c *Core) wrapInCubbyhole(req *logical.Request, resp *logical.Response, aut | ||||
| 	} | ||||
|  | ||||
| 	resp.WrapInfo.Token = te.ID | ||||
| 	resp.WrapInfo.Accessor = te.Accessor | ||||
| 	resp.WrapInfo.CreationTime = creationTime | ||||
| 	// If this is not a rewrap, store the request path as creation_path | ||||
| 	if req.Path != "sys/wrapping/rewrap" { | ||||
| @@ -328,7 +329,7 @@ func (c *Core) ValidateWrappingToken(req *logical.Request) (bool, error) { | ||||
| 		return false, nil | ||||
| 	} | ||||
|  | ||||
| 	if te.Policies[0] != responseWrappingPolicyName { | ||||
| 	if te.Policies[0] != responseWrappingPolicyName && te.Policies[0] != controlGroupPolicyName { | ||||
| 		return false, nil | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jeff Mitchell
					Jeff Mitchell