2020-10-15 01:22:58 +02:00
|
|
|
package security
|
|
|
|
|
2022-01-01 02:07:19 +01:00
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
2020-10-15 01:22:58 +02:00
|
|
|
|
2022-01-01 02:07:19 +01:00
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"golang.org/x/oauth2"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestConfig_IsValid(t *testing.T) {
|
|
|
|
c := &Config{
|
|
|
|
Basic: nil,
|
|
|
|
OIDC: nil,
|
2020-10-15 01:22:58 +02:00
|
|
|
}
|
2022-01-01 02:07:19 +01:00
|
|
|
if c.IsValid() {
|
|
|
|
t.Error("expected empty config to be valid")
|
2020-10-15 01:22:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-01 02:07:19 +01:00
|
|
|
func TestConfig_ApplySecurityMiddleware(t *testing.T) {
|
|
|
|
///////////
|
|
|
|
// BASIC //
|
|
|
|
///////////
|
|
|
|
c := &Config{Basic: &BasicConfig{
|
|
|
|
Username: "john.doe",
|
|
|
|
PasswordSha512Hash: "6b97ed68d14eb3f1aa959ce5d49c7dc612e1eb1dafd73b1e705847483fd6a6c809f2ceb4e8df6ff9984c6298ff0285cace6614bf8daa9f0070101b6c89899e22",
|
|
|
|
}}
|
|
|
|
api := mux.NewRouter()
|
|
|
|
api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
})
|
|
|
|
c.ApplySecurityMiddleware(api)
|
|
|
|
// Try to access the route without basic auth
|
2022-01-03 00:29:34 +01:00
|
|
|
request, _ := http.NewRequest("GET", "/test", http.NoBody)
|
2022-01-01 02:07:19 +01:00
|
|
|
responseRecorder := httptest.NewRecorder()
|
|
|
|
api.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Code != http.StatusUnauthorized {
|
|
|
|
t.Error("expected code to be 401, but was", responseRecorder.Code)
|
|
|
|
}
|
|
|
|
// Try again, but with basic auth
|
2022-01-03 00:29:34 +01:00
|
|
|
request, _ = http.NewRequest("GET", "/test", http.NoBody)
|
2022-01-01 02:07:19 +01:00
|
|
|
responseRecorder = httptest.NewRecorder()
|
|
|
|
request.SetBasicAuth("john.doe", "hunter2")
|
|
|
|
api.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Code != http.StatusOK {
|
|
|
|
t.Error("expected code to be 200, but was", responseRecorder.Code)
|
|
|
|
}
|
|
|
|
//////////
|
|
|
|
// OIDC //
|
|
|
|
//////////
|
|
|
|
api = mux.NewRouter()
|
|
|
|
api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
})
|
|
|
|
c.OIDC = &OIDCConfig{
|
|
|
|
IssuerURL: "https://sso.gatus.io/",
|
|
|
|
RedirectURL: "http://localhost:80/authorization-code/callback",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
AllowedSubjects: []string{"user1@example.com"},
|
|
|
|
oauth2Config: oauth2.Config{},
|
|
|
|
verifier: nil,
|
|
|
|
}
|
|
|
|
c.Basic = nil
|
|
|
|
c.ApplySecurityMiddleware(api)
|
|
|
|
// Try without any session cookie
|
2022-01-03 00:29:34 +01:00
|
|
|
request, _ = http.NewRequest("GET", "/test", http.NoBody)
|
2022-01-01 02:07:19 +01:00
|
|
|
responseRecorder = httptest.NewRecorder()
|
|
|
|
api.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Code != http.StatusUnauthorized {
|
|
|
|
t.Error("expected code to be 401, but was", responseRecorder.Code)
|
|
|
|
}
|
|
|
|
// Try with a session cookie
|
2022-01-03 00:29:34 +01:00
|
|
|
request, _ = http.NewRequest("GET", "/test", http.NoBody)
|
2022-01-01 02:07:19 +01:00
|
|
|
request.AddCookie(&http.Cookie{Name: "session", Value: "123"})
|
|
|
|
responseRecorder = httptest.NewRecorder()
|
|
|
|
api.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Code != http.StatusUnauthorized {
|
|
|
|
t.Error("expected code to be 401, but was", responseRecorder.Code)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfig_RegisterHandlers(t *testing.T) {
|
|
|
|
c := &Config{}
|
|
|
|
router := mux.NewRouter()
|
|
|
|
c.RegisterHandlers(router)
|
|
|
|
// Try to access the OIDC handler. This should fail, because the security config doesn't have OIDC
|
2022-01-03 00:29:34 +01:00
|
|
|
request, _ := http.NewRequest("GET", "/oidc/login", http.NoBody)
|
2022-01-01 02:07:19 +01:00
|
|
|
responseRecorder := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Code != http.StatusNotFound {
|
|
|
|
t.Error("expected code to be 404, but was", responseRecorder.Code)
|
|
|
|
}
|
|
|
|
// Set an empty OIDC config. This should fail, because the IssuerURL is required.
|
|
|
|
c.OIDC = &OIDCConfig{}
|
|
|
|
if err := c.RegisterHandlers(router); err == nil {
|
|
|
|
t.Fatal("expected an error, but got none")
|
|
|
|
}
|
|
|
|
// Set the OIDC config and try again
|
|
|
|
c.OIDC = &OIDCConfig{
|
|
|
|
IssuerURL: "https://sso.gatus.io/",
|
|
|
|
RedirectURL: "http://localhost:80/authorization-code/callback",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
AllowedSubjects: []string{"user1@example.com"},
|
|
|
|
}
|
|
|
|
if err := c.RegisterHandlers(router); err != nil {
|
|
|
|
t.Fatal("expected no error, but got", err)
|
2020-10-15 01:22:58 +02:00
|
|
|
}
|
2022-01-03 00:29:34 +01:00
|
|
|
request, _ = http.NewRequest("GET", "/oidc/login", http.NoBody)
|
2022-01-01 02:07:19 +01:00
|
|
|
responseRecorder = httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Code != http.StatusFound {
|
|
|
|
t.Error("expected code to be 302, but was", responseRecorder.Code)
|
2020-10-15 01:22:58 +02:00
|
|
|
}
|
|
|
|
}
|