github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/appserver.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 "fmt" 21 "sort" 22 "time" 23 24 "github.com/gravitational/trace" 25 26 "github.com/gravitational/teleport/api" 27 "github.com/gravitational/teleport/api/constants" 28 "github.com/gravitational/teleport/api/utils" 29 ) 30 31 // AppServer represents a single proxied web app. 32 type AppServer interface { 33 // ResourceWithLabels provides common resource methods. 34 ResourceWithLabels 35 // GetNamespace returns server namespace. 36 GetNamespace() string 37 // GetTeleportVersion returns the teleport version the server is running on. 38 GetTeleportVersion() string 39 // GetHostname returns the server hostname. 40 GetHostname() string 41 // GetHostID returns ID of the host the server is running on. 42 GetHostID() string 43 // GetRotation gets the state of certificate authority rotation. 44 GetRotation() Rotation 45 // SetRotation sets the state of certificate authority rotation. 46 SetRotation(Rotation) 47 // String returns string representation of the server. 48 String() string 49 // Copy returns a copy of this app server object. 50 Copy() AppServer 51 52 // CloneResource returns a copy of the AppServer as a ResourceWithLabels 53 CloneResource() ResourceWithLabels 54 // GetApp returns the app this app server proxies. 55 GetApp() Application 56 // SetApp sets the app this app server proxies. 57 SetApp(Application) error 58 // GetTunnelType returns the tunnel type associated with the app server. 59 GetTunnelType() TunnelType 60 // ProxiedService provides common methods for a proxied service. 61 ProxiedService 62 } 63 64 // NewAppServerV3 creates a new app server instance. 65 func NewAppServerV3(meta Metadata, spec AppServerSpecV3) (*AppServerV3, error) { 66 s := &AppServerV3{ 67 Metadata: meta, 68 Spec: spec, 69 } 70 if err := s.CheckAndSetDefaults(); err != nil { 71 return nil, trace.Wrap(err) 72 } 73 return s, nil 74 } 75 76 // NewAppServerV3FromApp creates a new app server from the provided app. 77 func NewAppServerV3FromApp(app *AppV3, hostname, hostID string) (*AppServerV3, error) { 78 return NewAppServerV3(Metadata{ 79 Name: app.GetName(), 80 }, AppServerSpecV3{ 81 Hostname: hostname, 82 HostID: hostID, 83 App: app, 84 }) 85 } 86 87 // NewAppServerForAWSOIDCIntegration creates a new AppServer that will be used to grant AWS App Access 88 // using the AWSOIDC credentials. 89 func NewAppServerForAWSOIDCIntegration(integrationName string, hostID string) (*AppServerV3, error) { 90 return NewAppServerV3(Metadata{ 91 Name: integrationName, 92 }, AppServerSpecV3{ 93 HostID: hostID, 94 App: &AppV3{Metadata: Metadata{ 95 Name: integrationName, 96 }, Spec: AppSpecV3{ 97 URI: constants.AWSConsoleURL, 98 Integration: integrationName, 99 }}, 100 }) 101 } 102 103 // GetVersion returns the database server resource version. 104 func (s *AppServerV3) GetVersion() string { 105 return s.Version 106 } 107 108 // GetTeleportVersion returns the Teleport version the server is running. 109 func (s *AppServerV3) GetTeleportVersion() string { 110 return s.Spec.Version 111 } 112 113 // GetHostname returns the database server hostname. 114 func (s *AppServerV3) GetHostname() string { 115 return s.Spec.Hostname 116 } 117 118 // GetHostID returns ID of the host the server is running on. 119 func (s *AppServerV3) GetHostID() string { 120 return s.Spec.HostID 121 } 122 123 // GetKind returns the resource kind. 124 func (s *AppServerV3) GetKind() string { 125 return s.Kind 126 } 127 128 // GetSubKind returns the resource subkind. 129 func (s *AppServerV3) GetSubKind() string { 130 return s.SubKind 131 } 132 133 // SetSubKind sets the resource subkind. 134 func (s *AppServerV3) SetSubKind(sk string) { 135 s.SubKind = sk 136 } 137 138 // GetResourceID returns the resource ID. 139 func (s *AppServerV3) GetResourceID() int64 { 140 return s.Metadata.ID 141 } 142 143 // SetResourceID sets the resource ID. 144 func (s *AppServerV3) SetResourceID(id int64) { 145 s.Metadata.ID = id 146 } 147 148 // GetRevision returns the revision 149 func (s *AppServerV3) GetRevision() string { 150 return s.Metadata.GetRevision() 151 } 152 153 // SetRevision sets the revision 154 func (s *AppServerV3) SetRevision(rev string) { 155 s.Metadata.SetRevision(rev) 156 } 157 158 // GetMetadata returns the resource metadata. 159 func (s *AppServerV3) GetMetadata() Metadata { 160 return s.Metadata 161 } 162 163 // GetNamespace returns the resource namespace. 164 func (s *AppServerV3) GetNamespace() string { 165 return s.Metadata.Namespace 166 } 167 168 // SetExpiry sets the resource expiry time. 169 func (s *AppServerV3) SetExpiry(expiry time.Time) { 170 s.Metadata.SetExpiry(expiry) 171 } 172 173 // Expiry returns the resource expiry time. 174 func (s *AppServerV3) Expiry() time.Time { 175 return s.Metadata.Expiry() 176 } 177 178 // GetName returns the resource name. 179 func (s *AppServerV3) GetName() string { 180 return s.Metadata.Name 181 } 182 183 // SetName sets the resource name. 184 func (s *AppServerV3) SetName(name string) { 185 s.Metadata.Name = name 186 } 187 188 // GetRotation returns the server CA rotation state. 189 func (s *AppServerV3) GetRotation() Rotation { 190 return s.Spec.Rotation 191 } 192 193 // SetRotation sets the server CA rotation state. 194 func (s *AppServerV3) SetRotation(r Rotation) { 195 s.Spec.Rotation = r 196 } 197 198 // GetApp returns the app this app server proxies. 199 func (s *AppServerV3) GetApp() Application { 200 if s.Spec.App == nil { 201 return nil 202 } 203 return s.Spec.App 204 } 205 206 // SetApp sets the app this app server proxies. 207 func (s *AppServerV3) SetApp(app Application) error { 208 appV3, ok := app.(*AppV3) 209 if !ok { 210 return trace.BadParameter("expected *AppV3, got %T", app) 211 } 212 s.Spec.App = appV3 213 return nil 214 } 215 216 // GetTunnelType returns the tunnel type associated with the app server. 217 func (s *AppServerV3) GetTunnelType() TunnelType { 218 switch { 219 case s.Origin() == OriginOkta: 220 return OktaTunnel 221 default: 222 return AppTunnel 223 } 224 } 225 226 // String returns the server string representation. 227 func (s *AppServerV3) String() string { 228 return fmt.Sprintf("AppServer(Name=%v, Version=%v, Hostname=%v, HostID=%v, App=%v)", 229 s.GetName(), s.GetTeleportVersion(), s.GetHostname(), s.GetHostID(), s.GetApp()) 230 } 231 232 // setStaticFields sets static resource header and metadata fields. 233 func (s *AppServerV3) setStaticFields() { 234 s.Kind = KindAppServer 235 s.Version = V3 236 } 237 238 // CheckAndSetDefaults checks and sets default values for any missing fields. 239 func (s *AppServerV3) CheckAndSetDefaults() error { 240 s.setStaticFields() 241 if err := s.Metadata.CheckAndSetDefaults(); err != nil { 242 return trace.Wrap(err) 243 } 244 if s.Spec.HostID == "" { 245 return trace.BadParameter("missing app server HostID") 246 } 247 if s.Spec.Version == "" { 248 s.Spec.Version = api.Version 249 } 250 if s.Spec.App == nil { 251 return trace.BadParameter("missing app server App") 252 } 253 if err := s.Spec.App.CheckAndSetDefaults(); err != nil { 254 return trace.Wrap(err) 255 } 256 return nil 257 } 258 259 // Origin returns the origin value of the resource. 260 func (s *AppServerV3) Origin() string { 261 return s.Metadata.Origin() 262 } 263 264 // SetOrigin sets the origin value of the resource. 265 func (s *AppServerV3) SetOrigin(origin string) { 266 s.Metadata.SetOrigin(origin) 267 } 268 269 // GetProxyID returns a list of proxy ids this server is connected to. 270 func (s *AppServerV3) GetProxyIDs() []string { 271 return s.Spec.ProxyIDs 272 } 273 274 // SetProxyID sets the proxy ids this server is connected to. 275 func (s *AppServerV3) SetProxyIDs(proxyIDs []string) { 276 s.Spec.ProxyIDs = proxyIDs 277 } 278 279 // GetLabel retrieves the label with the provided key. If not found 280 // value will be empty and ok will be false. 281 func (s *AppServerV3) GetLabel(key string) (value string, ok bool) { 282 if s.Spec.App != nil { 283 if v, ok := s.Spec.App.GetLabel(key); ok { 284 return v, ok 285 } 286 } 287 288 v, ok := s.Metadata.Labels[key] 289 return v, ok 290 } 291 292 // GetAllLabels returns all resource's labels. Considering: 293 // * Static labels from `Metadata.Labels` and `Spec.App`. 294 // * Dynamic labels from `Spec.App.Spec`. 295 func (s *AppServerV3) GetAllLabels() map[string]string { 296 staticLabels := make(map[string]string) 297 for name, value := range s.Metadata.Labels { 298 staticLabels[name] = value 299 } 300 301 var dynamicLabels map[string]CommandLabelV2 302 if s.Spec.App != nil { 303 for name, value := range s.Spec.App.Metadata.Labels { 304 staticLabels[name] = value 305 } 306 307 dynamicLabels = s.Spec.App.Spec.DynamicLabels 308 } 309 310 return CombineLabels(staticLabels, dynamicLabels) 311 } 312 313 // GetStaticLabels returns the app server static labels. 314 func (s *AppServerV3) GetStaticLabels() map[string]string { 315 return s.Metadata.Labels 316 } 317 318 // SetStaticLabels sets the app server static labels. 319 func (s *AppServerV3) SetStaticLabels(sl map[string]string) { 320 s.Metadata.Labels = sl 321 } 322 323 // Copy returns a copy of this app server object. 324 func (s *AppServerV3) Copy() AppServer { 325 return utils.CloneProtoMsg(s) 326 } 327 328 func (s *AppServerV3) CloneResource() ResourceWithLabels { 329 return s.Copy() 330 } 331 332 // MatchSearch goes through select field values and tries to 333 // match against the list of search values. 334 func (s *AppServerV3) MatchSearch(values []string) bool { 335 return MatchSearch(nil, values, nil) 336 } 337 338 // AppServers represents a list of app servers. 339 type AppServers []AppServer 340 341 // Len returns the slice length. 342 func (s AppServers) Len() int { return len(s) } 343 344 // Less compares app servers by name and host ID. 345 func (s AppServers) Less(i, j int) bool { 346 switch { 347 case s[i].GetName() < s[j].GetName(): 348 return true 349 case s[i].GetName() > s[j].GetName(): 350 return false 351 default: 352 return s[i].GetHostID() < s[j].GetHostID() 353 } 354 } 355 356 // Swap swaps two app servers. 357 func (s AppServers) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 358 359 // SortByCustom custom sorts by given sort criteria. 360 func (s AppServers) SortByCustom(sortBy SortBy) error { 361 if sortBy.Field == "" { 362 return nil 363 } 364 365 // We assume sorting by type AppServer, we are really 366 // wanting to sort its contained resource Application. 367 isDesc := sortBy.IsDesc 368 switch sortBy.Field { 369 case ResourceMetadataName: 370 sort.SliceStable(s, func(i, j int) bool { 371 return stringCompare(s[i].GetApp().GetName(), s[j].GetApp().GetName(), isDesc) 372 }) 373 case ResourceSpecDescription: 374 sort.SliceStable(s, func(i, j int) bool { 375 return stringCompare(s[i].GetApp().GetDescription(), s[j].GetApp().GetDescription(), isDesc) 376 }) 377 case ResourceSpecPublicAddr: 378 sort.SliceStable(s, func(i, j int) bool { 379 return stringCompare(s[i].GetApp().GetPublicAddr(), s[j].GetApp().GetPublicAddr(), isDesc) 380 }) 381 default: 382 return trace.NotImplemented("sorting by field %q for resource %q is not supported", sortBy.Field, KindAppServer) 383 } 384 385 return nil 386 } 387 388 // AsResources returns app servers as type resources with labels. 389 func (s AppServers) AsResources() []ResourceWithLabels { 390 resources := make([]ResourceWithLabels, 0, len(s)) 391 for _, server := range s { 392 resources = append(resources, ResourceWithLabels(server)) 393 } 394 return resources 395 } 396 397 // GetFieldVals returns list of select field values. 398 func (s AppServers) GetFieldVals(field string) ([]string, error) { 399 vals := make([]string, 0, len(s)) 400 switch field { 401 case ResourceMetadataName: 402 for _, server := range s { 403 vals = append(vals, server.GetApp().GetName()) 404 } 405 case ResourceSpecDescription: 406 for _, server := range s { 407 vals = append(vals, server.GetApp().GetDescription()) 408 } 409 case ResourceSpecPublicAddr: 410 for _, server := range s { 411 vals = append(vals, server.GetApp().GetPublicAddr()) 412 } 413 default: 414 return nil, trace.NotImplemented("getting field %q for resource %q is not supported", field, KindAppServer) 415 } 416 417 return vals, nil 418 }