From 9d63ad0dea50dbf63ffc3b34ff1bffb9aee19657 Mon Sep 17 00:00:00 2001 From: Dominik Kawka <31955648+dominikkawka@users.noreply.github.com> Date: Sat, 5 Nov 2022 19:01:28 +0000 Subject: [PATCH] IDP SAML testing (#3713) --- .../e2e/identity_providers_saml_test.spec.ts | 27 ++ .../social/ProviderSAMLSettings.ts | 248 ++++++++++++++++++ .../add/DescriptorSettings.tsx | 9 + 3 files changed, 284 insertions(+) create mode 100644 apps/admin-ui/cypress/support/pages/admin_console/manage/identity_providers/social/ProviderSAMLSettings.ts diff --git a/apps/admin-ui/cypress/e2e/identity_providers_saml_test.spec.ts b/apps/admin-ui/cypress/e2e/identity_providers_saml_test.spec.ts index 8c5b1f943f..6ddba1d3a4 100644 --- a/apps/admin-ui/cypress/e2e/identity_providers_saml_test.spec.ts +++ b/apps/admin-ui/cypress/e2e/identity_providers_saml_test.spec.ts @@ -6,6 +6,7 @@ import ListingPage from "../support/pages/admin_console/ListingPage"; import CreateProviderPage from "../support/pages/admin_console/manage/identity_providers/CreateProviderPage"; import ModalUtils from "../support/util/ModalUtils"; import AddMapperPage from "../support/pages/admin_console/manage/identity_providers/AddMapperPage"; +import ProviderSAMLSettings from "../support/pages/admin_console/manage/identity_providers/social/ProviderSAMLSettings"; describe("SAML identity provider test", () => { const loginPage = new LoginPage(); @@ -148,6 +149,32 @@ describe("SAML identity provider test", () => { masthead.checkNotificationMessage(saveMapperSuccessMsg, true); }); + it("should edit SAML settings", () => { + const providerSAMLSettings = new ProviderSAMLSettings(); + + sidebarPage.goToIdentityProviders(); + listingPage.goToItemDetails(samlProviderName); + providerSAMLSettings.disableProviderSwitch(); + sidebarPage.goToIdentityProviders(); + cy.findByText("Disabled"); + listingPage.goToItemDetails(samlProviderName); + providerSAMLSettings.enableProviderSwitch(); + + cy.get(".pf-c-jump-links__list").contains("SAML settings").click(); + providerSAMLSettings.assertIdAndURLFields(); + providerSAMLSettings.assertNameIdPolicyFormat(); + providerSAMLSettings.assertPrincipalType(); + providerSAMLSettings.assertSAMLSwitches(); + providerSAMLSettings.assertSignatureAlgorithm(); + providerSAMLSettings.assertValidateSignatures(); + providerSAMLSettings.assertTextFields(); + + cy.get(".pf-c-jump-links__list") + .contains("Requested AuthnContext Constraints") + .click(); + providerSAMLSettings.assertAuthnContext(); + }); + it("clean up providers", () => { const modalUtils = new ModalUtils(); diff --git a/apps/admin-ui/cypress/support/pages/admin_console/manage/identity_providers/social/ProviderSAMLSettings.ts b/apps/admin-ui/cypress/support/pages/admin_console/manage/identity_providers/social/ProviderSAMLSettings.ts new file mode 100644 index 0000000000..7d155246f7 --- /dev/null +++ b/apps/admin-ui/cypress/support/pages/admin_console/manage/identity_providers/social/ProviderSAMLSettings.ts @@ -0,0 +1,248 @@ +import PageObject from "../../../components/PageObject"; +import Masthead from "../../../Masthead"; + +const masthead = new Masthead(); + +export default class ProviderSAMLSettings extends PageObject { + private samlSwitch = "#Saml-switch"; + private modalConfirm = "#modal-confirm"; + private serviceProviderEntityID = "serviceProviderEntityId"; + private identityProviderEntityId = "identityProviderEntityId"; + private ssoServiceUrl = "sso-service-url"; + private singleLogoutServiceUrl = "single-logout-service-url"; + private nameIdPolicyFormat = "#kc-nameIdPolicyFormat"; + private principalType = "#kc-principalType"; + private principalAttribute = "principalAttribute"; + private principalSubjectNameId = "subjectNameId-option"; + private principalAttributeName = "attributeName-option"; + private principalFriendlyAttribute = "attributeFriendlyName-option"; + + private transientPolicy = "transient-option"; + private emailPolicy = "email-option"; + private kerberosPolicy = "kerberos-option"; + private x509Policy = "x509-option"; + private windowsDomainQNPolicy = "windowsDomainQN-option"; + private unspecifiedPolicy = "unspecified-option"; + private persistentPolicy = "persistent-option"; + + private allowCreate = "#allowCreate"; + private httpPostBindingResponse = "#httpPostBindingResponse"; + private httpPostBindingAuthnRequest = "#httpPostBindingAuthnRequest"; + private httpPostBindingLogout = "#httpPostBindingLogout"; + private wantAuthnRequestsSigned = "#wantAuthnRequestsSigned"; + + private signatureAlgorithm = "#kc-signatureAlgorithm"; + private samlSignatureKeyName = "#kc-samlSignatureKeyName"; + + private wantAssertionsSigned = "#wantAssertionsSigned"; + private wantAssertionsEncrypted = "#wantAssertionsEncrypted"; + private forceAuthentication = "#forceAuthentication"; + private validateSignature = "#validateSignature"; + private validatingX509Certs = "validatingX509Certs"; + private signServiceProviderMetadata = "#signServiceProviderMetadata"; + private passSubject = "#passSubject"; + private allowedClockSkew = "allowedClockSkew"; + private attributeConsumingServiceIndex = "attributeConsumingServiceIndex"; + private attributeConsumingServiceName = "attributeConsumingServiceName"; + + private comparison = "#comparison"; + private saveBtn = "save"; + private revertBtn = "revert"; + + public clickSaveBtn() { + cy.findByTestId(this.saveBtn).click(); + } + + public clickRevertBtn() { + cy.findByTestId(this.revertBtn).click(); + } + + public enableProviderSwitch() { + cy.get(this.samlSwitch).parent().click(); + masthead.checkNotificationMessage("Provider successfully updated"); + } + + public disableProviderSwitch() { + cy.get(this.samlSwitch).parent().click(); + cy.get(this.modalConfirm).click(); + masthead.checkNotificationMessage("Provider successfully updated"); + } + + public typeServiceProviderEntityId(entityId: string) { + cy.findByTestId(this.serviceProviderEntityID) + .click() + .clear() + .type(entityId); + return this; + } + + public typeIdentityProviderEntityId(entityId: string) { + cy.findByTestId(this.identityProviderEntityId) + .click() + .clear() + .type(entityId); + return this; + } + + public typeSsoServiceUrl(url: string) { + cy.findByTestId(this.ssoServiceUrl).click().clear().type(url); + return this; + } + + public typeSingleLogoutServiceUrl(url: string) { + cy.findByTestId(this.singleLogoutServiceUrl).click().clear().type(url); + return this; + } + + public typeX509Certs(cert: string) { + cy.findByTestId(this.validatingX509Certs).click().clear().type(cert); + return this; + } + + public selectNamePolicyIdFormat() { + cy.get(this.nameIdPolicyFormat).scrollIntoView().click(); + } + + public selectPrincipalFormat() { + cy.get(this.principalType).scrollIntoView().click(); + } + + public selectSignatureAlgorithm(algorithm: string) { + cy.get(this.signatureAlgorithm).scrollIntoView().click(); + cy.findByText(algorithm).click(); + } + + public selectSAMLSignature(key: string) { + cy.get(this.samlSignatureKeyName).scrollIntoView().click(); + cy.findByText(key).click(); + } + + public selectComparison(comparison: string) { + cy.get(this.comparison).scrollIntoView().click(); + cy.findByText(comparison).scrollIntoView().click(); + } + + public assertIdAndURLFields() { + const ssoServiceUrlError = + "Could not update the provider The url [singleSignOnServiceUrl] is malformed"; + const singleLogoutServiceUrlError = + "Could not update the provider The url [singleLogoutServiceUrl] is malformed"; + this.typeServiceProviderEntityId("ServiceProviderEntityId"); + this.typeIdentityProviderEntityId("IdentityProviderEntityId"); + this.clickSaveBtn(); + + this.typeSsoServiceUrl("Not a real URL"); + this.clickSaveBtn(); + masthead.checkNotificationMessage(ssoServiceUrlError); + this.clickRevertBtn(); + + this.typeSingleLogoutServiceUrl("Not a real URL"); + this.clickSaveBtn(); + masthead.checkNotificationMessage(singleLogoutServiceUrlError); + return this; + } + + public assertNameIdPolicyFormat() { + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.transientPolicy).click(); + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.emailPolicy).click(); + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.kerberosPolicy).click(); + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.x509Policy).click(); + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.windowsDomainQNPolicy).click(); + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.unspecifiedPolicy).click(); + this.selectNamePolicyIdFormat(); + cy.findByTestId(this.persistentPolicy).click(); + return this; + } + + public assertSignatureAlgorithm() { + cy.get(this.wantAuthnRequestsSigned).parent().click(); + cy.get(this.signatureAlgorithm).should("not.exist"); + cy.get(this.samlSignatureKeyName).should("not.exist"); + this.clickRevertBtn(); + cy.get(this.signatureAlgorithm).should("exist"); + cy.get(this.samlSignatureKeyName).should("exist"); + + this.selectSignatureAlgorithm("RSA_SHA1"); + this.selectSignatureAlgorithm("RSA_SHA256"); + this.selectSignatureAlgorithm("RSA_SHA256_MGF1"); + this.selectSignatureAlgorithm("RSA_SHA512"); + this.selectSignatureAlgorithm("RSA_SHA512_MGF1"); + this.selectSignatureAlgorithm("DSA_SHA1"); + + this.selectSAMLSignature("NONE"); + this.selectSAMLSignature("KEY_ID"); + this.selectSAMLSignature("CERT_SUBJECT"); + + return this; + } + + public assertPrincipalType() { + this.selectPrincipalFormat(); + cy.findByTestId(this.principalAttributeName).click(); + cy.findByTestId(this.principalAttribute).should("exist").scrollIntoView(); + this.selectPrincipalFormat(); + cy.findByTestId(this.principalFriendlyAttribute).click(); + cy.findByTestId(this.principalAttribute).should("exist"); + this.selectPrincipalFormat(); + cy.findByTestId(this.principalSubjectNameId).click(); + cy.findByTestId(this.principalAttribute).should("not.exist"); + return this; + } + + public assertSAMLSwitches() { + cy.get(this.allowCreate).parent().click(); + cy.get(this.httpPostBindingResponse).parent().click(); + cy.get(this.httpPostBindingLogout).parent().click(); + cy.get(this.httpPostBindingAuthnRequest).parent().click(); + + cy.get(this.wantAssertionsSigned).parent().click(); + cy.get(this.wantAssertionsEncrypted).parent().click(); + cy.get(this.forceAuthentication).parent().click(); + + cy.get(this.signServiceProviderMetadata).parent().click(); + cy.get(this.passSubject).parent().click(); + + return this; + } + + public assertValidateSignatures() { + cy.get(this.validateSignature).parent().click(); + cy.findByTestId(this.validatingX509Certs).should("not.exist"); + cy.get(this.validateSignature).parent().click(); + this.typeX509Certs("X509 Certificate"); + this.clickRevertBtn(); + cy.findByTestId(this.validatingX509Certs); + this.clickSaveBtn(); + return this; + } + + public assertTextFields() { + cy.findByTestId(this.allowedClockSkew) + .click() + .type("not a number") + .should("be.empty") + .type("111"); + + cy.findByTestId(this.attributeConsumingServiceIndex) + .click() + .type("not a number") + .should("be.empty") + .type("111"); + + cy.findByTestId(this.attributeConsumingServiceName).click().type("name"); + } + + public assertAuthnContext() { + this.selectComparison("minimum"); + this.selectComparison("maximum"); + this.selectComparison("better"); + this.selectComparison("exact"); + return this; + } +} diff --git a/apps/admin-ui/src/identity-providers/add/DescriptorSettings.tsx b/apps/admin-ui/src/identity-providers/add/DescriptorSettings.tsx index fe7391a542..90181304fd 100644 --- a/apps/admin-ui/src/identity-providers/add/DescriptorSettings.tsx +++ b/apps/admin-ui/src/identity-providers/add/DescriptorSettings.tsx @@ -132,6 +132,7 @@ const Fields = ({ readOnly }: DescriptorSettingsProps) => { /> } fieldId="single-logout-service-url" + data-testid="single-logout-service-url" validated={ errors.config?.singleLogoutServiceUrl ? ValidatedOptions.error @@ -150,6 +151,7 @@ const Fields = ({ readOnly }: DescriptorSettingsProps) => { { { )} @@ -471,6 +477,7 @@ const Fields = ({ readOnly }: DescriptorSettingsProps) => { min="0" max="2147483" id="allowedClockSkew" + data-testid="allowedClockSkew" name="config.allowedClockSkew" ref={register} isReadOnly={readOnly} @@ -493,6 +500,7 @@ const Fields = ({ readOnly }: DescriptorSettingsProps) => { min="0" max="65535" id="attributeConsumingServiceIndex" + data-testid="attributeConsumingServiceIndex" name="config.attributeConsumingServiceIndex" ref={register} isReadOnly={readOnly} @@ -513,6 +521,7 @@ const Fields = ({ readOnly }: DescriptorSettingsProps) => {