github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/trustedcluster.go (about) 1 /* 2 Copyright 2020 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 "slices" 22 "time" 23 24 "github.com/google/go-cmp/cmp" 25 "github.com/gravitational/trace" 26 ) 27 28 // TrustedCluster holds information needed for a cluster that can not be directly 29 // accessed (maybe be behind firewall without any open ports) to join a parent cluster. 30 type TrustedCluster interface { 31 // Resource provides common resource properties 32 Resource 33 // SetMetadata sets object metadata 34 SetMetadata(meta Metadata) 35 // GetEnabled returns the state of the TrustedCluster. 36 GetEnabled() bool 37 // SetEnabled enables (handshake and add ca+reverse tunnel) or disables TrustedCluster. 38 SetEnabled(bool) 39 // CombinedMapping is used to specify combined mapping from legacy property Roles 40 // and new property RoleMap 41 CombinedMapping() RoleMap 42 // GetRoleMap returns role map property 43 GetRoleMap() RoleMap 44 // SetRoleMap sets role map 45 SetRoleMap(m RoleMap) 46 // GetRoles returns the roles for the certificate authority. 47 GetRoles() []string 48 // SetRoles sets the roles for the certificate authority. 49 SetRoles([]string) 50 // GetToken returns the authorization and authentication token. 51 GetToken() string 52 // SetToken sets the authorization and authentication. 53 SetToken(string) 54 // GetProxyAddress returns the address of the proxy server. 55 GetProxyAddress() string 56 // SetProxyAddress sets the address of the proxy server. 57 SetProxyAddress(string) 58 // GetReverseTunnelAddress returns the address of the reverse tunnel. 59 GetReverseTunnelAddress() string 60 // SetReverseTunnelAddress sets the address of the reverse tunnel. 61 SetReverseTunnelAddress(string) 62 // CanChangeStateTo checks the TrustedCluster can transform into another. 63 CanChangeStateTo(TrustedCluster) error 64 } 65 66 // NewTrustedCluster is a convenience way to create a TrustedCluster resource. 67 func NewTrustedCluster(name string, spec TrustedClusterSpecV2) (TrustedCluster, error) { 68 c := &TrustedClusterV2{ 69 Metadata: Metadata{ 70 Name: name, 71 }, 72 Spec: spec, 73 } 74 if err := c.CheckAndSetDefaults(); err != nil { 75 return nil, trace.Wrap(err) 76 } 77 return c, nil 78 } 79 80 // setStaticFields sets static resource header and metadata fields. 81 func (c *TrustedClusterV2) setStaticFields() { 82 c.Kind = KindTrustedCluster 83 c.Version = V2 84 } 85 86 // CheckAndSetDefaults checks validity of all parameters and sets defaults 87 func (c *TrustedClusterV2) CheckAndSetDefaults() error { 88 c.setStaticFields() 89 if err := c.Metadata.CheckAndSetDefaults(); err != nil { 90 return trace.Wrap(err) 91 } 92 93 // This is to force users to migrate 94 if len(c.Spec.Roles) != 0 && len(c.Spec.RoleMap) != 0 { 95 return trace.BadParameter("should set either 'roles' or 'role_map', not both") 96 } 97 // Imply that by default proxy listens on the same port for 98 // web and reverse tunnel connections 99 if c.Spec.ReverseTunnelAddress == "" { 100 c.Spec.ReverseTunnelAddress = c.Spec.ProxyAddress 101 } 102 return nil 103 } 104 105 // GetVersion returns resource version 106 func (c *TrustedClusterV2) GetVersion() string { 107 return c.Version 108 } 109 110 // GetKind returns resource kind 111 func (c *TrustedClusterV2) GetKind() string { 112 return c.Kind 113 } 114 115 // GetSubKind returns resource sub kind 116 func (c *TrustedClusterV2) GetSubKind() string { 117 return c.SubKind 118 } 119 120 // SetSubKind sets resource subkind 121 func (c *TrustedClusterV2) SetSubKind(s string) { 122 c.SubKind = s 123 } 124 125 // GetResourceID returns resource ID 126 func (c *TrustedClusterV2) GetResourceID() int64 { 127 return c.Metadata.ID 128 } 129 130 // SetResourceID sets resource ID 131 func (c *TrustedClusterV2) SetResourceID(id int64) { 132 c.Metadata.ID = id 133 } 134 135 // GetRevision returns the revision 136 func (c *TrustedClusterV2) GetRevision() string { 137 return c.Metadata.GetRevision() 138 } 139 140 // SetRevision sets the revision 141 func (c *TrustedClusterV2) SetRevision(rev string) { 142 c.Metadata.SetRevision(rev) 143 } 144 145 // CombinedMapping is used to specify combined mapping from legacy property Roles 146 // and new property RoleMap 147 func (c *TrustedClusterV2) CombinedMapping() RoleMap { 148 if len(c.Spec.Roles) != 0 { 149 return []RoleMapping{{Remote: Wildcard, Local: c.Spec.Roles}} 150 } 151 return c.Spec.RoleMap 152 } 153 154 // GetRoleMap returns role map property 155 func (c *TrustedClusterV2) GetRoleMap() RoleMap { 156 return c.Spec.RoleMap 157 } 158 159 // SetRoleMap sets role map 160 func (c *TrustedClusterV2) SetRoleMap(m RoleMap) { 161 c.Spec.RoleMap = m 162 } 163 164 // GetMetadata returns object metadata 165 func (c *TrustedClusterV2) GetMetadata() Metadata { 166 return c.Metadata 167 } 168 169 // SetMetadata sets object metadata 170 func (c *TrustedClusterV2) SetMetadata(meta Metadata) { 171 c.Metadata = meta 172 } 173 174 // SetExpiry sets expiry time for the object 175 func (c *TrustedClusterV2) SetExpiry(expires time.Time) { 176 c.Metadata.SetExpiry(expires) 177 } 178 179 // Expiry returns object expiry setting 180 func (c *TrustedClusterV2) Expiry() time.Time { 181 return c.Metadata.Expiry() 182 } 183 184 // GetName returns the name of the TrustedCluster. 185 func (c *TrustedClusterV2) GetName() string { 186 return c.Metadata.Name 187 } 188 189 // SetName sets the name of the TrustedCluster. 190 func (c *TrustedClusterV2) SetName(e string) { 191 c.Metadata.Name = e 192 } 193 194 // GetEnabled returns the state of the TrustedCluster. 195 func (c *TrustedClusterV2) GetEnabled() bool { 196 return c.Spec.Enabled 197 } 198 199 // SetEnabled enables (handshake and add ca+reverse tunnel) or disables TrustedCluster. 200 func (c *TrustedClusterV2) SetEnabled(e bool) { 201 c.Spec.Enabled = e 202 } 203 204 // GetRoles returns the roles for the certificate authority. 205 func (c *TrustedClusterV2) GetRoles() []string { 206 return c.Spec.Roles 207 } 208 209 // SetRoles sets the roles for the certificate authority. 210 func (c *TrustedClusterV2) SetRoles(e []string) { 211 c.Spec.Roles = e 212 } 213 214 // GetToken returns the authorization and authentication token. 215 func (c *TrustedClusterV2) GetToken() string { 216 return c.Spec.Token 217 } 218 219 // SetToken sets the authorization and authentication. 220 func (c *TrustedClusterV2) SetToken(e string) { 221 c.Spec.Token = e 222 } 223 224 // GetProxyAddress returns the address of the proxy server. 225 func (c *TrustedClusterV2) GetProxyAddress() string { 226 return c.Spec.ProxyAddress 227 } 228 229 // SetProxyAddress sets the address of the proxy server. 230 func (c *TrustedClusterV2) SetProxyAddress(e string) { 231 c.Spec.ProxyAddress = e 232 } 233 234 // GetReverseTunnelAddress returns the address of the reverse tunnel. 235 func (c *TrustedClusterV2) GetReverseTunnelAddress() string { 236 return c.Spec.ReverseTunnelAddress 237 } 238 239 // SetReverseTunnelAddress sets the address of the reverse tunnel. 240 func (c *TrustedClusterV2) SetReverseTunnelAddress(e string) { 241 c.Spec.ReverseTunnelAddress = e 242 } 243 244 // CanChangeStateTo checks if the state change is allowed or not. If not, returns 245 // an error explaining the reason. 246 func (c *TrustedClusterV2) CanChangeStateTo(t TrustedCluster) error { 247 immutableFieldErr := func(name string) error { 248 return trace.BadParameter("can not update %s for existing leaf cluster, delete and re-create this leaf cluster with updated %s", name, name) 249 } 250 if c.GetToken() != t.GetToken() { 251 return immutableFieldErr("token") 252 } 253 if c.GetProxyAddress() != t.GetProxyAddress() { 254 return immutableFieldErr("web_proxy_address") 255 } 256 if c.GetReverseTunnelAddress() != t.GetReverseTunnelAddress() { 257 return immutableFieldErr("tunnel_addr") 258 } 259 if !slices.Equal(c.GetRoles(), t.GetRoles()) { 260 return immutableFieldErr("roles") 261 } 262 roleMapUpdated := !cmp.Equal(c.GetRoleMap(), t.GetRoleMap()) 263 264 if c.GetEnabled() == t.GetEnabled() && !roleMapUpdated { 265 if t.GetEnabled() { 266 return trace.AlreadyExists("leaf cluster is already enabled, this update would have no effect") 267 } 268 return trace.AlreadyExists("leaf cluster is already disabled, this update would have no effect") 269 } 270 271 return nil 272 } 273 274 // String represents a human readable version of trusted cluster settings. 275 func (c *TrustedClusterV2) String() string { 276 return fmt.Sprintf("TrustedCluster(Enabled=%v,Roles=%v,Token=%v,ProxyAddress=%v,ReverseTunnelAddress=%v)", 277 c.Spec.Enabled, c.Spec.Roles, c.Spec.Token, c.Spec.ProxyAddress, c.Spec.ReverseTunnelAddress) 278 } 279 280 // RoleMap is a list of mappings 281 type RoleMap []RoleMapping 282 283 // SortedTrustedCluster sorts clusters by name 284 type SortedTrustedCluster []TrustedCluster 285 286 // Len returns the length of a list. 287 func (s SortedTrustedCluster) Len() int { 288 return len(s) 289 } 290 291 // Less compares items by name. 292 func (s SortedTrustedCluster) Less(i, j int) bool { 293 return s[i].GetName() < s[j].GetName() 294 } 295 296 // Swap swaps two items in a list. 297 func (s SortedTrustedCluster) Swap(i, j int) { 298 s[i], s[j] = s[j], s[i] 299 }