github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/authority.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/gravitational/trace" 25 26 "github.com/gravitational/teleport/api/constants" 27 "github.com/gravitational/teleport/api/utils" 28 ) 29 30 // CertAuthority is a host or user certificate authority that can check and if 31 // it has private key stored as well, sign it too. 32 type CertAuthority interface { 33 // ResourceWithSecrets sets common resource properties 34 ResourceWithSecrets 35 // SetMetadata sets CA metadata 36 SetMetadata(meta Metadata) 37 // GetID returns certificate authority ID - 38 // combined type and name 39 GetID() CertAuthID 40 // GetType returns user or host certificate authority 41 GetType() CertAuthType 42 // GetClusterName returns cluster name this cert authority 43 // is associated with 44 GetClusterName() string 45 46 GetActiveKeys() CAKeySet 47 SetActiveKeys(CAKeySet) error 48 GetAdditionalTrustedKeys() CAKeySet 49 SetAdditionalTrustedKeys(CAKeySet) error 50 51 GetTrustedSSHKeyPairs() []*SSHKeyPair 52 GetTrustedTLSKeyPairs() []*TLSKeyPair 53 GetTrustedJWTKeyPairs() []*JWTKeyPair 54 55 // CombinedMapping is used to specify combined mapping from legacy property Roles 56 // and new property RoleMap 57 CombinedMapping() RoleMap 58 // GetRoleMap returns role map property 59 GetRoleMap() RoleMap 60 // SetRoleMap sets role map 61 SetRoleMap(m RoleMap) 62 // GetRoles returns a list of roles assumed by users signed by this CA 63 GetRoles() []string 64 // SetRoles sets assigned roles for this certificate authority 65 SetRoles(roles []string) 66 // AddRole adds a role to ca role list 67 AddRole(name string) 68 // String returns human readable version of the CertAuthority 69 String() string 70 // GetRotation returns rotation state. 71 GetRotation() Rotation 72 // SetRotation sets rotation state. 73 SetRotation(Rotation) 74 // AllKeyTypes returns the set of all different key types in the CA. 75 AllKeyTypes() []string 76 // Clone returns a copy of the cert authority object. 77 Clone() CertAuthority 78 } 79 80 // NewCertAuthority returns new cert authority 81 func NewCertAuthority(spec CertAuthoritySpecV2) (CertAuthority, error) { 82 ca := &CertAuthorityV2{Spec: spec} 83 if err := ca.CheckAndSetDefaults(); err != nil { 84 return nil, trace.Wrap(err) 85 } 86 return ca, nil 87 } 88 89 // GetVersion returns resource version 90 func (ca *CertAuthorityV2) GetVersion() string { 91 return ca.Version 92 } 93 94 // GetKind returns resource kind 95 func (ca *CertAuthorityV2) GetKind() string { 96 return ca.Kind 97 } 98 99 // GetSubKind returns resource sub kind 100 func (ca *CertAuthorityV2) GetSubKind() string { 101 return ca.SubKind 102 } 103 104 // SetSubKind sets resource subkind 105 func (ca *CertAuthorityV2) SetSubKind(s string) { 106 ca.SubKind = s 107 } 108 109 // Clone returns a copy of the cert authority object. 110 func (ca *CertAuthorityV2) Clone() CertAuthority { 111 return utils.CloneProtoMsg(ca) 112 } 113 114 // GetRotation returns rotation state. 115 func (ca *CertAuthorityV2) GetRotation() Rotation { 116 if ca.Spec.Rotation == nil { 117 return Rotation{} 118 } 119 return *ca.Spec.Rotation 120 } 121 122 // SetRotation sets rotation state. 123 func (ca *CertAuthorityV2) SetRotation(r Rotation) { 124 ca.Spec.Rotation = &r 125 } 126 127 // SetMetadata sets object metadata 128 func (ca *CertAuthorityV2) SetMetadata(meta Metadata) { 129 ca.Metadata = meta 130 } 131 132 // GetMetadata returns object metadata 133 func (ca *CertAuthorityV2) GetMetadata() Metadata { 134 return ca.Metadata 135 } 136 137 // SetExpiry sets expiry time for the object 138 func (ca *CertAuthorityV2) SetExpiry(expires time.Time) { 139 ca.Metadata.SetExpiry(expires) 140 } 141 142 // Expiry returns object expiry setting 143 func (ca *CertAuthorityV2) Expiry() time.Time { 144 return ca.Metadata.Expiry() 145 } 146 147 // GetResourceID returns resource ID 148 func (ca *CertAuthorityV2) GetResourceID() int64 { 149 return ca.Metadata.ID 150 } 151 152 // SetResourceID sets resource ID 153 func (ca *CertAuthorityV2) SetResourceID(id int64) { 154 ca.Metadata.ID = id 155 } 156 157 // GetRevision returns the revision 158 func (ca *CertAuthorityV2) GetRevision() string { 159 return ca.Metadata.GetRevision() 160 } 161 162 // SetRevision sets the revision 163 func (ca *CertAuthorityV2) SetRevision(rev string) { 164 ca.Metadata.SetRevision(rev) 165 } 166 167 // WithoutSecrets returns an instance of resource without secrets. 168 func (ca *CertAuthorityV2) WithoutSecrets() Resource { 169 ca2 := ca.Clone().(*CertAuthorityV2) 170 RemoveCASecrets(ca2) 171 return ca2 172 } 173 174 // RemoveCASecrets removes private (SSH, TLS, and JWT) keys from certificate 175 // authority. 176 func RemoveCASecrets(ca CertAuthority) { 177 cav2, ok := ca.(*CertAuthorityV2) 178 if !ok { 179 return 180 } 181 cav2.Spec.ActiveKeys = cav2.Spec.ActiveKeys.WithoutSecrets() 182 cav2.Spec.AdditionalTrustedKeys = cav2.Spec.AdditionalTrustedKeys.WithoutSecrets() 183 } 184 185 // String returns human readable version of the CertAuthorityV2. 186 func (ca *CertAuthorityV2) String() string { 187 return fmt.Sprintf("CA(name=%v, type=%v)", ca.GetClusterName(), ca.GetType()) 188 } 189 190 // AddRole adds a role to ca role list 191 func (ca *CertAuthorityV2) AddRole(name string) { 192 for _, r := range ca.Spec.Roles { 193 if r == name { 194 return 195 } 196 } 197 ca.Spec.Roles = append(ca.Spec.Roles, name) 198 } 199 200 // GetID returns certificate authority ID - 201 // combined type and name 202 func (ca *CertAuthorityV2) GetID() CertAuthID { 203 return CertAuthID{Type: ca.Spec.Type, DomainName: ca.Metadata.Name} 204 } 205 206 // SetName sets cert authority name 207 func (ca *CertAuthorityV2) SetName(name string) { 208 ca.Metadata.SetName(name) 209 } 210 211 // GetName returns cert authority name 212 func (ca *CertAuthorityV2) GetName() string { 213 return ca.Metadata.Name 214 } 215 216 // GetType returns user or host certificate authority 217 func (ca *CertAuthorityV2) GetType() CertAuthType { 218 return ca.Spec.Type 219 } 220 221 // GetClusterName returns cluster name this cert authority 222 // is associated with. 223 func (ca *CertAuthorityV2) GetClusterName() string { 224 return ca.Spec.ClusterName 225 } 226 227 // GetRoles returns a list of roles assumed by users signed by this CA 228 func (ca *CertAuthorityV2) GetRoles() []string { 229 return ca.Spec.Roles 230 } 231 232 // SetRoles sets assigned roles for this certificate authority 233 func (ca *CertAuthorityV2) SetRoles(roles []string) { 234 ca.Spec.Roles = roles 235 } 236 237 // CombinedMapping is used to specify combined mapping from legacy property Roles 238 // and new property RoleMap 239 func (ca *CertAuthorityV2) CombinedMapping() RoleMap { 240 if len(ca.Spec.Roles) != 0 { 241 return RoleMap([]RoleMapping{{Remote: Wildcard, Local: ca.Spec.Roles}}) 242 } 243 return RoleMap(ca.Spec.RoleMap) 244 } 245 246 // GetRoleMap returns role map property 247 func (ca *CertAuthorityV2) GetRoleMap() RoleMap { 248 return RoleMap(ca.Spec.RoleMap) 249 } 250 251 // SetRoleMap sets role map 252 func (ca *CertAuthorityV2) SetRoleMap(m RoleMap) { 253 ca.Spec.RoleMap = []RoleMapping(m) 254 } 255 256 // ID returns id (consisting of domain name and type) that 257 // identifies the authority this key belongs to 258 func (ca *CertAuthorityV2) ID() *CertAuthID { 259 return &CertAuthID{DomainName: ca.Spec.ClusterName, Type: ca.Spec.Type} 260 } 261 262 func (ca *CertAuthorityV2) GetActiveKeys() CAKeySet { 263 return ca.Spec.ActiveKeys 264 } 265 266 func (ca *CertAuthorityV2) SetActiveKeys(ks CAKeySet) error { 267 if err := ks.CheckAndSetDefaults(); err != nil { 268 return trace.Wrap(err) 269 } 270 ca.Spec.ActiveKeys = ks 271 return nil 272 } 273 274 func (ca *CertAuthorityV2) GetAdditionalTrustedKeys() CAKeySet { 275 return ca.Spec.AdditionalTrustedKeys 276 } 277 278 func (ca *CertAuthorityV2) SetAdditionalTrustedKeys(ks CAKeySet) error { 279 if err := ks.CheckAndSetDefaults(); err != nil { 280 return trace.Wrap(err) 281 } 282 ca.Spec.AdditionalTrustedKeys = ks 283 return nil 284 } 285 286 func (ca *CertAuthorityV2) GetTrustedSSHKeyPairs() []*SSHKeyPair { 287 var kps []*SSHKeyPair 288 for _, k := range ca.GetActiveKeys().SSH { 289 kps = append(kps, k.Clone()) 290 } 291 for _, k := range ca.GetAdditionalTrustedKeys().SSH { 292 kps = append(kps, k.Clone()) 293 } 294 return kps 295 } 296 297 func (ca *CertAuthorityV2) GetTrustedTLSKeyPairs() []*TLSKeyPair { 298 var kps []*TLSKeyPair 299 for _, k := range ca.GetActiveKeys().TLS { 300 kps = append(kps, k.Clone()) 301 } 302 for _, k := range ca.GetAdditionalTrustedKeys().TLS { 303 kps = append(kps, k.Clone()) 304 } 305 return kps 306 } 307 308 func (ca *CertAuthorityV2) GetTrustedJWTKeyPairs() []*JWTKeyPair { 309 var kps []*JWTKeyPair 310 for _, k := range ca.GetActiveKeys().JWT { 311 kps = append(kps, k.Clone()) 312 } 313 for _, k := range ca.GetAdditionalTrustedKeys().JWT { 314 kps = append(kps, k.Clone()) 315 } 316 return kps 317 } 318 319 // setStaticFields sets static resource header and metadata fields. 320 func (ca *CertAuthorityV2) setStaticFields() { 321 ca.Kind = KindCertAuthority 322 ca.Version = V2 323 // ca.Metadata.Name and ca.Spec.ClusterName should always be equal. 324 if ca.Metadata.Name == "" { 325 ca.Metadata.Name = ca.Spec.ClusterName 326 } else { 327 ca.Spec.ClusterName = ca.Metadata.Name 328 } 329 } 330 331 // CheckAndSetDefaults checks and set default values for any missing fields. 332 func (ca *CertAuthorityV2) CheckAndSetDefaults() error { 333 ca.setStaticFields() 334 if err := ca.Metadata.CheckAndSetDefaults(); err != nil { 335 return trace.Wrap(err) 336 } 337 338 if ca.SubKind == "" { 339 ca.SubKind = string(ca.Spec.Type) 340 } 341 342 if err := ca.ID().Check(); err != nil { 343 return trace.Wrap(err) 344 } 345 346 if err := ca.Spec.ActiveKeys.CheckAndSetDefaults(); err != nil { 347 return trace.Wrap(err) 348 } 349 if err := ca.Spec.AdditionalTrustedKeys.CheckAndSetDefaults(); err != nil { 350 return trace.Wrap(err) 351 } 352 if err := ca.Spec.Rotation.CheckAndSetDefaults(); err != nil { 353 return trace.Wrap(err) 354 } 355 356 if err := ca.GetType().Check(); err != nil { 357 return trace.Wrap(err) 358 } 359 360 return nil 361 } 362 363 // AllKeyTypes returns the set of all different key types in the CA. 364 func (ca *CertAuthorityV2) AllKeyTypes() []string { 365 keyTypes := make(map[PrivateKeyType]struct{}) 366 for _, keySet := range []CAKeySet{ca.Spec.ActiveKeys, ca.Spec.AdditionalTrustedKeys} { 367 for _, keyPair := range keySet.SSH { 368 keyTypes[keyPair.PrivateKeyType] = struct{}{} 369 } 370 for _, keyPair := range keySet.TLS { 371 keyTypes[keyPair.KeyType] = struct{}{} 372 } 373 for _, keyPair := range keySet.JWT { 374 keyTypes[keyPair.PrivateKeyType] = struct{}{} 375 } 376 } 377 var strs []string 378 for k := range keyTypes { 379 strs = append(strs, k.String()) 380 } 381 return strs 382 } 383 384 const ( 385 // RotationStateStandby is initial status of the rotation - 386 // nothing is being rotated. 387 RotationStateStandby = "standby" 388 // RotationStateInProgress - that rotation is in progress. 389 RotationStateInProgress = "in_progress" 390 // RotationPhaseStandby is the initial phase of the rotation 391 // it means no operations have started. 392 RotationPhaseStandby = "standby" 393 // RotationPhaseInit = is a phase of the rotation 394 // when new certificate authority is issued, but not used 395 // It is necessary for remote trusted clusters to fetch the 396 // new certificate authority, otherwise the new clients 397 // will reject it 398 RotationPhaseInit = "init" 399 // RotationPhaseUpdateClients is a phase of the rotation 400 // when client credentials will have to be updated and reloaded 401 // but servers will use and respond with old credentials 402 // because clients have no idea about new credentials at first. 403 RotationPhaseUpdateClients = "update_clients" 404 // RotationPhaseUpdateServers is a phase of the rotation 405 // when servers will have to reload and should start serving 406 // TLS and SSH certificates signed by new CA. 407 RotationPhaseUpdateServers = "update_servers" 408 // RotationPhaseRollback means that rotation is rolling 409 // back to the old certificate authority. 410 RotationPhaseRollback = "rollback" 411 // RotationModeManual is a manual rotation mode when all phases 412 // are set by the operator. 413 RotationModeManual = "manual" 414 // RotationModeAuto is set to go through all phases by the schedule. 415 RotationModeAuto = "auto" 416 ) 417 418 // RotatePhases lists all supported rotation phases 419 var RotatePhases = []string{ 420 RotationPhaseInit, 421 RotationPhaseStandby, 422 RotationPhaseUpdateClients, 423 RotationPhaseUpdateServers, 424 RotationPhaseRollback, 425 } 426 427 // Matches returns true if this state rotation matches 428 // external rotation state, phase and rotation ID should match, 429 // notice that matches does not behave like Equals because it does not require 430 // all fields to be the same. 431 func (r *Rotation) Matches(rotation Rotation) bool { 432 return r.CurrentID == rotation.CurrentID && r.State == rotation.State && r.Phase == rotation.Phase 433 } 434 435 // IsZero checks if this is the zero value of Rotation. Works on nil and non-nil rotation 436 // values. 437 func (r *Rotation) IsZero() bool { 438 if r == nil { 439 return true 440 } 441 442 return r.Matches(Rotation{}) 443 } 444 445 // LastRotatedDescription returns human friendly description. 446 func (r *Rotation) LastRotatedDescription() string { 447 if r.LastRotated.IsZero() { 448 return "never updated" 449 } 450 return fmt.Sprintf("last rotated %v", r.LastRotated.Format(constants.HumanDateFormatSeconds)) 451 } 452 453 // PhaseDescription returns human friendly description of a current rotation phase. 454 func (r *Rotation) PhaseDescription() string { 455 switch r.Phase { 456 case RotationPhaseInit: 457 return "initialized" 458 case RotationPhaseStandby, "": 459 return "on standby" 460 case RotationPhaseUpdateClients: 461 return "rotating clients" 462 case RotationPhaseUpdateServers: 463 return "rotating servers" 464 case RotationPhaseRollback: 465 return "rolling back" 466 default: 467 return fmt.Sprintf("unknown phase: %q", r.Phase) 468 } 469 } 470 471 // String returns user friendly information about certificate authority. 472 func (r *Rotation) String() string { 473 switch r.State { 474 case "", RotationStateStandby: 475 if r.LastRotated.IsZero() { 476 return "never updated" 477 } 478 return fmt.Sprintf("rotated %v", r.LastRotated.Format(constants.HumanDateFormatSeconds)) 479 case RotationStateInProgress: 480 return fmt.Sprintf("%v (mode: %v, started: %v, ending: %v)", 481 r.PhaseDescription(), 482 r.Mode, 483 r.Started.Format(constants.HumanDateFormatSeconds), 484 r.Started.Add(r.GracePeriod.Duration()).Format(constants.HumanDateFormatSeconds), 485 ) 486 default: 487 return "unknown" 488 } 489 } 490 491 // CheckAndSetDefaults checks and sets default rotation parameters. 492 func (r *Rotation) CheckAndSetDefaults() error { 493 if r == nil { 494 return nil 495 } 496 switch r.Phase { 497 case "", RotationPhaseInit, RotationPhaseStandby, RotationPhaseRollback, RotationPhaseUpdateClients, RotationPhaseUpdateServers: 498 default: 499 return trace.BadParameter("unsupported phase: %q", r.Phase) 500 } 501 switch r.Mode { 502 case "", RotationModeAuto, RotationModeManual: 503 default: 504 return trace.BadParameter("unsupported mode: %q", r.Mode) 505 } 506 switch r.State { 507 case "": 508 r.State = RotationStateStandby 509 case RotationStateStandby: 510 case RotationStateInProgress: 511 if r.CurrentID == "" { 512 return trace.BadParameter("set 'current_id' parameter for in progress rotation") 513 } 514 if r.Started.IsZero() { 515 return trace.BadParameter("set 'started' parameter for in progress rotation") 516 } 517 default: 518 return trace.BadParameter( 519 "unsupported rotation 'state': %q, supported states are: %q, %q", 520 r.State, RotationStateStandby, RotationStateInProgress) 521 } 522 return nil 523 } 524 525 // GenerateSchedule generates schedule based on the time period, using 526 // even time periods between rotation phases. 527 func GenerateSchedule(now time.Time, gracePeriod time.Duration) (*RotationSchedule, error) { 528 if gracePeriod <= 0 { 529 return nil, trace.BadParameter("invalid grace period %q, provide value > 0", gracePeriod) 530 } 531 return &RotationSchedule{ 532 UpdateClients: now.UTC().Add(gracePeriod / 3), 533 UpdateServers: now.UTC().Add((gracePeriod * 2) / 3), 534 Standby: now.UTC().Add(gracePeriod), 535 }, nil 536 } 537 538 // CheckAndSetDefaults checks and sets default values of the rotation schedule. 539 func (s *RotationSchedule) CheckAndSetDefaults(now time.Time) error { 540 if s.UpdateServers.IsZero() { 541 return trace.BadParameter("phase %q has no time switch scheduled", RotationPhaseUpdateServers) 542 } 543 if s.Standby.IsZero() { 544 return trace.BadParameter("phase %q has no time switch scheduled", RotationPhaseStandby) 545 } 546 if s.Standby.Before(s.UpdateServers) { 547 return trace.BadParameter("phase %q can not be scheduled before %q", RotationPhaseStandby, RotationPhaseUpdateServers) 548 } 549 if s.UpdateServers.Before(now) { 550 return trace.BadParameter("phase %q can not be scheduled in the past", RotationPhaseUpdateServers) 551 } 552 if s.Standby.Before(now) { 553 return trace.BadParameter("phase %q can not be scheduled in the past", RotationPhaseStandby) 554 } 555 return nil 556 } 557 558 // CertRoles defines certificate roles 559 type CertRoles struct { 560 // Version is current version of the roles 561 Version string `json:"version"` 562 // Roles is a list of roles 563 Roles []string `json:"roles"` 564 } 565 566 // Clone returns a deep copy of TLSKeyPair that can be mutated without 567 // modifying the original. 568 func (k *TLSKeyPair) Clone() *TLSKeyPair { 569 return &TLSKeyPair{ 570 KeyType: k.KeyType, 571 Key: slices.Clone(k.Key), 572 Cert: slices.Clone(k.Cert), 573 } 574 } 575 576 // Clone returns a deep copy of JWTKeyPair that can be mutated without 577 // modifying the original. 578 func (k *JWTKeyPair) Clone() *JWTKeyPair { 579 return &JWTKeyPair{ 580 PrivateKeyType: k.PrivateKeyType, 581 PrivateKey: slices.Clone(k.PrivateKey), 582 PublicKey: slices.Clone(k.PublicKey), 583 } 584 } 585 586 // Clone returns a deep copy of SSHKeyPair that can be mutated without 587 // modifying the original. 588 func (k *SSHKeyPair) Clone() *SSHKeyPair { 589 return &SSHKeyPair{ 590 PrivateKeyType: k.PrivateKeyType, 591 PrivateKey: slices.Clone(k.PrivateKey), 592 PublicKey: slices.Clone(k.PublicKey), 593 } 594 } 595 596 // Clone returns a deep copy of CAKeySet that can be mutated without modifying 597 // the original. 598 func (ks CAKeySet) Clone() CAKeySet { 599 var out CAKeySet 600 if len(ks.TLS) > 0 { 601 out.TLS = make([]*TLSKeyPair, 0, len(ks.TLS)) 602 for _, k := range ks.TLS { 603 out.TLS = append(out.TLS, k.Clone()) 604 } 605 } 606 if len(ks.JWT) > 0 { 607 out.JWT = make([]*JWTKeyPair, 0, len(ks.JWT)) 608 for _, k := range ks.JWT { 609 out.JWT = append(out.JWT, k.Clone()) 610 } 611 } 612 if len(ks.SSH) > 0 { 613 out.SSH = make([]*SSHKeyPair, 0, len(ks.SSH)) 614 for _, k := range ks.SSH { 615 out.SSH = append(out.SSH, k.Clone()) 616 } 617 } 618 return out 619 } 620 621 // WithoutSecrets returns a deep copy of CAKeySet with all secret fields 622 // (private keys) removed. 623 func (ks CAKeySet) WithoutSecrets() CAKeySet { 624 ks = ks.Clone() 625 for _, k := range ks.SSH { 626 k.PrivateKey = nil 627 } 628 for _, k := range ks.TLS { 629 k.Key = nil 630 } 631 for _, k := range ks.JWT { 632 k.PrivateKey = nil 633 } 634 return ks 635 } 636 637 // CheckAndSetDefaults validates CAKeySet and sets defaults on any empty fields 638 // as needed. 639 func (ks CAKeySet) CheckAndSetDefaults() error { 640 for _, kp := range ks.SSH { 641 if err := kp.CheckAndSetDefaults(); err != nil { 642 return trace.Wrap(err) 643 } 644 } 645 for _, kp := range ks.TLS { 646 if err := kp.CheckAndSetDefaults(); err != nil { 647 return trace.Wrap(err) 648 } 649 } 650 for _, kp := range ks.JWT { 651 if err := kp.CheckAndSetDefaults(); err != nil { 652 return trace.Wrap(err) 653 } 654 } 655 return nil 656 } 657 658 // Empty returns true if the CAKeySet holds no keys 659 func (ks *CAKeySet) Empty() bool { 660 return len(ks.SSH) == 0 && len(ks.TLS) == 0 && len(ks.JWT) == 0 661 } 662 663 // CheckAndSetDefaults validates SSHKeyPair and sets defaults on any empty 664 // fields as needed. 665 func (k *SSHKeyPair) CheckAndSetDefaults() error { 666 if len(k.PublicKey) == 0 { 667 return trace.BadParameter("SSH key pair missing public key") 668 } 669 return nil 670 } 671 672 // CheckAndSetDefaults validates TLSKeyPair and sets defaults on any empty 673 // fields as needed. 674 func (k *TLSKeyPair) CheckAndSetDefaults() error { 675 if len(k.Cert) == 0 { 676 return trace.BadParameter("TLS key pair missing certificate") 677 } 678 return nil 679 } 680 681 // CheckAndSetDefaults validates JWTKeyPair and sets defaults on any empty 682 // fields as needed. 683 func (k *JWTKeyPair) CheckAndSetDefaults() error { 684 if len(k.PublicKey) == 0 { 685 return trace.BadParameter("JWT key pair missing public key") 686 } 687 return nil 688 } 689 690 type CertAuthorityFilter map[CertAuthType]string 691 692 func (f CertAuthorityFilter) IsEmpty() bool { 693 return len(f) == 0 694 } 695 696 // Match checks if a given CA matches this filter. 697 func (f CertAuthorityFilter) Match(ca CertAuthority) bool { 698 if len(f) == 0 { 699 return true 700 } 701 702 return f[ca.GetType()] == Wildcard || f[ca.GetType()] == ca.GetClusterName() 703 } 704 705 // IntoMap makes this filter into a map for use as the Filter in a WatchKind. 706 func (f CertAuthorityFilter) IntoMap() map[string]string { 707 if len(f) == 0 { 708 return nil 709 } 710 711 m := make(map[string]string, len(f)) 712 for caType, name := range f { 713 m[string(caType)] = name 714 } 715 return m 716 } 717 718 // FromMap converts the provided map into this filter. 719 func (f *CertAuthorityFilter) FromMap(m map[string]string) { 720 if len(m) == 0 { 721 *f = nil 722 return 723 } 724 725 *f = make(CertAuthorityFilter, len(m)) 726 // there's not a lot of value in rejecting unknown values from the filter 727 for key, val := range m { 728 (*f)[CertAuthType(key)] = val 729 } 730 } 731 732 // Contains checks if the CA filter contains another CA filter as a subset. 733 // Unlike other filters, a CA filter's scope becomes more broad as map keys 734 // are added to it. 735 // Therefore, to check if kind's filter contains the subset's filter, 736 // we should check that the subset's keys are all present in kind and as 737 // narrow or narrower. 738 // A special case is when kind's filter is either empty or specifies all 739 // authorities, in which case it is as broad as possible and subset's filter 740 // is always contained within it. 741 func (f CertAuthorityFilter) Contains(other CertAuthorityFilter) bool { 742 if len(f) == 0 { 743 // f has no filter, which is as broad as possible. 744 return true 745 } 746 747 if len(other) == 0 { 748 // f has a filter, but other does not. 749 // treat this as "contained" if f's filter is for all authorities. 750 for _, caType := range CertAuthTypes { 751 clusterName, ok := f[caType] 752 if !ok || clusterName != Wildcard { 753 return false 754 } 755 } 756 return true 757 } 758 759 for k, v := range other { 760 v2, ok := f[k] 761 if !ok || (v2 != Wildcard && v2 != v) { 762 return false 763 } 764 } 765 return true 766 }