mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-24 19:01:51 +01:00
Merge remote-tracking branch 'remotes/from/ce/main'
This commit is contained in:
commit
7ecd47f104
@ -223,9 +223,7 @@ type DisplayAttributes struct {
|
||||
// to UI inputs where only arrays are valid. For example params with Type: framework.TypeCommaStringSlice
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Value is a sample value to display for this field. This may be used
|
||||
// to indicate a default value, but it is for display only and completely separate
|
||||
// from any Default member handling.
|
||||
// Value is used as the default value by the UI.
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
|
||||
// Sensitive indicates that the value should be masked by default in the UI.
|
||||
|
||||
@ -1476,7 +1476,7 @@ func (i *IdentityStore) MemDBUpsertEntityInTxn(txn *memdb.Txn, entity *identity.
|
||||
"entity_id": entity.ID,
|
||||
"entity_namespace_id": entity.NamespaceID,
|
||||
"metadata": entity.Metadata,
|
||||
"aliases": entity.Aliases,
|
||||
"aliases": aliasesToEntityObservationAliases(entity.Aliases),
|
||||
"policies": entity.Policies,
|
||||
"creation_time": entity.CreationTime.AsTime().Format(time.RFC3339),
|
||||
"last_updated_time": entity.LastUpdateTime.AsTime().Format(time.RFC3339),
|
||||
@ -1491,6 +1491,31 @@ func (i *IdentityStore) MemDBUpsertEntityInTxn(txn *memdb.Txn, entity *identity.
|
||||
return nil
|
||||
}
|
||||
|
||||
// EntityObservationAliases is a minimal version of aliases to contain only
|
||||
// salient information for entity upsert observations.
|
||||
type EntityObservationAliases struct {
|
||||
Id string `json:"id"`
|
||||
MountPath string `json:"mount_path"`
|
||||
MountType string `json:"mount_type"`
|
||||
MountAccessor string `json:"mount_accessor"`
|
||||
}
|
||||
|
||||
// aliasesToEntityObservationAliases translated a list of *identity.Alias into a list of EntityObservationAliases
|
||||
func aliasesToEntityObservationAliases(aliases []*identity.Alias) []*EntityObservationAliases {
|
||||
entityObservationAliases := make([]*EntityObservationAliases, 0, len(aliases))
|
||||
for _, alias := range aliases {
|
||||
if alias != nil {
|
||||
entityObservationAliases = append(entityObservationAliases, &EntityObservationAliases{
|
||||
Id: alias.ID,
|
||||
MountPath: alias.MountPath,
|
||||
MountType: alias.MountType,
|
||||
MountAccessor: alias.MountAccessor,
|
||||
})
|
||||
}
|
||||
}
|
||||
return entityObservationAliases
|
||||
}
|
||||
|
||||
func (i *IdentityStore) MemDBEntityByIDInTxn(txn *memdb.Txn, entityID string, clone bool) (*identity.Entity, error) {
|
||||
if entityID == "" {
|
||||
return nil, fmt.Errorf("missing entity id")
|
||||
|
||||
@ -3625,7 +3625,7 @@ func (b *SystemBackend) handlePoliciesSet(policyType PolicyType) framework.Opera
|
||||
}
|
||||
|
||||
// Update the policy
|
||||
if err := b.Core.policyStore.SetPolicy(ctx, policy); err != nil {
|
||||
if err := b.Core.policyStore.SetPolicyWithRequest(ctx, policy, req); err != nil {
|
||||
return handleError(err)
|
||||
}
|
||||
|
||||
@ -3645,7 +3645,7 @@ func (b *SystemBackend) handlePoliciesDelete(policyType PolicyType) framework.Op
|
||||
return func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
name := data.Get("name").(string)
|
||||
|
||||
if err := b.Core.policyStore.DeletePolicy(ctx, name, policyType); err != nil {
|
||||
if err := b.Core.policyStore.DeletePolicyWithRequest(ctx, name, policyType, req); err != nil {
|
||||
return handleError(err)
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
@ -22,6 +22,13 @@ const (
|
||||
// Type (i.e. batch/service) is included in 'type'.
|
||||
ObservationTypeTokenCreation = "token/create"
|
||||
|
||||
// ObservationTypePolicyUpsert is emitted when a policy is
|
||||
// inserted or updated.
|
||||
ObservationTypePolicyUpsert = "policy/upsert"
|
||||
// ObservationTypePolicyDelete is emitted when a policy is
|
||||
// deleted.
|
||||
ObservationTypePolicyDelete = "policy/delete"
|
||||
|
||||
// ObservationTypePolicyACLEvaluation is emitted when an ACL policy is evaluated
|
||||
ObservationTypePolicyACLEvaluation = "policy/acl/evaluation"
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import (
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/hashicorp/vault/vault/observations"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -341,14 +342,14 @@ func (ps *PolicyStore) invalidate(ctx context.Context, name string, policyType P
|
||||
// case another process has re-written the policy; instead next time Get is
|
||||
// called the values will be loaded back in.
|
||||
if out == nil {
|
||||
ps.switchedDeletePolicy(ctx, name, policyType, false, true)
|
||||
ps.switchedDeletePolicy(ctx, name, policyType, false, true, nil)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetPolicy is used to create or update the given policy
|
||||
func (ps *PolicyStore) SetPolicy(ctx context.Context, p *Policy) error {
|
||||
// SetPolicyWithRequest is used to create or update a given policy from a request
|
||||
func (ps *PolicyStore) SetPolicyWithRequest(ctx context.Context, p *Policy, req *logical.Request) error {
|
||||
defer metrics.MeasureSince([]string{"policy", "set_policy"}, time.Now())
|
||||
if p == nil {
|
||||
return fmt.Errorf("nil policy passed in for storage")
|
||||
@ -362,10 +363,15 @@ func (ps *PolicyStore) SetPolicy(ctx context.Context, p *Policy) error {
|
||||
return fmt.Errorf("cannot update %q policy", p.Name)
|
||||
}
|
||||
|
||||
return ps.setPolicyInternal(ctx, p)
|
||||
return ps.setPolicyInternal(ctx, p, req)
|
||||
}
|
||||
|
||||
func (ps *PolicyStore) setPolicyInternal(ctx context.Context, p *Policy) error {
|
||||
// SetPolicy is used to create or update the given policy
|
||||
func (ps *PolicyStore) SetPolicy(ctx context.Context, p *Policy) error {
|
||||
return ps.SetPolicyWithRequest(ctx, p, nil)
|
||||
}
|
||||
|
||||
func (ps *PolicyStore) setPolicyInternal(ctx context.Context, p *Policy, req *logical.Request) error {
|
||||
ps.modifyLock.Lock()
|
||||
defer ps.modifyLock.Unlock()
|
||||
|
||||
@ -454,9 +460,56 @@ func (ps *PolicyStore) setPolicyInternal(ctx context.Context, p *Policy) error {
|
||||
return fmt.Errorf("unknown policy type, cannot set")
|
||||
}
|
||||
|
||||
var clientId string
|
||||
var entityId string
|
||||
var requestId string
|
||||
if req != nil {
|
||||
clientId = req.ClientID
|
||||
entityId = req.EntityID
|
||||
requestId = req.ID
|
||||
}
|
||||
// TODO Violet 1
|
||||
err = ps.core.Observations().RecordObservationToLedger(ctx, observations.ObservationTypePolicyUpsert, p.namespace, map[string]interface{}{
|
||||
"client_id": clientId,
|
||||
"entity_id": entityId,
|
||||
"request_id": requestId,
|
||||
"type": p.Type.String(),
|
||||
"name": p.Name,
|
||||
"raw_policy": p.Raw,
|
||||
"path_rules": pathRulesToObservationPathRules(p.Paths),
|
||||
})
|
||||
if err != nil {
|
||||
ps.logger.Error("error recording observation for policy upsert", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObservationPathRules is a minimal version of PathRules to contain only
|
||||
// salient information for observations.
|
||||
type ObservationPathRules struct {
|
||||
Path string `json:"path"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
Prefix bool `json:"prefix"`
|
||||
HasSegmentWildcards bool `json:"has_segment_wildcards"`
|
||||
}
|
||||
|
||||
// pathRulesToObservationPathRules translated a list of PathRules into a list of ObservationPathRules
|
||||
func pathRulesToObservationPathRules(rules []*PathRules) []*ObservationPathRules {
|
||||
var observationPathRules []*ObservationPathRules
|
||||
for _, rule := range rules {
|
||||
if rule != nil {
|
||||
observationPathRules = append(observationPathRules, &ObservationPathRules{
|
||||
Path: rule.Path,
|
||||
Capabilities: rule.Capabilities,
|
||||
Prefix: rule.IsPrefix,
|
||||
HasSegmentWildcards: rule.HasSegmentWildcards,
|
||||
})
|
||||
}
|
||||
}
|
||||
return observationPathRules
|
||||
}
|
||||
|
||||
// GetNonEGPPolicyType returns a policy's type.
|
||||
// It will return an error if the policy doesn't exist in the store or isn't
|
||||
// an ACL or a Sentinel Role Governing Policy (RGP).
|
||||
@ -737,9 +790,14 @@ func (ps *PolicyStore) policiesByNamespaces(ctx context.Context, policyType Poli
|
||||
return keys, err
|
||||
}
|
||||
|
||||
// DeletePolicyWithRequest is used to delete the named policy with a given request
|
||||
func (ps *PolicyStore) DeletePolicyWithRequest(ctx context.Context, name string, policyType PolicyType, req *logical.Request) error {
|
||||
return ps.switchedDeletePolicy(ctx, name, policyType, true, false, req)
|
||||
}
|
||||
|
||||
// DeletePolicy is used to delete the named policy
|
||||
func (ps *PolicyStore) DeletePolicy(ctx context.Context, name string, policyType PolicyType) error {
|
||||
return ps.switchedDeletePolicy(ctx, name, policyType, true, false)
|
||||
return ps.switchedDeletePolicy(ctx, name, policyType, true, false, nil)
|
||||
}
|
||||
|
||||
// deletePolicyForce is used to delete the named policy and force it even if
|
||||
@ -747,10 +805,10 @@ func (ps *PolicyStore) DeletePolicy(ctx context.Context, name string, policyType
|
||||
// where we internally need to actually remove a policy that the user normally
|
||||
// isn't allowed to remove.
|
||||
func (ps *PolicyStore) deletePolicyForce(ctx context.Context, name string, policyType PolicyType) error {
|
||||
return ps.switchedDeletePolicy(ctx, name, policyType, true, true)
|
||||
return ps.switchedDeletePolicy(ctx, name, policyType, true, true, nil)
|
||||
}
|
||||
|
||||
func (ps *PolicyStore) switchedDeletePolicy(ctx context.Context, name string, policyType PolicyType, physicalDeletion, force bool) error {
|
||||
func (ps *PolicyStore) switchedDeletePolicy(ctx context.Context, name string, policyType PolicyType, physicalDeletion, force bool, req *logical.Request) error {
|
||||
defer metrics.MeasureSince([]string{"policy", "delete_policy"}, time.Now())
|
||||
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
@ -833,6 +891,26 @@ func (ps *PolicyStore) switchedDeletePolicy(ctx context.Context, name string, po
|
||||
ps.invalidateEGPTreePath(index)
|
||||
}
|
||||
|
||||
var clientId string
|
||||
var entityId string
|
||||
var requestId string
|
||||
if req != nil {
|
||||
clientId = req.ClientID
|
||||
entityId = req.EntityID
|
||||
requestId = req.ID
|
||||
}
|
||||
err = ps.core.Observations().RecordObservationToLedger(ctx, observations.ObservationTypePolicyDelete, ns, map[string]interface{}{
|
||||
"client_id": clientId,
|
||||
"entity_id": entityId,
|
||||
"request_id": requestId,
|
||||
"forced_delete": force,
|
||||
"type": policyType.String(),
|
||||
"name": name,
|
||||
})
|
||||
if err != nil {
|
||||
ps.logger.Error("error recording observation for policy delete", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -936,7 +1014,7 @@ func (ps *PolicyStore) loadACLPolicyInternal(ctx context.Context, policyName, po
|
||||
|
||||
policy.Name = policyName
|
||||
policy.Type = PolicyTypeACL
|
||||
return ps.setPolicyInternal(ctx, policy)
|
||||
return ps.setPolicyInternal(ctx, policy, nil)
|
||||
}
|
||||
|
||||
func (ps *PolicyStore) sanitizeName(name string) string {
|
||||
|
||||
@ -1071,6 +1071,41 @@ func (ts *TokenStore) create(ctx context.Context, entry *logical.TokenEntry) err
|
||||
}
|
||||
}
|
||||
|
||||
recordObservationFunc := func() {
|
||||
clientId, nonEntityToken := entry.CreateClientID()
|
||||
|
||||
var mountAccessor string
|
||||
var mountPath string
|
||||
var mountType string
|
||||
mountEntry := ts.core.router.MatchingMountEntry(ctx, entry.Path)
|
||||
if mountEntry != nil {
|
||||
mountAccessor = mountEntry.Accessor
|
||||
mountPath = mountEntry.Path
|
||||
mountType = mountEntry.Type
|
||||
}
|
||||
|
||||
// Note: this should not be modified to include the token's ID (the token's actual value),
|
||||
// due to sensitivity.
|
||||
ts.core.Observations().RecordObservationToLedger(ctx, observations.ObservationTypeTokenCreation, tokenNS, map[string]interface{}{
|
||||
"policies": entry.Policies,
|
||||
"path": entry.Path,
|
||||
"display_name": entry.DisplayName,
|
||||
"num_uses": entry.NumUses,
|
||||
"token_type": entry.Type.String(),
|
||||
"ttl": entry.TTL.String(),
|
||||
"role": entry.Role,
|
||||
"token_client_id": clientId,
|
||||
"token_entity_id": entry.EntityID,
|
||||
"token_client_id_is_entity_id": !nonEntityToken,
|
||||
"mount_accessor": mountAccessor,
|
||||
"mount_path": mountPath,
|
||||
"mount_type": mountType,
|
||||
})
|
||||
if err != nil {
|
||||
ts.logger.Error("error recording observation for token creation", err)
|
||||
}
|
||||
}
|
||||
|
||||
switch entry.Type {
|
||||
case logical.TokenTypeDefault, logical.TokenTypeService:
|
||||
// In case it was default, force to service
|
||||
@ -1148,6 +1183,9 @@ func (ts *TokenStore) create(ctx context.Context, entry *logical.TokenEntry) err
|
||||
if !userSelectedID && !ts.core.DisableSSCTokens() {
|
||||
entry.ExternalID = ts.GenerateSSCTokenID(entry.ID, logical.IndexStateFromContext(ctx), entry)
|
||||
}
|
||||
|
||||
recordObservationFunc()
|
||||
|
||||
return nil
|
||||
|
||||
case logical.TokenTypeBatch:
|
||||
@ -1217,6 +1255,8 @@ func (ts *TokenStore) create(ctx context.Context, entry *logical.TokenEntry) err
|
||||
entry.ID = fmt.Sprintf("%s.%s", entry.ID, tokenNS.ID)
|
||||
}
|
||||
|
||||
recordObservationFunc()
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
@ -3254,27 +3294,6 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
||||
}
|
||||
}
|
||||
|
||||
clientId, nonEntityToken := te.CreateClientID()
|
||||
// Note: this should not be modified to include the token's ID (the token's actual value),
|
||||
// due to sensitivity.
|
||||
ts.core.Observations().RecordObservationToLedger(ctx, observations.ObservationTypeTokenCreation, ns, map[string]interface{}{
|
||||
"policies": te.Policies,
|
||||
"path": te.Path,
|
||||
"display_name": te.DisplayName,
|
||||
"num_uses": te.NumUses,
|
||||
"token_type": te.Type.String(),
|
||||
"ttl": te.TTL.String(),
|
||||
"role": te.Role,
|
||||
"token_client_id": clientId,
|
||||
"token_entity_id": te.EntityID,
|
||||
"token_client_id_is_entity_id": !nonEntityToken,
|
||||
"request_client_id": req.ClientID,
|
||||
"request_entity_id": req.EntityID,
|
||||
})
|
||||
if err != nil {
|
||||
ts.logger.Error("error recording observation for token creation", err)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user