Skip to content

Commit

Permalink
Merge pull request #1967 from jackHay22/jh/saml
Browse files Browse the repository at this point in the history
Integration test fix
  • Loading branch information
techknowlogick authored Dec 10, 2023
2 parents 4d464a7 + 9909373 commit f374036
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 4 deletions.
8 changes: 8 additions & 0 deletions routers/web/admin/auths.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ func parseSAMLConfig(ctx *context.Context, form forms.AuthenticationForm) (*saml
if err != nil {
return nil, err
}
} else {
privateKey, cert, err := saml.GenerateSAMLSPKeypair()
if err != nil {
return nil, err
}

form.ServiceProviderPrivateKey = privateKey
form.ServiceProviderCertificate = cert
}

return &saml.Source{
Expand Down
50 changes: 47 additions & 3 deletions services/auth/source/saml/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ package saml

import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"encoding/xml"
"errors"
"fmt"
"math/big"
"net/url"
"time"

"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/json"
Expand Down Expand Up @@ -62,6 +67,47 @@ type Source struct {
samlSP *saml2.SAMLServiceProvider
}

func GenerateSAMLSPKeypair() (string, string, error) {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
return "", "", err
}

keyBytes := x509.MarshalPKCS1PrivateKey(key)
keyPem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: keyBytes,
},
)

now := time.Now()

template := &x509.Certificate{
SerialNumber: big.NewInt(0),
NotBefore: now.Add(-5 * time.Minute),
NotAfter: now.Add(365 * 24 * time.Hour),

KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{},
BasicConstraintsValid: true,
}

certificate, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
if err != nil {
return "", "", err
}

certPem := pem.EncodeToMemory(
&pem.Block{
Type: "CERTIFICATE",
Bytes: certificate,
},
)

return string(keyPem), string(certPem), nil
}

func (source *Source) initSAMLSp() error {
source.CallbackURL = setting.AppURL + "user/saml/" + url.PathEscape(source.authSource.Name) + "/acs"

Expand Down Expand Up @@ -120,8 +166,6 @@ func (source *Source) initSAMLSp() error {
return err
}
keyStore = dsig.TLSCertKeyStore(keyPair)
} else {
keyStore = dsig.RandomKeyStoreForTest()
}

source.samlSP = &saml2.SAMLServiceProvider{
Expand All @@ -132,7 +176,7 @@ func (source *Source) initSAMLSp() error {
SkipSignatureValidation: source.InsecureSkipAssertionSignatureValidation,
NameIdFormat: source.NameIDFormat.String(),
IDPCertificateStore: &certStore,
SignAuthnRequests: true,
SignAuthnRequests: source.ServiceProviderCertificate != "" && source.ServiceProviderPrivateKey != "",
SPKeyStore: keyStore,
ServiceProviderIssuer: setting.AppURL + "user/saml/" + url.PathEscape(source.authSource.Name) + "/metadata",
}
Expand Down
13 changes: 12 additions & 1 deletion tests/integration/saml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package integration

import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -40,6 +42,15 @@ func TestSAMLRegistration(t *testing.T) {
}
}

privateKey, cert, err := saml.GenerateSAMLSPKeypair()
assert.NoError(t, err)

// verify that the keypair can be parsed
keyPair, err := tls.X509KeyPair([]byte(cert), []byte(privateKey))
assert.NoError(t, err)
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
assert.NoError(t, err)

assert.NoError(t, auth.CreateSource(db.DefaultContext, &auth.Source{
Type: auth.SAML,
Name: "test-sp",
Expand All @@ -50,7 +61,7 @@ func TestSAMLRegistration(t *testing.T) {
IdentityProviderMetadataURL: fmt.Sprintf("http://%s/simplesaml/saml2/idp/metadata.php", samlURL),
InsecureSkipAssertionSignatureValidation: false,
NameIDFormat: 4,
ServiceProviderCertificate: "",
ServiceProviderCertificate: "", // SimpleSAMLPhp requires that the SP certificate be specified in the server configuration rather than SP metadata
ServiceProviderPrivateKey: "",
EmailAssertionKey: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
NameAssertionKey: "http://schemas.xmlsoap.org/claims/CommonName",
Expand Down

0 comments on commit f374036

Please sign in to comment.