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

Changes the way policies are reported in audit logs #4747

Merged
merged 9 commits into from
Jun 14, 2018
87 changes: 70 additions & 17 deletions api/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ func (s *Secret) TokenRemainingUses() (int, error) {
}

// TokenPolicies returns the standardized list of policies for the given secret.
// If the secret is nil or does not contain any policies, this returns nil.
// If the secret is nil or does not contain any policies, this returns nil. It
// also populates the secret's Auth info with identity/token policy info.
func (s *Secret) TokenPolicies() ([]string, error) {
if s == nil {
return nil, nil
Expand All @@ -115,25 +116,75 @@ func (s *Secret) TokenPolicies() ([]string, error) {
return nil, nil
}

sList, ok := s.Data["policies"].([]string)
if ok {
return sList, nil
}
var tokenPolicies []string

list, ok := s.Data["policies"].([]interface{})
if !ok {
return nil, fmt.Errorf("unable to convert token policies to expected format")
// Token policies
{
_, ok := s.Data["policies"]
if !ok {
goto TOKEN_DONE
}

sList, ok := s.Data["policies"].([]string)
if ok {
tokenPolicies = sList
goto TOKEN_DONE
}

list, ok := s.Data["policies"].([]interface{})
if !ok {
return nil, fmt.Errorf("unable to convert token policies to expected format")
}
for _, v := range list {
p, ok := v.(string)
if !ok {
return nil, fmt.Errorf("unable to convert policy %v to string", v)
}
tokenPolicies = append(tokenPolicies, p)
}
}

policies := make([]string, len(list))
for i := range list {
p, ok := list[i].(string)
TOKEN_DONE:
var identityPolicies []string

// Identity policies
{
_, ok := s.Data["identity_policies"]
if !ok {
return nil, fmt.Errorf("unable to convert policy %v to string", list[i])
goto DONE
}

sList, ok := s.Data["identity_policies"].([]string)
if ok {
identityPolicies = sList
goto DONE
}

list, ok := s.Data["identity_policies"].([]interface{})
if !ok {
return nil, fmt.Errorf("unable to convert identity policies to expected format")
}
for _, v := range list {
p, ok := v.(string)
if !ok {
return nil, fmt.Errorf("unable to convert policy %v to string", v)
}
identityPolicies = append(identityPolicies, p)
}
policies[i] = p
}

DONE:

if s.Auth == nil {
s.Auth = &SecretAuth{}
}

policies := append(tokenPolicies, identityPolicies...)

s.Auth.TokenPolicies = tokenPolicies
s.Auth.IdentityPolicies = identityPolicies
s.Auth.Policies = policies

return policies, nil
}

Expand Down Expand Up @@ -234,10 +285,12 @@ type SecretWrapInfo struct {

// SecretAuth is the structure containing auth information if we have it.
type SecretAuth struct {
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
Policies []string `json:"policies"`
Metadata map[string]string `json:"metadata"`
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
Policies []string `json:"policies"`
TokenPolicies []string `json:"token_policies"`
IdentityPolicies []string `json:"identity_policies"`
Metadata map[string]string `json:"metadata"`

LeaseDuration int `json:"lease_duration"`
Renewable bool `json:"renewable"`
Expand Down
64 changes: 36 additions & 28 deletions audit/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config
Error: errString,

Auth: AuditAuth{
ClientToken: auth.ClientToken,
Accessor: auth.Accessor,
DisplayName: auth.DisplayName,
Policies: auth.Policies,
Metadata: auth.Metadata,
EntityID: auth.EntityID,
RemainingUses: req.ClientTokenRemainingUses,
ClientToken: auth.ClientToken,
Accessor: auth.Accessor,
DisplayName: auth.DisplayName,
Policies: auth.Policies,
TokenPolicies: auth.TokenPolicies,
IdentityPolicies: auth.IdentityPolicies,
Metadata: auth.Metadata,
EntityID: auth.EntityID,
RemainingUses: req.ClientTokenRemainingUses,
},

Request: AuditRequest{
Expand Down Expand Up @@ -277,12 +279,14 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
var respAuth *AuditAuth
if resp.Auth != nil {
respAuth = &AuditAuth{
ClientToken: resp.Auth.ClientToken,
Accessor: resp.Auth.Accessor,
DisplayName: resp.Auth.DisplayName,
Policies: resp.Auth.Policies,
Metadata: resp.Auth.Metadata,
NumUses: resp.Auth.NumUses,
ClientToken: resp.Auth.ClientToken,
Accessor: resp.Auth.Accessor,
DisplayName: resp.Auth.DisplayName,
Policies: resp.Auth.Policies,
TokenPolicies: resp.Auth.TokenPolicies,
IdentityPolicies: resp.Auth.IdentityPolicies,
Metadata: resp.Auth.Metadata,
NumUses: resp.Auth.NumUses,
}
}

Expand Down Expand Up @@ -313,13 +317,15 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
Type: "response",
Error: errString,
Auth: AuditAuth{
DisplayName: auth.DisplayName,
Policies: auth.Policies,
Metadata: auth.Metadata,
ClientToken: auth.ClientToken,
Accessor: auth.Accessor,
RemainingUses: req.ClientTokenRemainingUses,
EntityID: auth.EntityID,
DisplayName: auth.DisplayName,
Policies: auth.Policies,
TokenPolicies: auth.TokenPolicies,
IdentityPolicies: auth.IdentityPolicies,
Metadata: auth.Metadata,
ClientToken: auth.ClientToken,
Accessor: auth.Accessor,
RemainingUses: req.ClientTokenRemainingUses,
EntityID: auth.EntityID,
},

Request: AuditRequest{
Expand Down Expand Up @@ -397,14 +403,16 @@ type AuditResponse struct {
}

type AuditAuth struct {
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
DisplayName string `json:"display_name"`
Policies []string `json:"policies"`
Metadata map[string]string `json:"metadata"`
NumUses int `json:"num_uses,omitempty"`
RemainingUses int `json:"remaining_uses,omitempty"`
EntityID string `json:"entity_id"`
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
DisplayName string `json:"display_name"`
Policies []string `json:"policies"`
TokenPolicies []string `json:"token_policies,omitempty"`
IdentityPolicies []string `json:"identity_policies,omitempty"`
Metadata map[string]string `json:"metadata"`
NumUses int `json:"num_uses,omitempty"`
RemainingUses int `json:"remaining_uses,omitempty"`
EntityID string `json:"entity_id"`
}

type AuditSecret struct {
Expand Down
13 changes: 8 additions & 5 deletions builtin/credential/token/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
if err != nil {
return nil, errwrap.Wrapf("error accessing token accessor: {{err}}", err)
}
policies, err := secret.TokenPolicies()
// This populates secret.Auth
_, err = secret.TokenPolicies()
if err != nil {
return nil, errwrap.Wrapf("error accessing token policies: {{err}}", err)
}
Expand All @@ -122,10 +123,12 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
}
return &api.Secret{
Auth: &api.SecretAuth{
ClientToken: id,
Accessor: accessor,
Policies: policies,
Metadata: metadata,
ClientToken: id,
Accessor: accessor,
Policies: secret.Auth.Policies,
TokenPolicies: secret.Auth.TokenPolicies,
IdentityPolicies: secret.Auth.IdentityPolicies,
Metadata: metadata,

LeaseDuration: int(dur.Seconds()),
Renewable: renewable,
Expand Down
4 changes: 3 additions & 1 deletion command/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,9 @@ func (t TableFormatter) OutputSecret(ui cli.Ui, secret *api.Secret) error {
out = append(out, fmt.Sprintf("token_duration %s %s", hopeDelim, humanDurationInt(secret.Auth.LeaseDuration)))
}
out = append(out, fmt.Sprintf("token_renewable %s %t", hopeDelim, secret.Auth.Renewable))
out = append(out, fmt.Sprintf("token_policies %s %v", hopeDelim, secret.Auth.Policies))
out = append(out, fmt.Sprintf("token_policies %s %v", hopeDelim, secret.Auth.TokenPolicies))
out = append(out, fmt.Sprintf("identity_policies %s %v", hopeDelim, secret.Auth.IdentityPolicies))
out = append(out, fmt.Sprintf("policies %s %v", hopeDelim, secret.Auth.Policies))
for k, v := range secret.Auth.Metadata {
out = append(out, fmt.Sprintf("token_meta_%s %s %v", k, hopeDelim, v))
}
Expand Down
4 changes: 4 additions & 0 deletions command/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ func RawField(secret *api.Secret, field string) interface{} {
case "token_renewable":
val = secret.Auth.Renewable
case "token_policies":
val = secret.Auth.TokenPolicies
case "identity_policies":
val = secret.Auth.IdentityPolicies
case "policies":
val = secret.Auth.Policies
default:
val = secret.Data[field]
Expand Down
1 change: 1 addition & 0 deletions http/logical_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ func TestLogical_CreateToken(t *testing.T) {
"wrap_info": nil,
"auth": map[string]interface{}{
"policies": []interface{}{"root"},
"token_policies": []interface{}{"root"},
"metadata": nil,
"lease_duration": json.Number("0"),
"renewable": false,
Expand Down
5 changes: 5 additions & 0 deletions logical/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ type Auth struct {
// is associated with.
Policies []string `json:"policies" mapstructure:"policies" structs:"policies"`

// TokenPolicies and IdentityPolicies break down the list in Policies to
// help determine where a policy was sourced
TokenPolicies []string `json:"token_policies" mapstructure:"token_policies" structs:"token_policies"`
IdentityPolicies []string `json:"identity_policies" mapstructure:"identity_policies" structs:"identity_policies"`

// Metadata is used to attach arbitrary string-type metadata to
// an authenticated user. This metadata will be outputted into the
// audit log.
Expand Down
44 changes: 25 additions & 19 deletions logical/translate_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ func LogicalResponseToHTTPResponse(input *Response) *HTTPResponse {
// set up the result structure.
if input.Auth != nil {
httpResp.Auth = &HTTPAuth{
ClientToken: input.Auth.ClientToken,
Accessor: input.Auth.Accessor,
Policies: input.Auth.Policies,
Metadata: input.Auth.Metadata,
LeaseDuration: int(input.Auth.TTL.Seconds()),
Renewable: input.Auth.Renewable,
EntityID: input.Auth.EntityID,
ClientToken: input.Auth.ClientToken,
Accessor: input.Auth.Accessor,
Policies: input.Auth.Policies,
TokenPolicies: input.Auth.TokenPolicies,
IdentityPolicies: input.Auth.IdentityPolicies,
Metadata: input.Auth.Metadata,
LeaseDuration: int(input.Auth.TTL.Seconds()),
Renewable: input.Auth.Renewable,
EntityID: input.Auth.EntityID,
}
}

Expand All @@ -56,11 +58,13 @@ func HTTPResponseToLogicalResponse(input *HTTPResponse) *Response {

if input.Auth != nil {
logicalResp.Auth = &Auth{
ClientToken: input.Auth.ClientToken,
Accessor: input.Auth.Accessor,
Policies: input.Auth.Policies,
Metadata: input.Auth.Metadata,
EntityID: input.Auth.EntityID,
ClientToken: input.Auth.ClientToken,
Accessor: input.Auth.Accessor,
Policies: input.Auth.Policies,
TokenPolicies: input.Auth.TokenPolicies,
IdentityPolicies: input.Auth.IdentityPolicies,
Metadata: input.Auth.Metadata,
EntityID: input.Auth.EntityID,
}
logicalResp.Auth.Renewable = input.Auth.Renewable
logicalResp.Auth.TTL = time.Second * time.Duration(input.Auth.LeaseDuration)
Expand All @@ -81,13 +85,15 @@ type HTTPResponse struct {
}

type HTTPAuth struct {
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
Policies []string `json:"policies"`
Metadata map[string]string `json:"metadata"`
LeaseDuration int `json:"lease_duration"`
Renewable bool `json:"renewable"`
EntityID string `json:"entity_id"`
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
Policies []string `json:"policies"`
TokenPolicies []string `json:"token_policies,omitempty"`
IdentityPolicies []string `json:"identity_policies,omitempty"`
Metadata map[string]string `json:"metadata"`
LeaseDuration int `json:"lease_duration"`
Renewable bool `json:"renewable"`
EntityID string `json:"entity_id"`
}

type HTTPWrapInfo struct {
Expand Down
9 changes: 6 additions & 3 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,7 @@ func (c *Core) sealInitCommon(ctx context.Context, req *logical.Request) (retErr
}

// Validate the token is a root token
acl, te, entity, err := c.fetchACLTokenEntryAndEntity(req)
acl, te, entity, identityPolicies, err := c.fetchACLTokenEntryAndEntity(req)
if err != nil {
retErr = multierror.Append(retErr, err)
c.stateLock.RUnlock()
Expand All @@ -1013,10 +1013,13 @@ func (c *Core) sealInitCommon(ctx context.Context, req *logical.Request) (retErr

// Audit-log the request before going any further
auth := &logical.Auth{
ClientToken: req.ClientToken,
ClientToken: req.ClientToken,
Policies: identityPolicies,
IdentityPolicies: identityPolicies,
}
if te != nil {
auth.Policies = te.Policies
auth.TokenPolicies = te.Policies
auth.Policies = append(te.Policies, identityPolicies...)
auth.Metadata = te.Meta
auth.DisplayName = te.DisplayName
auth.EntityID = te.EntityID
Expand Down
9 changes: 6 additions & 3 deletions vault/ha.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,21 @@ func (c *Core) StepDown(req *logical.Request) (retErr error) {

ctx := c.activeContext

acl, te, entity, err := c.fetchACLTokenEntryAndEntity(req)
acl, te, entity, identityPolicies, err := c.fetchACLTokenEntryAndEntity(req)
if err != nil {
retErr = multierror.Append(retErr, err)
return retErr
}

// Audit-log the request before going any further
auth := &logical.Auth{
ClientToken: req.ClientToken,
ClientToken: req.ClientToken,
Policies: identityPolicies,
IdentityPolicies: identityPolicies,
}
if te != nil {
auth.Policies = te.Policies
auth.TokenPolicies = te.Policies
auth.Policies = append(te.Policies, identityPolicies...)
auth.Metadata = te.Meta
auth.DisplayName = te.DisplayName
auth.EntityID = te.EntityID
Expand Down
Loading