Skip to content

Commit

Permalink
feat: cypress integration tests (#42)
Browse files Browse the repository at this point in the history
* initial commit integration tests

* way too many changes

* fix pepr init

* add cleanup command

* complete cac registration and login and cleanup

* final cleanup

* use bundle for testing

* update common

* update task descriptions

* no cache dev build

* format typescript code

* typo

---------

Co-authored-by: Rob Ferguson <rjferguson21@gmail.com>
  • Loading branch information
UnicornChance and rjferguson21 authored Apr 11, 2024
1 parent bade26d commit 12ea0cc
Show file tree
Hide file tree
Showing 28 changed files with 5,112 additions and 15 deletions.
40 changes: 37 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Environment setup
uses: defenseunicorns/uds-common/.github/actions/setup@fc12e3a773580020a1d63e254525eab0f8b99fc8
uses: defenseunicorns/uds-common/.github/actions/setup@5e4414dc25302739063bb58aa96b8afef5be9851 # v0.10.3

- name: Test building the docker image
run: uds run dev-build
Expand All @@ -40,7 +40,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Environment setup
uses: defenseunicorns/uds-common/.github/actions/setup@fc12e3a773580020a1d63e254525eab0f8b99fc8
uses: defenseunicorns/uds-common/.github/actions/setup@5e4414dc25302739063bb58aa96b8afef5be9851 # v0.10.3

- name: Test building a zarf package
run: uds run build-zarf-pkg
Expand All @@ -57,7 +57,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Environment setup
uses: defenseunicorns/uds-common/.github/actions/setup@fc12e3a773580020a1d63e254525eab0f8b99fc8
uses: defenseunicorns/uds-common/.github/actions/setup@5e4414dc25302739063bb58aa96b8afef5be9851 # v0.10.3

- name: Set up JDK 17
uses: actions/setup-java@v4
Expand All @@ -67,3 +67,37 @@ jobs:

- name: Plugin Unit Tests
run: mvn -B package --file src/plugin/pom.xml

uds_core_base_integration:
runs-on: ubuntu-latest
name: UDS Core + Identity Config smoke test with base realm.json
permissions:
pull-requests: read
contents: read

steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Environment setup
uses: defenseunicorns/uds-common/.github/actions/setup@5e4414dc25302739063bb58aa96b8afef5be9851 # v0.10.3

- name: Test building the docker image
run: uds run uds-core-smoke-test

uds_core_cypress_integration:
runs-on: ubuntu-latest
name: UDS Core + Identity Config cypress integration tests
permissions:
pull-requests: read
contents: read

steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Environment setup
uses: defenseunicorns/uds-common/.github/actions/setup@5e4414dc25302739063bb58aa96b8afef5be9851 # v0.10.3

- name: Test building the docker image
run: uds run uds-core-integration-tests
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ build/
zarf-sbom
tmp/
cacert.b64
csr.conf
ca.crt
ca.pem
ca.cer
test.cer
test.csr
test.pem
*authorized_certs*
uds-core/
./src/authorized_certs.zip
./tls_cacert.yaml
./test.pfx
src/extra-jars/
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ This repo builds the UDS Identity (Keycloak) Config image used by UDS Identity.
| cacert | Get the CA cert value for the Istio Gateway |
| debug-istio-traffic | Debug Istio traffic on keycloak |
| regenerate-test-pki | Generate a PKI cert for testing |
| uds-core-integration-test | Create cluster and deploy uds-core identity using local uds-identity-config image |
| uds-core-registration-integration-test | Web flow registration integration test |

## Customizing UDS Identity Config

Expand Down
44 changes: 44 additions & 0 deletions bundles/uds-bundle.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
kind: UDSBundle
metadata:
name: k3d-core-slim-dev
description: A UDS bundle for deploying Istio from UDS Core on a development cluster
version: "dev"

packages:
- name: uds-k3d-dev
repository: ghcr.io/defenseunicorns/packages/uds-k3d
# renovate: datasource=github-tags depName=defenseunicorns/uds-k3d versioning=semver
ref: 0.6.0

- name: init
repository: ghcr.io/defenseunicorns/packages/init
# renovate: datasource=github-tags depName=defenseunicorns/zarf versioning=semver
ref: v0.32.5

- name: keycloak-identity-config
path: ../
ref: dev

- name: core-slim-dev
path: ../uds-core/build/
# renovate: datasource=github-tags depName=defenseunicorns/uds-core versioning=semver
ref: 0.18.0
overrides:
keycloak:
keycloak:
variables:
- name: KEYCLOAK_CONFIG_IMAGE
description: "The keycloak config image to deploy plugin and initial setup configuration"
path: configImage
istio-admin-gateway:
uds-istio-config:
variables:
- name: ADMIN_TLS_CACERT
description: "The CA cert for the tenant gateway (must be base64 encoded)"
path: tls.cacert
istio-tenant-gateway:
uds-istio-config:
variables:
- name: TENANT_TLS_CACERT
description: "The CA cert for the tenant gateway (must be base64 encoded)"
path: tls.cacert
41 changes: 41 additions & 0 deletions docs/INTEGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Integration Testing For UDS Identity Config + UDS Core

[Cypress Web Flow/Integration Testing Docs](https://docs.cypress.io/guides/overview/why-cypress)

## Implemented Tests

| Test Name (link) | Test Description |
|------------------|------------------|
| [Login Existing User](../src/test/cypress/e2e/login.cy.ts) | Login in existing user that is created in the testing [realm.json](../src/test/cypress/realm.json) |
| [Login Nonexistant User / Incorrect creds](../src/test/cypress/e2e/login.cy.ts) | User cannot login / authenticate with incorrect creds or without account |
| [Successfuly CAC Registration](../src/test/cypress/e2e/registration.cy.ts) | New user can successfully register with CAC |
| [CAC User Login](../src/test/cypress/e2e/registration.cy.ts) | New user can successfully login with CAC |
| [Duplicate User Registration](../src/test/cypress/e2e/registration.cy.ts) | User cannot register more than once |
| [Password check for special characters](../src/test/cypress/e2e/registration.cy.ts) | User registration requires password special characters |
| [Password check for length](../src/test/cypress/e2e/registration.cy.ts) | User registration requires password length check |

## Cypress Testing
Using uds-cli task [`uds-core-integration-tests`](../../tasks.yaml).

Task explanation:
- Cleanup an existing uds-core directory ( mainly for local testing )
- Create docker image that uses the new certs as well as a testing realm.json ( has a defined user, no MFA, and no email verification )
- Clone [`uds-core`](https://github.com/defenseunicorns/uds-core) necessary for setting up k3d cluster to test against
- Use that cacert in deploying `uds-core` [istio gateways](https://github.com/defenseunicorns/uds-core/tree/main/src/istio/values)
- Create zarf package that combines uds-core and identity-config
- Setup k3d cluster by utilizing `uds-core` (istio, keycloak, pepr, zarf)
- Deploy zarf package that was created earlier
- Run cypress tests against deployed cluster

## Updating Cypress Certs

Cypress testing requires that a ca.cer be created and put into an authorized_certs.zip, done by using the `regenerate-test-pki` uds task, which is then utilized by the [Dockerfile](../src/Dockerfile). Once a docker image has been created another command is used for pulling that cacert, uds task `cacert`, from the image using it's value to configure uds-core's gateways, `uds-core-gateway-cacert` uds task . Eventually cypress will require a [pfx cert](../src/test/cypress/cypress.config.ts) for its CAC testing.

Our cypress testing utilizes [static certs](../src/test/cypress/certs/) that are created and saved to limit the need for constantly rebuilding and importing those certs.

Follow these steps to update the certs for cypress:
1. Run `uds run regenerate-test-pki` to regenerate the necessary certs and authorized_certs.zip
2. Run `docker build --build-arg CA_ZIP_URL="authorized_certs.zip" -t uds-core-config:keycloak --no-cache src` to create docker image
3. Run `uds run cacert` to extract cacert from docker image for the tls_cacert.yaml file
4. Copy the authorized_certs.zip, test.pfx, and tls_cacert.yaml into the [certs directory](../src/test/cypress/certs/)
- `mv test.pfx tls_cacert.yaml src/authorized_certs.zip src/cypress/certs/`
3 changes: 2 additions & 1 deletion src/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ COPY --chown=nonroot --from=truststore /home/build/authorized_certs.pem .
COPY --chown=nonroot --from=truststore /home/build/truststore.jks .

# The realm.json is loaded into Keycloak on startup only if the realm does not exist
COPY --chown=nonroot realm.json .
ARG REALM_FILE=realm.json
COPY --chown=nonroot ${REALM_FILE} .

# This provides the custom theme for the Keycloak instance
COPY --chown=nonroot theme theme
Expand Down
37 changes: 37 additions & 0 deletions src/csr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[req]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_ext

[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Colorado
localityName = Locality Name (eg, city)
localityName_default = Colorado Springs
organizationName = Organization Name (eg, company)
organizationName_default = Defense Unicorns
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = uds.dev

[req_ext]
subjectAltName = @alt_names

[v3_ext]
subjectAltName = @v3_alt_names
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = digitalSignature
extendedKeyUsage = clientAuth, 2.16.840.1.101.3.6.8
certificatePolicies = @policy_anything

[alt_names]
DNS.0 = *.uds.dev

[v3_alt_names]
otherName.0 = 2.16.840.1.101.3.6.6;UTF8:test@mil

[policy_anything]
policyIdentifier = 2.16.840.1.101.3.2.1.3.12
2 changes: 2 additions & 0 deletions src/test/cypress/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
cypress
13 changes: 13 additions & 0 deletions src/test/cypress/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"arrowParens": "avoid",
"bracketSameLine": true,
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"insertPragma": false,
"printWidth": 100,
"quoteProps": "as-needed",
"requirePragma": false,
"semi": true,
"useTabs": false,
"tabWidth": 2
}
3 changes: 3 additions & 0 deletions src/test/cypress/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Integration Testing For UDS Identity Config + UDS Core

See [docs](../../../docs/INTEGRATION.md)
Binary file added src/test/cypress/certs/authorized_certs.zip
Binary file not shown.
Empty file.
Binary file added src/test/cypress/certs/test.pfx
Binary file not shown.
2 changes: 2 additions & 0 deletions src/test/cypress/certs/tls_cacert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tls:
cacert: "Ci0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlEcVRDQ0FwR2dBd0lCQWdJVUE0WlU1ZWVQaGkxQWFLcEZybXAvcjUzV3VtQXdEUVlKS29aSWh2Y05BUUVMCkJRQXdaREVMTUFrR0ExVUVCaE1DVlZNeEdEQVdCZ05WQkFvTUQxVXVVeTRnUjI5MlpYSnViV1Z1ZERFTU1Bb0cKQTFVRUN3d0RSRzlFTVF3d0NnWURWUVFMREFOUVMwa3hIekFkQmdOVkJBTU1Ga1JQUkNCSlJDQkRRUzAxT1NCRwpRVXRGSUZSRlUxUXdIaGNOTWpRd05EQTBNVFF6TXpNMFdoY05Namt3TkRBek1UUXpNek0wV2pCa01Rc3dDUVlEClZRUUdFd0pWVXpFWU1CWUdBMVVFQ2d3UFZTNVRMaUJIYjNabGNtNXRaVzUwTVF3d0NnWURWUVFMREFORWIwUXgKRERBS0JnTlZCQXNNQTFCTFNURWZNQjBHQTFVRUF3d1dSRTlFSUVsRUlFTkJMVFU1SUVaQlMwVWdWRVZUVkRDQwpBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtkejk3dUovZ3RmVDRWbXFzMmZRUDRnCmVtd2lkQjJBd01iQ1ZaYzZMTEhCUi9oWG96Mk8xYTFGT3NwMlhPWldWT1llQTM1WVlMZVpOYjI1OEQ1eXBLdnYKVTI0V2xkWUZId1JFeUVEbmYvNzJZTytFcXJndkdlOFJyMnJhUTlzQ29tQ2w3K1N4TnBVdFdaM2x0OEtYKzFVRwpTV2lIT1phVG93ZFVFY3ZTWHJsNnkzcUZ6Vmw3MFErL0h5SnBzczl6OTBIZnpaMndDYld0aU1FK3BSVmhGenBsCjBaSi9mTzJjUUJUV1NOTnZTenhuTUZOYUExT3FRekp5ZWpueE5DVnRzYmJ1MmdaMk5VS2tQQmJYRmhMZlVLUHMKVStoQjJFVEt5OEFBYXVGVlkxMmtiZWlMTk5jSmJpQjZvRlJHNmNaK1VoSlRoN1pBY0pTRWNCSUVUTHk5RDgwQwpBd0VBQWFOVE1GRXdIUVlEVlIwT0JCWUVGT0RuOVNlSTU4cHU4bDZRUmpOMkZ3TmlTVE1TTUI4R0ExVWRJd1FZCk1CYUFGT0RuOVNlSTU4cHU4bDZRUmpOMkZ3TmlTVE1TTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFIc054NXBCN1UyWVlCb1hQTGxuUm1oYit6RkxHSTBqU3J4cjh1dFpSQTNHN25IaQpONFErY3NYOEFoY1lzbHVhNGNCanZSVnlHVU5ybVlldGczQmFidVlCb1BhS3VHM2lzUDJJZnBUMVNxNUFhTUFDCjlrc2RHcDZKV3RJdlFlQ3lBRGh2YUNYRHo1YWdDaFhsUFQ4T1ZaOEU2QUk4VDhxUXdtYXVCajBnbE5lZHVjb0EKdHpVSVBaWEtYVFJhVURnalhoRFNXWTNCK1kvWVp3S3lrdW40RFl4dkx0bXZ2NVEwZmtjVjVmYnVUbGtRbEJHYwowZWROZEYrOU5TZmIxcmtnSVo0RTVhYU5INDNTcHk5VzNxdkFYVDkwUlhEeDcxK0t4dkNSeTk5eW5ybFVsSDZTCksrdDJNNkgrcVAzc3A5OW44L2FyYzV2S0VKZWlSQVd1UmtMRmo0TT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
30 changes: 30 additions & 0 deletions src/test/cypress/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { defineConfig } from "cypress";

module.exports = defineConfig({
clientCertificates: [
{
url: "https://sso.uds.dev/**",
ca: [],
certs: [
{
pfx: "certs/test.pfx",
passphrase: "certs/pfx_passphrase.txt",
},
],
},
],

e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
retries: 3,
specPattern: "e2e/**/*.cy.ts",
supportFolder: "support/",
supportFile: "support/e2e.ts",
screenshotOnRunFailure: false,
video: false,
},

pageLoadTimeout: 12000,
});
35 changes: 35 additions & 0 deletions src/test/cypress/e2e/login.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { RegistrationFormData } from "../support/types";

describe("Login Flow", () => {
it("Existing User", () => {
// existing user created in test realm.json
const formData: RegistrationFormData = {
firstName: "Testing",
lastName: "User",
username: "testing_user",
password: "testingpassword!!",
};

cy.loginUser(formData.username, formData.password);

// skip the DoD PKI Detected Pop Up
cy.get("input#kc-cancel.btn.btn-light").click();

// Verify Successful Registration and on User Account Page
cy.get("#landingLoggedInUser")
.should("be.visible")
.and("contain", formData.firstName + " " + formData.lastName);
});

it("Invalid User Creds", () => {
const formData: RegistrationFormData = {
username: "testing_user",
password: "PrettyUnicorns!!",
};

cy.loginUser(formData.username, formData.password);

// user doesn't exist or password is incorrect
cy.contains("span", "Invalid username or password.").should("be.visible");
});
});
Loading

0 comments on commit 12ea0cc

Please sign in to comment.