2020-06-02 22:37:10 +00:00
|
|
|
package state
|
|
|
|
|
|
|
|
import (
|
2021-03-16 18:53:56 +00:00
|
|
|
memdb "github.com/hashicorp/go-memdb"
|
|
|
|
|
2020-06-15 22:49:00 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul/stream"
|
2020-06-02 22:37:10 +00:00
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
|
|
)
|
|
|
|
|
2020-07-06 18:34:58 +00:00
|
|
|
// aclChangeUnsubscribeEvent creates and returns stream.UnsubscribeEvents that
|
|
|
|
// are used to unsubscribe any subscriptions which match the tokens from the events.
|
|
|
|
//
|
|
|
|
// These are special events that will never be returned to a subscriber.
|
2020-07-06 22:44:51 +00:00
|
|
|
func aclChangeUnsubscribeEvent(tx ReadTxn, changes Changes) ([]stream.Event, error) {
|
2020-07-06 18:34:58 +00:00
|
|
|
var secretIDs []string
|
2020-06-02 22:37:10 +00:00
|
|
|
|
2020-07-06 18:24:30 +00:00
|
|
|
for _, change := range changes.Changes {
|
2020-06-02 22:37:10 +00:00
|
|
|
switch change.Table {
|
|
|
|
case "acl-tokens":
|
2020-06-15 22:49:00 +00:00
|
|
|
token := changeObject(change).(*structs.ACLToken)
|
2020-07-06 18:34:58 +00:00
|
|
|
secretIDs = append(secretIDs, token.SecretID)
|
|
|
|
|
2021-03-16 20:39:22 +00:00
|
|
|
case tableACLRoles:
|
2020-07-06 18:34:58 +00:00
|
|
|
role := changeObject(change).(*structs.ACLRole)
|
|
|
|
tokens, err := aclTokenListByRole(tx, role.ID, &role.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-06-02 22:37:10 +00:00
|
|
|
}
|
2020-07-06 18:34:58 +00:00
|
|
|
secretIDs = appendSecretIDsFromTokenIterator(secretIDs, tokens)
|
|
|
|
|
2021-03-16 18:53:56 +00:00
|
|
|
case tableACLPolicies:
|
2020-06-15 22:49:00 +00:00
|
|
|
policy := changeObject(change).(*structs.ACLPolicy)
|
2020-07-06 18:34:58 +00:00
|
|
|
tokens, err := aclTokenListByPolicy(tx, policy.ID, &policy.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-06-02 22:37:10 +00:00
|
|
|
}
|
2020-07-06 18:34:58 +00:00
|
|
|
secretIDs = appendSecretIDsFromTokenIterator(secretIDs, tokens)
|
|
|
|
|
2021-03-19 20:07:55 +00:00
|
|
|
q := Query{Value: policy.ID, EnterpriseMeta: policy.EnterpriseMeta}
|
|
|
|
roles, err := tx.Get(tableACLRoles, indexPolicies, q)
|
2020-07-06 18:34:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for role := roles.Next(); role != nil; role = roles.Next() {
|
|
|
|
role := role.(*structs.ACLRole)
|
|
|
|
|
|
|
|
tokens, err := aclTokenListByRole(tx, role.ID, &policy.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
secretIDs = appendSecretIDsFromTokenIterator(secretIDs, tokens)
|
2020-06-02 22:37:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-08 18:45:18 +00:00
|
|
|
// There may be duplicate secretIDs here. We rely on this event allowing
|
|
|
|
// for duplicate IDs.
|
2020-07-06 21:29:45 +00:00
|
|
|
return []stream.Event{stream.NewCloseSubscriptionEvent(secretIDs)}, nil
|
2020-06-02 22:37:10 +00:00
|
|
|
}
|
2020-06-15 22:49:00 +00:00
|
|
|
|
|
|
|
// changeObject returns the object before it was deleted if the change was a delete,
|
|
|
|
// otherwise returns the object after the change.
|
|
|
|
func changeObject(change memdb.Change) interface{} {
|
|
|
|
if change.Deleted() {
|
|
|
|
return change.Before
|
|
|
|
}
|
|
|
|
return change.After
|
|
|
|
}
|
2020-07-06 18:34:58 +00:00
|
|
|
|
|
|
|
func appendSecretIDsFromTokenIterator(seq []string, tokens memdb.ResultIterator) []string {
|
|
|
|
for token := tokens.Next(); token != nil; token = tokens.Next() {
|
|
|
|
token := token.(*structs.ACLToken)
|
|
|
|
seq = append(seq, token.SecretID)
|
|
|
|
}
|
|
|
|
return seq
|
|
|
|
}
|