github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/system_role.go (about) 1 /* 2 Copyright 2021 Gravitational, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package types 18 19 import ( 20 "strings" 21 22 "github.com/gravitational/trace" 23 ) 24 25 // SystemRole identifies the role of an SSH connection. Unlike "user roles" 26 // introduced as part of RBAC in Teleport 1.4+ these are built-in roles used 27 // for different Teleport components when connecting to each other. 28 type SystemRole string 29 30 // SystemRoles is a TeleportRole list 31 type SystemRoles []SystemRole 32 33 const ( 34 // RoleAuth is for teleport auth server (authority, authentication and authorization) 35 RoleAuth SystemRole = "Auth" 36 // RoleNode is a role for SSH node in the cluster 37 RoleNode SystemRole = "Node" 38 // RoleProxy is a role for SSH proxy in the cluster 39 RoleProxy SystemRole = "Proxy" 40 // RoleAdmin is admin role 41 RoleAdmin SystemRole = "Admin" 42 // RoleProvisionToken is a role for nodes authenticated using provisioning tokens 43 RoleProvisionToken SystemRole = "ProvisionToken" 44 // RoleTrustedCluster is a role needed for tokens used to add trusted clusters. 45 RoleTrustedCluster SystemRole = "Trusted_cluster" 46 // RoleSignup is for first time signing up users 47 RoleSignup SystemRole = "Signup" 48 // RoleNop is used for actions that are already using external authz mechanisms 49 // e.g. tokens or passwords 50 RoleNop SystemRole = "Nop" 51 // RoleRemoteProxy is a role for remote SSH proxy in the cluster 52 RoleRemoteProxy SystemRole = "RemoteProxy" 53 // RoleKube is a role for a kubernetes service. 54 RoleKube SystemRole = "Kube" 55 // RoleApp is a role for a app proxy in the cluster. 56 RoleApp SystemRole = "App" 57 // RoleDatabase is a role for a database proxy in the cluster. 58 RoleDatabase SystemRole = "Db" 59 // RoleWindowsDesktop is a role for a Windows desktop service. 60 RoleWindowsDesktop SystemRole = "WindowsDesktop" 61 // RoleBot is a role for a bot. 62 RoleBot SystemRole = "Bot" 63 // RoleInstance is a role implicitly held by teleport servers (i.e. any teleport 64 // auth token which grants a server role such as proxy/node/etc also implicitly 65 // grants the instance role, and any valid cert that proves that the caller holds 66 // a server role also implies that the caller holds the instance role). This role 67 // doesn't grant meaningful privileges on its own, but is a useful placeholder in 68 // contexts such as multi-role certs where there is no particular system role that 69 // is "primary". 70 RoleInstance SystemRole = "Instance" 71 // RoleDiscovery is a role for discovery nodes in the cluster 72 RoleDiscovery SystemRole = "Discovery" 73 // RoleOkta is a role for Okta nodes in the cluster 74 RoleOkta SystemRole = "Okta" 75 // RoleMDM is the role for MDM services in the cluster. 76 // An MDM service, like Jamf Service, has the powers to manage the cluster's 77 // device inventory. 78 // Device Trust requires Teleport Enteprise. 79 RoleMDM SystemRole = "MDM" 80 81 // RoleAccessGraphPlugin is a role for Access Graph plugins to access 82 // Teleport's internal API and access graph. 83 RoleAccessGraphPlugin SystemRole = "AccessGraphPlugin" 84 ) 85 86 // roleMappings maps a set of allowed lowercase system role names 87 // to the proper system role 88 var roleMappings = map[string]SystemRole{ 89 "auth": RoleAuth, 90 "node": RoleNode, 91 "proxy": RoleProxy, 92 "admin": RoleAdmin, 93 "provisiontoken": RoleProvisionToken, 94 "trusted_cluster": RoleTrustedCluster, 95 "trustedcluster": RoleTrustedCluster, 96 "signup": RoleSignup, 97 "nop": RoleNop, 98 "remoteproxy": RoleRemoteProxy, 99 "remote_proxy": RoleRemoteProxy, 100 "kube": RoleKube, 101 "app": RoleApp, 102 "db": RoleDatabase, 103 "windowsdesktop": RoleWindowsDesktop, 104 "windows_desktop": RoleWindowsDesktop, 105 "bot": RoleBot, 106 "instance": RoleInstance, 107 "discovery": RoleDiscovery, 108 "okta": RoleOkta, 109 "mdm": RoleMDM, 110 "accessgraphplugin": RoleAccessGraphPlugin, 111 } 112 113 func normalizedSystemRole(s string) SystemRole { 114 if role, ok := roleMappings[strings.ToLower(strings.TrimSpace(s))]; ok { 115 return role 116 } 117 return SystemRole(s) 118 } 119 120 func normalizedSystemRoles(s []string) []SystemRole { 121 roles := make([]SystemRole, 0, len(s)) 122 for _, role := range s { 123 roles = append(roles, normalizedSystemRole(role)) 124 } 125 return roles 126 } 127 128 // localServiceMappings is the subset of role mappings which happen to be true 129 // teleport services (e.g. db, kube, etc), excluding those which represent remote 130 // services (i.e. remoteproxy). 131 var localServiceMappings = map[SystemRole]struct{}{ 132 RoleAuth: {}, 133 RoleNode: {}, 134 RoleProxy: {}, 135 RoleKube: {}, 136 RoleApp: {}, 137 RoleDatabase: {}, 138 RoleWindowsDesktop: {}, 139 RoleDiscovery: {}, 140 RoleOkta: {}, 141 RoleMDM: {}, 142 RoleAccessGraphPlugin: {}, 143 } 144 145 // controlPlaneMapping is the subset of local services which are definitively control plane 146 // elements. 147 var controlPlaneMapping = map[SystemRole]struct{}{ 148 RoleAuth: {}, 149 RoleProxy: {}, 150 } 151 152 // LocalServiceMappings returns the subset of role mappings which happen 153 // to be true Teleport services (e.g. db, kube, proxy, etc), excluding 154 // those which represent remote service (i.e. remoteproxy). 155 func LocalServiceMappings() SystemRoles { 156 var sr SystemRoles 157 for k := range localServiceMappings { 158 sr = append(sr, k) 159 } 160 return sr 161 } 162 163 // NewTeleportRoles return a list of teleport roles from slice of strings 164 func NewTeleportRoles(in []string) (SystemRoles, error) { 165 roles := SystemRoles(normalizedSystemRoles(in)) 166 return roles, roles.Check() 167 } 168 169 // ParseTeleportRoles takes a comma-separated list of roles and returns a slice 170 // of teleport roles, or an error if parsing failed 171 func ParseTeleportRoles(str string) (SystemRoles, error) { 172 var roles SystemRoles 173 for _, s := range strings.Split(str, ",") { 174 if r := normalizedSystemRole(s); r.Check() == nil { 175 roles = append(roles, r) 176 continue 177 } 178 return nil, trace.BadParameter("invalid role %q", s) 179 } 180 if len(roles) == 0 { 181 return nil, trace.BadParameter("no valid roles in $%q", str) 182 } 183 184 return roles, roles.Check() 185 } 186 187 // Include returns 'true' if a given list of teleport roles includes a given role 188 func (roles SystemRoles) Include(role SystemRole) bool { 189 for _, r := range roles { 190 if r == role { 191 return true 192 } 193 } 194 return false 195 } 196 197 // IncludeAny returns 'true' if a given list of teleport roles includes any of 198 // the given candidate roles. 199 func (roles SystemRoles) IncludeAny(candidates ...SystemRole) bool { 200 for _, r := range candidates { 201 if roles.Include(r) { 202 return true 203 } 204 } 205 return false 206 } 207 208 // StringSlice returns teleport roles as string slice 209 func (roles SystemRoles) StringSlice() []string { 210 s := make([]string, 0) 211 for _, r := range roles { 212 s = append(s, r.String()) 213 } 214 return s 215 } 216 217 // asSet returns teleport roles as set (map). 218 func (roles SystemRoles) asSet() map[SystemRole]struct{} { 219 s := make(map[SystemRole]struct{}, len(roles)) 220 for _, r := range roles { 221 s[r] = struct{}{} 222 } 223 return s 224 } 225 226 // Equals compares two sets of teleport roles 227 func (roles SystemRoles) Equals(other SystemRoles) bool { 228 rs, os := roles.asSet(), other.asSet() 229 if len(rs) != len(os) { 230 return false 231 } 232 for r := range rs { 233 if _, ok := os[r]; !ok { 234 return false 235 } 236 } 237 return true 238 } 239 240 // Check returns an error if the teleport role set is incorrect (contains unknown roles) 241 func (roles SystemRoles) Check() error { 242 seen := make(map[SystemRole]struct{}) 243 for _, role := range roles { 244 if err := role.Check(); err != nil { 245 return trace.Wrap(err) 246 } 247 if _, ok := seen[role]; ok { 248 return trace.BadParameter("duplicate role %q", role) 249 } 250 seen[role] = struct{}{} 251 } 252 return nil 253 } 254 255 // String returns comma separated string with teleport roles 256 func (roles SystemRoles) String() string { 257 return strings.Join(roles.StringSlice(), ",") 258 } 259 260 // Set sets the value of the teleport role from string, used to integrate with CLI tools 261 func (r *SystemRole) Set(v string) error { 262 if len(v) > 0 { 263 v = strings.ToUpper(v[:1]) + v[1:] 264 } 265 val := SystemRole(v) 266 if err := val.Check(); err != nil { 267 return trace.Wrap(err) 268 } 269 *r = val 270 return nil 271 } 272 273 // String returns the system role string representation. Returned values must 274 // match (case-insensitive) the role mappings; otherwise, the validation check 275 // will fail. 276 func (r *SystemRole) String() string { 277 switch *r { 278 case RoleTrustedCluster: 279 return "trusted_cluster" 280 default: 281 return string(*r) 282 } 283 } 284 285 // Check checks if this a a valid teleport role value, returns nil 286 // if it's ok, false otherwise 287 // Check checks if this a a valid teleport role value, returns nil 288 // if it's ok, false otherwise 289 func (r *SystemRole) Check() error { 290 sr, ok := roleMappings[strings.ToLower(string(*r))] 291 if ok && string(*r) == string(sr) { 292 return nil 293 } 294 295 return trace.BadParameter("role %v is not registered", *r) 296 } 297 298 // IsLocalService checks if the given system role is a teleport service (e.g. auth), 299 // as opposed to some non-service role (e.g. admin). Excludes remote services such 300 // as remoteproxy. 301 func (r *SystemRole) IsLocalService() bool { 302 _, ok := localServiceMappings[*r] 303 return ok 304 } 305 306 // IsControlPlane checks if the given system role is a control plane element (i.e. auth/proxy). 307 func (r *SystemRole) IsControlPlane() bool { 308 _, ok := controlPlaneMapping[*r] 309 return ok 310 }