github.com/kjdelisle/consul@v1.4.5/agent/acl.go (about) 1 package agent 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/consul/acl" 7 "github.com/hashicorp/consul/agent/local" 8 "github.com/hashicorp/consul/agent/structs" 9 "github.com/hashicorp/consul/types" 10 "github.com/hashicorp/serf/serf" 11 ) 12 13 // resolveToken is the primary interface used by ACL-checkers in the agent 14 // endpoints, which is the one place where we do some ACL enforcement on 15 // clients. Some of the enforcement is normative (e.g. self and monitor) 16 // and some is informative (e.g. catalog and health). 17 func (a *Agent) resolveToken(id string) (acl.Authorizer, error) { 18 // ACLs are disabled 19 if !a.delegate.ACLsEnabled() { 20 return nil, nil 21 } 22 23 // Disable ACLs if version 8 enforcement isn't enabled. 24 if !a.config.ACLEnforceVersion8 { 25 return nil, nil 26 } 27 28 if acl.RootAuthorizer(id) != nil { 29 return nil, acl.ErrRootDenied 30 } 31 32 if a.tokens.IsAgentMasterToken(id) { 33 return a.aclMasterAuthorizer, nil 34 } 35 return a.delegate.ResolveToken(id) 36 } 37 38 func (a *Agent) initializeACLs() error { 39 // Build a policy for the agent master token. 40 // The builtin agent master policy allows reading any node information 41 // and allows writes to the agent with the node name of the running agent 42 // only. This used to allow a prefix match on agent names but that seems 43 // entirely unnecessary so it is now using an exact match. 44 policy := &acl.Policy{ 45 Agents: []*acl.AgentPolicy{ 46 &acl.AgentPolicy{ 47 Node: a.config.NodeName, 48 Policy: acl.PolicyWrite, 49 }, 50 }, 51 NodePrefixes: []*acl.NodePolicy{ 52 &acl.NodePolicy{ 53 Name: "", 54 Policy: acl.PolicyRead, 55 }, 56 }, 57 } 58 master, err := acl.NewPolicyAuthorizer(acl.DenyAll(), []*acl.Policy{policy}, nil) 59 if err != nil { 60 return err 61 } 62 a.aclMasterAuthorizer = master 63 return nil 64 } 65 66 // resolveProxyToken attempts to resolve an ACL ID to a local proxy token. 67 // If a local proxy isn't found with that token, nil is returned. 68 func (a *Agent) resolveProxyToken(id string) *local.ManagedProxy { 69 for _, p := range a.State.Proxies() { 70 if p.ProxyToken == id { 71 return p 72 } 73 } 74 75 return nil 76 } 77 78 // vetServiceRegister makes sure the service registration action is allowed by 79 // the given token. 80 func (a *Agent) vetServiceRegister(token string, service *structs.NodeService) error { 81 // Resolve the token and bail if ACLs aren't enabled. 82 rule, err := a.resolveToken(token) 83 if err != nil { 84 return err 85 } 86 if rule == nil { 87 return nil 88 } 89 90 // Vet the service itself. 91 if !rule.ServiceWrite(service.Service, nil) { 92 return acl.ErrPermissionDenied 93 } 94 95 // Vet any service that might be getting overwritten. 96 services := a.State.Services() 97 if existing, ok := services[service.ID]; ok { 98 if !rule.ServiceWrite(existing.Service, nil) { 99 return acl.ErrPermissionDenied 100 } 101 } 102 103 // If the service is a proxy, ensure that it has write on the destination too 104 // since it can be discovered as an instance of that service. 105 if service.Kind == structs.ServiceKindConnectProxy { 106 if !rule.ServiceWrite(service.Proxy.DestinationServiceName, nil) { 107 return acl.ErrPermissionDenied 108 } 109 } 110 111 return nil 112 } 113 114 // vetServiceUpdate makes sure the service update action is allowed by the given 115 // token. 116 func (a *Agent) vetServiceUpdate(token string, serviceID string) error { 117 // Resolve the token and bail if ACLs aren't enabled. 118 rule, err := a.resolveToken(token) 119 if err != nil { 120 return err 121 } 122 if rule == nil { 123 return nil 124 } 125 126 // Vet any changes based on the existing services's info. 127 services := a.State.Services() 128 if existing, ok := services[serviceID]; ok { 129 if !rule.ServiceWrite(existing.Service, nil) { 130 return acl.ErrPermissionDenied 131 } 132 } else { 133 return fmt.Errorf("Unknown service %q", serviceID) 134 } 135 136 return nil 137 } 138 139 // vetCheckRegister makes sure the check registration action is allowed by the 140 // given token. 141 func (a *Agent) vetCheckRegister(token string, check *structs.HealthCheck) error { 142 // Resolve the token and bail if ACLs aren't enabled. 143 rule, err := a.resolveToken(token) 144 if err != nil { 145 return err 146 } 147 if rule == nil { 148 return nil 149 } 150 151 // Vet the check itself. 152 if len(check.ServiceName) > 0 { 153 if !rule.ServiceWrite(check.ServiceName, nil) { 154 return acl.ErrPermissionDenied 155 } 156 } else { 157 if !rule.NodeWrite(a.config.NodeName, nil) { 158 return acl.ErrPermissionDenied 159 } 160 } 161 162 // Vet any check that might be getting overwritten. 163 checks := a.State.Checks() 164 if existing, ok := checks[check.CheckID]; ok { 165 if len(existing.ServiceName) > 0 { 166 if !rule.ServiceWrite(existing.ServiceName, nil) { 167 return acl.ErrPermissionDenied 168 } 169 } else { 170 if !rule.NodeWrite(a.config.NodeName, nil) { 171 return acl.ErrPermissionDenied 172 } 173 } 174 } 175 176 return nil 177 } 178 179 // vetCheckUpdate makes sure that a check update is allowed by the given token. 180 func (a *Agent) vetCheckUpdate(token string, checkID types.CheckID) error { 181 // Resolve the token and bail if ACLs aren't enabled. 182 rule, err := a.resolveToken(token) 183 if err != nil { 184 return err 185 } 186 if rule == nil { 187 return nil 188 } 189 190 // Vet any changes based on the existing check's info. 191 checks := a.State.Checks() 192 if existing, ok := checks[checkID]; ok { 193 if len(existing.ServiceName) > 0 { 194 if !rule.ServiceWrite(existing.ServiceName, nil) { 195 return acl.ErrPermissionDenied 196 } 197 } else { 198 if !rule.NodeWrite(a.config.NodeName, nil) { 199 return acl.ErrPermissionDenied 200 } 201 } 202 } else { 203 return fmt.Errorf("Unknown check %q", checkID) 204 } 205 206 return nil 207 } 208 209 // filterMembers redacts members that the token doesn't have access to. 210 func (a *Agent) filterMembers(token string, members *[]serf.Member) error { 211 // Resolve the token and bail if ACLs aren't enabled. 212 rule, err := a.resolveToken(token) 213 if err != nil { 214 return err 215 } 216 if rule == nil { 217 return nil 218 } 219 220 // Filter out members based on the node policy. 221 m := *members 222 for i := 0; i < len(m); i++ { 223 node := m[i].Name 224 if rule.NodeRead(node) { 225 continue 226 } 227 a.logger.Printf("[DEBUG] agent: dropping node %q from result due to ACLs", node) 228 m = append(m[:i], m[i+1:]...) 229 i-- 230 } 231 *members = m 232 return nil 233 } 234 235 // filterServices redacts services that the token doesn't have access to. 236 func (a *Agent) filterServices(token string, services *map[string]*structs.NodeService) error { 237 // Resolve the token and bail if ACLs aren't enabled. 238 rule, err := a.resolveToken(token) 239 if err != nil { 240 return err 241 } 242 if rule == nil { 243 return nil 244 } 245 246 // Filter out services based on the service policy. 247 for id, service := range *services { 248 if rule.ServiceRead(service.Service) { 249 continue 250 } 251 a.logger.Printf("[DEBUG] agent: dropping service %q from result due to ACLs", id) 252 delete(*services, id) 253 } 254 return nil 255 } 256 257 // filterChecks redacts checks that the token doesn't have access to. 258 func (a *Agent) filterChecks(token string, checks *map[types.CheckID]*structs.HealthCheck) error { 259 // Resolve the token and bail if ACLs aren't enabled. 260 rule, err := a.resolveToken(token) 261 if err != nil { 262 return err 263 } 264 if rule == nil { 265 return nil 266 } 267 268 // Filter out checks based on the node or service policy. 269 for id, check := range *checks { 270 if len(check.ServiceName) > 0 { 271 if rule.ServiceRead(check.ServiceName) { 272 continue 273 } 274 } else { 275 if rule.NodeRead(a.config.NodeName) { 276 continue 277 } 278 } 279 a.logger.Printf("[DEBUG] agent: dropping check %q from result due to ACLs", id) 280 delete(*checks, id) 281 } 282 return nil 283 }