From 52cb104ccfe5bb5efa6b9882d1e5644c4553e04a Mon Sep 17 00:00:00 2001 From: Sword Date: Tue, 21 Nov 2023 05:49:16 +0000 Subject: [PATCH] Add test for samlidp --- identity_provider.go | 5 +-- samlidp/samlidp.go | 26 ++++++------ samlidp/samlidp_test.go | 41 ++++++++++++++++--- ...tadata_response_with_custom_entity_id.html | 25 +++++++++++ 4 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 samlidp/testdata/http_metadata_response_with_custom_entity_id.html diff --git a/identity_provider.go b/identity_provider.go index 135915e7..abf180c3 100644 --- a/identity_provider.go +++ b/identity_provider.go @@ -110,6 +110,7 @@ type IdentityProvider struct { EntityIDConstructor EntityIDConstructor } +// EntityIDConstructor is a function that returns the entityID for customization. type EntityIDConstructor func() string // Metadata returns the metadata structure for this identity provider. @@ -339,9 +340,7 @@ func (idp *IdentityProvider) ServeIDPInitiated(w http.ResponseWriter, r *http.Re // createDefaultEntityIDConstructor creates a function to return entityID from metadataURL. func createDefaultEntityIDConstructor(metadataURL url.URL) func() string { - return func() string { - return metadataURL.String() - } + return metadataURL.String } func (idp *IdentityProvider) getEntityID() string { diff --git a/samlidp/samlidp.go b/samlidp/samlidp.go index 13ca10b9..d6e6f8a7 100644 --- a/samlidp/samlidp.go +++ b/samlidp/samlidp.go @@ -18,12 +18,13 @@ import ( // Options represent the parameters to New() for creating a new IDP server type Options struct { - URL url.URL - Key crypto.PrivateKey - Signer crypto.Signer - Logger logger.Interface - Certificate *x509.Certificate - Store Store + URL url.URL + Key crypto.PrivateKey + Signer crypto.Signer + Logger logger.Interface + Certificate *x509.Certificate + Store Store + EntityIDConstructor saml.EntityIDConstructor } // Server represents an IDP server. The server provides the following URLs: @@ -59,12 +60,13 @@ func New(opts Options) (*Server, error) { s := &Server{ serviceProviders: map[string]*saml.EntityDescriptor{}, IDP: saml.IdentityProvider{ - Key: opts.Key, - Signer: opts.Signer, - Logger: logr, - Certificate: opts.Certificate, - MetadataURL: metadataURL, - SSOURL: ssoURL, + Key: opts.Key, + Signer: opts.Signer, + Logger: logr, + Certificate: opts.Certificate, + MetadataURL: metadataURL, + SSOURL: ssoURL, + EntityIDConstructor: opts.EntityIDConstructor, }, logger: logr, Store: opts.Store, diff --git a/samlidp/samlidp_test.go b/samlidp/samlidp_test.go index e5b2dafb..e1fd9dd9 100644 --- a/samlidp/samlidp_test.go +++ b/samlidp/samlidp_test.go @@ -66,6 +66,15 @@ func mustParseCertificate(pemStr []byte) *x509.Certificate { return cert } +func setupTestVariables() { + saml.TimeNow = func() time.Time { + rv, _ := time.Parse("Mon Jan 2 15:04:05 MST 2006", "Mon Dec 1 01:57:09 UTC 2015") + return rv + } + jwt.TimeFunc = saml.TimeNow + saml.RandReader = &testRandomReader{} +} + type ServerTest struct { SPKey *rsa.PrivateKey SPCertificate *x509.Certificate @@ -79,12 +88,7 @@ type ServerTest struct { func NewServerTest(t *testing.T) *ServerTest { test := ServerTest{} - saml.TimeNow = func() time.Time { - rv, _ := time.Parse("Mon Jan 2 15:04:05 MST 2006", "Mon Dec 1 01:57:09 UTC 2015") - return rv - } - jwt.TimeFunc = saml.TimeNow - saml.RandReader = &testRandomReader{} + setupTestVariables() test.SPKey = mustParsePrivateKey(golden.Get(t, "sp_key.pem")).(*rsa.PrivateKey) test.SPCertificate = mustParseCertificate(golden.Get(t, "sp_cert.pem")) @@ -143,3 +147,28 @@ func TestHTTPCanSSORequest(t *testing.T) { w.Body.String()) golden.Assert(t, w.Body.String(), "http_sso_response.html") } + +func TestHTTPMetadataResponseWithCustomEntityID(t *testing.T) { + setupTestVariables() + + server, err := New(Options{ + Certificate: mustParseCertificate(golden.Get(t, "idp_cert.pem")), + Key: mustParsePrivateKey(golden.Get(t, "idp_key.pem")).(*rsa.PrivateKey), + Logger: logger.DefaultLogger, + URL: url.URL{Scheme: "https", Host: "idp.example.com"}, + Store: &MemoryStore{}, + EntityIDConstructor: func() string { + return "https://idp.example.com/idp-id" + }, + }) + assert.Check(t, err) + + w := httptest.NewRecorder() + r, _ := http.NewRequest("GET", "https://idp.example.com/metadata", nil) + server.ServeHTTP(w, r) + assert.Check(t, is.Equal(http.StatusOK, w.Code)) + assert.Check(t, + strings.HasPrefix(w.Body.String(), " + + + + + MIIB7zCCAVgCCQDFzbKIp7b3MTANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGEwJVUzELMAkGA1UECAwCR0ExDDAKBgNVBAoMA2ZvbzESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTEzMTAwMjAwMDg1MVoXDTE0MTAwMjAwMDg1MVowPDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkdBMQwwCgYDVQQKDANmb28xEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1PMHYmhZj308kWLhZVT4vOulqx/9ibm5B86fPWwUKKQ2i12MYtz07tzukPymisTDhQaqyJ8Kqb/6JjhmeMnEOdTvSPmHO8m1ZVveJU6NoKRn/mP/BD7FW52WhbrUXLSeHVSKfWkNk6S4hk9MV9TswTvyRIKvRsw0X/gfnqkroJcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCMMlIO+GNcGekevKgkakpMdAqJfs24maGb90DvTLbRZRD7Xvn1MnVBBS9hzlXiFLYOInXACMW5gcoRFfeTQLSouMM8o57h0uKjfTmuoWHLQLi6hnF+cvCsEFiJZ4AbF+DgmO6TarJ8O05t8zvnOwJlNCASPZRH/JmF8tX0hoHuAQ== + + + + + + + MIIB7zCCAVgCCQDFzbKIp7b3MTANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGEwJVUzELMAkGA1UECAwCR0ExDDAKBgNVBAoMA2ZvbzESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTEzMTAwMjAwMDg1MVoXDTE0MTAwMjAwMDg1MVowPDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkdBMQwwCgYDVQQKDANmb28xEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1PMHYmhZj308kWLhZVT4vOulqx/9ibm5B86fPWwUKKQ2i12MYtz07tzukPymisTDhQaqyJ8Kqb/6JjhmeMnEOdTvSPmHO8m1ZVveJU6NoKRn/mP/BD7FW52WhbrUXLSeHVSKfWkNk6S4hk9MV9TswTvyRIKvRsw0X/gfnqkroJcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCMMlIO+GNcGekevKgkakpMdAqJfs24maGb90DvTLbRZRD7Xvn1MnVBBS9hzlXiFLYOInXACMW5gcoRFfeTQLSouMM8o57h0uKjfTmuoWHLQLi6hnF+cvCsEFiJZ4AbF+DgmO6TarJ8O05t8zvnOwJlNCASPZRH/JmF8tX0hoHuAQ== + + + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + \ No newline at end of file