github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/saml.go (about)

     1  /*
     2  Copyright 2020-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  	"slices"
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/gravitational/trace"
    25  	"golang.org/x/crypto/ssh"
    26  
    27  	"github.com/gravitational/teleport/api/constants"
    28  	"github.com/gravitational/teleport/api/defaults"
    29  	"github.com/gravitational/teleport/api/utils"
    30  )
    31  
    32  // SAMLConnector specifies configuration for SAML 2.0 identity providers
    33  type SAMLConnector interface {
    34  	// ResourceWithSecrets provides common methods for objects
    35  	ResourceWithSecrets
    36  	ResourceWithOrigin
    37  
    38  	// SetMetadata sets the connector metadata
    39  	SetMetadata(Metadata)
    40  	// GetDisplay returns display - friendly name for this provider.
    41  	GetDisplay() string
    42  	// SetDisplay sets friendly name for this provider.
    43  	SetDisplay(string)
    44  	// GetAttributesToRoles returns attributes to roles mapping
    45  	GetAttributesToRoles() []AttributeMapping
    46  	// SetAttributesToRoles sets attributes to roles mapping
    47  	SetAttributesToRoles(mapping []AttributeMapping)
    48  	// GetAttributes returns list of attributes expected by mappings
    49  	GetAttributes() []string
    50  	// GetTraitMappings converts gets all attribute mappings in the
    51  	// generic trait mapping format.
    52  	GetTraitMappings() TraitMappingSet
    53  	// SetIssuer sets issuer
    54  	SetIssuer(issuer string)
    55  	// GetIssuer returns issuer
    56  	GetIssuer() string
    57  	// GetSigningKeyPair returns signing key pair
    58  	GetSigningKeyPair() *AsymmetricKeyPair
    59  	// GetSigningKeyPair sets signing key pair
    60  	SetSigningKeyPair(k *AsymmetricKeyPair)
    61  	// GetSSO returns SSO service
    62  	GetSSO() string
    63  	// SetSSO sets SSO service
    64  	SetSSO(string)
    65  	// GetEntityDescriptor returns XML entity descriptor of the service
    66  	GetEntityDescriptor() string
    67  	// SetEntityDescriptor sets entity descriptor of the service
    68  	SetEntityDescriptor(v string)
    69  	// GetEntityDescriptorURL returns the URL to obtain the entity descriptor.
    70  	GetEntityDescriptorURL() string
    71  	// SetEntityDescriptorURL sets the entity descriptor url.
    72  	SetEntityDescriptorURL(string)
    73  	// GetCert returns identity provider checking x509 certificate
    74  	GetCert() string
    75  	// SetCert sets identity provider checking certificate
    76  	SetCert(string)
    77  	// GetServiceProviderIssuer returns service provider issuer
    78  	GetServiceProviderIssuer() string
    79  	// SetServiceProviderIssuer sets service provider issuer
    80  	SetServiceProviderIssuer(v string)
    81  	// GetAudience returns audience
    82  	GetAudience() string
    83  	// SetAudience sets audience
    84  	SetAudience(v string)
    85  	// GetAssertionConsumerService returns assertion consumer service URL
    86  	GetAssertionConsumerService() string
    87  	// SetAssertionConsumerService sets assertion consumer service URL
    88  	SetAssertionConsumerService(v string)
    89  	// GetProvider returns the identity provider.
    90  	GetProvider() string
    91  	// SetProvider sets the identity provider.
    92  	SetProvider(string)
    93  	// GetEncryptionKeyPair returns the key pair for SAML assertions.
    94  	GetEncryptionKeyPair() *AsymmetricKeyPair
    95  	// SetEncryptionKeyPair sets the key pair for SAML assertions.
    96  	SetEncryptionKeyPair(k *AsymmetricKeyPair)
    97  	// GetAllowIDPInitiated returns whether the identity provider can initiate a login or not.
    98  	GetAllowIDPInitiated() bool
    99  	// SetAllowIDPInitiated sets whether the identity provider can initiate a login or not.
   100  	SetAllowIDPInitiated(bool)
   101  }
   102  
   103  // NewSAMLConnector returns a new SAMLConnector based off a name and SAMLConnectorSpecV2.
   104  func NewSAMLConnector(name string, spec SAMLConnectorSpecV2) (SAMLConnector, error) {
   105  	o := &SAMLConnectorV2{
   106  		Metadata: Metadata{
   107  			Name: name,
   108  		},
   109  		Spec: spec,
   110  	}
   111  	if err := o.CheckAndSetDefaults(); err != nil {
   112  		return nil, trace.Wrap(err)
   113  	}
   114  	return o, nil
   115  }
   116  
   117  // GetVersion returns resource version
   118  func (o *SAMLConnectorV2) GetVersion() string {
   119  	return o.Version
   120  }
   121  
   122  // GetKind returns resource kind
   123  func (o *SAMLConnectorV2) GetKind() string {
   124  	return o.Kind
   125  }
   126  
   127  // GetSubKind returns resource sub kind
   128  func (o *SAMLConnectorV2) GetSubKind() string {
   129  	return o.SubKind
   130  }
   131  
   132  // SetSubKind sets resource subkind
   133  func (o *SAMLConnectorV2) SetSubKind(sk string) {
   134  	o.SubKind = sk
   135  }
   136  
   137  // GetResourceID returns resource ID
   138  func (o *SAMLConnectorV2) GetResourceID() int64 {
   139  	return o.Metadata.ID
   140  }
   141  
   142  // SetResourceID sets resource ID
   143  func (o *SAMLConnectorV2) SetResourceID(id int64) {
   144  	o.Metadata.ID = id
   145  }
   146  
   147  // GetRevision returns the revision
   148  func (o *SAMLConnectorV2) GetRevision() string {
   149  	return o.Metadata.GetRevision()
   150  }
   151  
   152  // SetRevision sets the revision
   153  func (o *SAMLConnectorV2) SetRevision(rev string) {
   154  	o.Metadata.SetRevision(rev)
   155  }
   156  
   157  // WithoutSecrets returns an instance of resource without secrets.
   158  func (o *SAMLConnectorV2) WithoutSecrets() Resource {
   159  	k1 := o.GetSigningKeyPair()
   160  	k2 := o.GetEncryptionKeyPair()
   161  	o2 := *o
   162  	if k1 != nil {
   163  		q1 := *k1
   164  		q1.PrivateKey = ""
   165  		o2.SetSigningKeyPair(&q1)
   166  	}
   167  	if k2 != nil {
   168  		q2 := *k2
   169  		q2.PrivateKey = ""
   170  		o2.SetEncryptionKeyPair(&q2)
   171  	}
   172  	return &o2
   173  }
   174  
   175  // GetServiceProviderIssuer returns service provider issuer
   176  func (o *SAMLConnectorV2) GetServiceProviderIssuer() string {
   177  	return o.Spec.ServiceProviderIssuer
   178  }
   179  
   180  // SetServiceProviderIssuer sets service provider issuer
   181  func (o *SAMLConnectorV2) SetServiceProviderIssuer(v string) {
   182  	o.Spec.ServiceProviderIssuer = v
   183  }
   184  
   185  // GetAudience returns audience
   186  func (o *SAMLConnectorV2) GetAudience() string {
   187  	return o.Spec.Audience
   188  }
   189  
   190  // SetAudience sets audience
   191  func (o *SAMLConnectorV2) SetAudience(v string) {
   192  	o.Spec.Audience = v
   193  }
   194  
   195  // GetCert returns identity provider checking x509 certificate
   196  func (o *SAMLConnectorV2) GetCert() string {
   197  	return o.Spec.Cert
   198  }
   199  
   200  // SetCert sets identity provider checking certificate
   201  func (o *SAMLConnectorV2) SetCert(cert string) {
   202  	o.Spec.Cert = cert
   203  }
   204  
   205  // GetSSO returns SSO service
   206  func (o *SAMLConnectorV2) GetSSO() string {
   207  	return o.Spec.SSO
   208  }
   209  
   210  // SetSSO sets SSO service
   211  func (o *SAMLConnectorV2) SetSSO(sso string) {
   212  	o.Spec.SSO = sso
   213  }
   214  
   215  // GetEntityDescriptor returns XML entity descriptor of the service
   216  func (o *SAMLConnectorV2) GetEntityDescriptor() string {
   217  	return o.Spec.EntityDescriptor
   218  }
   219  
   220  // SetEntityDescriptor sets entity descriptor of the service
   221  func (o *SAMLConnectorV2) SetEntityDescriptor(v string) {
   222  	o.Spec.EntityDescriptor = v
   223  }
   224  
   225  // GetEntityDescriptorURL returns the URL to obtain the entity descriptor.
   226  func (o *SAMLConnectorV2) GetEntityDescriptorURL() string {
   227  	return o.Spec.EntityDescriptorURL
   228  }
   229  
   230  // SetEntityDescriptorURL sets the entity descriptor url.
   231  func (o *SAMLConnectorV2) SetEntityDescriptorURL(v string) {
   232  	o.Spec.EntityDescriptorURL = v
   233  }
   234  
   235  // GetAssertionConsumerService returns assertion consumer service URL
   236  func (o *SAMLConnectorV2) GetAssertionConsumerService() string {
   237  	return o.Spec.AssertionConsumerService
   238  }
   239  
   240  // SetAssertionConsumerService sets assertion consumer service URL
   241  func (o *SAMLConnectorV2) SetAssertionConsumerService(v string) {
   242  	o.Spec.AssertionConsumerService = v
   243  }
   244  
   245  // SetDisplay sets friendly name for this provider.
   246  func (o *SAMLConnectorV2) SetDisplay(display string) {
   247  	o.Spec.Display = display
   248  }
   249  
   250  // GetMetadata returns object metadata
   251  func (o *SAMLConnectorV2) GetMetadata() Metadata {
   252  	return o.Metadata
   253  }
   254  
   255  // SetMetadata sets object metadata
   256  func (o *SAMLConnectorV2) SetMetadata(m Metadata) {
   257  	o.Metadata = m
   258  }
   259  
   260  // Origin returns the origin value of the resource.
   261  func (o *SAMLConnectorV2) Origin() string {
   262  	return o.Metadata.Origin()
   263  }
   264  
   265  // SetOrigin sets the origin value of the resource.
   266  func (o *SAMLConnectorV2) SetOrigin(origin string) {
   267  	o.Metadata.SetOrigin(origin)
   268  }
   269  
   270  // SetExpiry sets expiry time for the object
   271  func (o *SAMLConnectorV2) SetExpiry(expires time.Time) {
   272  	o.Metadata.SetExpiry(expires)
   273  }
   274  
   275  // Expiry returns object expiry setting
   276  func (o *SAMLConnectorV2) Expiry() time.Time {
   277  	return o.Metadata.Expiry()
   278  }
   279  
   280  // GetName returns the name of the connector
   281  func (o *SAMLConnectorV2) GetName() string {
   282  	return o.Metadata.GetName()
   283  }
   284  
   285  // SetName sets client secret to some value
   286  func (o *SAMLConnectorV2) SetName(name string) {
   287  	o.Metadata.SetName(name)
   288  }
   289  
   290  // SetIssuer sets issuer
   291  func (o *SAMLConnectorV2) SetIssuer(issuer string) {
   292  	o.Spec.Issuer = issuer
   293  }
   294  
   295  // GetIssuer returns issuer
   296  func (o *SAMLConnectorV2) GetIssuer() string {
   297  	return o.Spec.Issuer
   298  }
   299  
   300  // GetDisplay returns the friendly name for this provider.
   301  func (o *SAMLConnectorV2) GetDisplay() string {
   302  	if o.Spec.Display != "" {
   303  		return o.Spec.Display
   304  	}
   305  	return o.GetName()
   306  }
   307  
   308  // GetAttributesToRoles returns attributes to roles mapping
   309  func (o *SAMLConnectorV2) GetAttributesToRoles() []AttributeMapping {
   310  	return o.Spec.AttributesToRoles
   311  }
   312  
   313  // SetAttributesToRoles sets attributes to roles mapping
   314  func (o *SAMLConnectorV2) SetAttributesToRoles(mapping []AttributeMapping) {
   315  	o.Spec.AttributesToRoles = mapping
   316  }
   317  
   318  // SetProvider sets the identity provider.
   319  func (o *SAMLConnectorV2) SetProvider(identityProvider string) {
   320  	o.Spec.Provider = identityProvider
   321  }
   322  
   323  // GetProvider returns the identity provider.
   324  func (o *SAMLConnectorV2) GetProvider() string {
   325  	return o.Spec.Provider
   326  }
   327  
   328  // GetAttributes returns list of attributes expected by mappings
   329  func (o *SAMLConnectorV2) GetAttributes() []string {
   330  	var out []string
   331  	for _, mapping := range o.Spec.AttributesToRoles {
   332  		out = append(out, mapping.Name)
   333  	}
   334  	return utils.Deduplicate(out)
   335  }
   336  
   337  // GetTraitMappings returns the SAMLConnector's TraitMappingSet
   338  func (o *SAMLConnectorV2) GetTraitMappings() TraitMappingSet {
   339  	tms := make([]TraitMapping, 0, len(o.Spec.AttributesToRoles))
   340  	for _, mapping := range o.Spec.AttributesToRoles {
   341  		tms = append(tms, TraitMapping{
   342  			Trait: mapping.Name,
   343  			Value: mapping.Value,
   344  			Roles: mapping.Roles,
   345  		})
   346  	}
   347  	return TraitMappingSet(tms)
   348  }
   349  
   350  // GetSigningKeyPair returns signing key pair
   351  func (o *SAMLConnectorV2) GetSigningKeyPair() *AsymmetricKeyPair {
   352  	return o.Spec.SigningKeyPair
   353  }
   354  
   355  // SetSigningKeyPair sets signing key pair
   356  func (o *SAMLConnectorV2) SetSigningKeyPair(k *AsymmetricKeyPair) {
   357  	o.Spec.SigningKeyPair = k
   358  }
   359  
   360  // GetEncryptionKeyPair returns the key pair for SAML assertions.
   361  func (o *SAMLConnectorV2) GetEncryptionKeyPair() *AsymmetricKeyPair {
   362  	return o.Spec.EncryptionKeyPair
   363  }
   364  
   365  // SetEncryptionKeyPair sets the key pair for SAML assertions.
   366  func (o *SAMLConnectorV2) SetEncryptionKeyPair(k *AsymmetricKeyPair) {
   367  	o.Spec.EncryptionKeyPair = k
   368  }
   369  
   370  // GetAllowIDPInitiated returns whether the identity provider can initiate a login or not.
   371  func (o *SAMLConnectorV2) GetAllowIDPInitiated() bool {
   372  	return o.Spec.AllowIDPInitiated
   373  }
   374  
   375  // SetAllowIDPInitiated sets whether the identity provider can initiate a login or not.
   376  func (o *SAMLConnectorV2) SetAllowIDPInitiated(allow bool) {
   377  	o.Spec.AllowIDPInitiated = allow
   378  }
   379  
   380  // setStaticFields sets static resource header and metadata fields.
   381  func (o *SAMLConnectorV2) setStaticFields() {
   382  	o.Kind = KindSAMLConnector
   383  	o.Version = V2
   384  }
   385  
   386  // CheckAndSetDefaults checks and sets default values
   387  func (o *SAMLConnectorV2) CheckAndSetDefaults() error {
   388  	o.setStaticFields()
   389  	if err := o.Metadata.CheckAndSetDefaults(); err != nil {
   390  		return trace.Wrap(err)
   391  	}
   392  
   393  	if name := o.Metadata.Name; slices.Contains(constants.SystemConnectors, name) {
   394  		return trace.BadParameter("ID: invalid connector name, %v is a reserved name", name)
   395  	}
   396  	if o.Spec.AssertionConsumerService == "" {
   397  		return trace.BadParameter("missing acs - assertion consumer service parameter, set service URL that will receive POST requests from SAML")
   398  	}
   399  	if o.Spec.AllowIDPInitiated && !strings.HasSuffix(o.Spec.AssertionConsumerService, "/"+o.Metadata.Name) {
   400  		return trace.BadParameter("acs - assertion consumer service parameter must end with /%v when allow_idp_initiated is set to true, eg https://cluster.domain/webapi/v1/saml/acs/%v. Ensure this URI matches the one configured at the identity provider.", o.Metadata.Name, o.Metadata.Name)
   401  	}
   402  	if o.Spec.ServiceProviderIssuer == "" {
   403  		o.Spec.ServiceProviderIssuer = o.Spec.AssertionConsumerService
   404  	}
   405  	if o.Spec.Audience == "" {
   406  		o.Spec.Audience = o.Spec.AssertionConsumerService
   407  	}
   408  	// Issuer and SSO can be automatically set later if EntityDescriptor is provided
   409  	if o.Spec.EntityDescriptorURL == "" && o.Spec.EntityDescriptor == "" && (o.Spec.Issuer == "" || o.Spec.SSO == "") {
   410  		return trace.BadParameter("no entity_descriptor set, either provide entity_descriptor or entity_descriptor_url in spec")
   411  	}
   412  	// make sure claim mappings have either roles or a role template
   413  	for _, v := range o.Spec.AttributesToRoles {
   414  		if len(v.Roles) == 0 {
   415  			return trace.BadParameter("need roles field in attributes_to_roles")
   416  		}
   417  	}
   418  	return nil
   419  }
   420  
   421  // Check returns nil if all parameters are great, err otherwise
   422  func (i *SAMLAuthRequest) Check() error {
   423  	if i.ConnectorID == "" {
   424  		return trace.BadParameter("ConnectorID: missing value")
   425  	}
   426  	if len(i.PublicKey) != 0 {
   427  		_, _, _, _, err := ssh.ParseAuthorizedKey(i.PublicKey)
   428  		if err != nil {
   429  			return trace.BadParameter("PublicKey: bad key: %v", err)
   430  		}
   431  		if (i.CertTTL > defaults.MaxCertDuration) || (i.CertTTL < defaults.MinCertDuration) {
   432  			return trace.BadParameter("CertTTL: wrong certificate TTL")
   433  		}
   434  	}
   435  
   436  	// we could collapse these two checks into one, but the error message would become ambiguous.
   437  	if i.SSOTestFlow && i.ConnectorSpec == nil {
   438  		return trace.BadParameter("ConnectorSpec cannot be nil when SSOTestFlow is true")
   439  	}
   440  
   441  	if !i.SSOTestFlow && i.ConnectorSpec != nil {
   442  		return trace.BadParameter("ConnectorSpec must be nil when SSOTestFlow is false")
   443  	}
   444  
   445  	return nil
   446  }