Skip to content

Commit

Permalink
Improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
micafer committed Nov 22, 2024
1 parent 93cf1c1 commit ef3e9da
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 30 deletions.
2 changes: 1 addition & 1 deletion pkg/utils/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func CustomAuth(cfg *types.Config, kubeClientset kubernetes.Interface) gin.Handl
minIOAdminClient.CreateAllUsersGroup()
minIOAdminClient.UpdateUsersInGroup(oscarUser, "all_users_group", false)

oidcHandler := getOIDCMiddleware(kubeClientset, minIOAdminClient, cfg.OIDCIssuer, cfg.OIDCSubject, cfg.OIDCGroups)
oidcHandler := getOIDCMiddleware(kubeClientset, minIOAdminClient, cfg.OIDCIssuer, cfg.OIDCSubject, cfg.OIDCGroups, nil)
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if strings.HasPrefix(authHeader, "Bearer ") {
Expand Down
7 changes: 5 additions & 2 deletions pkg/utils/auth/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ func NewOIDCManager(issuer string, subject string, groups []string) (*oidcManage
}

// getIODCMiddleware returns the Gin's handler middleware to validate OIDC-based auth
func getOIDCMiddleware(kubeClientset kubernetes.Interface, minIOAdminClient *utils.MinIOAdminClient, issuer string, subject string, groups []string) gin.HandlerFunc {
func getOIDCMiddleware(kubeClientset kubernetes.Interface, minIOAdminClient *utils.MinIOAdminClient, issuer string, subject string, groups []string, oidcConfig *oidc.Config) gin.HandlerFunc {
oidcManager, err := NewOIDCManager(issuer, subject, groups)
if oidcConfig != nil {
oidcManager.config = oidcConfig
}
if err != nil {
return func(c *gin.Context) {
c.AbortWithStatus(http.StatusUnauthorized)
Expand Down Expand Up @@ -199,7 +202,7 @@ func (om *oidcManager) UserHasVO(rawToken string, vo string) (bool, error) {
func (om *oidcManager) GetUID(rawToken string) (string, error) {
ui, err := om.GetUserInfo(rawToken)
oidcLogger.Println("received uid: ", ui.Subject)
if err != nil {
if err == nil {
return ui.Subject, nil
}
return "", err
Expand Down
125 changes: 98 additions & 27 deletions pkg/utils/auth/oidc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import (
"testing"
"time"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
"github.com/grycap/oscar/v3/pkg/types"
"github.com/grycap/oscar/v3/pkg/utils"
"k8s.io/client-go/kubernetes/fake"
)
Expand Down Expand Up @@ -89,60 +91,129 @@ func TestIsAuthorised(t *testing.T) {
if hreq.URL.Path == "/.well-known/openid-configuration" {
rw.Write([]byte(`{"issuer": "http://` + hreq.Host + `", "userinfo_endpoint": "http://` + hreq.Host + `/userinfo"}`))
} else if hreq.URL.Path == "/userinfo" {
rw.Write([]byte(`{"sub": "test-subject", "eduperson_entitlement": ["urn:mace:egi.eu:group:group1"]}`))
rw.Write([]byte(`{"sub": "user1@egi.eu", "eduperson_entitlement": ["urn:mace:egi.eu:group:group1"]}`))
}
}))

issuer := server.URL
subject := "test-subject"
subject := "user1@egi.eu"
groups := []string{"group1", "group2"}

oidcManager, err := NewOIDCManager(issuer, subject, groups)
if err != nil {
t.Errorf("expected no error, got %v", err)
}

claims := jwt.MapClaims{
"iss": issuer,
"sub": subject,
"exp": time.Now().Add(1 * time.Hour).Unix(),
"iat": time.Now().Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
privateKey, _ := rsa.GenerateKey(rand.Reader, 1024)
rawToken, _ := token.SignedString(privateKey)
rawToken := GetToken(issuer, subject)
oidcManager.config.InsecureSkipSignatureCheck = true

if !oidcManager.IsAuthorised(rawToken) {
t.Errorf("expected token to be authorised")
}

resg1, err2 := oidcManager.UserHasVO(rawToken, "group1")
if err2 != nil {
t.Errorf("expected no error, got %v", err)
}
if !resg1 {
t.Errorf("expected user to have VO")
}
resg2, err3 := oidcManager.UserHasVO(rawToken, "group2")
if err3 != nil {
t.Errorf("expected no error, got %v", err)
}
if resg2 {
t.Errorf("expected user not to have VO")
}

uid, _ := oidcManager.GetUID(rawToken)
if uid != subject {
t.Errorf("expected uid to be %v, got %v", subject, uid)
}
}

func TestGetOIDCMiddleware(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, hreq *http.Request) {
if hreq.URL.Path == "/.well-known/openid-configuration" {
rw.Write([]byte(`{"issuer": "http://` + hreq.Host + `", "userinfo_endpoint": "http://` + hreq.Host + `/userinfo"}`))
} else if hreq.URL.Path == "/userinfo" {
rw.Write([]byte(`{"sub": "user@egi.eu", "eduperson_entitlement": ["urn:mace:egi.eu:group:group1"]}`))
} else if hreq.URL.Path == "/minio/admin/v3/info" {
rw.WriteHeader(http.StatusOK)
rw.Write([]byte(`{"Mode": "local", "Region": "us-east-1"}`))
} else {
rw.WriteHeader(http.StatusOK)
rw.Write([]byte(`{"status": "success"}`))
}
}))

kubeClientset := fake.NewSimpleClientset()
minIOAdminClient := &utils.MinIOAdminClient{}
issuer := "https://example.com"
subject := "test-subject"
cfg := types.Config{
MinIOProvider: &types.MinIOProvider{
Endpoint: server.URL,
Verify: false,
},
}
minIOAdminClient, _ := utils.MakeMinIOAdminClient(&cfg)
issuer := server.URL
subject := "user@egi.eu"
groups := []string{"group1", "group2"}

middleware := getOIDCMiddleware(kubeClientset, minIOAdminClient, issuer, subject, groups)
oidcConfig := &oidc.Config{
InsecureSkipSignatureCheck: true,
SkipClientIDCheck: true,
}
middleware := getOIDCMiddleware(kubeClientset, minIOAdminClient, issuer, subject, groups, oidcConfig)
if middleware == nil {
t.Errorf("expected middleware to be non-nil")
}

// Create a new Gin context
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)

// Test the middleware with an invalid token
c.Request = &http.Request{
Header: http.Header{
"Authorization": []string{"Bearer invalid-token"},
scenarios := []struct {
token string
code int
name string
}{
{
name: "invalid-token",
token: "invalid-token",
code: http.StatusUnauthorized,
},
{
name: "valid-token",
token: GetToken(issuer, subject),
code: http.StatusOK,
},
}
middleware(c)
if c.Writer.Status() != http.StatusUnauthorized {
t.Errorf("expected status to be %v, got %v", http.StatusUnauthorized, c.Writer.Status())
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
// Create a new Gin context
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)

// Test the middleware with an invalid token
c.Request = &http.Request{
Header: http.Header{
"Authorization": []string{"Bearer " + s.token},
},
}
middleware(c)
if c.Writer.Status() != s.code {
t.Errorf("expected status to be %v, got %v", s.code, c.Writer.Status())
}
})
}
}

func GetToken(issuer string, subject string) string {
claims := jwt.MapClaims{
"iss": issuer,
"sub": subject,
"exp": time.Now().Add(1 * time.Hour).Unix(),
"iat": time.Now().Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
privateKey, _ := rsa.GenerateKey(rand.Reader, 1024)
rawToken, _ := token.SignedString(privateKey)
return rawToken
}

0 comments on commit ef3e9da

Please sign in to comment.