github.phpd.cn/hashicorp/consul@v1.4.5/agent/consul/acl_server.go (about) 1 package consul 2 3 import ( 4 "sync/atomic" 5 6 "github.com/hashicorp/consul/acl" 7 "github.com/hashicorp/consul/agent/structs" 8 "github.com/hashicorp/consul/lib" 9 ) 10 11 var serverACLCacheConfig *structs.ACLCachesConfig = &structs.ACLCachesConfig{ 12 // The server's ACL caching has a few underlying assumptions: 13 // 14 // 1 - All policies can be resolved locally. Hence we do not cache any 15 // unparsed policies as we have memdb for that. 16 // 2 - While there could be many identities being used within a DC the 17 // number of distinct policies and combined multi-policy authorizers 18 // will be much less. 19 // 3 - If you need more than 10k tokens cached then you should probably 20 // enable token replication or be using DC local tokens. In both 21 // cases resolving the tokens from memdb will avoid the cache 22 // entirely 23 // 24 Identities: 10 * 1024, 25 Policies: 0, 26 ParsedPolicies: 512, 27 Authorizers: 1024, 28 } 29 30 func (s *Server) checkTokenUUID(id string) (bool, error) { 31 state := s.fsm.State() 32 if _, token, err := state.ACLTokenGetByAccessor(nil, id); err != nil { 33 return false, err 34 } else if token != nil { 35 return false, nil 36 } 37 38 if _, token, err := state.ACLTokenGetBySecret(nil, id); err != nil { 39 return false, err 40 } else if token != nil { 41 return false, nil 42 } 43 44 return !structs.ACLIDReserved(id), nil 45 } 46 47 func (s *Server) checkPolicyUUID(id string) (bool, error) { 48 state := s.fsm.State() 49 if _, policy, err := state.ACLPolicyGetByID(nil, id); err != nil { 50 return false, err 51 } else if policy != nil { 52 return false, nil 53 } 54 55 return !structs.ACLIDReserved(id), nil 56 } 57 58 func (s *Server) updateACLAdvertisement() { 59 // One thing to note is that once in new ACL mode the server will 60 // never transition to legacy ACL mode. This is not currently a 61 // supported use case. 62 63 // always advertise to all the LAN Members 64 lib.UpdateSerfTag(s.serfLAN, "acls", string(structs.ACLModeEnabled)) 65 66 if s.serfWAN != nil { 67 // advertise on the WAN only when we are inside the ACL datacenter 68 lib.UpdateSerfTag(s.serfWAN, "acls", string(structs.ACLModeEnabled)) 69 } 70 } 71 72 func (s *Server) canUpgradeToNewACLs(isLeader bool) bool { 73 if atomic.LoadInt32(&s.useNewACLs) != 0 { 74 // can't upgrade because we are already upgraded 75 return false 76 } 77 78 if !s.InACLDatacenter() { 79 numServers, mode, _ := ServersGetACLMode(s.WANMembers(), "", s.config.ACLDatacenter) 80 if mode != structs.ACLModeEnabled || numServers == 0 { 81 return false 82 } 83 } 84 85 if isLeader { 86 if _, mode, _ := ServersGetACLMode(s.LANMembers(), "", ""); mode == structs.ACLModeLegacy { 87 return true 88 } 89 } else { 90 leader := string(s.raft.Leader()) 91 if _, _, leaderMode := ServersGetACLMode(s.LANMembers(), leader, ""); leaderMode == structs.ACLModeEnabled { 92 return true 93 } 94 } 95 96 return false 97 } 98 99 func (s *Server) InACLDatacenter() bool { 100 return s.config.ACLDatacenter == "" || s.config.Datacenter == s.config.ACLDatacenter 101 } 102 103 func (s *Server) UseLegacyACLs() bool { 104 return atomic.LoadInt32(&s.useNewACLs) == 0 105 } 106 107 func (s *Server) LocalTokensEnabled() bool { 108 // in ACL datacenter so local tokens are always enabled 109 if s.InACLDatacenter() { 110 return true 111 } 112 113 if !s.config.ACLTokenReplication || s.tokens.ReplicationToken() == "" { 114 return false 115 } 116 117 // token replication is off so local tokens are disabled 118 return true 119 } 120 121 func (s *Server) ACLDatacenter(legacy bool) string { 122 // For resolution running on servers the only option 123 // is to contact the configured ACL Datacenter 124 if s.config.ACLDatacenter != "" { 125 return s.config.ACLDatacenter 126 } 127 128 // This function only gets called if ACLs are enabled. 129 // When no ACL DC is set then it is assumed that this DC 130 // is the primary DC 131 return s.config.Datacenter 132 } 133 134 func (s *Server) ACLsEnabled() bool { 135 return s.config.ACLsEnabled 136 } 137 138 func (s *Server) ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) { 139 // only allow remote RPC resolution when token replication is off and 140 // when not in the ACL datacenter 141 if !s.InACLDatacenter() && !s.config.ACLTokenReplication { 142 return false, nil, nil 143 } 144 145 index, aclToken, err := s.fsm.State().ACLTokenGetBySecret(nil, token) 146 if err != nil { 147 return true, nil, err 148 } else if aclToken != nil { 149 return true, aclToken, nil 150 } 151 152 return s.InACLDatacenter() || index > 0, nil, acl.ErrNotFound 153 } 154 155 func (s *Server) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) { 156 index, policy, err := s.fsm.State().ACLPolicyGetByID(nil, policyID) 157 if err != nil { 158 return true, nil, err 159 } else if policy != nil { 160 return true, policy, nil 161 } 162 163 // If the max index of the policies table is non-zero then we have acls, until then 164 // we may need to allow remote resolution. This is particularly useful to allow updating 165 // the replication token via the API in a non-primary dc. 166 return s.InACLDatacenter() || index > 0, policy, acl.ErrNotFound 167 } 168 169 func (s *Server) ResolveToken(token string) (acl.Authorizer, error) { 170 return s.acls.ResolveToken(token) 171 } 172 173 func (s *Server) filterACL(token string, subj interface{}) error { 174 return s.acls.filterACL(token, subj) 175 } 176 177 func (s *Server) filterACLWithAuthorizer(authorizer acl.Authorizer, subj interface{}) error { 178 return s.acls.filterACLWithAuthorizer(authorizer, subj) 179 }