SSO Metadata URL can only be https/http (#12388)

When setting up SSO, validate that the Metadata URL has the proper scheme.
This commit is contained in:
Juan Fernandez 2023-06-22 08:17:37 -04:00 committed by GitHub
parent 1080406266
commit 0c172c85c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 431 additions and 1 deletions

View File

@ -0,0 +1 @@
- When setting up SSO, validate the scheme used in the Metadata URL

View File

@ -73,7 +73,10 @@ const Sso = ({
if (!metadataUrl) {
errors.metadata_url = "Metadata or Metadata URL must be present";
errors.metadata = "Metadata or Metadata URL must be present";
} else if (!validUrl({ url: metadataUrl })) {
} else if (
!validUrl({ url: metadataUrl, protocol: "http" }) &&
!validUrl({ url: metadataUrl, protocol: "https" })
) {
errors.metadata_url = `${metadataUrl} is not a valid URL`;
}
}

View File

@ -676,6 +676,14 @@ func validateSSOProviderSettings(incoming, existing fleet.SSOProviderSettings, i
invalid.Append("idp_name", "required")
}
}
if incoming.MetadataURL != "" {
if u, err := url.ParseRequestURI(incoming.MetadataURL); err != nil {
invalid.Append("metadata_url", err.Error())
} else if u.Scheme != "https" && u.Scheme != "http" {
invalid.Append("metadata_url", "must be either https or http")
}
}
}
func validateSSOSettings(p fleet.AppConfig, existing *fleet.AppConfig, invalid *fleet.InvalidArgumentError, license *fleet.LicenseInfo) {

View File

@ -5,11 +5,13 @@ import (
"crypto/tls"
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"strings"
"testing"
"github.com/fleetdm/fleet/v4/pkg/optjson"
@ -399,6 +401,32 @@ func TestMissingMetadata(t *testing.T) {
assert.Contains(t, invalid.Error(), "either metadata or metadata_url must be defined")
}
func TestSSOValidationValidatesSchemaInMetadataURL(t *testing.T) {
var schemas []string
schemas = append(schemas, getURISchemas()...)
schemas = append(schemas, "asdfaklsdfjalksdfja")
for _, scheme := range schemas {
actual := &fleet.InvalidArgumentError{}
sut := fleet.AppConfig{
SSOSettings: &fleet.SSOSettings{
EnableSSO: true,
SSOProviderSettings: fleet.SSOProviderSettings{
EntityID: "fleet",
IDPName: "onelogin",
MetadataURL: fmt.Sprintf("%s://somehost", scheme),
},
},
}
validateSSOSettings(sut, &fleet.AppConfig{}, actual, &fleet.LicenseInfo{})
require.Equal(t, scheme == "http" || scheme == "https", !actual.HasErrors())
require.Equal(t, scheme == "http" || scheme == "https", !strings.Contains(actual.Error(), "metadata_url"))
require.Equal(t, scheme == "http" || scheme == "https", !strings.Contains(actual.Error(), "must be either https or http"))
}
}
func TestJITProvisioning(t *testing.T) {
config := fleet.AppConfig{
SSOSettings: &fleet.SSOSettings{

View File

@ -80,6 +80,19 @@ func (s *integrationSSOTestSuite) TestGetSSOSettings() {
assert.True(t, strings.HasPrefix(authReq.ID, "id"), authReq.ID)
}
func (s *integrationSSOTestSuite) TestSSOValidation() {
acResp := appConfigResponse{}
// Test we are validating metadata_url
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
"sso_settings": {
"enable_sso": true,
"entity_id": "https://localhost:8080",
"idp_name": "SimpleSAML",
"metadata_url": "ssh://localhost:9080/simplesaml/saml2/idp/metadata.php"
}
}`), http.StatusUnprocessableEntity, &acResp)
}
func (s *integrationSSOTestSuite) TestSSOLogin() {
t := s.T()

View File

@ -613,3 +613,380 @@ func mdmAppleConfigurationRequiredEndpoints() []struct {
{"POST", "/api/latest/fleet/mdm/apple/profiles/match", false, true},
}
}
// getURLSchemas returns a list of all valid URI schemas
func getURISchemas() []string {
return []string{
"aaa",
"aaas",
"about",
"acap",
"acct",
"acd",
"acr",
"adiumxtra",
"adt",
"afp",
"afs",
"aim",
"amss",
"android",
"appdata",
"apt",
"ar",
"ark",
"at",
"attachment",
"aw",
"barion",
"bb",
"beshare",
"bitcoin",
"bitcoincash",
"blob",
"bolo",
"browserext",
"cabal",
"calculator",
"callto",
"cap",
"cast",
"casts",
"chrome",
"chrome-extension",
"cid",
"coap",
"coap+tcp",
"coap+ws",
"coaps",
"coaps+tcp",
"coaps+ws",
"com-eventbrite-attendee",
"content",
"content-type",
"crid",
"cstr",
"cvs",
"dab",
"dat",
"data",
"dav",
"dhttp",
"diaspora",
"dict",
"did",
"dis",
"dlna-playcontainer",
"dlna-playsingle",
"dns",
"dntp",
"doi",
"dpp",
"drm",
"drop",
"dtmi",
"dtn",
"dvb",
"dvx",
"dweb",
"ed2k",
"eid",
"elsi",
"embedded",
"ens",
"ethereum",
"example",
"facetime",
"fax",
"feed",
"feedready",
"fido",
"file",
"filesystem",
"finger",
"first-run-pen-experience",
"fish",
"fm",
"ftp",
"fuchsia-pkg",
"geo",
"gg",
"git",
"gitoid",
"gizmoproject",
"go",
"gopher",
"graph",
"grd",
"gtalk",
"h323",
"ham",
"hcap",
"hcp",
"http",
"https",
"hxxp",
"hxxps",
"hydrazone",
"hyper",
"iax",
"icap",
"icon",
"im",
"imap",
"info",
"iotdisco",
"ipfs",
"ipn",
"ipns",
"ipp",
"ipps",
"irc",
"irc6",
"ircs",
"iris",
"iris.beep",
"iris.lwz",
"iris.xpc",
"iris.xpcs",
"isostore",
"itms",
"jabber",
"jar",
"jms",
"keyparc",
"lastfm",
"lbry",
"ldap",
"ldaps",
"leaptofrogans",
"lorawan",
"lpa",
"lvlt",
"magnet",
"mailserver",
"mailto",
"maps",
"market",
"matrix",
"message",
"microsoft.windows.camera",
"microsoft.windows.camera.multipicker",
"microsoft.windows.camera.picker",
"mid",
"mms",
"modem",
"mongodb",
"moz",
"ms-access",
"ms-appinstaller",
"ms-browser-extension",
"ms-calculator",
"ms-drive-to",
"ms-enrollment",
"ms-excel",
"ms-eyecontrolspeech",
"ms-gamebarservices",
"ms-gamingoverlay",
"ms-getoffice",
"ms-help",
"ms-infopath",
"ms-inputapp",
"ms-launchremotedesktop",
"ms-lockscreencomponent-config",
"ms-media-stream-id",
"ms-meetnow",
"ms-mixedrealitycapture",
"ms-mobileplans",
"ms-newsandinterests",
"ms-officeapp",
"ms-people",
"ms-project",
"ms-powerpoint",
"ms-publisher",
"ms-remotedesktop",
"ms-remotedesktop-launch",
"ms-restoretabcompanion",
"ms-screenclip",
"ms-screensketch",
"ms-search",
"ms-search-repair",
"ms-secondary-screen-controller",
"ms-secondary-screen-setup",
"ms-settings",
"ms-settings-airplanemode",
"ms-settings-bluetooth",
"ms-settings-camera",
"ms-settings-cellular",
"ms-settings-cloudstorage",
"ms-settings-connectabledevices",
"ms-settings-displays-topology",
"ms-settings-emailandaccounts",
"ms-settings-language",
"ms-settings-location",
"ms-settings-lock",
"ms-settings-nfctransactions",
"ms-settings-notifications",
"ms-settings-power",
"ms-settings-privacy",
"ms-settings-proximity",
"ms-settings-screenrotation",
"ms-settings-wifi",
"ms-settings-workplace",
"ms-spd",
"ms-stickers",
"ms-sttoverlay",
"ms-transit-to",
"ms-useractivityset",
"ms-virtualtouchpad",
"ms-visio",
"ms-walk-to",
"ms-whiteboard",
"ms-whiteboard-cmd",
"ms-word",
"msnim",
"msrp",
"msrps",
"mss",
"mt",
"mtqp",
"mumble",
"mupdate",
"mvn",
"news",
"nfs",
"ni",
"nih",
"nntp",
"notes",
"num",
"ocf",
"oid",
"onenote",
"onenote-cmd",
"opaquelocktoken",
"openpgp4fpr",
"otpauth",
"p1",
"pack",
"palm",
"paparazzi",
"payment",
"payto",
"pkcs11",
"platform",
"pop",
"pres",
"prospero",
"proxy",
"pwid",
"psyc",
"pttp",
"qb",
"query",
"quic-transport",
"redis",
"rediss",
"reload",
"res",
"resource",
"rmi",
"rsync",
"rtmfp",
"rtmp",
"rtsp",
"rtsps",
"rtspu",
"sarif",
"secondlife",
"secret-token",
"service",
"session",
"sftp",
"sgn",
"shc",
"shttp",
"sieve",
"simpleledger",
"simplex",
"sip",
"sips",
"skype",
"smb",
"smp",
"sms",
"smtp",
"snews",
"snmp",
"soap.beep",
"soap.beeps",
"soldat",
"spiffe",
"spotify",
"ssb",
"ssh",
"starknet",
"steam",
"stun",
"stuns",
"submit",
"svn",
"swh",
"swid",
"swidpath",
"tag",
"taler",
"teamspeak",
"tel",
"teliaeid",
"telnet",
"tftp",
"things",
"thismessage",
"tip",
"tn3270",
"tool",
"turn",
"turns",
"tv",
"udp",
"unreal",
"upt",
"urn",
"ut2004",
"uuid-in-package",
"v-event",
"vemmi",
"ventrilo",
"ves",
"videotex",
"vnc",
"view-source",
"vscode",
"vscode-insiders",
"vsls",
"w3",
"wais",
"web3",
"wcr",
"webcal",
"web+ap",
"wifi",
"wpid",
"ws",
"wss",
"wtai",
"wyciwyg",
"xcon",
"xcon-userid",
"xfire",
"xmlrpc.beep",
"xmlrpc.beeps",
"xmpp",
"xri",
"ymsgr",
"z39.50",
"z39.50r",
"z39.50s",
}
}