1package acl 2 3// ChainedAuthorizer can combine multiple Authorizers into one. 4// Each Authorizer in the chain is asked (in order) for an 5// enforcement decision. The first non-Default decision that 6// is rendered by an Authorizer in the chain will be used 7// as the overall decision of the ChainedAuthorizer 8type ChainedAuthorizer struct { 9 chain []Authorizer 10} 11 12// NewChainedAuthorizer creates a ChainedAuthorizer with the provided 13// chain of Authorizers. The slice provided should be in the order of 14// most precedent Authorizer at the beginning and least precedent 15// Authorizer at the end. 16func NewChainedAuthorizer(chain []Authorizer) *ChainedAuthorizer { 17 return &ChainedAuthorizer{ 18 chain: chain, 19 } 20} 21 22func (c *ChainedAuthorizer) AuthorizerChain() []Authorizer { 23 return c.chain 24} 25 26func (c *ChainedAuthorizer) executeChain(enforce func(authz Authorizer) EnforcementDecision) EnforcementDecision { 27 for _, authz := range c.chain { 28 decision := enforce(authz) 29 if decision != Default { 30 return decision 31 } 32 } 33 return Deny 34} 35 36// ACLRead checks for permission to list all the ACLs 37func (c *ChainedAuthorizer) ACLRead(entCtx *AuthorizerContext) EnforcementDecision { 38 return c.executeChain(func(authz Authorizer) EnforcementDecision { 39 return authz.ACLRead(entCtx) 40 }) 41} 42 43// ACLWrite checks for permission to manipulate ACLs 44func (c *ChainedAuthorizer) ACLWrite(entCtx *AuthorizerContext) EnforcementDecision { 45 return c.executeChain(func(authz Authorizer) EnforcementDecision { 46 return authz.ACLWrite(entCtx) 47 }) 48} 49 50// AgentRead checks for permission to read from agent endpoints for a 51// given node. 52func (c *ChainedAuthorizer) AgentRead(node string, entCtx *AuthorizerContext) EnforcementDecision { 53 return c.executeChain(func(authz Authorizer) EnforcementDecision { 54 return authz.AgentRead(node, entCtx) 55 }) 56} 57 58// AgentWrite checks for permission to make changes via agent endpoints 59// for a given node. 60func (c *ChainedAuthorizer) AgentWrite(node string, entCtx *AuthorizerContext) EnforcementDecision { 61 return c.executeChain(func(authz Authorizer) EnforcementDecision { 62 return authz.AgentWrite(node, entCtx) 63 }) 64} 65 66// EventRead determines if a specific event can be queried. 67func (c *ChainedAuthorizer) EventRead(name string, entCtx *AuthorizerContext) EnforcementDecision { 68 return c.executeChain(func(authz Authorizer) EnforcementDecision { 69 return authz.EventRead(name, entCtx) 70 }) 71} 72 73// EventWrite determines if a specific event may be fired. 74func (c *ChainedAuthorizer) EventWrite(name string, entCtx *AuthorizerContext) EnforcementDecision { 75 return c.executeChain(func(authz Authorizer) EnforcementDecision { 76 return authz.EventWrite(name, entCtx) 77 }) 78} 79 80// IntentionDefaultAllow determines the default authorized behavior 81// when no intentions match a Connect request. 82func (c *ChainedAuthorizer) IntentionDefaultAllow(entCtx *AuthorizerContext) EnforcementDecision { 83 return c.executeChain(func(authz Authorizer) EnforcementDecision { 84 return authz.IntentionDefaultAllow(entCtx) 85 }) 86} 87 88// IntentionRead determines if a specific intention can be read. 89func (c *ChainedAuthorizer) IntentionRead(prefix string, entCtx *AuthorizerContext) EnforcementDecision { 90 return c.executeChain(func(authz Authorizer) EnforcementDecision { 91 return authz.IntentionRead(prefix, entCtx) 92 }) 93} 94 95// IntentionWrite determines if a specific intention can be 96// created, modified, or deleted. 97func (c *ChainedAuthorizer) IntentionWrite(prefix string, entCtx *AuthorizerContext) EnforcementDecision { 98 return c.executeChain(func(authz Authorizer) EnforcementDecision { 99 return authz.IntentionWrite(prefix, entCtx) 100 }) 101} 102 103// KeyList checks for permission to list keys under a prefix 104func (c *ChainedAuthorizer) KeyList(keyPrefix string, entCtx *AuthorizerContext) EnforcementDecision { 105 return c.executeChain(func(authz Authorizer) EnforcementDecision { 106 return authz.KeyList(keyPrefix, entCtx) 107 }) 108} 109 110// KeyRead checks for permission to read a given key 111func (c *ChainedAuthorizer) KeyRead(key string, entCtx *AuthorizerContext) EnforcementDecision { 112 return c.executeChain(func(authz Authorizer) EnforcementDecision { 113 return authz.KeyRead(key, entCtx) 114 }) 115} 116 117// KeyWrite checks for permission to write a given key 118func (c *ChainedAuthorizer) KeyWrite(key string, entCtx *AuthorizerContext) EnforcementDecision { 119 return c.executeChain(func(authz Authorizer) EnforcementDecision { 120 return authz.KeyWrite(key, entCtx) 121 }) 122} 123 124// KeyWritePrefix checks for permission to write to an 125// entire key prefix. This means there must be no sub-policies 126// that deny a write. 127func (c *ChainedAuthorizer) KeyWritePrefix(keyPrefix string, entCtx *AuthorizerContext) EnforcementDecision { 128 return c.executeChain(func(authz Authorizer) EnforcementDecision { 129 return authz.KeyWritePrefix(keyPrefix, entCtx) 130 }) 131} 132 133// KeyringRead determines if the encryption keyring used in 134// the gossip layer can be read. 135func (c *ChainedAuthorizer) KeyringRead(entCtx *AuthorizerContext) EnforcementDecision { 136 return c.executeChain(func(authz Authorizer) EnforcementDecision { 137 return authz.KeyringRead(entCtx) 138 }) 139} 140 141// KeyringWrite determines if the keyring can be manipulated 142func (c *ChainedAuthorizer) KeyringWrite(entCtx *AuthorizerContext) EnforcementDecision { 143 return c.executeChain(func(authz Authorizer) EnforcementDecision { 144 return authz.KeyringWrite(entCtx) 145 }) 146} 147 148// NodeRead checks for permission to read (discover) a given node. 149func (c *ChainedAuthorizer) NodeRead(node string, entCtx *AuthorizerContext) EnforcementDecision { 150 return c.executeChain(func(authz Authorizer) EnforcementDecision { 151 return authz.NodeRead(node, entCtx) 152 }) 153} 154 155// NodeWrite checks for permission to create or update (register) a 156// given node. 157func (c *ChainedAuthorizer) NodeWrite(node string, entCtx *AuthorizerContext) EnforcementDecision { 158 return c.executeChain(func(authz Authorizer) EnforcementDecision { 159 return authz.NodeWrite(node, entCtx) 160 }) 161} 162 163// OperatorRead determines if the read-only Consul operator functions 164// can be used. 165func (c *ChainedAuthorizer) OperatorRead(entCtx *AuthorizerContext) EnforcementDecision { 166 return c.executeChain(func(authz Authorizer) EnforcementDecision { 167 return authz.OperatorRead(entCtx) 168 }) 169} 170 171// OperatorWrite determines if the state-changing Consul operator 172// functions can be used. 173func (c *ChainedAuthorizer) OperatorWrite(entCtx *AuthorizerContext) EnforcementDecision { 174 return c.executeChain(func(authz Authorizer) EnforcementDecision { 175 return authz.OperatorWrite(entCtx) 176 }) 177} 178 179// PreparedQueryRead determines if a specific prepared query can be read 180// to show its contents (this is not used for execution). 181func (c *ChainedAuthorizer) PreparedQueryRead(query string, entCtx *AuthorizerContext) EnforcementDecision { 182 return c.executeChain(func(authz Authorizer) EnforcementDecision { 183 return authz.PreparedQueryRead(query, entCtx) 184 }) 185} 186 187// PreparedQueryWrite determines if a specific prepared query can be 188// created, modified, or deleted. 189func (c *ChainedAuthorizer) PreparedQueryWrite(query string, entCtx *AuthorizerContext) EnforcementDecision { 190 return c.executeChain(func(authz Authorizer) EnforcementDecision { 191 return authz.PreparedQueryWrite(query, entCtx) 192 }) 193} 194 195// ServiceRead checks for permission to read a given service 196func (c *ChainedAuthorizer) ServiceRead(name string, entCtx *AuthorizerContext) EnforcementDecision { 197 return c.executeChain(func(authz Authorizer) EnforcementDecision { 198 return authz.ServiceRead(name, entCtx) 199 }) 200} 201 202// ServiceWrite checks for permission to create or update a given 203// service 204func (c *ChainedAuthorizer) ServiceWrite(name string, entCtx *AuthorizerContext) EnforcementDecision { 205 return c.executeChain(func(authz Authorizer) EnforcementDecision { 206 return authz.ServiceWrite(name, entCtx) 207 }) 208} 209 210// SessionRead checks for permission to read sessions for a given node. 211func (c *ChainedAuthorizer) SessionRead(node string, entCtx *AuthorizerContext) EnforcementDecision { 212 return c.executeChain(func(authz Authorizer) EnforcementDecision { 213 return authz.SessionRead(node, entCtx) 214 }) 215} 216 217// SessionWrite checks for permission to create sessions for a given 218// node. 219func (c *ChainedAuthorizer) SessionWrite(node string, entCtx *AuthorizerContext) EnforcementDecision { 220 return c.executeChain(func(authz Authorizer) EnforcementDecision { 221 return authz.SessionWrite(node, entCtx) 222 }) 223} 224 225// Snapshot checks for permission to take and restore snapshots. 226func (c *ChainedAuthorizer) Snapshot(entCtx *AuthorizerContext) EnforcementDecision { 227 return c.executeChain(func(authz Authorizer) EnforcementDecision { 228 return authz.Snapshot(entCtx) 229 }) 230} 231