From dfd1a7e78d46b4877afef9acc90ac8e0f389faec Mon Sep 17 00:00:00 2001 From: Matt Fellows <53900+mefellows@users.noreply.github.com> Date: Thu, 26 Jun 2025 13:29:52 +1000 Subject: [PATCH 1/2] chore: documentation and release notes for 2.0.0 release PACT-4181 --- website/docs/docs/on-premises-2x.md | 57 ++ .../docs/on-premises-2x/authentication.md | 16 + .../on-premises-2x/authentication/demo.md | 29 + .../on-premises-2x/authentication/oauth2.md | 48 ++ .../on-premises-2x/authentication/saml.md | 128 ++++ website/docs/docs/on-premises-2x/database.md | 60 ++ .../on-premises-2x/docker-compose-example.md | 128 ++++ .../on-premises-2x/docker-image-registry.md | 50 ++ .../on-premises-2x/environment-variables.md | 646 ++++++++++++++++++ .../environment-variables/1.14-beta.md | 259 +++++++ .../environment-variables/jwt.md | 109 +++ .../environment-variables/oauth2.md | 193 ++++++ .../environment-variables/templates.md | 75 ++ .../environment-variables/timezones.md | 601 ++++++++++++++++ .../on-premises-2x/installation/checklist.md | 43 ++ .../installation/load-testing.md | 28 + .../migrating-from-pact-broker.md | 41 ++ website/docs/docs/on-premises-2x/license.md | 66 ++ website/docs/docs/on-premises-2x/logging.md | 15 + .../on-premises-2x/maintenance/database.md | 274 ++++++++ .../on-premises-2x/network-configuration.md | 27 + website/docs/docs/on-premises-2x/redis.md | 38 ++ .../docs/on-premises-2x/releases/1.10.0.md | 17 + .../docs/on-premises-2x/releases/1.11.0.md | 72 ++ .../docs/on-premises-2x/releases/1.11.1.md | 11 + .../docs/on-premises-2x/releases/1.12.0.md | 14 + .../docs/on-premises-2x/releases/1.13.0.md | 11 + .../docs/on-premises-2x/releases/1.13.1.md | 11 + .../docs/on-premises-2x/releases/1.14.0.md | 30 + .../docs/on-premises-2x/releases/1.14.1.md | 11 + .../docs/on-premises-2x/releases/1.14.2.md | 15 + .../docs/on-premises-2x/releases/1.14.3.md | 15 + .../docs/on-premises-2x/releases/1.14.4.md | 17 + .../docs/on-premises-2x/releases/1.14.5.md | 15 + .../docs/on-premises-2x/releases/1.14.6.md | 19 + .../docs/on-premises-2x/releases/1.14.7.md | 15 + .../docs/on-premises-2x/releases/1.14.8.md | 15 + .../docs/on-premises-2x/releases/1.15.0.md | 18 + .../docs/on-premises-2x/releases/1.16.0.md | 15 + .../docs/on-premises-2x/releases/1.17.0.md | 15 + .../docs/on-premises-2x/releases/1.17.1.md | 12 + .../docs/on-premises-2x/releases/1.17.2.md | 11 + .../docs/on-premises-2x/releases/1.17.3.md | 11 + .../docs/on-premises-2x/releases/1.18.0.md | 28 + .../docs/on-premises-2x/releases/1.19.0.md | 20 + .../docs/on-premises-2x/releases/1.19.1.md | 12 + .../docs/on-premises-2x/releases/1.19.2.md | 11 + .../docs/on-premises-2x/releases/1.20.0.md | 18 + .../docs/on-premises-2x/releases/1.21.0.md | 16 + .../docs/on-premises-2x/releases/1.21.1.md | 11 + .../docs/on-premises-2x/releases/1.22.0.md | 26 + .../docs/on-premises-2x/releases/1.22.1.md | 16 + .../docs/on-premises-2x/releases/1.23.0.md | 16 + .../docs/on-premises-2x/releases/1.23.1.md | 11 + .../docs/on-premises-2x/releases/1.24.0.md | 25 + .../docs/on-premises-2x/releases/1.25.0.md | 22 + .../docs/on-premises-2x/releases/1.26.0.md | 51 ++ .../docs/on-premises-2x/releases/1.27.0.md | 27 + .../docs/on-premises-2x/releases/1.28.0.md | 27 + .../docs/on-premises-2x/releases/1.29.0.md | 25 + .../docs/on-premises-2x/releases/1.30.0.md | 25 + .../docs/on-premises-2x/releases/1.31.0.md | 31 + .../docs/on-premises-2x/releases/1.32.0.md | 25 + .../docs/on-premises-2x/releases/1.33.0.md | 21 + .../docs/on-premises-2x/releases/1.34.0.md | 27 + .../docs/on-premises-2x/releases/1.35.0.md | 29 + .../docs/on-premises-2x/releases/1.36.0.md | 23 + .../docs/on-premises-2x/releases/1.4.0.md | 10 + .../docs/on-premises-2x/releases/1.4.1.md | 7 + .../docs/on-premises-2x/releases/1.5.0.md | 8 + .../docs/on-premises-2x/releases/1.6.0.md | 10 + .../docs/on-premises-2x/releases/1.6.1.md | 7 + .../docs/on-premises-2x/releases/1.7.0.md | 11 + .../docs/on-premises-2x/releases/1.8.0.md | 16 + .../docs/on-premises-2x/releases/1.9.0.md | 18 + website/docs/docs/on-premises-2x/scim.md | 288 ++++++++ .../on-premises-2x/security-audit-report.md | 199 ++++++ .../docs/on-premises-2x/support-policy.md | 58 ++ .../on-premises-2x/system-requirements.md | 135 ++++ .../docs/on-premises-2x/troubleshooting.md | 47 ++ website/docs/docs/on-premises-2x/upgrading.md | 5 + .../upgrading/database-migrations.md | 70 ++ .../docs/docs/on-premises/releases/2.0.0.md | 43 ++ .../notices/2025-06-27-on-premises-2.0.0.md | 7 + website/sidebars.js | 133 +++- website/static/img/saas-architecture-2x.png | Bin 0 -> 253406 bytes 86 files changed, 4913 insertions(+), 3 deletions(-) create mode 100644 website/docs/docs/on-premises-2x.md create mode 100644 website/docs/docs/on-premises-2x/authentication.md create mode 100644 website/docs/docs/on-premises-2x/authentication/demo.md create mode 100644 website/docs/docs/on-premises-2x/authentication/oauth2.md create mode 100644 website/docs/docs/on-premises-2x/authentication/saml.md create mode 100644 website/docs/docs/on-premises-2x/database.md create mode 100644 website/docs/docs/on-premises-2x/docker-compose-example.md create mode 100644 website/docs/docs/on-premises-2x/docker-image-registry.md create mode 100644 website/docs/docs/on-premises-2x/environment-variables.md create mode 100644 website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md create mode 100644 website/docs/docs/on-premises-2x/environment-variables/jwt.md create mode 100644 website/docs/docs/on-premises-2x/environment-variables/oauth2.md create mode 100644 website/docs/docs/on-premises-2x/environment-variables/templates.md create mode 100644 website/docs/docs/on-premises-2x/environment-variables/timezones.md create mode 100644 website/docs/docs/on-premises-2x/installation/checklist.md create mode 100644 website/docs/docs/on-premises-2x/installation/load-testing.md create mode 100644 website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md create mode 100644 website/docs/docs/on-premises-2x/license.md create mode 100644 website/docs/docs/on-premises-2x/logging.md create mode 100644 website/docs/docs/on-premises-2x/maintenance/database.md create mode 100644 website/docs/docs/on-premises-2x/network-configuration.md create mode 100644 website/docs/docs/on-premises-2x/redis.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.10.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.11.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.11.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.12.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.13.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.13.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.2.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.3.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.4.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.5.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.6.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.7.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.14.8.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.15.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.16.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.17.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.17.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.17.2.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.17.3.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.18.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.19.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.19.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.19.2.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.20.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.21.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.21.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.22.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.22.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.23.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.23.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.24.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.25.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.26.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.27.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.28.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.29.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.30.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.31.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.32.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.33.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.34.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.35.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.36.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.4.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.4.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.5.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.6.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.6.1.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.7.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.8.0.md create mode 100644 website/docs/docs/on-premises-2x/releases/1.9.0.md create mode 100644 website/docs/docs/on-premises-2x/scim.md create mode 100644 website/docs/docs/on-premises-2x/security-audit-report.md create mode 100644 website/docs/docs/on-premises-2x/support-policy.md create mode 100644 website/docs/docs/on-premises-2x/system-requirements.md create mode 100644 website/docs/docs/on-premises-2x/troubleshooting.md create mode 100644 website/docs/docs/on-premises-2x/upgrading.md create mode 100644 website/docs/docs/on-premises-2x/upgrading/database-migrations.md create mode 100644 website/docs/docs/on-premises/releases/2.0.0.md create mode 100644 website/notices/2025-06-27-on-premises-2.0.0.md create mode 100644 website/static/img/saas-architecture-2x.png diff --git a/website/docs/docs/on-premises-2x.md b/website/docs/docs/on-premises-2x.md new file mode 100644 index 00000000..f0ead206 --- /dev/null +++ b/website/docs/docs/on-premises-2x.md @@ -0,0 +1,57 @@ +--- +title: PactFlow On-Premises Architecture +sidebar_label: Architecture +--- + +## System architecture + +### Minimum requirements + +* An application server capable of running Docker +* PostgreSQL database +* Redis cache +* SAML IDP for SSO +* PactFlow license file + +### Recommended architecture + +* Deploy to a service designed for Docker container orchestration (ECS, Fargate, Kubernetes etc.) + +### Example AWS deployment using ECS + +![System architecture](/img/saas-architecture-2x.png) + +## Internal architecture + +The PactFlow On-Premises application is distributed as a Docker image. It is based on the open source [Pact Broker](https://github.com/pact-foundation/pact_broker), which is a Ruby application. + +### Application user requirements + +The PactFlow application does not need any elevated privileges to run. It runs under the user `app`. + +### Application port + +The PactFlow application runs on port `9292` by default. This can be configured by setting the [PACTFLOW_HTTP_PORT](/docs/on-premises/environment-variables#pactflow_http_port) environment variable. + +### Healthcheck endpoint + +A healthcheck endpoint for use by a Docker container managment service is available at `http:///diagnostic/status/heartbeat`. No authentication is required. This endpoint does not make a connection to the database. You can use this check to confirm your load balancer targets are healthy. + +If the healthcheck is running from inside the container, make sure to use the port defined in the environment variable `$PACTFLOW_HTTP_PORT`, which defaults to `9292`. You can use `supervisorctl` to perform the healthcheck request. + +An example healthcheck configuration for Docker Compose: + +```yaml +healthcheck: + test: ["supervisorctl", "status", "haproxy", "marko", "pactflow"] + interval: 30s + timeout: 10s + retries: 3 +``` + +To check the connection to the database, use the endpoint `/diagnostic/status/dependencies`. This endpoint should not be used by Docker container managment services, as unrelated database issues might cause the Docker container to churn. + +### License file + +PactFlow on-premises version requires a license file to run. [Contact us](https://support.smartbear.com/pactflow/message/) if you have not +received one when your account was setup. See the [section on licenses for installation instructions](/docs/on-premises/license). diff --git a/website/docs/docs/on-premises-2x/authentication.md b/website/docs/docs/on-premises-2x/authentication.md new file mode 100644 index 00000000..3684ff6a --- /dev/null +++ b/website/docs/docs/on-premises-2x/authentication.md @@ -0,0 +1,16 @@ +--- +title: Authentication +--- + +## User interface + +The PactFlow On-Premises application currently supports single sign for SAML identity providers. It supports both IDP and SP initiated log in. + +Any user who is able to authenticate to the configured IDP is allowed access to PactFlow. + +The SAML IDP is configured via [environment variables](environment-variables#saml-authentication). + +## API + +The API is accessed using a bearer token that is set in the HTTP header of the request (eg. `Authorization: Bearer `). The tokens are administered on a per user basis in the [settings page](/docs/user-interface/settings/api-tokens) of the PactFlow application. + diff --git a/website/docs/docs/on-premises-2x/authentication/demo.md b/website/docs/docs/on-premises-2x/authentication/demo.md new file mode 100644 index 00000000..c9544f14 --- /dev/null +++ b/website/docs/docs/on-premises-2x/authentication/demo.md @@ -0,0 +1,29 @@ +--- +title: Demo Auth +--- + +To allow experimentation with PactFlow without the need to configure an external identity provider, the "demo" authentication provider can be enabled. With demo auth enabled, any user can log in to PactFlow by providing a name and email address. No password is used to authenticate the user. + +The first user to log in will be assigned the [Administrator](/docs/permissions/predefined-roles#administrator) role, and every user thereafter will receive the default ([User](/docs/permissions/predefined-roles#user)) role. + +After a user has logged in, they may perform all the actions their role allows, as if they were a user created via a real identify provider. + +:::caution + +This method of authentication is NOT secure and should not be used in production. + +::: + +Demo auth replaces the basic auth capability that was previously used for this purpose. + +## Configuration + +See the [Demo](/docs/on-premises-2x/environment-variables#demo_auth_enabled) section of the environment variables page. Demo auth cannot be enabled at the same time as any other method of authentication (ie. SAML). + +## Converting to a production IDP + +Demo authentication cannot be enabled at the same time as a real authentication provider (eg. SAML). We recommend starting with a clean database when installing PactFlow for production use. This will ensure no demo users remain in the system. + +## Docker Compose example + +This [Docker Compose example](/docs/on-premises-2x/docker-compose-example) is configured using Demo Auth. diff --git a/website/docs/docs/on-premises-2x/authentication/oauth2.md b/website/docs/docs/on-premises-2x/authentication/oauth2.md new file mode 100644 index 00000000..81aea089 --- /dev/null +++ b/website/docs/docs/on-premises-2x/authentication/oauth2.md @@ -0,0 +1,48 @@ +--- +title: OAuth2 +--- + +## Configuration + +An OAuth2 identify provider is configured by a set of environment variables prefixed with `PACTFLOW_TEST_OAUTH2_`, or using the `test_oauth2` key in a YAML configuration file. See the [Test OAuth2](/docs/on-premises-2x/environment-variables/1.14-beta) section of the environment variables page for the full list. + +## Callback URL + +The callback URL is `https:///auth/oauth2/callback`. This must be configured in the settings for the PactFlow client in your Identify Provider. + +## Authorize params + +The following parameters are sent to the Identity Provider's configured [`authorize_url`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__authorize_url) during the request phase. + +| Parameter | Description | +|-----------|-------------| +| scope | `openid profile email` | +| response_type | `code` | +| response_mode | `form_post` | +| state | A randomly generated hex string | +| client_id | The configured [client_id](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__client_id) | +| redirect_uri | The [callback URL](#callback-url) as documented above | + +The parameters configured in the [`custom_authorize_params`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__custom_authorize_params__key) are also merged into these default parameters. + +## Token params + +The following parameters are sent to the Identity Provider's configured [`token_url`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__token_url). + +| Parameter | Description | +|-----------|-------------| +| code | The `code` returned by the IDP during the callback phase. | +| grant_type | `authorization_code` | +| client_id | The configured [client_id](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__client_id) | +| client_secret | The configured [client_secret](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__client_secret) | +| redirect_uri | The [callback URL](#callback-url) as documented above | + +The parameters configured in the [`custom_token_params`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__custom_token_params__key) are also merged into these default parameters. + +## Custom Auth handler + +At the end of the OAuth2 login flow, a JWT is retrieved by PactFlow from the customer's Identify Provider. A custom Ruby auth handler configuration file will be supplied by PactFlow to map claims from the JWT to PactFlow roles and teams. The auth handler configuration file must be mounted as a volume on the PactFlow container, in the directory `/home/pactflow/extensions/` eg. `/home/pactflow/extensions/auth_ext_script.rb`. + +## Debugging + +The URLs and headers of the HTTP interactions with the Identity Provider will be logged at `info` level in the PactFlow logs. To see the request and response bodies, set the `PACTFLOW_LOG_LEVEL` to `debug`. Note that this will log sensitive information, so do not leave the logging at this level permanently. diff --git a/website/docs/docs/on-premises-2x/authentication/saml.md b/website/docs/docs/on-premises-2x/authentication/saml.md new file mode 100644 index 00000000..b3840c69 --- /dev/null +++ b/website/docs/docs/on-premises-2x/authentication/saml.md @@ -0,0 +1,128 @@ +--- +title: SAML +--- + +PactFlow supports single sign on using the SAML authentication protocol. + +Once SAML has been configured, if the database contains no users, the first user to log in will be assigned the [Administrator](/docs/permissions/predefined-roles#administrator) role, and every user thereafter will receive the default ([User](/docs/permissions/predefined-roles#user)) role. + +## Configuration + +A SAML provider is configured by a set of environment variables prefixed with `PACTFLOW_SAML_`. See the [SAML](/docs/on-premises-2x/environment-variables#saml-authentication) section of the environment variables page for the full list. + +## Assertion Consumer URL + +This is the endpoint to which the IDP will post the SAML assertion after the user is authenticated. It is also called the "sign on URL", "reply URL", and "callback URL", depending on your IDP. You will need to configure this value in your IDP when you set up the PactFlow service provider. + +The URL is `https:///auth/saml/callback`. + +## Metadata URL + +The PactFlow SAML service provider metadata URL is available at `https:///auth/saml/metadata`. + +## Configuring multiple SAML providers + +In PactFlow 1.7.0 and later, multiple SAML providers may be configured. To configure a second SAML provider, create another set of the [SAML environment variables](/docs/on-premises-2x/environment-variables#saml-authentication) with the prefix `PACTFLOW_SAML_2_` (and `PACTFLOW_SAML_3_` for the third, etc). The `PACTFLOW_SAML_ISSUER` does not need to be specified again, as it is shared between all SAML providers. + +The callback path for the second provider is `/auth/saml/2/callback`, and for the third `/auth/saml/3/callback` etc. The path for the metadata for subsequent SAML providers will be `/auth/saml/2/metadata`, `/auth/saml/3/metadata` etc. + +## Configuring Azure Active Directory + +### Create a non gallery application + +* Follow the [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/add-non-gallery-app) for creating a non gallery application. + * Choose `Non-gallery application` at the `Add your own app` screen. + * Set the name to `PactFlow On-Premesis` when prompted. + +* When the application has been created, assign the users that should be allowed to login to PactFlow. + +* Once the users have been assigned, select the `Single sign-on` tab. Select `SAML`. + +* Set the Identifier (Entity ID) to `https://pactflow.` eg. `https://pactflow.mycompany.com`. This field must match the [PACTFLOW_SAML_ISSUER]../(environment-variables#pactflow_saml_issuer) environment variable. + +* Set the Reply URL to `https:///auth/saml/callback` + +* Leave the Sign On URL, Relay State and Logout Url fields blank. + +### Configure the PactFlow environment variables + +You can find a template for the required environment variables [here](/docs/on-premises-2x/environment-variables/templates#azure-active-directory). + +* Set the [PACTFLOW_SAML_ISSUER](/docs/on-premises-2x/environment-variables#pactflow_saml_issuer) to the `Identifier (Entity ID)`. +* Set the [PACTFLOW_SAML_IDP_SSO_TARGET_URL](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_sso_target_url) to the `Login URL`. +* Set the [PACTFLOW_SAML_IDP_ENTITY_ID](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_entity_id) to the `Azure AD Identifier` +* Set the [PACTFLOW_SAML_IDP_CERT_FINGERPRINT](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_cert_fingerprint) to the `Thumbprint` +* Set the [PACTFLOW_SAML_IDP_NAME](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_name) to your choice - this is a display name for the login button. +* Set the identifier, email and name attributes as per the [template](/docs/on-premises-2x/environment-variables#/templates#azure-active-directory). + + +## Docker Compose Example + +Follow [steps 1 and 2](/docs/on-premises-2x/docker-compose-example) from the Docker Compose example that uses Demo Auth, then use the following `docker-compose.yml` file to run your services. + +``` +version: "3" + +services: + simplesaml: + image: kristophjunge/test-saml-idp + logging: + driver: none # comment out the logging config to see the SAML server logs + ports: + - "8080:8080" + - "8443:8443" + environment: + - SIMPLESAMLPHP_SP_ENTITY_ID=https://pactflow.io + - SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost/auth/saml/callback + + pactflow: + image: quay.io/pactflow/enterprise + depends_on: + - postgres + environment: + - PACTFLOW_HTTP_PORT=9292 + - PACTFLOW_BASE_URL=http://localhost + - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres + # insecure settings only for the purposes of this demo! Not to be used in production. + - PACTFLOW_DATABASE_SSLMODE=disable + - PACTFLOW_REQUIRE_HTTPS=false + - PACTFLOW_LOG_FORMAT=short # normally this would be set to json, use short for demo only + - PACTFLOW_ADMIN_API_KEY=admin + - PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY=thisissomerandombytes + - PACTFLOW_SAML_AUTH_ENABLED=true + - PACTFLOW_SAML_IDP_NAME=Simple SAML + - PACTFLOW_SAML_IDP_SSO_TARGET_URL=http://localhost:8080/simplesaml/saml2/idp/SSOService.php + - PACTFLOW_SAML_IDP_CERT_FINGERPRINT=11:9B:9E:02:79:59:CD:B7:C6:62:CF:D0:75:D9:E2:EF:38:4E:44:5F + - PACTFLOW_SAML_IDP_ID_ATTRIBUTE=uid + - PACTFLOW_SAML_EMAIL_ATTRIBUTE=email + - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- + - PACT_BROKER_ADMIN_API_KEY=admin + - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ + ports: + - "80:9292" + healthcheck: + test: ["CMD", "wget", "-nv", "-t1", "--spider", "http://localhost:9292/diagnostic/status/heartbeat"] + interval: 30s + timeout: 10s + retries: 3 + entrypoint: dockerize + command: -wait tcp://postgres:5432 docker-entrypoint + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic + + postgres: + image: postgres:13-alpine + healthcheck: + test: psql postgres --command "select 1" -U postgres + ports: + - "5432:5432" + volumes: + - postgres-volume:/var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: postgres + +volumes: + postgres-volume: +``` diff --git a/website/docs/docs/on-premises-2x/database.md b/website/docs/docs/on-premises-2x/database.md new file mode 100644 index 00000000..7716694e --- /dev/null +++ b/website/docs/docs/on-premises-2x/database.md @@ -0,0 +1,60 @@ +--- +title: Database +--- + +A PostgreSQL database is required for storage of the application data. + +:::info + If you would like to migrate an existing PostgreSQL database, skip this section and instead follow the guide [**here**](/docs/on-premises-2x/installation/migrating). +::: + +## Supported versions + +PostgreSQL version 10.6 and later are supported. + +## Database creation + +Log in as your database administrator, and execute the following statements in an SQL session. + +```sql +CREATE USER pactflow_user WITH PASSWORD ''; +CREATE DATABASE pactflow; +GRANT ALL PRIVILEGES ON DATABASE pactflow TO pactflow_user; +REVOKE ALL ON DATABASE pactflow FROM PUBLIC; +``` + +## SSL + +The application's PostgreSQL SSL mode is set to `require` by default, which means it requires the connection to the database to be encrypted, but does not verify the server's certificate. See the documentation for the [PACTFLOW_DATABASE_SSLMODE](environment-variables#pactflow_database_sslmode) environment variable for more options. It is not recommended to use any option weaker than `require`. + +## Authentication + +## Username/password authentication + +Database access between the PactFlow application and Postgres instance can be secured using a [username](/docs/on-premises-2x/environment-variables#pactflow_database_username) and [password](/docs/on-premises-2x/environment-variables#pactflow_database_password), configured via environment variables. + +## AWS IAM authentication + +When deploying PactFlow on AWS Cloud infrastructure, database access between the PactFlow application and the RDS Postgres instance can be secured using IAM. Please see the [AWS RDS IAM documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAM.html) for more information. + +The following environmet variables must be set for the PactFlow application: + +* [`PACTFLOW_DATABASE_ADAPTER="postgresiam"`](/docs/on-premises-2x/environment-variables#pactflow_database_adapter) +* [`PACTFLOW_DATABASE_USERNAME`](/docs/on-premises-2x/environment-variables#pactflow_database_username) +* [`PACTFLOW_DATABASE_HOST`](/docs/on-premises-2x/environment-variables#pactflow_database_host) +* [`PACTFLOW_DATABASE_PORT`](/docs/on-premises-2x/environment-variables#pactflow_database_port) +* [`PACTFLOW_DATABASE_NAME`](/docs/on-premises-2x/environment-variables#pactflow_database_name) +* [`PACTFLOW_DATABASE_SSLMODE="require"`](/docs/on-premises-2x/environment-variables#pactflow_database_sslmode) +* [`AWS_REGION`](/docs/on-premises-2x/environment-variables#aws_region) + +## Schema migrations + +The database schema migrations will be run automatically on start up. See the documentation on [Database migrations](upgrading/database-migrations) for more information. + +### Migrating from OSS Pact Broker to PactFlow + +If you have been hosting your own instance of the open source Pact Broker, you can point the new PactFlow On-Premises application at the same database, and the missing migrations will be applied. + +## Schema + +![Database schema](/on-premises/schema.png) diff --git a/website/docs/docs/on-premises-2x/docker-compose-example.md b/website/docs/docs/on-premises-2x/docker-compose-example.md new file mode 100644 index 00000000..2b5cd739 --- /dev/null +++ b/website/docs/docs/on-premises-2x/docker-compose-example.md @@ -0,0 +1,128 @@ +--- +title: Docker Compose example +--- + +In this guide, we'll provide an example `docker compose` setup so that you can see how all of the bits hang together. We will demonstrate: + +* Authenticating to Quay.io +* Running the PactFlow enterprise container +* Persistent storage with a postgres database + +**Pre-requsites** +* [Docker](https://docs.docker.com/engine/install/) +* [Docker Compose](https://docs.docker.com/compose/install/) +* A working *nix environment and access to a terminal +* Valid credentials to authenticate to our [Docker image registry](docker-image-registry) +* PactFlow license file + +## 1. Authenticating to Quay.io + +After obtaining valid robot credentials, you need to authenticate to Quay.io so that the docker engine is able to fetch our images. + +``` +docker login -u="" -p="" quay.io +docker pull quay.io/pactflow/enterprise +``` + +After this, you should have the latest PactFlow enterprise image on your machine. You can verify by executing + +```sh +docker images quay.io/pactflow/enterprise +``` + +Which should produce an output such as: + +```sh +> docker images quay.io/pactflow/enterprise +REPOSITORY TAG IMAGE ID CREATED SIZE +quay.io/pactflow/enterprise 2.0.0 32db429fda01 1 day ago 462MB # <- this guide applies to 2.x.x version +quay.io/pactflow/enterprise latest 32db429fda01 1 day ago 462MB +quay.io/pactflow/enterprise 1.36.0 7f9b3c3aa50e 7 weeks ago 454MB +``` + +## 2. PactFlow license file + +The PactFlow on-premises version requires a license file to run. You should have received this from us during the +on-boarding process. If not, please contact your Account Manager. + +Save the license file into a temporary directory with the name `pactflow-onprem.lic` (it needs to be the same directory as used in step 3). + +## 3. Startup PactFlow and supporting services + +Save the below file as `docker-compose.yml` in the same directory as the license file and then run `docker-compose up`: + +```yaml +version: "3" + +services: + pactflow: + image: quay.io/pactflow/enterprise:2.0.0 + depends_on: + - postgres + - redis + environment: + # This is set to localhost for this example but in a real deployment, this needs to be set to the actual URL of the application + - PACTFLOW_BASE_URL=http://localhost + # Insecure setting only for the purposes of this demo! Not to be used in production. + - PACTFLOW_DATABASE_SSLMODE=disable + # Insecure setting only for the purposes of this demo! Not to be used in production. + - PACTFLOW_REQUIRE_HTTPS=false + # Demo auth should only be used for demo purposes. Not to be used in production. + - PACTFLOW_DEMO_AUTH_ENABLED=true + # 'Allow all' for the webhook host whitelist should only be used for demo purposes. See docs for configuring this in production. + - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ + - PACTFLOW_HTTP_PORT=9292 + # Link to the postgres database + - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres + - PACTFLOW_LOG_LEVEL=info + - PACTFLOW_ADMIN_API_KEY=admin + - PACTFLOW_MASTER_ENCRYPTION_KEY=thisissomerandombytes + - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- + - PACT_BROKER_ADMIN_API_KEY=admin + - PACTFLOW_HTTP_LOGGING_ENABLED=true + # Link to the redis cache + - REDIS_URL=redis://redis:6379 + ports: + - "80:9292" + healthcheck: + test: ["CMD", "supervisorctl", "status", "haproxy", "marko", "pactflow"] + interval: 30s + timeout: 10s + retries: 3 + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic + + postgres: + image: postgres:13-alpine + healthcheck: + test: psql postgres --command "select 1" -U postgres + volumes: + - postgres-volume:/var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: postgres + + redis: + image: redis:latest + +volumes: + postgres-volume: +``` + +You can verify all services by running `docker ps`: + +``` +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +1cefdf8b1e1b quay.io/pactflow/enterprise:2.0.0 "docker-entrypoint" 24 minutes ago Up 24 minutes (healthy) 0.0.0.0:80->9292/tcp tmp_pactflow_1 +6bedae5936dc redis:latest "docker-entrypoint.s…" 2 hours ago Up 24 minutes 6379/tcp tmp_redis_1 +8b393d35a20c postgres:13-alpine "docker-entrypoint.s…" 9 days ago Up 24 minutes (healthy) 5432/tcp tmp_postgres_1 +``` + +## 3. Login to PactFlow + +Head to [http://localhost](http://localhost) in your browser, and choose to login with "PACTFLOW DEMO AUTH". Provide a name and email address to create your account and login. (The details don't need to be valid, and won't be used to send any emails.) + +That's it 🎉. + +For production use, you'll need to replicate this setup using a proper container orchestration tool, such as Kubernetes, AWS ECS/Fargate, AKS, GKE, Mesos etc, and your real Identity Provider. diff --git a/website/docs/docs/on-premises-2x/docker-image-registry.md b/website/docs/docs/on-premises-2x/docker-image-registry.md new file mode 100644 index 00000000..8a2f6880 --- /dev/null +++ b/website/docs/docs/on-premises-2x/docker-image-registry.md @@ -0,0 +1,50 @@ +--- +title: Docker image registry +--- + +## Accessing the Enterprise PactFlow container registry + +Docker images for our self-hosted PactFlow Enterprise product are hosted at [Quay](http://quay.io). We will provide Quay.io access for you when signing up to the product. + +### User Account Access + +:::note +If you are on a PactFlow trial, creating a RedHat account is **not** required. You will be issued a separate set of credentials (see [CI Access](#ci-access) below) by your Account Manager for the duration of the trial. +::: + +To set you up with console access, you will need to create a [RedHat account](https://quay.io/signin/). Choose "Register for a RedHat account" and once comwpleted, provide the username/email address to us to add you to the registry. + +Once we have granted access to your given email address, you should receive an email from Red Hat Quay confirming access to the PactFlow organization. + +### CI Access + +In additional to user access, we will create you one or more [Robot Accounts](https://docs.quay.io/glossary/robot-accounts.html) for use in CI. + +## Getting started + +Once we have created you a new user, you will receive an email from Quay.io inviting you to join a new team and a license file from us. You can setup the new account as follows: + +1. Make sure you have received a PactFlow on-premises license file from your Account Manager +1. You should receive an email from Red Hat Quay, requesting you join a team `pactflow/`: + + ![Join PactFlow repository email](/on-premises/quay-join-team-email.png) + +1. Follow the link in your email to login to an existing accoun + + +1. You will be added to the correct team and you should then see our Enterprise repository (click [Repositories](https://quay.io/repository/) in the menu bar to see this): + + ![Completed signup](/on-premises/quay-completed.png) + +1. You should now have access to the `enterprise` repository in the `pactflow` organization. + +1. You can now sign in with your account (in addition to your Robot Account) to quay to pull docker images. See [getting started with Quay.io](https://docs.quay.io/solution/getting-started.html) for more on this. + +## Downloading the image + +With your personal credentials or Robot token (provided by your PactFlow Account Manager), you can login to your docker management system and pull the image: + +```sh +docker login -u="" -p="" quay.io # you can use either the robot token or your user credentials here +docker pull quay.io/pactflow/enterprise +``` diff --git a/website/docs/docs/on-premises-2x/environment-variables.md b/website/docs/docs/on-premises-2x/environment-variables.md new file mode 100644 index 00000000..c8a60327 --- /dev/null +++ b/website/docs/docs/on-premises-2x/environment-variables.md @@ -0,0 +1,646 @@ +--- +title: Environment variables +--- + + + + + +## Logging + +
+ + + +### PACTFLOW_LOG_LEVEL + +The PactFlow application log level + +**Required:** false
+**Default:** `INFO`
+**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
+ +### PACTFLOW_HTTP_LOGGING_ENABLED + +When true, HTTP request details and response status and duration will be logged to stdout in json format + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +## Monitoring + +
+ + + +### NEW_RELIC_AGENT_ENABLED + +Set this to true to enable New Relic application monitoring. The New Relic config file should be mounted at /home/pactflow/config/newrelic.yml + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +## Database + +
+ + + +### PACTFLOW_DATABASE_URL + +The fully qualified database connection string. If using Postgres on RDS with IAM authentication, the scheme must be `postgresiam` and the port must also be set. + +**Required:** if separate host, name, username, password environment variables are not set
+**Example:** `postgresql://username:password@host:port/database`
+ +### PACTFLOW_DATABASE_ADAPTER + +The database adapter to use. Use `postgresiam` when using Postgres on RDS with IAM authentication (rather than username/password authentication). + +**Required:** false
+**Default:** `postgres`
+**Allowed values:** `postgres`, `postgresiam`
+ +### PACTFLOW_DATABASE_USERNAME + +The database username + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +### PACTFLOW_DATABASE_PASSWORD + +The database password + +**Required:** if PACTFLOW_DATABASE_URL is not set, unless using Postgres on RDS with IAM authentication
+ +### PACTFLOW_DATABASE_HOST + +The database host + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +### PACTFLOW_DATABASE_PORT + +The database port + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +### PACTFLOW_DATABASE_NAME + +The database name + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +### PACTFLOW_DATABASE_SSLMODE + +The Postgresql ssl mode. Note, if using Postgres on AWS RDS with IAM authentication, this must be `require`. + +**Required:** false
+**Default:** `require`
+**Allowed values:** `disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full`
+**More information:** https://ankane.org/postgres-sslmode-explained
+ +### PACTFLOW_DATABASE_CONNECTION_VALIDATION_TIMEOUT + +The number of seconds after which to check the health of a connection from a connection pool before passing it to the application. + +`-1` means that connections will be validated every time, which avoids errors +when databases are restarted and connections are killed. This has a performance +penalty, so consider increasing this timeout if building a frequently accessed service. + +**Required:** false
+**Default:** `3600`
+**Allowed values:** -1 or any positive integer.
+**More information:** https://sequel.jeremyevans.net/rdoc-plugins/files/lib/sequel/extensions/connection_validator_rb.html
+ +### PACTFLOW_SQL_LOG_WARN_DURATION + +The duration in seconds, as a float, after which to log an SQL statement + +**Required:** false
+**Default:** `5`
+ +### PACTFLOW_SQL_LOG_LEVEL + +The log level that will be specified when the SQL query statements are logged. + +**Required:** false
+**Default:** `NONE`
+**Allowed values:** `NONE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
+ +### PACTFLOW_DATABASE_MAX_CONNECTIONS + +The maximum size of the connection pool per application instance. The total number of connections for the database must be calculated by multiplying this value by the number of instances (ie. running Docker containers). + +**Required:** false
+**Default:** `4`
+**Allowed values:** A positive integer value.
+**More information:** https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
+ +### PACTFLOW_DATABASE_POOL_TIMEOUT + +The number of seconds to wait if a connection cannot be acquired before raising an error. + +**Required:** false
+**Default:** `5`
+**Allowed values:** A positive integer.
+**More information:** https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
+ +### PACTFLOW_DATABASE_AUTO_MIGRATE + +Whether or not to automatically apply the schema and data migrations to the database on startup + +**Required:** false
+**Default:** `true`
+**Allowed values:** `true`, `false`
+ +### AWS_REGION + +Required for running Postgres on RDS with IAM authentication. This must be set to the AWS region where the RDS database instance is running. + +**Required:** false
+ +## Webhooks + +
+ + + +### PACTFLOW_WEBHOOK_HOST_WHITELIST + +A space delimited list of hosts for which webhook response logging will be enabled. By default, all responses will be redacted for security purposes. To allow logging for all hosts, use the value `/.*/`. + +**Required:** false
+**Example:** `/.*\.foo\.com$/ github.com foo.slack.com`
+**More information:** https://docs.pact.io/pact_broker/configuration#webhook-whitelists
+ +### PACTFLOW_WEBHOOK_SCHEME_WHITELIST + +A space delimited list of allowed schemes for a webhook to use. + +**Required:** false
+**Default:** `https`
+**Allowed values:** `https`, `http`
+**More information:** https://docs.pact.io/pact_broker/configuration#webhook-whitelists
+ +### PACTFLOW_WEBHOOK_HTTP_METHOD_WHITELIST + +A space delimited list of allowed http methods for a webhook to use. *It is strongly recommended to only allow POST requests for security purposes.* + +**Required:** false
+**Default:** `POST`
+**Allowed values:** `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
+**More information:** https://docs.pact.io/pact_broker/configuration#webhook-whitelists
+ +### PACTFLOW_DISABLE_SSL_VERIFICATION + +Whether or not to disable SSL verificaton when executing webhooks. + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_WEBHOOK_CERTIFICATES + +A list of SSL certificate configuration objects with the properties `description`, and either `content` or `path`. These +certificates are used when a webhook needs to connect to a server that uses a self signed certificate. + +Each certificate configuration item accepts a chain of certificates in PEM format - there may be multiple 'BEGIN CERTIFICATE' and 'END CERTIFICATE' in the content of each item. + +The certificate configuration is not validated on startup. If any of the configured certificates cannot be loaded during the execution of a webhook, an error +will be logged, and they will be ignored. You can check if the configuration is working by testing the execution of +a webhook that connects to the server with the self signed certificate by following these instructions https://docs.pact.io/pact_broker/webhooks/debugging_webhooks#testing-webhook-execution + +When setting the path, the full path to the certificate file in PEM format must be specified. When using Docker, you must ensure the +certificate file is [mounted into the container](https://docs.docker.com/storage/volumes/). + +Each property of the certificate is described by an indexed environment variable in the format `PACTFLOW_WEBHOOK_CERTIFICATES____`. +Environment variables with the same index are grouped together to form the complete object. Note the use of the double underscores before the index and property. + +Example: + +```shell +PACTFLOW_WEBHOOK_CERTIFICATES__0__LABEL="An example self signed certificate with content" +PACTFLOW_WEBHOOK_CERTIFICATES__0__CONTENT="-----BEGIN CERTIFICATE----- + MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYKCZImiZPyLGQB + + jHT1Ty2CglM= + -----END CERTIFICATE-----" +PACTFLOW_WEBHOOK_CERTIFICATES__1__LABEL="An example self signed certificate with a path" +PACTFLOW_WEBHOOK_CERTIFICATES__1__PATH="/full/path/to/the/cert.pem" +``` + +**Supported versions:** From v1.14.0
+**Required:** false
+ +## SAML authentication + +
+ +To configure more than one SAML identity provider, specify another set of the following environment variables with a `_2` after the `PACTFLOW_SAML` prefix (and `_3` for the third etc.). The `PACTFLOW_SAML_ISSUER` is shared between all the SAML providers so does not need to be duplicated. + +eg. For the second SAML identity provider set `PACTFLOW_SAML_2_AUTH_ENABLED`, `PACTFLOW_SAML_2_IDP_NAME` etc and for the third `PACTFLOW_SAML_3_AUTH_ENABLED`, `PACTFLOW_SAML_3_IDP_NAME` etc. + + +### PACTFLOW_SAML_AUTH_ENABLED + +Whether or not to enable SAML authentication. + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_SAML_ISSUER + +The name of this application as it is known to the SAML IDP. + +**Required:** false
+**Default:** `https://pactflow.io`
+**Example:** `http://pactflow.mycompany.com`
+ +### PACTFLOW_SAML_IDP_NAME + +The display name of the SAML IDP. This value will be used as the login button label. + +**Required:** true
+ +### PACTFLOW_SAML_IDP_LOGO + +URL of a logo for IDP, to be displayed next to the login button. + +**Required:** false
+ +### PACTFLOW_SAML_IDP_SSO_TARGET_URL + +The URL to which the authentication request should be sent. This endpoint is on the identity provider. + +**Required:** if PACTFLOW_SAML_IDP_METADATA_URL is not set
+**More information:** https://github.com/omniauth/omniauth-saml#options
+ +### PACTFLOW_SAML_IDP_CERT_FINGERPRINT + +The SHA1 fingerprint of the certificate, e.g. "90:CC:16:F0:8D:...". This is provided from the identity provider when setting up the relationship. + +**Required:** if PACTFLOW_SAML_IDP_METADATA_URL is not set
+**More information:** https://github.com/omniauth/omniauth-saml#options
+ +### PACTFLOW_SAML_IDP_ID_ATTRIBUTE + +The name of the SAML response attribute that uniquely and permanently identifies a user for the IDP. + +**Required:** true
+ +### PACTFLOW_SAML_EMAIL_ATTRIBUTE + +The name of the SAML response attribute that contains the email address. + +**Required:** true
+ +### PACTFLOW_SAML_NAME_ATTRIBUTE + +The name of the SAML response attribute that contains the full name. + +**Required:** true
+ +### PACTFLOW_SAML_FIRST_NAME_ATTRIBUTE + +The name of the SAML response attribute that contains the first name. + +**Required:** false
+ +### PACTFLOW_SAML_LAST_NAME_ATTRIBUTE + +The name of the SAML response attribute that contains the last name. + +**Required:** false
+ +### PACTFLOW_SAML_IDP_METADATA_URL + +The URL of the IDP's metadata endpoint. If this is set, then the PACTFLOW_SAML_IDP_SSO_TARGET_URL and PACTFLOW_SAML_IDP_CERT_FINGERPRINT can be skipped. + +**Required:** false
+**More information:** https://github.com/omniauth/omniauth-saml#idp-metadata
+ +### PACTFLOW_SAML_NAME_IDENTIFIER_FORMAT + +Used during SP-initiated SSO. Describes the format of the username required by this application. + +**Required:** false
+**Default:** `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`
+**Allowed values:** `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`, `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`
+ +### PACTFLOW_SAML_ALLOWED_CLOCK_DRIFT + +To allow for a small amount of clock drift between PactFlow and the Identity Provider, the allowed clock drift may be specified. Its value must be given in a number (and/or fraction) of seconds. The value is added to the current time at which the response is validated, before it is tested against the NotBefore assertion. + +**Required:** false
+**Default:** `0`
+ +## Demo authentication + +
+ + + +### PACTFLOW_DEMO_AUTH_ENABLED + +Whether or not to enable authentication for demo users. For demonstration purposes only - not to be set to `true` for production use. + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +## Encryption + +
+ + + +### PACTFLOW_MASTER_ENCRYPTION_KEY + +A randomly generated string which will be the master key for encrypting secrets and API tokens. Renamed from `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY`. + +Do not change or lose the value of this key. All encrypted data (secrets and API keys) will be unretrievable if this key is lost. Rotation is not currently supported but will be added in a future release. + +To generate an appropriate value, run the following on Linux/Mac: + +``` +env LC_CTYPE=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 32 | head -n 1 +``` + +**Required:** true
+**Example:** `eLM5xPxPu9ftDhA34ZUw2ry2okpMnOPCrA-twxLBUUk`
+ +## Secrets + +
+ + + +### PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY + +Deprecated in favour of `PACTFLOW_MASTER_ENCRYPTION_KEY`. If you have a previous installation of PactFlow with `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY` set, please rename it to `PACTFLOW_MASTER_ENCRYPTION_KEY`. + +**Required:** false
+ +## Content Security + +
+ + + +### PACTFLOW_CSP_ALLOWED_SOURCES + +Space separated list of allowed content sources that should be allowed in addition to the hosts configured in the identity provider settings (eg. `PACTFLOW_SAML_IDP_SSO_TARGET_URL`). This may be useful if you need additional assets on your instance of PactFlow. For example, if you need to support multiple redirects for SAML authentication, you need to add them here for PactFlow to generate the appropriate Content-Security-Policy to allow that to happen. + +**Required:** false
+**Example:** `https://my-intermediate-idp-host.com`
+ +## User administration + +
+ + + +### PACTFLOW_ADMIN_API_KEY + +The value of the X-Api-Key header required to make the HTTP call to provision the admin user. + +To generate an appropriate value, run the following on Linux/Mac: + +``` +env LC_CTYPE=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 32 | head -n 1 +``` + +**Required:** true
+**Allowed values:** `A-Za-z0-9!#$%&*+-^_``|~.`
+**Example:** `4wmplZfucVG-LdIHD9L`
+**More information:** https://tools.ietf.org/html/rfc7230#section-3.2.6
+ +## Domain + +
+ + + +### PACTFLOW_ALLOW_DANGEROUS_CONTRACT_MODIFICATION + +Whether or not to allow the pact content for an existing consumer version to be modified. It is strongly recommended that this is set to false, +as allowing modification makes the results of can-i-deploy unreliable. When this is set to false as recommended, each commit must publish pacts +with a unique version number. + +**Supported versions:** From v1.14.0
+**Required:** false
+**Default:** For new installations of v1.14.0 and later, this defaults to `false`.
+**Allowed values:** `true`, `false`
+**More information:** https://docs.pact.io/versioning
+ +### PACTFLOW_USE_FIRST_TAG_AS_BRANCH + +When the value is `true`, the first tag applied to a version (within 10 seconds) +will be used to populate the `branch` property of the version. + +This is to assist in the migration from using tags to track branches to using the branches feature. + +**Required:** false
+**Default:** `true`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_CREATE_DEPLOYED_VERSIONS_FOR_TAGS + +When the value is `true` and a tag is created, if there is an environment with the name of the newly created tag, a deployed version is +also created for the pacticipant version. + +This is to assist in the migration from using tags to track deployments to using the deployed and released versions feature. + +**Supported versions:** From v1.14.0
+**Required:** false
+**Default:** `true`
+**Allowed values:** `true`, `false`
+**More information:** https://docs.pact.io/pact_broker/recording_deployments_and_releases/
+ +## Badges + +
+ + + +### PACTFLOW_SHIELDS_IO_BASE_URL + +The URL of the free service that is used to generate the build badges. Note that the badge files are served via a redirect in the browser, so there is no request made from the PactFlow application to the shields server. + +**Required:** false
+**Default:** `https://img.shields.io`
+**More information:** https://shields.io
+ +## Resources + +
+ + + +### PACTFLOW_BASE_URL + +The base url, including HTTP scheme and any application context path, at which the PactFlow application will be publicly +accessible. It should not include a trailing slash. If there are multiple interfaces on which the application will be addressed, +list all the base URLs separated by spaces. + + +**Required:** true
+**Example:** `https://pactflow.mycompany.com https://pactflow.internal.mycompany.com`
+ +### PACTFLOW_HTTP_PORT + +The HTTP port on which the PactFlow application will be exposed on the Docker container. Must be greater than 1024. + +**Required:** false
+**Default:** `9292`
+ +### PACTFLOW_SESSION_LENGTH + +The number of seconds after which the user needs to re-authenticate with the IDP. Default is 1 week. + +**Required:** false
+**Default:** `604800`
+ +### PACTFLOW_SESSION_INACTIVITY_TIMEOUT + +The number of seconds of inactivity after which the user needs to re-authenticate with the IDP. By default, this will be set to the value of the `PACTFLOW_SESSION_LENGTH`, effectively disabling the feature, unless a value is specified by the user. + +**Required:** false
+**Default:** `604800`
+ +### PACTFLOW_COOKIE_SECRET + +The secret used to encrypt the rack.session cookie. +To generate an appropriate value, run the following on Linux/Mac: + +``` +env LC_ALL=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 64 | head -n 1 +``` + +**Required:** true
+**Example:** `X-sbeCpAUgO-8FRtKxYrVhgZ2hIJhPuzCh_89PypYrI`
+ +### PACTFLOW_OLD_COOKIE_SECRET + +The previous secret - used when rotating the rack.session cookie secret. + +**Required:** false
+ +### PACTFLOW_REQUIRE_HTTPS + +When set to `true`, the header `Strict-Transport-Security: max-age=31536000 ; includeSubDomains` is added to ensure connections are made over HTTPS, and the `PACTFLOW_BASE_URL` is validated to ensure it starts with https. + +This value should never be set to false in a production environment. It should only ever be set to false for local testing or demonstration purposes where an SSL certificate is not available. + + +**Required:** false
+**Default:** `true`
+**Allowed values:** `true`, `false`
+ +### SSL_CERT_FILE + +The PEM certificate file to use if the webhooks have to connect to servers that use self signed certificates. + +**Required:** false
+ +### SSL_CERT_DIR + +The PEM certificate directory to use if the webhooks have to connect to servers that use self signed certificates. + +**Required:** false
+ +### http_proxy + +HTTP proxy used when making outgoing HTTP requests + +**Required:** false
+ +### https_proxy + +HTTPS proxy used when making outgoing HTTP requests + +**Required:** false
+ +### no_proxy + +The hosts for which to not use a proxy + +**Required:** false
+ +### PACTFLOW_USE_HAL_BROWSER + +Whether or not to enable the embedded HAL Browser. + +**Required:** false
+**Default:** `true`
+**Allowed values:** `true`, `false`
+**More information:** https://github.com/mikekelly/hal-browser
+ +## Miscellaneous + +
+ + + +### TZ + +The timezone in which to display dates for server side rendered pages. + +**Required:** true
+**More information:** [Valid timezones](/docs/on-premises-2x/environment-variables/timezones)
+ +## API Tokens + +
+ + + +### PACTFLOW_API_TOKEN_AUTH_ENABLED + +Whether or not to enable the inbuilt PactFlow API tokens used for bearer authentication. Used to disable API tokens if an external Identify Provider is configured for API authentication. + +**Required:** false
+**Default:** `true`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED + +Enables encryption of API token values in the database. Requires `PACTFLOW_API_TOKEN_IV` and `PACTFLOW_MASTER_ENCRYPTION_KEY` to also be set. + +**Required:** false
+ +### PACTFLOW_API_TOKEN_IV + +If `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` is set to `true`, then this value must contain a base 64 encoded string of random 16 bytes for the +encryption initialization vector. + +To generate an appropriate value, run the following on Linux/Mac: + +``` +head < /dev/random -c 16 | base64 +``` + +**Required:** if `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` is set to `true`
+**Example:** `JUVDdnRzLXZyWHA7UF93RAo=`
+ +## User Interface + +
+ + + +### PACTFLOW_CLARITY_DISABLED + +Disables the new user interface introduced in version 2.0.0. When this environment variable is set, the legacy interface becomes the default and users cannot switch to the new UI. + +**Required:** false
+**Default:** unset
+**Allowed values:** `true`
\ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md b/website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md new file mode 100644 index 00000000..d8ae64d4 --- /dev/null +++ b/website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md @@ -0,0 +1,259 @@ +# PactFlow Environment Variables - 1.14 beta features + +This page contains documentation for the usage of the JWT and OAuth2 features that are in beta release in PactFlow 1.14 + +## Test JWT bearer authentication + +
+These settings can be configured in a YAML file, as per this example. + +```yaml +test_jwt_bearer_token_auth_enabled: true +test_jwt_bearer_token: + iss: https://idp + exp_leeway: 60 + jwks_url: https://idp/jwks + aud: some-aud + auth_config_handler: auth_ext_script.rb + claim_mappings: + idp_id: SomeUniqueIdentifier + email: EmailAddress + name: DisplayName + first_name: FirstName + last_name: LastName + ``` + + +### PACTFLOW_TEST_JWT_BEARER_TOKEN_AUTH_ENABLED + +Whether or not to enable JWT bearer token authentication for testing purposes. This is not yet ready for production use. + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_TEST_JWT_BEARER_TOKEN__JWKS_URL + +The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT used as the bearer token. + +**Required:** false
+ +### PACTFLOW_TEST_JWT_BEARER_TOKEN__AUD + +The expected token audience ("aud") of the JWT. + +**Required:** false
+ +### PACTFLOW_TEST_JWT_BEARER_TOKEN__ISS + +The expected token issuer ("iss") of the JWT. + +**Required:** false
+ +### PACTFLOW_TEST_JWT_BEARER_TOKEN__EXP_LEEWAY + +The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. + +**Required:** false
+**Default:** `0`
+ +### PACTFLOW_TEST_JWT_BEARER_TOKEN__AUTH_CONFIG_HANDLER + +The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. + +**Required:** false
+ +### PACTFLOW_TEST_JWT\_\_CLAIM_MAPPINGS__{KEY} + +This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. +At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. +The other recommended keys are `name`, `email`, `first_name` and `last_name`. + +eg. + +```yaml +test_jwt_bearer_token: + # other configurations here ... + claim_mappings: + idp_id: "SomeUniqueIdentifier" + name: "Name" + email: "Email" + first_name: "FirstName" + last_name: "LastName" +``` + +When setting the claim mappings using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_JWT__CLAIM_MAPPINGS__` eg. `PACTFLOW_TEST_JWT__CLAIM_MAPPINGS__EMAIL=Email`. This will be mapped to a lower case `{ "email": "Email" }` internally. + +**Required:** false
+ +
+ +## Test OAuth2 authentication + +
+These settings can be configured in a YAML file, as per this example. + +```yaml +test_oauth2_auth_enabled: true +test_oauth2: + client_id: "..." + client_secret: "..." + idp_url: "https://idp" + authorize_url: "https://idp/authorize" + token_url: "https://idp/token" + jwks_url: "https://idp/jwks" + token_issuer: "https://idp" + token_audience: "..." + token_exp_leeway: 60 + auth_config_handler: "auth_ext_script.rb" + custom_authorize_params: + resource: "SomeResource" + claim_mappings: + idp_id: "SomeUniqueIdentifier" + email: "Email" + name: "DisplayName" + first_name: "FirstName" + last_name: "LastName" +``` + + +### PACTFLOW_TEST_OAUTH2_AUTH_ENABLED + +Whether or not to enable OAuth2 authentication for testing purposes. This is not yet ready for production use. + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_TEST_OAUTH2__CLIENT_ID + +The unique identier by which the PactFlow application is known to the identity provider. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__CLIENT_SECRET + +The client secret which the PactFlow application shares with the identity provider. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__IDP_URL + +The identity provider's URL. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__AUTHORIZE_URL + +The authorize endpoint of the OAuth2 provider. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__TOKEN_URL + +The endpoint at which PactFlow can retrieve the JWT containing the user's information. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__JWKS_URL + +The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT returned by the token endpoint. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__TOKEN_ISSUER + +The expected token issuer ("iss") of the JWT. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__TOKEN_AUDIENCE + +The expected token audience ("aud") of the JWT. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2__TOKEN_EXP_LEEWAY + +The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. + +**Required:** false
+**Default:** `0`
+ +### PACTFLOW_TEST_OAUTH2__AUTH_CONFIG_HANDLER + +The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2\_\_CUSTOM_AUTHORIZE_PARAMS__{KEY} + +Allows custom authorize parameters to be set. These will be sent to the IDP in the request phase along with the default authorize parameters. + +eg. + +```yaml +test_oauth2: + custom_authorize_params: + resource: "SomeResource" +``` + +When setting the custom authorize params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_OAUTH2__CUSTOM_AUTHORIZE_PARAMS__` +eg. `PACTFLOW_TEST_OAUTH2__CLAIM_MAPPINGS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2\_\_CUSTOM_TOKEN_PARAMS__{KEY} + +Allows custom token parameters to be set. These will be sent to the token endpoint along with the default token parameters. + +eg. + +```yaml +test_oauth2: + custom_token_params: + resource: "SomeResource" +``` + +When setting the custom token params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_OAUTH2__CUSTOM_TOKEN_PARAMS__` +eg. `PACTFLOW_TEST_OAUTH2__CUSTOM_TOKEN_PARAMS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. + +**Required:** false
+ +### PACTFLOW_TEST_OAUTH2\_\_CLAIM_MAPPINGS__{KEY} + +This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. +At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. +The other recommended keys are `name`, `email`, `first_name` and `last_name`. + +eg. + +```yaml +test_oauth2: + # other configurations here ... + claim_mappings: + idp_id: "SomeUniqueIdentifier" + name: "Name" + email: "Email" + first_name: "FirstName" + last_name: "LastName" +``` + +When setting the claim mappings using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_OAUTH2__CLAIM_MAPPINGS__` +eg. `PACTFLOW_TEST_OAUTH2__CLAIM_MAPPINGS__EMAIL=Email`. This will be mapped to a lower case `{ "email": "Email" }` internally. + +**Required:** false
+ +
+ +## API Tokens + +
+ + +### PACTFLOW_API_TOKENS__ENABLED + +Whether or not to enable the inbuilt PactFlow API tokens used for bearer authentication. Used to disable API tokens if an external Identify Provider is configured for API authentication. + +**Required:** false
+**Allowed values:** `true`, `false`
diff --git a/website/docs/docs/on-premises-2x/environment-variables/jwt.md b/website/docs/docs/on-premises-2x/environment-variables/jwt.md new file mode 100644 index 00000000..dbdeffac --- /dev/null +++ b/website/docs/docs/on-premises-2x/environment-variables/jwt.md @@ -0,0 +1,109 @@ +# Environment Variables - JWT + + + + + +## JWT bearer authentication + +
+These settings can be configured in a YAML file, as per this example. + +```yaml +jwt_bearer_token_auth_enabled: true +jwt_bearer_token: + issuer: https://idp + audience: some-aud + expiry_leeway: 60 + jwks_url: https://idp/jwks + auth_config_handler: auth_ext_script.rb + claim_mappings: + idp_id: SomeUniqueIdentifier + email: EmailAddress + name: DisplayName + first_name: FirstName + last_name: LastName + ``` + + +### PACTFLOW_JWT_BEARER_TOKEN_AUTH_ENABLED + +Whether or not to enable JWT bearer token authentication. + +**Supported versions:** From v1.16.0
+**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_JWT_BEARER_TOKEN\_\_JWKS_URL + +The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT used as the bearer token. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_JWT_BEARER_TOKEN\_\_AUDIENCE + +The expected token audience ("aud") of the JWT. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_JWT_BEARER_TOKEN\_\_ISSUER + +The expected token issuer ("iss") of the JWT. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_JWT_BEARER_TOKEN\_\_EXPIRY_LEEWAY + +The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. + +**Supported versions:** From v1.16.0
+**Required:** false
+**Default:** `0`
+ +### PACTFLOW_JWT_BEARER_TOKEN\_\_AUTH_CONFIG_HANDLER + +The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. + +**Supported versions:** From v1.16.0
+**Required:** false
+ +### PACTFLOW_JWT\_\_CLAIM_MAPPINGS\_\_{KEY} + +This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. +At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. +The other recommended keys are `name`, `email`, `first_name` and `last_name`. + +eg. + +```yaml +jwt_bearer_token_auth_enabled: true +jwt_bearer_token: + # other configurations here ... + claim_mappings: + idp_id: "SomeUniqueIdentifier" + name: "Name" + email: "Email" + first_name: "FirstName" + last_name: "LastName" +``` + +When setting the claim mappings using environment variables, a separate environment variable must be used for each claim mapping. +The key name must be uppercased and prefixed by `PACTFLOW_JWT__CLAIM_MAPPINGS__`. + +eg. + +```shell +PACTFLOW_JWT__CLAIM_MAPPINGS__IDP_ID="SomeUniqueIdentifier" +PACTFLOW_JWT__CLAIM_MAPPINGS__NAME="Name" +PACTFLOW_JWT__CLAIM_MAPPINGS__EMAIL="Email" +PACTFLOW_JWT__CLAIM_MAPPINGS__FIRST_NAME="FirstName" +PACTFLOW_JWT__CLAIM_MAPPINGS__LAST_NAME="LastName" +```` + +**Supported versions:** From v1.16.0
+**Required:** false
+ diff --git a/website/docs/docs/on-premises-2x/environment-variables/oauth2.md b/website/docs/docs/on-premises-2x/environment-variables/oauth2.md new file mode 100644 index 00000000..7d9de85d --- /dev/null +++ b/website/docs/docs/on-premises-2x/environment-variables/oauth2.md @@ -0,0 +1,193 @@ +# Environment Variables - OAuth2 + + + + + +## OAuth2 authentication + +
+These settings can be configured in a YAML file, as per this example. + +```yaml +oauth2_auth_enabled: true +oauth2: + client_id: "..." + client_secret: "..." + idp_name: "Some IDP" + idp_url: "https://idp" + authorize_url: "https://idp/authorize" + token_url: "https://idp/token" + jwks_url: "https://idp/jwks" + token_issuer: "https://idp" + token_audience: "..." + token_expiry_leeway: 60 + auth_config_handler: "auth_ext_script.rb" + custom_authorize_params: + resource: "SomeResource" + claim_mappings: + idp_id: "SomeUniqueIdentifier" + email: "Email" + name: "DisplayName" + first_name: "FirstName" + last_name: "LastName" +``` + + +### PACTFLOW_OAUTH2_AUTH_ENABLED + +Whether or not to enable OAuth2 authentication. + +**Supported versions:** From v1.16.0
+**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +### PACTFLOW_OAUTH2\_\_CLIENT_ID + +The unique identier by which the PactFlow application is known to the identity provider. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_CLIENT_SECRET + +The client secret which the PactFlow application shares with the identity provider. + +**Supported versions:** From v1.16.0
+**Required:** false
+ +### PACTFLOW_OAUTH2\_\_IDP_NAME + +The identity provider's name. This value will appear on the login button. + +**Supported versions:** From v1.16.0
+**Required:** false
+ +### PACTFLOW_OAUTH2\_\_IDP_URL + +The identity provider's URL. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_AUTHORIZE_URL + +The authorize endpoint of the OAuth2 provider. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_TOKEN_URL + +The endpoint at which PactFlow can retrieve the JWT containing the user's information. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_JWKS_URL + +The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT returned by the token endpoint. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_TOKEN_ISSUER + +The expected token issuer ("iss") of the JWT. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_TOKEN_AUDIENCE + +The expected token audience ("aud") of the JWT. + +**Supported versions:** From v1.16.0
+**Required:** true
+ +### PACTFLOW_OAUTH2\_\_TOKEN_EXPIRY_LEEWAY + +The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. + +**Supported versions:** From v1.16.0
+**Required:** false
+**Default:** `0`
+ +### PACTFLOW_OAUTH2\_\_AUTH_CONFIG_HANDLER + +The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. + +**Supported versions:** From v1.16.0
+**Required:** false
+ +### PACTFLOW_OAUTH2\_\_CUSTOM_AUTHORIZE_PARAMS\_\_{KEY} + +Allows custom authorize parameters to be set. These will be sent to the IDP in the request phase along with the default authorize parameters. + +eg. + +```yaml +oauth2: + custom_authorize_params: + resource: "SomeResource" +``` + +When setting the custom authorize params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_OAUTH2__CUSTOM_AUTHORIZE_PARAMS__` +eg. `PACTFLOW_OAUTH2__CUSTOM_AUTHORIZE_PARAMS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. + +**Supported versions:** From v1.16.0
+**Required:** false
+ +### PACTFLOW_OAUTH2\_\_CUSTOM_TOKEN_PARAMS\_\_{KEY} + +Allows custom token parameters to be set. These will be sent to the token endpoint along with the default token parameters. + +eg. + +```yaml +oauth2: + custom_token_params: + resource: "SomeResource" +``` + +When setting the custom token params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_OAUTH2__CUSTOM_TOKEN_PARAMS__` +eg. `PACTFLOW_OAUTH2__CUSTOM_TOKEN_PARAMS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. + +**Supported versions:** From v1.16.0
+**Required:** false
+ +### PACTFLOW_OAUTH2\_\_CLAIM_MAPPINGS\_\_{KEY} + +This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. +At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. +The other recommended keys are `name`, `email`, `first_name` and `last_name`. + +eg. + +```yaml +oauth2: + # other configurations here ... + claim_mappings: + idp_id: "SomeUniqueIdentifier" + name: "Name" + email: "Email" + first_name: "FirstName" + last_name: "LastName" +``` + +When setting the claim mappings using environment variables, a separate environment variable must be used for each claim mapping. +The key name must be uppercased and prefixed by `PACTFLOW_OAUTH2__CLAIM_MAPPINGS__`. + +eg. + +```shell +PACTFLOW_OAUTH2__CLAIM_MAPPINGS__IDP_ID="SomeUniqueIdentifier" +PACTFLOW_OAUTH2__CLAIM_MAPPINGS__NAME="Name" +PACTFLOW_OAUTH2__CLAIM_MAPPINGS__EMAIL="Email" +PACTFLOW_OAUTH2__CLAIM_MAPPINGS__FIRST_NAME="FirstName" +PACTFLOW_OAUTH2__CLAIM_MAPPINGS__LAST_NAME="LastName" +```` + +**Supported versions:** From v1.16.0
+**Required:** false
diff --git a/website/docs/docs/on-premises-2x/environment-variables/templates.md b/website/docs/docs/on-premises-2x/environment-variables/templates.md new file mode 100644 index 00000000..333de9c7 --- /dev/null +++ b/website/docs/docs/on-premises-2x/environment-variables/templates.md @@ -0,0 +1,75 @@ +--- +title: Configuration file templates +--- + +## Required environment variables + +```yml +- name: "PACTFLOW_DATABASE_URL" + value: "postgres://username:password@host:port/database" +- name: "PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY" + value: "" +- name: "PACTFLOW_COOKIE_SECRET" + value: "" +- name: "TZ" + value: "" +- name: "PACTFLOW_BASE_URL" + value: "" + +# SAML +- name: "PACTFLOW_SAML_IDP_NAME" + value: "" +- name: "PACTFLOW_SAML_ISSUER" + value: "" +- name: "PACTFLOW_SAML_NAME_IDENTIFIER_FORMAT" + value: "" +- name: "PACTFLOW_SAML_EMAIL_ATTRIBUTE" + value: "" +- name: "PACTFLOW_SAML_NAME_ATTRIBUTE" + value: "" +- name: "PACTFLOW_SAML_FIRST_NAME_ATTRIBUTE" + value: "" +- name: "PACTFLOW_SAML_LAST_NAME_ATTRIBUTE" + value: "" +- name: "PACTFLOW_SAML_IDP_SSO_TARGET_URL" + value: "" +- name: "PACTFLOW_SAML_IDP_CERT_FINGERPRINT" + value: "" +- name: "PACTFLOW_SAML_IDP_ID_ATTRIBUTE" + value: "" +``` + +## Recommended environment variables + +```yml +- name: "PACTFLOW_WEBHOOK_HOST_WHITELIST" + value: "" +``` + +## SAML +### Azure Active Directory + +```yml +- name: "PACTFLOW_SAML_ISSUER" + value: "eg. https://pactflow.mycompany.com" +- name: "PACTFLOW_SAML_IDP_NAME" + value: "eg. Azure AD" +- name: "PACTFLOW_SAML_IDP_SSO_TARGET_URL" + value: "eg. https://login.microsoftonline.com/abcd/saml2" +- name: "PACTFLOW_SAML_IDP_CERT_FINGERPRINT" + value: "eg. E97D948158F893A93827A0A4D70701A38AB1A499" +- name: "PACTFLOW_SAML_IDP_ENTITY_ID" + value: "eg. https://sts.windows.net/abcd/" +- name: "PACTFLOW_SAML_NAME_IDENTIFIER_FORMAT" + value: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" +- name: "PACTFLOW_SAML_IDP_ID_ATTRIBUTE" + value: "http://schemas.microsoft.com/identity/claims/objectidentifier" +- name: "PACTFLOW_SAML_EMAIL_ATTRIBUTE" + value: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" +- name: "PACTFLOW_SAML_NAME_ATTRIBUTE" + value: "http://schemas.microsoft.com/identity/claims/displayname" +- name: "PACTFLOW_SAML_FIRST_NAME_ATTRIBUTE" + value: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" +- name: "PACTFLOW_SAML_LAST_NAME_ATTRIBUTE" + value: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" +``` diff --git a/website/docs/docs/on-premises-2x/environment-variables/timezones.md b/website/docs/docs/on-premises-2x/environment-variables/timezones.md new file mode 100644 index 00000000..9a039699 --- /dev/null +++ b/website/docs/docs/on-premises-2x/environment-variables/timezones.md @@ -0,0 +1,601 @@ +--- +title: Timezones +--- + +These are the valid values for the [TZ environment variable](/docs/on-premises-2x/environment-variables#tz). + +* Africa/Abidjan +* Africa/Accra +* Africa/Addis_Ababa +* Africa/Algiers +* Africa/Asmara +* Africa/Asmera +* Africa/Bamako +* Africa/Bangui +* Africa/Banjul +* Africa/Bissau +* Africa/Blantyre +* Africa/Brazzaville +* Africa/Bujumbura +* Africa/Cairo +* Africa/Casablanca +* Africa/Ceuta +* Africa/Conakry +* Africa/Dakar +* Africa/Dar_es_Salaam +* Africa/Djibouti +* Africa/Douala +* Africa/El_Aaiun +* Africa/Freetown +* Africa/Gaborone +* Africa/Harare +* Africa/Johannesburg +* Africa/Juba +* Africa/Kampala +* Africa/Khartoum +* Africa/Kigali +* Africa/Kinshasa +* Africa/Lagos +* Africa/Libreville +* Africa/Lome +* Africa/Luanda +* Africa/Lubumbashi +* Africa/Lusaka +* Africa/Malabo +* Africa/Maputo +* Africa/Maseru +* Africa/Mbabane +* Africa/Mogadishu +* Africa/Monrovia +* Africa/Nairobi +* Africa/Ndjamena +* Africa/Niamey +* Africa/Nouakchott +* Africa/Ouagadougou +* Africa/Porto-Novo +* Africa/Sao_Tome +* Africa/Timbuktu +* Africa/Tripoli +* Africa/Tunis +* Africa/Windhoek +* America/Adak +* America/Anchorage +* America/Anguilla +* America/Antigua +* America/Araguaina +* America/Argentina/Buenos_Aires +* America/Argentina/Catamarca +* America/Argentina/ComodRivadavia +* America/Argentina/Cordoba +* America/Argentina/Jujuy +* America/Argentina/La_Rioja +* America/Argentina/Mendoza +* America/Argentina/Rio_Gallegos +* America/Argentina/Salta +* America/Argentina/San_Juan +* America/Argentina/San_Luis +* America/Argentina/Tucuman +* America/Argentina/Ushuaia +* America/Aruba +* America/Asuncion +* America/Atikokan +* America/Atka +* America/Bahia +* America/Bahia_Banderas +* America/Barbados +* America/Belem +* America/Belize +* America/Blanc-Sablon +* America/Boa_Vista +* America/Bogota +* America/Boise +* America/Buenos_Aires +* America/Cambridge_Bay +* America/Campo_Grande +* America/Cancun +* America/Caracas +* America/Catamarca +* America/Cayenne +* America/Cayman +* America/Chicago +* America/Chihuahua +* America/Coral_Harbour +* America/Cordoba +* America/Costa_Rica +* America/Creston +* America/Cuiaba +* America/Curacao +* America/Danmarkshavn +* America/Dawson +* America/Dawson_Creek +* America/Denver +* America/Detroit +* America/Dominica +* America/Edmonton +* America/Eirunepe +* America/El_Salvador +* America/Ensenada +* America/Fort_Nelson +* America/Fort_Wayne +* America/Fortaleza +* America/Glace_Bay +* America/Godthab +* America/Goose_Bay +* America/Grand_Turk +* America/Grenada +* America/Guadeloupe +* America/Guatemala +* America/Guayaquil +* America/Guyana +* America/Halifax +* America/Havana +* America/Hermosillo +* America/Indiana/Indianapolis +* America/Indiana/Knox +* America/Indiana/Marengo +* America/Indiana/Petersburg +* America/Indiana/Tell_City +* America/Indiana/Vevay +* America/Indiana/Vincennes +* America/Indiana/Winamac +* America/Indianapolis +* America/Inuvik +* America/Iqaluit +* America/Jamaica +* America/Jujuy +* America/Juneau +* America/Kentucky/Louisville +* America/Kentucky/Monticello +* America/Knox_IN +* America/Kralendijk +* America/La_Paz +* America/Lima +* America/Los_Angeles +* America/Louisville +* America/Lower_Princes +* America/Maceio +* America/Managua +* America/Manaus +* America/Marigot +* America/Martinique +* America/Matamoros +* America/Mazatlan +* America/Mendoza +* America/Menominee +* America/Merida +* America/Metlakatla +* America/Mexico_City +* America/Miquelon +* America/Moncton +* America/Monterrey +* America/Montevideo +* America/Montreal +* America/Montserrat +* America/Nassau +* America/New_York +* America/Nipigon +* America/Nome +* America/Noronha +* America/North_Dakota/Beulah +* America/North_Dakota/Center +* America/North_Dakota/New_Salem +* America/Nuuk +* America/Ojinaga +* America/Panama +* America/Pangnirtung +* America/Paramaribo +* America/Phoenix +* America/Port-au-Prince +* America/Port_of_Spain +* America/Porto_Acre +* America/Porto_Velho +* America/Puerto_Rico +* America/Punta_Arenas +* America/Rainy_River +* America/Rankin_Inlet +* America/Recife +* America/Regina +* America/Resolute +* America/Rio_Branco +* America/Rosario +* America/Santa_Isabel +* America/Santarem +* America/Santiago +* America/Santo_Domingo +* America/Sao_Paulo +* America/Scoresbysund +* America/Shiprock +* America/Sitka +* America/St_Barthelemy +* America/St_Johns +* America/St_Kitts +* America/St_Lucia +* America/St_Thomas +* America/St_Vincent +* America/Swift_Current +* America/Tegucigalpa +* America/Thule +* America/Thunder_Bay +* America/Tijuana +* America/Toronto +* America/Tortola +* America/Vancouver +* America/Virgin +* America/Whitehorse +* America/Winnipeg +* America/Yakutat +* America/Yellowknife +* Antarctica/Casey +* Antarctica/Davis +* Antarctica/DumontDUrville +* Antarctica/Macquarie +* Antarctica/Mawson +* Antarctica/McMurdo +* Antarctica/Palmer +* Antarctica/Rothera +* Antarctica/South_Pole +* Antarctica/Syowa +* Antarctica/Troll +* Antarctica/Vostok +* Arctic/Longyearbyen +* Asia/Aden +* Asia/Almaty +* Asia/Amman +* Asia/Anadyr +* Asia/Aqtau +* Asia/Aqtobe +* Asia/Ashgabat +* Asia/Ashkhabad +* Asia/Atyrau +* Asia/Baghdad +* Asia/Bahrain +* Asia/Baku +* Asia/Bangkok +* Asia/Barnaul +* Asia/Beirut +* Asia/Bishkek +* Asia/Brunei +* Asia/Calcutta +* Asia/Chita +* Asia/Choibalsan +* Asia/Chongqing +* Asia/Chungking +* Asia/Colombo +* Asia/Dacca +* Asia/Damascus +* Asia/Dhaka +* Asia/Dili +* Asia/Dubai +* Asia/Dushanbe +* Asia/Famagusta +* Asia/Gaza +* Asia/Harbin +* Asia/Hebron +* Asia/Ho_Chi_Minh +* Asia/Hong_Kong +* Asia/Hovd +* Asia/Irkutsk +* Asia/Istanbul +* Asia/Jakarta +* Asia/Jayapura +* Asia/Jerusalem +* Asia/Kabul +* Asia/Kamchatka +* Asia/Karachi +* Asia/Kashgar +* Asia/Kathmandu +* Asia/Katmandu +* Asia/Khandyga +* Asia/Kolkata +* Asia/Krasnoyarsk +* Asia/Kuala_Lumpur +* Asia/Kuching +* Asia/Kuwait +* Asia/Macao +* Asia/Macau +* Asia/Magadan +* Asia/Makassar +* Asia/Manila +* Asia/Muscat +* Asia/Nicosia +* Asia/Novokuznetsk +* Asia/Novosibirsk +* Asia/Omsk +* Asia/Oral +* Asia/Phnom_Penh +* Asia/Pontianak +* Asia/Pyongyang +* Asia/Qatar +* Asia/Qostanay +* Asia/Qyzylorda +* Asia/Rangoon +* Asia/Riyadh +* Asia/Saigon +* Asia/Sakhalin +* Asia/Samarkand +* Asia/Seoul +* Asia/Shanghai +* Asia/Singapore +* Asia/Srednekolymsk +* Asia/Taipei +* Asia/Tashkent +* Asia/Tbilisi +* Asia/Tehran +* Asia/Tel_Aviv +* Asia/Thimbu +* Asia/Thimphu +* Asia/Tokyo +* Asia/Tomsk +* Asia/Ujung_Pandang +* Asia/Ulaanbaatar +* Asia/Ulan_Bator +* Asia/Urumqi +* Asia/Ust-Nera +* Asia/Vientiane +* Asia/Vladivostok +* Asia/Yakutsk +* Asia/Yangon +* Asia/Yekaterinburg +* Asia/Yerevan +* Atlantic/Azores +* Atlantic/Bermuda +* Atlantic/Canary +* Atlantic/Cape_Verde +* Atlantic/Faeroe +* Atlantic/Faroe +* Atlantic/Jan_Mayen +* Atlantic/Madeira +* Atlantic/Reykjavik +* Atlantic/South_Georgia +* Atlantic/St_Helena +* Atlantic/Stanley +* Australia/ACT +* Australia/Adelaide +* Australia/Brisbane +* Australia/Broken_Hill +* Australia/Canberra +* Australia/Currie +* Australia/Darwin +* Australia/Eucla +* Australia/Hobart +* Australia/LHI +* Australia/Lindeman +* Australia/Lord_Howe +* Australia/Melbourne +* Australia/NSW +* Australia/North +* Australia/Perth +* Australia/Queensland +* Australia/South +* Australia/Sydney +* Australia/Tasmania +* Australia/Victoria +* Australia/West +* Australia/Yancowinna +* Brazil/Acre +* Brazil/DeNoronha +* Brazil/East +* Brazil/West +* CET +* CST6CDT +* Canada/Atlantic +* Canada/Central +* Canada/Eastern +* Canada/Mountain +* Canada/Newfoundland +* Canada/Pacific +* Canada/Saskatchewan +* Canada/Yukon +* Chile/Continental +* Chile/EasterIsland +* Cuba +* EET +* EST +* EST5EDT +* Egypt +* Eire +* Etc/GMT +* Etc/GMT+0 +* Etc/GMT+1 +* Etc/GMT+10 +* Etc/GMT+11 +* Etc/GMT+12 +* Etc/GMT+2 +* Etc/GMT+3 +* Etc/GMT+4 +* Etc/GMT+5 +* Etc/GMT+6 +* Etc/GMT+7 +* Etc/GMT+8 +* Etc/GMT+9 +* Etc/GMT-0 +* Etc/GMT-1 +* Etc/GMT-10 +* Etc/GMT-11 +* Etc/GMT-12 +* Etc/GMT-13 +* Etc/GMT-14 +* Etc/GMT-2 +* Etc/GMT-3 +* Etc/GMT-4 +* Etc/GMT-5 +* Etc/GMT-6 +* Etc/GMT-7 +* Etc/GMT-8 +* Etc/GMT-9 +* Etc/GMT0 +* Etc/Greenwich +* Etc/UCT +* Etc/UTC +* Etc/Universal +* Etc/Zulu +* Europe/Amsterdam +* Europe/Andorra +* Europe/Astrakhan +* Europe/Athens +* Europe/Belfast +* Europe/Belgrade +* Europe/Berlin +* Europe/Bratislava +* Europe/Brussels +* Europe/Bucharest +* Europe/Budapest +* Europe/Busingen +* Europe/Chisinau +* Europe/Copenhagen +* Europe/Dublin +* Europe/Gibraltar +* Europe/Guernsey +* Europe/Helsinki +* Europe/Isle_of_Man +* Europe/Istanbul +* Europe/Jersey +* Europe/Kaliningrad +* Europe/Kiev +* Europe/Kirov +* Europe/Lisbon +* Europe/Ljubljana +* Europe/London +* Europe/Luxembourg +* Europe/Madrid +* Europe/Malta +* Europe/Mariehamn +* Europe/Minsk +* Europe/Monaco +* Europe/Moscow +* Europe/Nicosia +* Europe/Oslo +* Europe/Paris +* Europe/Podgorica +* Europe/Prague +* Europe/Riga +* Europe/Rome +* Europe/Samara +* Europe/San_Marino +* Europe/Sarajevo +* Europe/Saratov +* Europe/Simferopol +* Europe/Skopje +* Europe/Sofia +* Europe/Stockholm +* Europe/Tallinn +* Europe/Tirane +* Europe/Tiraspol +* Europe/Ulyanovsk +* Europe/Uzhgorod +* Europe/Vaduz +* Europe/Vatican +* Europe/Vienna +* Europe/Vilnius +* Europe/Volgograd +* Europe/Warsaw +* Europe/Zagreb +* Europe/Zaporozhye +* Europe/Zurich +* Factory +* GB +* GB-Eire +* GMT +* GMT+0 +* GMT-0 +* GMT0 +* Greenwich +* HST +* Hongkong +* Iceland +* Indian/Antananarivo +* Indian/Chagos +* Indian/Christmas +* Indian/Cocos +* Indian/Comoro +* Indian/Kerguelen +* Indian/Mahe +* Indian/Maldives +* Indian/Mauritius +* Indian/Mayotte +* Indian/Reunion +* Iran +* Israel +* Jamaica +* Japan +* Kwajalein +* Libya +* MET +* MST +* MST7MDT +* Mexico/BajaNorte +* Mexico/BajaSur +* Mexico/General +* NZ +* NZ-CHAT +* Navajo +* PRC +* PST8PDT +* Pacific/Apia +* Pacific/Auckland +* Pacific/Bougainville +* Pacific/Chatham +* Pacific/Chuuk +* Pacific/Easter +* Pacific/Efate +* Pacific/Enderbury +* Pacific/Fakaofo +* Pacific/Fiji +* Pacific/Funafuti +* Pacific/Galapagos +* Pacific/Gambier +* Pacific/Guadalcanal +* Pacific/Guam +* Pacific/Honolulu +* Pacific/Johnston +* Pacific/Kiritimati +* Pacific/Kosrae +* Pacific/Kwajalein +* Pacific/Majuro +* Pacific/Marquesas +* Pacific/Midway +* Pacific/Nauru +* Pacific/Niue +* Pacific/Norfolk +* Pacific/Noumea +* Pacific/Pago_Pago +* Pacific/Palau +* Pacific/Pitcairn +* Pacific/Pohnpei +* Pacific/Ponape +* Pacific/Port_Moresby +* Pacific/Rarotonga +* Pacific/Saipan +* Pacific/Samoa +* Pacific/Tahiti +* Pacific/Tarawa +* Pacific/Tongatapu +* Pacific/Truk +* Pacific/Wake +* Pacific/Wallis +* Pacific/Yap +* Poland +* Portugal +* ROC +* ROK +* Singapore +* Turkey +* UCT +* US/Alaska +* US/Aleutian +* US/Arizona +* US/Central +* US/East-Indiana +* US/Eastern +* US/Hawaii +* US/Indiana-Starke +* US/Michigan +* US/Mountain +* US/Pacific +* US/Pacific-New +* US/Samoa +* UTC +* Universal +* W-SU +* WET +* Zulu \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/installation/checklist.md b/website/docs/docs/on-premises-2x/installation/checklist.md new file mode 100644 index 00000000..3c6f148e --- /dev/null +++ b/website/docs/docs/on-premises-2x/installation/checklist.md @@ -0,0 +1,43 @@ +--- +title: Installation checklist +--- + +## 1. PactFlow license file + +The PactFlow on-premises version requires a license file to run. You should have received this from us during the +on-boarding process. If not, please contact your Account Manager. + +## 2. Run Docker Compose example + +See the [Docker Compose example](/docs/on-premises-2x/docker-compose-example). + +## 3. Choose the domain name for your PactFlow On-Premises application + +eg. `https://pactflow.mycompany.com` + +You will need this for the next step. + +## 4. Configure identity provider + +Configure the PactFlow On-Premises application in your identity provider. See the [Azure Active Directory](/docs/on-premises-2x/authentication/saml#configuring-azure-active-directory) documentation. + +## 5. Deploy PactFlow On-Premises application stack + +* Configure the [PactFlow Docker image](/docs/on-premises-2x/docker-image-registry) to be pulled from Quay. +* Use the [environment variable templates](/docs/on-premises-2x/environment-variables/templates) to create the appropriate deployment configuration artifacts for the PactFlow Docker image (eg. Cloudformation template, Helm chart etc.) +* Ensure the [compute resources](/docs/on-premises-2x/system-requirements) have the appropriate specifications. +* Create a [PostgreSQL database](/docs/on-premises-2x/database) +* Setup a [Redis cache](/docs/on-premises-2x/redis) +* Ensure the [network](/docs/on-premises-2x/network-configuration) is configured appropriately. +* Ensure the [logs](/docs/on-premises-2x/logging) are forwarded to a log aggregation service. +* Make sure the [license file](/docs/on-premises-2x/license) is mounted into the running containers. +* Ensure you have [load tested](load-testing) the system and have confidence the system can handle your baseline load, and can scale with increased demand. + +## 6. Setup database cleaning + +Setup [database cleaning](/docs/on-premises-2x/maintenance/database) to ensure optimal PactFlow performance and reliability. + +:::warning this step is not optional +Failure to enable database cleaning is likely to result in a gradual decline in system performance and, eventually, query timeouts and system failure. +::: + diff --git a/website/docs/docs/on-premises-2x/installation/load-testing.md b/website/docs/docs/on-premises-2x/installation/load-testing.md new file mode 100644 index 00000000..3fcf7835 --- /dev/null +++ b/website/docs/docs/on-premises-2x/installation/load-testing.md @@ -0,0 +1,28 @@ +--- +title: Load Testing +--- + + +# Load testing + +Load testing is an important part of installation, it helps to give confidence that the system is setup and configured to scale with the needs of the organisation. + +It also helps us to identify the key scaling properties - e.g. is it CPU, I/O or network bound - in order to tune autoscaling, metrics and alarms. + +## Calculating base usage + +There is no easy answer on how many requests per second should the system be able to handle, but the simplest approach is to base it off the number of CI builds and releases you perform on your busiest day. + +If you can imagine a histogram of these builds with time as the x-axis, and number of builds on the y-axis, you can take the peak number and use that as your baseline "concurrent users" metric. + +A starting point of being able to handle 10 concurrent users (builds) is a good start, as each build will usually perform several API calls. + +It's worth pointing out that each real CI build will usually span multiple minutes, and only a fraction of the build time will be dedicated Pact and communicting with PactFlow directly. + +## Running a load test + +We have created a tool that you can use to run a load test on your platform. + +Using the metric from above, the load testing tool maps to a random scenario (which may perform multiple API calls to PactFlow), attempting to create a more realistic system load. + +You can download and run the tool from: https://github.com/pactflow/pactflow-load-test \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md b/website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md new file mode 100644 index 00000000..a006ccf0 --- /dev/null +++ b/website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md @@ -0,0 +1,41 @@ +--- +id: migrating +title: Migrating from Pact Broker +--- + +# Migrating from Pact Broker + +If you have previously used the open source Pact Broker with a PostgreSQL database it is possible to migrate that data to PactFlow, keeping everything and making it available in PactFlow. The migration process uses the existing Pact Broker database. Database migrations are then performed to add additional tables and data used for PactFlow features. + +:::note +Migration is only supported for a Pact Broker running a PostgreSQL database. +::: + +## Single Pact Broker instance + +Follow existing [set up documentation](/docs/on-premises-2x) for setting up your new PactFlow. When you reach the section regarding setting up a [Database](/docs/on-premises-2x/database) follow these steps to migrate instead of creating a new database: + +1. Re-use your existing Pact Broker environment variables, updating the names to read `PACTFLOW_*` instead of `PACT_BROKER_*`. A full list of the PactFlow environment variables can be found [here](/docs/on-premises-2x/environment-variables). + +:::tip + +It is crucial that all `PACT_BROKER_DATABASE_*` environment variables are renamed to `PACTFLOW_DATABASE_*` while their `values` remain the same. This is because your existing Pact Broker database will be used, and updated for use with PactFlow as part of the process. +::: + +2. If you previously set the environment variables `PACT_BROKER_AUTO_MIGRATE_DB` and `PACT_BROKER_AUTO_MIGRATE_DB_DATA` remove these and replace them with a new environment variable named `PACTFLOW_DATABASE_AUTO_MIGRATE`. Set its value to `true`. This environment variable will allow your existing database to be updated with the required structures and data to support PactFlow, and maintain any existing data. +You do not need to add the new variable if you did not previously set `PACT_BROKER_AUTO_MIGRATE_DB` and `PACT_BROKER_AUTO_MIGRATE_DB_DATA`. + +4. When the PactFlow instance starts up the migrations will run automatically. The migrations can be run manually instead if needed. See details [here](/docs/on-premises-2x/upgrading/database-migrations) + +## Multiple Pact Broker instances + +It is not currently possible to combine multiple Pact Broker databases into a single database for use with PactFlow. Instead one Pact Broker database can be used in the migration, and the others ran in parallel with the new PactFlow instance until sufficient data is transferred. The PactFlow instance must contain all production versions of all services used in the contract test before it can safely take over all 'can-i-deploy' checks. + +The recommended steps are as follows: + +1. Select one of the Pact Broker databases to update and use going forwards. +2. Follow instructions above to set up PactFlow using this database. +3. The Pact Broker instances that was used in the upgrade process and be decommissioned, as the database and its contents are now available in PactFlow. +4. Run the PactFlow instance and any other existing Pact Broker instances in parallel. Duplicate the pact publication and pact verification tasks in your pipeline. The duplicated task should use the new PactFlow instance details. In this way all new data can gradually added to PactFlow while ensuring `can-i-deploy` still has access to production versions of all services. +5. Continue to run PactFlow and Pact Brokers in parallel. Once the PactFlow instance contains all the `production` versions for all the services used in the contract tests the old Pact Broker instances can be safely decommissioned. This will allow PactFlow to be the sole source of data for 'can-i-deploy' +6. Clean up any code and API calls that were used to run PactFlow and existing Pact Brokers in parallel. The pact publication and pact verification steps in your pipeline that used the old Pact Brokers can be removed. diff --git a/website/docs/docs/on-premises-2x/license.md b/website/docs/docs/on-premises-2x/license.md new file mode 100644 index 00000000..97640294 --- /dev/null +++ b/website/docs/docs/on-premises-2x/license.md @@ -0,0 +1,66 @@ +--- +title: License file +--- + +The PactFlow on-premises version requires a license file to run. You should have received this from us during the +on-boarding process. If not, please contact your Account Manager. + +The license file needs to be mounted into the docker container at the `/home/pactflow-onprem.lic` path. This can +be done by either using a volume mount or building a new image with the license file in it. + +## Volume mounting the license file + +Refer to the docker documentation on using [volumes](https://docs.docker.com/storage/volumes/). + +For an example, you can use the docker CLI `-v` parameter to mount the license file (i.e. if the license file +is stored at `/opt/pactflow/pactflow-onprem.lic` on your server, then `-v /opt/pactflow/pactflow-onprem.lic/pactflow-onprem.lic:/home/pactflow-onprem.lic` will mount it). + +## Building a new image with the license file in + +You can also create a new docker file with the license file baked in. Here is an example docker build file that does that: + +```dockerfile +ARG ONPREM_IMAGE +FROM ${ONPREM_IMAGE} + +COPY --chown=app:app pactflow-onprem.lic $APP_HOME/../pactflow-onprem.lic +``` + +This can then be built with the following docker command: + +```console +$ docker build . --build-arg ONPREM_IMAGE=quay.io/pactflow/enterprise:1.10.0 +``` + +## Customising the location of the license file + +If mounting the license file in `/home` is not desirable, you can specify a custom directory using the `RG_LIC_PATH` environment variable. + +For example, to change the path to `/opt/pactflow/pactflow-onprem.lic` you would set the environment variable in the container to `RG_LIC_PATH=/opt/pactflow/`. + +## License enforcement + +The license provided encodes your designated subscription limits, such as your allocated number of users and the expiration date of your subscription. These limits are enforced by the application at runtime. In the event you have an invalid or incompatible license, the system will not boot and will provide an error in your system log file + + + +In the event the license does expire, the [health check endpoint](/docs/on-premises-2x#healthcheck-endpoint) will continue to remain operational. + +## FAQ + +### What happens when I reach my licenses user limit? + +New users will be unable to login and will receive a message indicating the user limit has been reached. + +You can rectify this by: + +1. Disabling any users that no longer require access to Pactflow +2. Upgrading your subscription to allow more users + +### What happens when my license expires? + +Well ahead of your license expiration you will be contacted from a SmartBear representative to help with ensuring a smooth transition from your expiring license to a new one. + +Pactflow will provide in-application notices when there are 30 days or less until expiry of the subscription. The notices will be displayed on both the login screen and in the footer. + +When the subscription reaches its end date, if the license has not been replaced you will lose access to Pactflow and the system will cease to function (with the exception of the [health check endpoint](/docs/on-premises-2x#healthcheck-endpoint)). diff --git a/website/docs/docs/on-premises-2x/logging.md b/website/docs/docs/on-premises-2x/logging.md new file mode 100644 index 00000000..fca9cc15 --- /dev/null +++ b/website/docs/docs/on-premises-2x/logging.md @@ -0,0 +1,15 @@ +--- +title: Logging +--- + +## Output + +PactFlow application logs are sent to the standard output stream of the Docker container, with the expectation that the container orchestration service will collect and forward them to a log aggregation service. Both the UI and App logs will be interspersed here. They are distinguishable by the `application` property. UI will be `pactflow-ui` and API will be `pactflow-application`. + +## Format + +The log format is JSON. + +## Level + +The default log level is `INFO`. This can be changed by setting the [PACTFLOW_LOG_LEVEL](environment-variables#pactflow_log_level) environment variable. diff --git a/website/docs/docs/on-premises-2x/maintenance/database.md b/website/docs/docs/on-premises-2x/maintenance/database.md new file mode 100644 index 00000000..ad6cbd9b --- /dev/null +++ b/website/docs/docs/on-premises-2x/maintenance/database.md @@ -0,0 +1,274 @@ +--- +title: Database +--- + + + +## Automatic data clean up + +:::note +Automatic data clean up is available in PactFlow On-Premises version 1.23.0 and later. +::: + +Performance can degrade when too much data accumulates in the PactFlow database. Fortunately, a lot of the data in a PactFlow instance is "unreachable" and can be removed without affecting the way it operates functionally, as generally speaking, the application (pacticipant) versions that are referenced in the verification and can-i-deploy tasks are a very small subset of the total published dataset. + +### Categories of removable data + +* Overwritten data for application versions + * Overwritten consumer contracts: these are created when a consumer contract is published with the same consumer version but different content from a previous publication - it shouldn't happen if following best practice, and there is a configuration option to stop this occurring, but such data may exist in older PactFlow instances. + * Duplicate verifications: these are created when verification results for the same pact version content are published by the same provider version multiple times - this can happen quite often under normal operation. +* Historical webhook execution data. +* Old or superseded (ie. versions that are not the latest for their branch/tag) application versions and their associated tags/pacts/verifications/webhooks. + +### How the application version cleaning works + +To ensure that the data that is still in use is not deleted, a list of "keep" selectors must be configured to specify which application versions (and associated data) should be kept. Any application version not selected by one or more of the keep selectors will (eventually) be deleted. To ensure that the clean up task itself does not impact the performance of the Broker, a limit is placed on the number of application versions that will be deleted at one time. The task will first identify all the application versions to keep, exclude those records, and then delete the oldest \[configurable number\] of application versions and their associated contracts, verifications, tags, webhook executions, and any orphan contract versions. + +### Understanding the "keep" selectors + +The keep selectors operate in a very similar way to the [consumer version selectors](https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/) used during verification. Each selector can have the following properties: + +* `pacticipant`: the name of the pacticipant +* `branch`: the name of the branch as a string to indicate a particular branch, or a boolean `true` to indicate "any version associated with a branch" +* `tag`: the name of the tag as a string to indicate a particular tag, or a boolean `true` to indicate "any version with a tag" +* `latest`: if `true`, then the latest version matching the other selection properties is specified. If `false` or omitted, all versions matching the other selection properties are specified. +* `mainBranch`: if set to true, specifies all versions that belong to the pacticipant's configured main branch. +* `deployed`: if set to true, specifies all currently deployed pacticipant versions +* `released`: if set to true, specifies all released pacticipant versions that are currently in support +* `max_age`: the number of days since it was created, as an integer, for which to keep the application version. + +The `pacticipant` and `max_age` property may be used in combination with the other tags. The `max_age` and `latest` keys cannot be used together. + +:::note + +The selectors `{ "deployed": true }` and `{ "released": true }` will automatically be added to the keep selectors, meaning that all versions that have ever been deployed or released will be kept. + +::: + +#### Examples + +* keep all versions on the main branch of each pacticipant that are less than 30 days old: `{ "max_age": 30, "mainBranch": true }` +* keep the latest version from each pacticipant's branch: `{ "branch": true, "latest": true }` +* keep the latest version for each pacticipant/tag: `{ "latest": true, "tag": true }` +* keep all versions less than 30 days old: `{ "max_age": 30 }` +* keep all currently deployed versions: `{ "deployed": true }` +* keep all released and currently supported versions: `{ "released": true }` +* keep all versions for Foo app: `{ "pacticipant": "Foo" }` +* keep the latest version for each pacticipant: `{ "latest": true }` +* keep all versions tagged "develop" for Foo app: `{ "pacticipant": "Foo", "tag": "develop" }` + +The selectors combine by "OR", meaning that a version is kept if it matches any of the selectors. So `[{ "max_age": 30 }, { "branch": true, "latest": true }, { "deployed": true }]` would mean "keep every version younger than 30 days old, or is the latest version for its branch, or is currently deployed". + +#### Recommended starting configuration for keep selectors + +The following are the default keep selectors specified in the clean tool, and they are a good place to start. (Remember, only one of the selectors needs to be matched to keep the version). + +* Keep all versions under 90 days old - `{ "max_age": 90 }` +* Keep all versions that are the latest for their branch - `{ "branch": true, "latest": true }` +* Keep all versions that are the latest for their tag - `{ "tag": true, "latest": true }` +* Keep all the currently deployed versions - `{ "deployed": true }` +* Keep all the released and currently supported versions - `{ "released": true }` +* Keep the latest version for every pacticipant - `{ "latest": true }` + +Notes: + +* When you deploy an application to production, the relevant pacticipant version needs to be recorded as deployed in PactFlow, so you need to ensure that you keep any version that you're likely to deploy (or rollback to). Specify a `max_age` value that is at minimum the number of days it takes between a commit being created and that commit being deployed (with a very comfortable margin of error) and any branch that you deploy from. A reasonable max_age value might be 90 days for the `main` branch. eg. `{"max_age": 90, "mainBranch": true }` +* If an application is not under active development, a selector that keeps versions by age limit might not actually select any versions. To ensure that we don't lose those critical "latest" versions for our main line of development or our deployed environments, add a selector with `{"mainBranch": true, "latest": true }`, or keep the latest version from each branch by specifying `{"branch": true, "latest": true }`. + +### Execution + +The database clean tool comes built into the PactFlow On-Premises Docker image. The Docker container should be executed using a tool like Kubernetes CronJob or AWS Batch. It should run on a regular schedule (eg. daily) and be configured to delete at least as many application versions as are expected to be created between each clean execution. + +:::note + +The clean task must use the same Docker image tag as the currently running PactFlow application. + +::: + +To execute the clean task, run the Docker container with the appropriate environment variables (documented below), the PactFlow license mounted, and the entrypoint set to `db-clean`. + +eg. +```sh +docker run --rm \ + --entrypoint db-clean \ + --volume ./pactflow-onprem.lic:/home/pactflow-onprem.lic \ + --env PACTFLOW_DATABASE_URL="..." \ # appropriate environment variables here + quay.io/pactflow/enterprise +``` + +This example Docker Compose file shows an example configuration. It can be run by saving the contents as `docker-compose.yml` and then running `docker compose up` in the same directory. Note that a PactFlow license file is required to run the PactFlow container. + +There will be no data in the database to delete, but the logs will show that the clean process has run. + +```yml +version: "3" + +services: + postgres: + image: postgres:13-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: postgres + + clean: + image: quay.io/pactflow/enterprise + depends_on: + - postgres + environment: + PACTFLOW_DATABASE_URL: "postgres://postgres:password@postgres/postgres" + PACTFLOW_DATABASE_SSLMODE: "disable" # overriding default value of "require" for demo only - "disable" should never be used in production + PACTFLOW_DATABASE_CLEAN_DELETION_LIMIT: "500" + PACTFLOW_SQL_LOG_WARN_DURATION: "60" + # Keep the latest version for every pacticipant branch, and all versions less than 30 days old, and anything deployed or released + PACTFLOW_DATABASE_CLEAN_KEEP_VERSION_SELECTORS: "[{ \"branch\": true, \"latest\": true }, {\"max_age\": 30 }, {\"deployed\": true }, {\"released\": true }]" + PACTFLOW_LOG_LEVEL: "INFO" + PACTFLOW_SQL_LOG_LEVEL: "DEBUG" + entrypoint: dockerize + # There will be no data in the database to delete, but the logs will show that the clean process has run + command: -wait tcp://postgres:5432 sh -c 'db-migrate && db-clean' + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic + +``` + +#### Initial clean strategy + +If you have a very large database, and you are just now enabling the clean, the initial clean up might take some time. To ensure that the clean does not have an impact on the performance of PactFlow, it is recommended to set the cron schedule to something quite regular for the first day (eg. every 2 minutes), and set the clean limit quite low (eg. 100). Once the task has stopped deleting any more records, set the schedule back to something like once/twice a day, and make sure the clean limit is higher than the number of new versions you expect in that time period. + +### Configuration + + + + +#### PACTFLOW_LOG_LEVEL + +The PactFlow application log level + +**Required:** false
+**Default:** `INFO`
+**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
+ +#### PACTFLOW_LOG_FORMAT + +The PactFlow application log format + +**Required:** false
+**Default:** `json`
+**Allowed values:** `json`, `default`, `color`
+**More information:** https://github.com/rocketjob/semantic_logger/tree/master/lib/semantic_logger/formatters
+ +#### PACTFLOW_SQL_LOG_LEVEL + +The log level that will be specified when the SQL query statements are logged. + +**Required:** false
+**Default:** `NONE`
+**Allowed values:** `NONE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
+ +#### PACTFLOW_DATABASE_URL + +The fully qualifed database connection string. If using Postgres on RDS with IAM authentication, the scheme must be `postgresiam` and the port must also be set. + +**Required:** if separate host, name, username, password environment variables are not set
+**Example:** `postgresql://username:password@host:port/database`
+ +#### PACTFLOW_DATABASE_ADAPTER + +The database adapter to use. Use `postgresiam` when using Postgres on RDS with IAM authentication (rather than username/password authentication). + +**Required:** false
+**Default:** `postgres`
+**Allowed values:** `postgres`, `postgresiam`
+ +#### PACTFLOW_DATABASE_USERNAME + +The database username + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +#### PACTFLOW_DATABASE_PASSWORD + +The database password + +**Required:** if PACTFLOW_DATABASE_URL is not set, unless using Postgres on RDS with IAM authentication
+ +#### PACTFLOW_DATABASE_HOST + +The database host + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +#### PACTFLOW_DATABASE_PORT + +The database port + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +#### PACTFLOW_DATABASE_NAME + +The database name + +**Required:** if PACTFLOW_DATABASE_URL is not set
+ +#### PACTFLOW_DATABASE_SSLMODE + +The Postgresql ssl mode. Note, if using Postgres on AWS RDS with IAM authentication, this must be `require`. + +**Required:** false
+**Default:** `require`
+**Allowed values:** `disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full`
+**More information:** https://ankane.org/postgres-sslmode-explained
+ +#### PACTFLOW_DATABASE_CLEAN_DELETION_LIMIT + +Only required when running the `db-clean` entrypoint in the PactFlow Docker container. +The maximum number of records to delete at a time from each of the (categories of removable data)[#categories-of-removable-data]. +Should be set to a number higher than the expected number of application versions that will be created between each clean, +but not so high that it will impact on the performance of the application while it is running. You may need to run tests find the optimal number to use in your environment. + +**Required:** false
+**Default:** `500`
+ +#### PACTFLOW_DATABASE_CLEAN_KEEP_VERSION_SELECTORS + +Only required when running the `db-clean` entrypoint in the PactFlow Docker container. +A JSON string containing a list of the "keep" selectors described in (Understanding the keep selectors)[#understanding-the-keep-selectors]. +To ensure the integity of the PactFlow data, the selectors `{ "deployed": true }` and `{ "released": true }` will be automatically added to the selector list if they are not specified. +Remember to escape the quotes if necessary in your configuration files. + +**Required:** false
+**Default:** `[{ "max_age": 90 }, { "branch": true, "latest": true }, { "tag": true, "latest": true }, { "deployed": true }, { "released": true }, { "latest": true }]`
+ +#### PACTFLOW_DATABASE_CLEAN_OVERWRITTEN_DATA_MAX_AGE + +Only required when running the `db-clean` entrypoint in the PactFlow Docker container. +The maximum number of days to keep "overwritten" data as described in (categories of removable data)[#categories-of-removable-data] + +**Required:** false
+**Default:** `7`
+ +#### PACTFLOW_DATABASE_CLEAN_DRY_RUN + +Only required when running the `db-clean` entrypoint in the PactFlow Docker container. +When set to `true`, the `db-clean` process will not delete any data, but will instead log the data that would be deleted if dry run was not enabled. +Use this to test that the container is configured correctly. + +**Required:** false
+**Default:** `false`
+**Allowed values:** `true`, `false`
+ +#### AWS_REGION + +Required for running Postgres on RDS with IAM authentication. This must be set to the AWS region where the RDS database instance is running. + +**Required:** false
+ + + diff --git a/website/docs/docs/on-premises-2x/network-configuration.md b/website/docs/docs/on-premises-2x/network-configuration.md new file mode 100644 index 00000000..4c0e2fa3 --- /dev/null +++ b/website/docs/docs/on-premises-2x/network-configuration.md @@ -0,0 +1,27 @@ +--- +title: Network configuration +--- + +## Firewall Configuration + +### Inbound + +#### Application port + +The PactFlow application runs on port `9292` by default. This can be configured by setting the [PACTFLOW_HTTP_PORT](/docs/on-premises-2x/environment-variables#pactflow_http_port) environment variable. + +### Outbound + +#### Webhooks + +The PactFlow application provides [webhooks](https://docs.pact.io/pact_broker/advanced_topics/webhooks) that are primarily designed for triggering builds in the **CI systems** of integrated applications. They may also be used to provide status updates to **source control systems** (eg. Github) or **team chat software** (eg. Slack). To enable PactFlow to operate correctly, network access should be configured to systems that are likely to be the targets of these webhooks. + +The host names of these services should also be whitelisted in the [PACTFLOW_WEBHOOK_HOST_WHITELIST](/docs/on-premises-2x/environment-variables/#pactflow_webhook_host_whitelist) environment variable. + +## Certificate and TLS termination + +The recommended configuration is to terminate TLS at the load balancer, communicating over HTTP to the target application servers, which in turn communicate over local sockets to applications within the container. + +If you would like to run PactFlow in a TLS-everywhere configuration, modify the HAProxy configuration file (`/tmp/haproxy.cfg`) to bind a certificate to the `frontend`, and ensure the certificate has been appropriately mounted/added to the container. + +Refer to the [HAProxy documentation](https://www.haproxy.com/documentation/haproxy-configuration-tutorials/security/ssl-tls/client-side-encryption/) for further information. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/redis.md b/website/docs/docs/on-premises-2x/redis.md new file mode 100644 index 00000000..f926b955 --- /dev/null +++ b/website/docs/docs/on-premises-2x/redis.md @@ -0,0 +1,38 @@ +--- +title: Redis Cache +--- + +## Introduction + +PactFlow requires a Redis-compatible storage for the following functions: + +- User session management +- UI caching for performance + +## Session management + +User sessions are stored in Redis. Only a 128-bit session ID is shared with the user's browser. This ID is valid for 30 days and is signed with a server-side secret to prevent tampering—regardless of the cookie's expiry time. This protects against cookie replay attacks. + +All user data, including `idToken` and `accessToken`, is stored server-side and is never exposed to the user. + +## Caching + +To improve UI performance, PactFlow uses a server-side caching layer. + +This may result in temporary staleness—displayed content can differ based on when data was last fetched. Differences may appear between users or across browser sessions. + +PactFlow uses a *per-user* server-side cache, following a `stale-while-revalidate` strategy: + +- **Hot cache:** Data is used without validation. +- **Warm cache:** Data is served immediately, and the cache is refreshed in the background. +- **Cold cache:** The UI blocks until data is fetched from the API. + +This approach balances performance and freshness. + +When a user writes data through the UI, their *entire user cache* is invalidated immediately. This ensures correctness for the current user. However, if the change is made by another user or via the API, it may take longer to appear. + +As a fallback, the PactFlow UI follows HTTP cache-control conventions. If a user performs a hard refresh (`Shift+Refresh`), the browser sends headers like `Cache-Control: no-cache` or `Pragma: no-cache`, which bypass the cache. + +## Supported versions + +Redis 7.0 and later is supported. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.10.0.md b/website/docs/docs/on-premises-2x/releases/1.10.0.md new file mode 100644 index 00000000..90460c95 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.10.0.md @@ -0,0 +1,17 @@ +--- +title: 1.10.0 +--- + +## Release date + +31 March 2021 + +## Notes + +* The on-premises version of PactFlow requires a license file to run. Contact your Account Manager if you have not received one. + +## Features + +* Update OSS broker to 2.79.0 +* Generate downloadable example projects for consumers and providers + diff --git a/website/docs/docs/on-premises-2x/releases/1.11.0.md b/website/docs/docs/on-premises-2x/releases/1.11.0.md new file mode 100644 index 00000000..9903ba26 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.11.0.md @@ -0,0 +1,72 @@ +--- +title: 1.11.0 +--- + +## Release date + +5 July 2021 + +## Features + +- Allow a banner to be configured and displayed post-login. +- Support [user preferences](/docs/user-interface/settings/preferences#personal-preferences). +- Support [system preferences](/docs/user-interface/settings/preferences#system-preferences). +- Support [PACTFLOW_DATABASE_PORT](/docs/on-premises-2x/environment-variables#pactflow_database_port) environment variable. +- Allow API token expiry to be configured. +- Show warning in UI when API token is due to expire. +- Support database field level encryption of API tokens. +- Support [ignoring specified applications](https://docs.pact.io/pact_broker/client_cli/readme#can-i-deploy) when using can-i-deploy. +- Allow [secrets](/docs/user-interface/settings/secrets) and [webhooks](/docs/user-interface/settings/webhooks) to be assigned to, and managed by, a specific team. +- Improve [pending pacts and WIP pacts](https://github.com/pact-foundation/pact_broker/pull/432) logic. +- Add [pactbroker.azureDevOpsVerificationStatus webhook parameter](/docs/user-interface/settings/webhooks#pactflow). +- Validate that well formed JSON or YAML is used when publishing Base64 encoded provider contracts. +- Disallow the deletion of predefined roles. +- Add endpoint to [reset role/permissions assignments](/docs/permissions/predefined-roles#resetting-permissions-for-predefined-roles) for predefined roles. +- Deprecate `system:preference:read` permission. All logged in users may now read the system preferences. +- Allow team administrators to be assigned to teams. Team administrators can add and remove users and applications from teams. +- Add [`system_account:manage:team`](/docs/permissions#system_accountmanageteam) permission to allow team users to view/regenerate the API tokens for system account users that are assigned to their team. +- Update default permissions assigned to predefined roles to use [team scoped permissions](/docs/permissions/predefined-roles#user) where ever applicable. +- Renamed "Test Maintainer" role to ["User"](/docs/permissions/predefined-roles#user) for new installations. + +## Fixes + +- Ensure the SAML provider base URL is derived correctly when the login endpoint is specified in the metadata, not an environment variable +- Correctly record which SAML provider was used to log in when multiple SAML providers are configured +- Ensure api token values are not show in debug logging + +## Migration notes + +- If not already set, the `PACTFLOW_BASE_URL` should be set to mitigate cache poisoning vulnerabilities. +- The `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY` environment variable has been renamed to `PACTFLOW_MASTER_ENCRYPTION_KEY`. The old name will continue to work, but please update your configuration to avoid warnings. Do not change the value of this key. +- Steps to enable API token database field level encryption: + + - Please read the relevant documentation for each of the following environment variables, and update your configuration with the appropriate values. + - [`PACTFLOW_MASTER_ENCRYPTION_KEY`](/docs/on-premises-2x/environment-variables#pactflow_master_encryption_key) - renamed from `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY`. Do not change the value of this key. + - [`PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED`](/docs/on-premises-2x/environment-variables#pactflow_api_token_encryption_enabled) - must be set to "true" + - [`PACTFLOW_API_TOKEN_IV`](/docs/on-premises-2x/environment-variables#pactflow_api_token_iv) - a random value must be assigned as per the documentation. + - Restart the PactFlow application. The API tokens will be encrypted during start up once the `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` environment variable has been set to true. + - Verify that the API tokens have been encrypted by running the SQL: + + ```sql + SELECT COUNT(*) FROM saas_api_tokens; + SELECT COUNT(*) FROM saas_api_tokens WHERE encrypted_value IS NOT NULL; + ``` + + Both counts should be the same. + + - Verify that users still have access to the API using their existing tokens executing the following curl command, or making the same request with Postman or equivalent: + + ```bash + curl -v https://{YOUR_PACTFLOW_DOMAIN} \ + -H "Authorization: Bearer {EXISTING_TOKEN_VALUE}" + ``` + + The response should be a 200 OK with a JSON body. + + - Once it has been confirmed that the now-encrypted API tokens are working correctly, please clear the unencrypted values from the database using the following SQL: + + ```sql + UPDATE saas_api_tokens SET value = NULL; + ``` + + - Once API token encryption has been enabled and the unencrypted values removed, encryption cannot be disabled again. diff --git a/website/docs/docs/on-premises-2x/releases/1.11.1.md b/website/docs/docs/on-premises-2x/releases/1.11.1.md new file mode 100644 index 00000000..ca99878c --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.11.1.md @@ -0,0 +1,11 @@ +--- +title: 1.11.1 +--- + +## Release date + +9 July 2021 + +## Fixes + +* Fix runtime error generating validation message for can-i-deploy diff --git a/website/docs/docs/on-premises-2x/releases/1.12.0.md b/website/docs/docs/on-premises-2x/releases/1.12.0.md new file mode 100644 index 00000000..b3350c04 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.12.0.md @@ -0,0 +1,14 @@ +--- +title: 1.12.0 +--- + +## Release date + +21 September 2021 + +## Features + +* Add support for [PACTFLOW_SAML_ALLOWED_CLOCK_DRIFT](/docs/on-premises-2x/environment-variables#pactflow_saml_allowed_clock_drift) +* Validate encryption master key on startup +* Allow the default role and team to be configured in the system preferences +* Add [Guest role](/docs/permissions/predefined-roles#guest). diff --git a/website/docs/docs/on-premises-2x/releases/1.13.0.md b/website/docs/docs/on-premises-2x/releases/1.13.0.md new file mode 100644 index 00000000..c1796a09 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.13.0.md @@ -0,0 +1,11 @@ +--- +title: 1.13.0 +--- + +## Release date + +23 September 2021 + +## Features + +* Add support for [PACTFLOW_HTTP_LOGGING_ENABLED](/docs/on-premises-2x/environment-variables#pactflow_http_logging_enabled) diff --git a/website/docs/docs/on-premises-2x/releases/1.13.1.md b/website/docs/docs/on-premises-2x/releases/1.13.1.md new file mode 100644 index 00000000..77d17db7 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.13.1.md @@ -0,0 +1,11 @@ +--- +title: 1.13.1 +--- + +## Release date + +27 September 2021 + +## Fixes + +* Correct missing default value for the database adapter which stops the application from starting up when the individual database connection attributes are used. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.0.md b/website/docs/docs/on-premises-2x/releases/1.14.0.md new file mode 100644 index 00000000..9672fb4c --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.0.md @@ -0,0 +1,30 @@ +--- +title: 1.14.0 +--- + +## Release date + +2 December 2021 + +## Features + +- Add support for publishing pacts and verification results with [branches](https://docs.pact.io/pact_broker/branches). +- Add support for recording [deployments and releases](https://docs.pact.io/pact_broker/recording_deployments_and_releases). +- Add [global](/docs/permissions#deployment_and_releaserecord) and [team](/docs/permissions#deployment_and_releaserecordteam) scoped permissions for recording deployments and releases. +- Add support for the new [`contract_requiring_verification_published` webhook](https://docs.pact.io/blog/2021/10/11/contract-requiring-verification-published-webhook-event). +- Add support for disabling [dangerous pact modification](https://docs.pact.io/pact_broker/configuration/settings#allow_dangerous_contract_modification). +- Added support for the following configuration settings: + - [PACTFLOW_DATABASE_CONNECTION_VALIDATION_TIMEOUT](/docs/on-premises-2x/environment-variables#pactflow_database_connection_validation_timeout) + - [PACTFLOW_ALLOW_DANGEROUS_CONTRACT_MODIFICATION](/docs/on-premises-2x/environment-variables#pactflow_allow_dangerous_contract_modification) + - [PACTFLOW_USE_FIRST_TAG_AS_BRANCH](/docs/on-premises-2x/environment-variables#pactflow_use_first_tag_as_branch) + - [PACTFLOW_CREATE_DEPLOYED_VERSIONS_FOR_TAGS](/docs/on-premises-2x/environment-variables#pactflow_create_deployed_versions_for_tags) + - [PACTFLOW_USE_HAL_BROWSER](/docs/on-premises-2x/environment-variables#pactflow_use_hal_browser) + +## Fixes + +- Do not error when attempting to add a user or application to the default team as configured in the system preferences, and the default team no longer exists. + +## Migration notes + +- Update the PactFlow Docker image tag to `1.14.0` and redeploy the PactFlow application infrastructure. +- There are no configuration changes to be made. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.1.md b/website/docs/docs/on-premises-2x/releases/1.14.1.md new file mode 100644 index 00000000..090f470f --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.1.md @@ -0,0 +1,11 @@ +--- +title: 1.14.1 +--- + +## Release date + +7 December 2021 + +## Fixes + +* Display correct icon for pacts with status "failed_pending". diff --git a/website/docs/docs/on-premises-2x/releases/1.14.2.md b/website/docs/docs/on-premises-2x/releases/1.14.2.md new file mode 100644 index 00000000..c8cd5431 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.2.md @@ -0,0 +1,15 @@ +--- +title: 1.14.2 +--- + +## Release date + +31 January 2022 + +## Fixes + +* Fix error raised when setting [`database_connection_validation_timeout`](/docs/on-premises-2x/environment-variables#pactflow_database_connection_validation_timeout). + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.3.md b/website/docs/docs/on-premises-2x/releases/1.14.3.md new file mode 100644 index 00000000..84c8252d --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.3.md @@ -0,0 +1,15 @@ +--- +title: 1.14.3 +--- + +## Release date + +1 February 2022 + +## Fixes + +* Fixed CVE-2021-23807 + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.4.md b/website/docs/docs/on-premises-2x/releases/1.14.4.md new file mode 100644 index 00000000..1e1c29d9 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.4.md @@ -0,0 +1,17 @@ +--- +title: 1.14.4 +--- + +## Release date + +3 February 2022 + +## Fixes + +* Updated Docker base image to `ruby:2.7.5-alpine3.13` +* Fixed `disable_ssl_verification` setting which was not being honoured in the webhook background process. +* Fixed `webhook_certificates` setting which was not being honoured in the webhook background process. + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.5.md b/website/docs/docs/on-premises-2x/releases/1.14.5.md new file mode 100644 index 00000000..c574b88e --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.5.md @@ -0,0 +1,15 @@ +--- +title: 1.14.5 +--- + +## Release date + +7 February 2022 + +## Fixes + +* Fix CVE-2021-3918 + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.6.md b/website/docs/docs/on-premises-2x/releases/1.14.6.md new file mode 100644 index 00000000..9b4f3056 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.6.md @@ -0,0 +1,19 @@ +--- +title: 1.14.6 +--- + +## Release date + +10 February 2022 + +## Fixes + +* Fix CVE-2018-20677 (bootstrap) +* Fix CVE-2018-20676 (bootstrap) +* Fix CVE-2018-14041 (bootstrap) +* Fix CVE-2021-23358 (underscore) +* Fix CVE-2021-31799 (rdoc) + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.7.md b/website/docs/docs/on-premises-2x/releases/1.14.7.md new file mode 100644 index 00000000..b038761a --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.7.md @@ -0,0 +1,15 @@ +--- +title: 1.14.7 +--- + +## Release date + +11 February 2022 + +## Fixes + +* Add missing custom token params to JWT retrieval call. + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.8.md b/website/docs/docs/on-premises-2x/releases/1.14.8.md new file mode 100644 index 00000000..82bad596 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.14.8.md @@ -0,0 +1,15 @@ +--- +title: 1.14.8 +--- + +## Release date + +11 February 2022 + +## Fixes + +* Parse teams and roles from access token instead of id token. + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.15.0.md b/website/docs/docs/on-premises-2x/releases/1.15.0.md new file mode 100644 index 00000000..6d082f59 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.15.0.md @@ -0,0 +1,18 @@ +--- +title: 1.15.0 +--- + +:::caution NOTE +Docker 19.03 support is dropped with this release. +::: + +## Release date + +15 February 2022 + + +## Migration notes + +This release upgrades the base image from alpine3.13 to alpine3.15. **Please note that Docker 19.03 is no longer supported** as it is EOL and alpine3.15 requires Docker 20.10.0 or later (see point 2 in the `faccessat2` section of the [Alpine 3.14 release notes](https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2) for more information). + +If you are already running PactFlow on Docker 20.10.0 or later, no action is required. Please update your PactFlow image version as normal. If you are running a version of Docker older than 20.10.0, please upgrade your Docker version to 20.10.0 or later before upgrading to PactFlow 1.15.0. diff --git a/website/docs/docs/on-premises-2x/releases/1.16.0.md b/website/docs/docs/on-premises-2x/releases/1.16.0.md new file mode 100644 index 00000000..8a4727ab --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.16.0.md @@ -0,0 +1,15 @@ +--- +title: 1.16.0 +--- + +## Release date + +18 February 2022 + +## Features + +* Added support for using AWS IAM authentication between the PactFlow application and an RDS Postgres instance. See documentation [here](/docs/on-premises-2x/database#aws-iam-authentication). + +## Migration notes + +N/A. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.17.0.md b/website/docs/docs/on-premises-2x/releases/1.17.0.md new file mode 100644 index 00000000..7ea5d873 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.17.0.md @@ -0,0 +1,15 @@ +--- +title: 1.17.0 +--- + +## Release date + +25 February 2022 + +## Features + +* Added support for server side session inactivity timeout, configurable via the environment variable [`PACTFLOW_SESSION_INACTIVITY_TIMEOUT`](/docs/on-premises-2x/environment-variables#pactflow_session_inactivity_timeout) + +## Migration notes + +By default, the `PACTFLOW_SESSION_INACTIVITY_TIMEOUT` will be set to the configured value of `PACTFLOW_SESSION_LENGTH`. This effectively disables the feature, for backwards compatibility purposes. If you would like to take advantage of this new feature, set the `PACTFLOW_SESSION_INACTIVITY_TIMEOUT` to the value of your choice. If you do not wish to use this feature, no change is required. diff --git a/website/docs/docs/on-premises-2x/releases/1.17.1.md b/website/docs/docs/on-premises-2x/releases/1.17.1.md new file mode 100644 index 00000000..12a9f10b --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.17.1.md @@ -0,0 +1,12 @@ +--- +title: 1.17.1 +--- + +## Release date + +10 March 2022 + +## Fixes + +* Upgrade busybox to fix CVE-2021-42377 +* Fix error returned when viewing OSS server side rendered UI. diff --git a/website/docs/docs/on-premises-2x/releases/1.17.2.md b/website/docs/docs/on-premises-2x/releases/1.17.2.md new file mode 100644 index 00000000..3dad692e --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.17.2.md @@ -0,0 +1,11 @@ +--- +title: 1.17.2 +--- + +## Release date + +28 March 2022 + +## Fixes + +* Ensure commas in database and basic auth credential configurations do not cause the values to be parsed as arrays. diff --git a/website/docs/docs/on-premises-2x/releases/1.17.3.md b/website/docs/docs/on-premises-2x/releases/1.17.3.md new file mode 100644 index 00000000..4785d60a --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.17.3.md @@ -0,0 +1,11 @@ +--- +title: 1.17.3 +--- + +## Release date + +12 April 2022 + +## Fixes + +* CVE-2018-25032 diff --git a/website/docs/docs/on-premises-2x/releases/1.18.0.md b/website/docs/docs/on-premises-2x/releases/1.18.0.md new file mode 100644 index 00000000..44d03d3e --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.18.0.md @@ -0,0 +1,28 @@ +--- +title: 1.18.0 +--- + + + + +## Release date + +31 May 2022 + +## Features + +* Enable [bi-directional contracts](https://pactflow.io/blog/introducing-bi-directional-contract-testing/) feature. +* Add support for monitoring with [New Relic](/docs/on-premises-2x/environment-variables#new_relic_agent_enabled). +* Require that the `PACTFLOW_BASE_URL` specifies a `https` URL (rather than `http`) unless [`PACTFLOW_REQUIRE_HTTPS`](/docs/on-premises-2x/environment-variables#pactflow_require_https) is set to false. +* Check for potential duplicate pacticipants in publish contracts endpoint. +* Timeout long running pact content diff requests. +* Improve error message when request has non UTF-8 characters. + +## Fixes + +* Matrix - fix performance issue when querying matrix with one selector +* Ensure cookie secret set via environment variable is not parsed as an array when it contains commas. +* CVE-2018-25032 +* CVE-2022-29824 +* CVE-2022-30122 + diff --git a/website/docs/docs/on-premises-2x/releases/1.19.0.md b/website/docs/docs/on-premises-2x/releases/1.19.0.md new file mode 100644 index 00000000..995b74c9 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.19.0.md @@ -0,0 +1,20 @@ +--- +title: 1.19.0 +--- + +## Release date + +1 August 2022 + +## Features + +* Return user email to ui for user with unknown names +* Allow configuration of [max_connections](https://docs.pactflow.io/docs/on-premises-2x/environment-variables/#pactflow_database_max_connections) and [pool_timeout](https://docs.pactflow.io/docs/on-premises-2x/environment-variables/#pactflow_database_pool_timeout) + +## Fixes + +* [Correctly apply the `deployment_and_release:record:team` permission](https://github.com/pactflow/roadmap/issues/71) when recording deployments and releases. +* Gracefully handle policy check when no contracts are defined in the request to publish contracts +* Apply the integrations limit to the publish contracts endpoint +* CVE-2022-30122 CVE-2022-30123 GHSA-cgx6-hpwq-fhv5 CVE-2022-29181 GHSA-xh29-r2w5-wx8m +* Update mechanize for CVE-2022-31033 diff --git a/website/docs/docs/on-premises-2x/releases/1.19.1.md b/website/docs/docs/on-premises-2x/releases/1.19.1.md new file mode 100644 index 00000000..be751823 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.19.1.md @@ -0,0 +1,12 @@ +--- +title: 1.19.1 +--- + +## Release date + +18 August 2022 + +## Fixes + +* Show correct cross contract comparison result in Matrix UI when comparisons exist for multiple consumer pacts +* Show correct contract deletion options in kebab menu when viewing the bi-directional contract details page \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.19.2.md b/website/docs/docs/on-premises-2x/releases/1.19.2.md new file mode 100644 index 00000000..b6e8bcc3 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.19.2.md @@ -0,0 +1,11 @@ +--- +title: 1.19.2 +--- + +## Release date + +24 August 2022 + +## Fixes + +* Correctly use default value for PACTFLOW_SQL_LOG_LEVEL when the environment variable has not been set \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.20.0.md b/website/docs/docs/on-premises-2x/releases/1.20.0.md new file mode 100644 index 00000000..3164c587 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.20.0.md @@ -0,0 +1,18 @@ +--- +title: 1.20.0 +--- + +## Release date + +2 September 2022 + +## Features + +* Added support for [demo authentication](/docs/on-premises-2x/authentication/demo). Note: using basic auth for demonstration mode is no longer supported. + +## Fixes + +* CVE-2020-36599 +* Fixed error message "unable to load resource, as it was not found" shown on user admin page. +* When deleting an integration, ensure a provider with an OAS is not deleted if another consumer has a pact with it. +* Correctly identify database version when schema_migrations table is empty. diff --git a/website/docs/docs/on-premises-2x/releases/1.21.0.md b/website/docs/docs/on-premises-2x/releases/1.21.0.md new file mode 100644 index 00000000..f368b014 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.21.0.md @@ -0,0 +1,16 @@ +--- +title: 1.21.0 +--- + +## Release date + +21 October 2022 + +## Features + +* Display license expiry notices in the UI when there are fewer than 30 days until expiry. +* Implement pending logic for provider branches. + +## Fix + +* Fix performance issue when calculating the work in progress pacts for the "pacts for verification" endpoint. diff --git a/website/docs/docs/on-premises-2x/releases/1.21.1.md b/website/docs/docs/on-premises-2x/releases/1.21.1.md new file mode 100644 index 00000000..efb40bfd --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.21.1.md @@ -0,0 +1,11 @@ +--- +title: 1.21.1 +--- + +## Release date + +4 Nov 2022 + +## Fix + +* Fix argument error when publishing pacts diff --git a/website/docs/docs/on-premises-2x/releases/1.22.0.md b/website/docs/docs/on-premises-2x/releases/1.22.0.md new file mode 100644 index 00000000..ecb36dbb --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.22.0.md @@ -0,0 +1,26 @@ +--- +title: 1.22.0 +--- + +## Release date + +13 Feb 2023 + +## Features + +* Pagination has been added to the Pacticipant end point +* Miscellaneous performance improvements + +## Fixes + +* Fix BDC incorrectly requiring consumer to be deployed to deploy the provider +* Restrict users from changing their own roles in PactFlow API +* Restrict users from updating their own roles via bulk actions +* Restrict users without required permissions from creating and updating other users +* Add validation to ensure an environment or to tag is specified for the /can-i-deploy endpoint +* Check that request body does not contain any invalid UTF-8 characters before JSON parsing + + +## Migration notes + +N/A. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.22.1.md b/website/docs/docs/on-premises-2x/releases/1.22.1.md new file mode 100644 index 00000000..56a561af --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.22.1.md @@ -0,0 +1,16 @@ +--- +title: 1.22.1 +--- + +## Release date + +23 Feb 2023 + +## Fixes + +* Fix error raised for clean task when one keep selector has a max age, and another keep selector has a max age and branch. +* Fix incorrect "no" response for can-i-deploy when a provider with a provider contract has multiple consumers. + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.23.0.md b/website/docs/docs/on-premises-2x/releases/1.23.0.md new file mode 100644 index 00000000..8cef25a7 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.23.0.md @@ -0,0 +1,16 @@ +--- +title: 1.23.0 +--- + +## Release date + +23 Feb 2023 + +## Features + +* Improve pre-calculation of pact/provider contract comparisons to reduce chance of missing comparison when can-i-deploy is run. +* Add db-clean entrypoint to PactFlow Docker image to support [database maintenance](/docs/on-premises-2x/maintenance/database). + +## Migration notes + +N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.23.1.md b/website/docs/docs/on-premises-2x/releases/1.23.1.md new file mode 100644 index 00000000..e86667d6 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.23.1.md @@ -0,0 +1,11 @@ +--- +title: 1.23.1 +--- + +## Release date + +22 May 2023 + +## Fixes + +* Fix vulnerabilities diff --git a/website/docs/docs/on-premises-2x/releases/1.24.0.md b/website/docs/docs/on-premises-2x/releases/1.24.0.md new file mode 100644 index 00000000..7f51a04a --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.24.0.md @@ -0,0 +1,25 @@ +--- +title: 1.24.0 +--- + +## Release date + +6 June 2023 + +## Features + +* Upgrade to Ruby 3.2 +* Execute missing pact/OAS comparisons asynchronously to prevent can-i-deploy HTTP requests timing out. See [blog post](https://pactflow.io/blog/resilient-builds-with-can-i-deploy-2/). +* Allow pacticipants to be searched by name using the query string `?q={term}` +* Add pagination to teams endpoint +* Compress response payloads with gzip +* Upgrade to latest swagger-mock-validator +* When comparing a pact and OAS for a bi-directional contract, select OAS response schema based on accept and request schema based on content-type headers +* When comparing a pact and OAS for a bi-directional contract, support comparisons for [Pact V4 bodies](https://github.com/pact-foundation/pact-specification/tree/version-4#bodies) rather than treating the section as JSON. + +## Fixes + +* Fix error raised when querying the matrix for an integration using bi-directional contracts with a single selector and no 'deploy to' selector (tag, environment, or branch). +* Fix error raised when updating a team with a team member that has been marked as inactive. +* SCIM - allow externalIdpId and externalIdpUsername fields to be writable in the create user endpoint, to ensure provisioned user details are correctly matched with the newly logged in user details. +* Add missing validation for the provider version branch when fetching pacts for verification, to ensure that empty strings are disallowed diff --git a/website/docs/docs/on-premises-2x/releases/1.25.0.md b/website/docs/docs/on-premises-2x/releases/1.25.0.md new file mode 100644 index 00000000..68542329 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.25.0.md @@ -0,0 +1,22 @@ +--- +title: 1.25.0 +--- + +## Release date + +28 June 2023 + +## Features + +* Add support for negative scenarios in bi-directional contracts. When the expected response code is >= 400, request parameters, headers, body and security requirements are ignored, and the expected response schema is selected for comparison. + +## Fixes + +* Address performance issues in the dashboard when large numbers of pacticipants are present. +* Improve performance of integrations list on dashboard by using pagination. +* Improve performance of API for network diagram by updating network discovery algorithm and limiting the number of applications that are included in the diagram. +* When deleting a team, disassociate webhooks and secrets to prevent foreign key errors. + +## Migration notes + +N/A diff --git a/website/docs/docs/on-premises-2x/releases/1.26.0.md b/website/docs/docs/on-premises-2x/releases/1.26.0.md new file mode 100644 index 00000000..30354c2c --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.26.0.md @@ -0,0 +1,51 @@ +--- +title: 1.26.0 +--- + +## Release date + +07 August 2023 + +## Features + +* Support application/problem+json error response format for all non-200 responses +* [Major version upgrade of AJV](https://docs.pactflow.io/docs/bi-directional-contract-testing/contracts/oas/changelog) from v6 to v8 and Improve support for allOf, anyOf, oneOf, including polymorphic inheritance. +* Add new SCIM role to be assigned to the System Account that is used to access the PactFlow SCIM API. + +## Fixes + +* Fix error occuring when can-i-deploy badge is requested and no version is found +* Fix incorrect decoding of pact v4 bodies +* OAS now supports `exclusiveMinimum` and `exclusiveMaximum` correctly in request and response bodies +* Fix null pointer in role users endpoint + +## Migration notes + +### SCIM role migration + +These migration steps are only relevant if the PactFlow SCIM API is in use. + +1. Identify the System Account that is being used to access the SCIM API. + * Login to PactFlow as an Administrator. + * Click the Settings icon in the top right. + * Click the `Users` link in the left menu. + * Select `System Accounts` in the drop down box above the User list. + * Identify the relevant System Account and note the name. +2. Ensure that no role called `SCIM` exists. + * From the PactFlow Settings page, click the `Roles` link. + * If a role called `SCIM` exists, click the `EDIT` button, change the name (eg. `SCIM (Deprecated)`), and click `SAVE` +3. Perform the release as normal. +4. Assign the new SCIM role to the System Account identified in step 1. + * Login to PactFlow as an Administrator. + * Click the Settings icon in the top right. + * Click the `Users` link in the left menu. + * Select `System Accounts` in the drop down box above the User list. + * Locate the relevant System Account in the list. + * Click the `...` icon at the right of the row for the relevant System Account. + * Select `Edit roles`. + * Deselect the existing role. + * Select `SCIM`. + * Click `OK` +5. If there was a custom role previously used for the SCIM System Account, delete it. + * From the PactFlow Settings page, click the `Roles` link. + * Click the `DELETE` button next to the custom role. diff --git a/website/docs/docs/on-premises-2x/releases/1.27.0.md b/website/docs/docs/on-premises-2x/releases/1.27.0.md new file mode 100644 index 00000000..4fb0acf0 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.27.0.md @@ -0,0 +1,27 @@ +--- +title: 1.27.0 +--- + +## Release date + +21 September 2023 + +## Features + +* Bi-directional contracts - add "all in one" endpoint for publishing provider contracts with branch and tags +* Bi-directional contracts Pact/OAS comparison tool (swagger-mock-validator) + * Support OAS schemas with nested `allOf` operators + * Set default `additionalProperties` in response to false + * Handle exclusiveMinimum/exclusiveMaximum in bodies + * Support polymorphic inheritance in request bodies + * Improve support for allOf, anyOf, oneOf +* Add branch endpoint supporting GET and DELETE +* Add pagination parameter validation to endpoints that support pagination. + +## Fixes + +* Do not raise an error when attempting to save a duplicate provider contract version +* Matrix - optimise long running query +* Bi-directional contracts Pact/OAS comparison tool (swagger-mock-validator) - correctly decode Pact v4 bodies + +## Migration notes diff --git a/website/docs/docs/on-premises-2x/releases/1.28.0.md b/website/docs/docs/on-premises-2x/releases/1.28.0.md new file mode 100644 index 00000000..3ed84761 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.28.0.md @@ -0,0 +1,27 @@ +--- +title: 1.28.0 +--- + +## Release date + +28 November 2023 + +## Features + +* Add endpoint to list branches +* Removed "generate project" links +* Allow additional sources to be added to the Content-Security-Policy +* Pagination parameters `pageSize` and `pageNumber` have been renamed to `size` and `page`, but the older name is retained for backward compatibility +* Support ignoring applications for "can-i-deploy" with bi-directional contracts + +## Fixes + +* Fixed an issue when trying to read individual system preferences +* Add index to fix performance issue when deleting versions with many deployed or released versions. +* Fix null pointer error raised when no matching environment found when querying environments by name + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.29.0.md b/website/docs/docs/on-premises-2x/releases/1.29.0.md new file mode 100644 index 00000000..230d9cd1 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.29.0.md @@ -0,0 +1,25 @@ +--- +title: 1.29.0 +--- + +## Release date + +31 January 2024 + +## Features + +* Add verification modes to the GET /integration endpoint +* Reduce time for a successful can-i-deploy result when using bi-directional contracts by reducing the number of historical branches to generate pact/OAS comparisons for + +## Fixes + +* Add validation to ensure a pacticipant cannot be created with an empty name when publishing a contract. +* Fix performance issues due to contention in the integrations table when publishing a large number of contracts (> 20) per request, in parallel +* Fix contention on the API tokens table when large numbers of parallel requests come in with the same token +* Correct the logic used to calculate the pactRevisionsPerConsumerVersion distribution in the metrics endpoint + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.30.0.md b/website/docs/docs/on-premises-2x/releases/1.30.0.md new file mode 100644 index 00000000..62b2de28 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.30.0.md @@ -0,0 +1,25 @@ +--- +title: 1.30.0 +--- + +## Release date + +10 April 2024 + +## Features + +* Add team-specific metric details via an endpoint `/metrics/teams` + +## Fixes + +* Fix bug where a user with `environment:team:read` permission received a 403 when performing a GET request for an individual environment +* Ensure matrix and can-i-deploy use the latest revision of the pact when using bi-directional contracts and the pact for a consumer version is modified +* Fix bug where searching integrations in the dashboard would only search from the first 1000 integrations +* Improved performance of the `/admin/users` endpoint +* Disables “dangerous contract modification” by default for new installations. Existing on-premises installations are unaffected. See https://docs.pactflow.io/docs/troubleshooting/disabling-dangerous-contract-modification/#on-premesis-1 for more, and how to disable it for existing installations. + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.31.0.md b/website/docs/docs/on-premises-2x/releases/1.31.0.md new file mode 100644 index 00000000..1824fccc --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.31.0.md @@ -0,0 +1,31 @@ +--- +title: 1.31.0 +--- + +## Release date + +22 August 2024 + +## Features + +* Added new `/labels` API that lists all labels + +## Fixes + +* Fixes an issue where the "next" embedded link was not documented in the response body of the `GET /audit` endpoint +* Fixes the `NoMethodError` for pacticipants PATCH request when request body contains embedded labels +* Documents the API `/pacticipants/:pacticipant_name/labels/:label_name` for managing labels for a pacticipant +* Fixed unique team name issue when updating team in settings +* Fix bug which caused a missing row in the matrix when there are a mix of classic Pact and bi-directional contracts +* Resolves the `UniqueConstraintViolation` issue when updating team users via a PUT request. +* Fixed incorrect type standardization for openapi -v 3.1.0 +* Team Administrators will now have permission to view environments +* Deprecated _embedded payload format in the team update APIs +* Fixes an issue where deleting an integration in the context of BDCT leads to the unintended deletion of provider contracts +* Added provider version number to webhook endpoint + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.32.0.md b/website/docs/docs/on-premises-2x/releases/1.32.0.md new file mode 100644 index 00000000..9ff3dcc1 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.32.0.md @@ -0,0 +1,25 @@ +--- +title: 1.32.0 +--- + +## Release date + +09 September 2024 + +## Features + +N/A + +## Fixes + +* fixed the situation when a consumer-provider pair has both an OAS and traditional pact containing both HTTP and message interactions. Message interactions that haven't been validated at comparison time or when `can-i-deploy` is called, returns a new Message Verification Missing reason. +* Fixed vulnerability GHSA-4xqq-m2hx-25v8 ( rexml ) +* Fixed vulnerability GHSA-vg3r-rm7w-2xgh ( rexml ) +* Fixed vulnerability GHSA-vmwr-mc7x-5vc3 ( rexml ) +* Fixed vulnerability CVE-2024-6119 ( openssl-dev, libssl-dev, libcrypto3 ) + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.33.0.md b/website/docs/docs/on-premises-2x/releases/1.33.0.md new file mode 100644 index 00000000..a6c57c5f --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.33.0.md @@ -0,0 +1,21 @@ +--- +title: 1.33.0 +--- + +## Release date + +18 September 2024 + +## Features + +N/A + +## Fixes + +* CVEs GHSA-cvp8-5r8g-fhvq, GHSA-jw9c-mfg7-9rx2, GHSA-r55c-59qm-vjw6, GHSA-5866-49gr-22v4, GHSA-vmwr-mc7x-5vc3 + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.34.0.md b/website/docs/docs/on-premises-2x/releases/1.34.0.md new file mode 100644 index 00000000..a57a6ad0 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.34.0.md @@ -0,0 +1,27 @@ +--- +title: 1.34.0 +--- + +## Release date + +22 October 2024 + +## Features + +N/A + +## Fixes +* updated packages to fix multiple CVEs + - webrick ( GHSA-6f62-3596-g6w7 ) + - wget ( CVE-2024-38428 ) + - puma ( GHSA-9hf4-67fc-4vf4 ) + - openssl-dev ( CVE-2024-9143 ) + - libssl3 ( CVE-2024-9143 ) + - openssl ( CVE-2024-9143 ) + - libcrypto3 ( CVE-2024-9143 ) + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.35.0.md b/website/docs/docs/on-premises-2x/releases/1.35.0.md new file mode 100644 index 00000000..c82b6214 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.35.0.md @@ -0,0 +1,29 @@ +--- +title: 1.35.0 +--- + +## Release date + +18 November 2024 + +## Features + +* using time based sort when combining BDCT + classic pacts +* upgraded to ruby 3.2.6 + +## Fixes + +* updated packages to fix multiple CVEs + - cross-spawn ( CVE-2024-21538 ) + - rexml (GHSA-2rxp-v6pw-ch6m) + - postgresql14-dev (CVE-2024-10979) + - libpq (CVE-2024-10979) + - libecpg-dev (CVE-2024-10979) + - libecpg (CVE-2024-10979) + - libpq-dev (CVE-2024-10979) + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.36.0.md b/website/docs/docs/on-premises-2x/releases/1.36.0.md new file mode 100644 index 00000000..35f3cd36 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.36.0.md @@ -0,0 +1,23 @@ +--- +title: 1.36.0 +--- + +## Release date + +17 January 2025 + +## Features + +* New AI user permission (NOTE: AI features are not yet available to on-premises customers) + +## Fixes + +* Added validation to publish provider contract endpoint to prevent invalid data +* Support x-www-form-urlencoded validation in bi-directional contract testing + + +## Migration notes + +N/A + + diff --git a/website/docs/docs/on-premises-2x/releases/1.4.0.md b/website/docs/docs/on-premises-2x/releases/1.4.0.md new file mode 100644 index 00000000..32f0aad7 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.4.0.md @@ -0,0 +1,10 @@ +--- +title: 1.4.0 +--- + +## Features + +* Provide an [API stub](https://pactflow.io/blog/hosted-stubs/) for every pact. +* Automatically assign first user to log in as the administrator. +* Allow administrators to assign and unassign the administrator role to other users. +* Allow administrators to disable and enable users. diff --git a/website/docs/docs/on-premises-2x/releases/1.4.1.md b/website/docs/docs/on-premises-2x/releases/1.4.1.md new file mode 100644 index 00000000..2d0bf290 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.4.1.md @@ -0,0 +1,7 @@ +--- +title: 1.4.1 +--- + +## Fixes + +* Fixed the users screen to not overflow text with long email addresses diff --git a/website/docs/docs/on-premises-2x/releases/1.5.0.md b/website/docs/docs/on-premises-2x/releases/1.5.0.md new file mode 100644 index 00000000..8a05a7fa --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.5.0.md @@ -0,0 +1,8 @@ +--- +title: 1.5.0 +--- + +## Features + +* Allow users and applications to be assigned to teams +* Allow applications on dashboard to be filtered by selecting a team diff --git a/website/docs/docs/on-premises-2x/releases/1.6.0.md b/website/docs/docs/on-premises-2x/releases/1.6.0.md new file mode 100644 index 00000000..ed55367e --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.6.0.md @@ -0,0 +1,10 @@ +--- +title: 1.6.0 +--- + +## Features + +- Add all new users and applications to a [Default team](/docs/user-interface/settings/teams#the-default-team). +- Support [Test Maintainer](/docs/permissions/predefined-roles#test-maintainer), [CI/CD](/docs/permissions/predefined-roles#cicd) and [Viewer](/docs/permissions/predefined-roles#viewer) roles. +- Add ["team" scoped permissions](/docs/permissions/#contract_datamanageteam) that allow a user to manage applications that are assigned to their team(s). +- Alter the "Test Maintainer" role to use the new "team" scoped permissions. diff --git a/website/docs/docs/on-premises-2x/releases/1.6.1.md b/website/docs/docs/on-premises-2x/releases/1.6.1.md new file mode 100644 index 00000000..aa0c452c --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.6.1.md @@ -0,0 +1,7 @@ +--- +title: 1.6.1 +--- + +## Fixes + +* Remove unused vulnerable version of Bundler from base Docker image diff --git a/website/docs/docs/on-premises-2x/releases/1.7.0.md b/website/docs/docs/on-premises-2x/releases/1.7.0.md new file mode 100644 index 00000000..49b45869 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.7.0.md @@ -0,0 +1,11 @@ +--- +title: 1.7.0 +--- + +## Release date + +8 December 2020 + +## Features + +* Allow configuration of [multiple SAML providers](/docs/on-premises-2x/authentication/saml#configuring-multiple-saml-providers) diff --git a/website/docs/docs/on-premises-2x/releases/1.8.0.md b/website/docs/docs/on-premises-2x/releases/1.8.0.md new file mode 100644 index 00000000..a502b0d0 --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.8.0.md @@ -0,0 +1,16 @@ +--- +title: 1.8.0 +--- + +## Release date + +18 December 2020 + +## Features + +* Add [menus](/docs/user-interface/dashboard/#version-tag-menus) to application version tags to allow copying of relevant URLs and deletion of associated resources. +* Add screens to display webhook execution logs. + +## Fixes + +* Fix vulnerabilities in base image. diff --git a/website/docs/docs/on-premises-2x/releases/1.9.0.md b/website/docs/docs/on-premises-2x/releases/1.9.0.md new file mode 100644 index 00000000..415bea5f --- /dev/null +++ b/website/docs/docs/on-premises-2x/releases/1.9.0.md @@ -0,0 +1,18 @@ +--- +title: 1.9.0 +--- + +## Release date + +1 February 2021 + +## Features + +* Support [deleting verification results](/docs/how_to#delete-verification-results) through the UI. +* Add Pact Broker/PactFlow version to UI. + +## Fixes + +* Fix cache poisoning vulnerability +* Updated JQuery and Bootstrap libraries +* Fix missing request path in audit logs diff --git a/website/docs/docs/on-premises-2x/scim.md b/website/docs/docs/on-premises-2x/scim.md new file mode 100644 index 00000000..c46ea17e --- /dev/null +++ b/website/docs/docs/on-premises-2x/scim.md @@ -0,0 +1,288 @@ +--- +title: On-Premises SCIM API +--- + +The PactFlow SCIM API can be added as a façade to your on-premises PactFlow instance. It runs in its own +docker container and access the PactFlow APIs using a system account API token. + +For details on the PactFlow SCIM API, refer to the [main SCIM documentation](/docs/scim/main). + +## Installation + +### First + +Before running the SCIM API, you must have a correctly running PactFlow instance that is version 1.26.0 or later. Follow the +[PactFlow On-Premises installation instructions](/docs/on-premises-2x/installation/checklist). + +### Then + +* Configure the SCIM Docker image to be pulled from Quay. Follow the [Docker image registry instructions](/docs/on-premises-2x/docker-image-registry) + to get access to the Quay registry and then run `docker pull quay.io/pactflow/scim-api` to pull down the latest SCIM API image. +* You can then deploy the docker container to your docker orchestration service (AWS ECS, K8, etc.). You need to provide the external URL of +your PactFlow instance as the `PACTFLOW_URL` environment variable to the running container. + +**NOTE: The SCIM API has to access your PactFlow instance using the URL/one of the URLs listed in the [PACTFLOW_BASE_URL](/docs/on-premises-2x/environment-variables#pactflow_base_url) environment variable used for the PactFlow application.** This is due to PactFlow using the HAL media format which uses embedded links in the responses. + +For instance, if your PactFlow instance is running as `https://pactflow.mycompany.com` then you need to the set the +`PACTFLOW_URL` environment variable for the SCIM API to that address. + +### Next + +You can now test the running SCIM API by using a tool like `curl`. First, login to your PactFlow instance and create [a +system account](/docs/user-interface/settings/users#system-accounts) with the [SCIM role](/docs/permissions/predefined-roles#scim) and then copy the system account API token. + +For instance, assuming your PactFlow instance is running as `https://pactflow.mycompany.com` and your SCIM API is +running as `https://pactflow-scim.mycompany.com` with its `PACTFLOW_URL` environment variable set to `https://pactflow.mycompany.com` and +you have copied the SCIM system account API token, you can then run `curl -H 'Authorization: Bearer ' https://pactflow-scim.mycompany.com/Users` +to fetch the users as a SCIM request. + +## Docker Compose example + +Here is an example docker compose setup (modified from the [PactFlow Docker Compose example](/docs/on-premises-2x/docker-compose-example)) +to show how the SCIM API can be setup alongside the PactFlow instance. Run through the [PactFlow Docker Compose example](/docs/on-premises-2x/docker-compose-example) +first, and when that is working you can use this docker compose file to add SCIM as a façade. + +### 1. Authenticating to Quay.io + +Authenticate to Quay.io so that the docker engine is able to fetch our images. + +``` +docker login -u="" -p="" quay.io +docker pull quay.io/pactflow/scim-api +``` + +### 2. Startup PactFlow with SCIM API + +Save the below file as `docker-compose.yml` into a temporary directory and then run `docker-compose up`. Make sure you +have setup the PactFlow license file correctly as per [2. PactFlow license file](/docs/on-premises-2x/docker-compose-example#2-pactflow-license-file). + +```yaml +version: "3" + +services: + simplesaml: + image: kristophjunge/test-saml-idp + logging: + driver: none # comment out the logging config to see the SAML server logs + ports: + - "8080:8080" + - "8443:8443" + environment: + - SIMPLESAMLPHP_SP_ENTITY_ID=https://pactflow.io + - SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost/auth/saml/callback + + pactflow: + image: quay.io/pactflow/enterprise:2.0.0 + depends_on: + - postgres + - redis + environment: + # This is set to localhost for this example but in a real deployment, this needs to be set to the actual URL of the application + - PACTFLOW_BASE_URL=http://localhost + # Insecure setting only for the purposes of this demo! Not to be used in production. + - PACTFLOW_DATABASE_SSLMODE=disable + # Insecure setting only for the purposes of this demo! Not to be used in production. + - PACTFLOW_REQUIRE_HTTPS=false + # Demo auth should only be used for demo purposes. Not to be used in production. + - PACTFLOW_DEMO_AUTH_ENABLED=true + # 'Allow all' for the webhook host whitelist should only be used for demo purposes. See docs for configuring this in production. + - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ + - PACTFLOW_HTTP_PORT=9292 + # Link to the postgres database + - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres + - PACTFLOW_LOG_LEVEL=info + - PACTFLOW_ADMIN_API_KEY=admin + - PACTFLOW_MASTER_ENCRYPTION_KEY=thisissomerandombytes + - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- + - PACT_BROKER_ADMIN_API_KEY=admin + - PACTFLOW_HTTP_LOGGING_ENABLED=true + # Link to the redis cache + - REDIS_URL=redis://redis:6379 + # SAML settings + - PACTFLOW_SAML_AUTH_ENABLED=true + - PACTFLOW_SAML_IDP_NAME=Simple SAML + - PACTFLOW_SAML_IDP_SSO_TARGET_URL=http://localhost:8080/simplesaml/saml2/idp/SSOService.php + - PACTFLOW_SAML_IDP_CERT_FINGERPRINT=11:9B:9E:02:79:59:CD:B7:C6:62:CF:D0:75:D9:E2:EF:38:4E:44:5F + - PACTFLOW_SAML_IDP_ID_ATTRIBUTE=uid + - PACTFLOW_SAML_EMAIL_ATTRIBUTE=email + ports: + - "80:9294" + healthcheck: + test: ["CMD", "supervisorctl", "status", "haproxy", "marko", "pactflow"] + interval: 30s + timeout: 10s + retries: 3 + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic + ports: + - "80:9292" + healthcheck: + test: ["CMD", "wget", "-nv", "-t1", "--spider", "http://localhost:9292/diagnostic/status/heartbeat"] + interval: 30s + timeout: 10s + retries: 3 + entrypoint: dockerize + command: -wait tcp://postgres:5432 docker-entrypoint + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic + + postgres: + image: postgres + healthcheck: + test: psql postgres --command "select 1" -U postgres + ports: + - "5432:5432" + volumes: + - postgres-volume:/var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: postgres + + scim-api: + image: quay.io/pactflow/scim-api + depends_on: + - pactflow + environment: + PACTFLOW_URL: "http://pactflow:9292" + LOGGING_LEVEL_ROOT: DEBUG + LOGGING_LEVEL_ORG_APACHE_HC_CLIENT5_HTTP_WIRE: INFO + ports: + - "8100:8080" + + redis: + image: redis:latest + +volumes: + postgres-volume: + +``` + +## 3. Login to PactFlow + +Head to http://localhost in your browser, and choose to login with "SIMPLE SAML", with the username `user1` and password `user1pass`. +Then go to Settings -> API Tokens and COPY an API token. + +## 4. Use Curl and JQ to test access to the SCIM API + +Replace `` below with the API token copied from the last step. + +```console +❯ curl -H 'Authorization: Bearer ' http://localhost:8100/scim/Users | jq + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 1530 100 1530 0 0 3026 0 --:--:-- --:--:-- --:--:-- 3029 +{ + "schemas": [ + "urn:ietf:params:scim:api:messages:2.0:ListResponse" + ], + "totalResults": 2, + "Resources": [ + { + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "61cfa5ff-1be6-4e7e-a620-7efac4a370df", + "meta": { + "created": "2022-12-06T03:49:22Z", + "lastModified": "2022-12-06T03:49:29Z", + "resourceType": "User", + "location": "http://localhost:8100/scim/Users/61cfa5ff-1be6-4e7e-a620-7efac4a370df" + }, + "name": { + "formatted": "SCIM" + }, + "displayName": "SCIM", + "userType": "System Account", + "active": true, + "groups": [ + { + "value": "4ac05ed8-9e3b-4159-96c0-ad19e3b93658", + "display": "Default", + "type": "direct", + "$ref": "Groups/4ac05ed8-9e3b-4159-96c0-ad19e3b93658" + } + ], + "roles": [ + { + "value": "c1878b8e-d09e-11ea-8fde-af02c4677eb7", + "display": "CI/CD", + "type": "CI/CD" + }, + { + "value": "cf75d7c2-416b-11ea-af5e-53c3b1a4efd8", + "display": "Administrator", + "type": "Administrator" + } + ] + }, + { + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "aaa3e1a2-3648-4453-b3a6-2195b6822e2d", + "meta": { + "created": "2022-12-06T00:25:56Z", + "lastModified": "2022-12-06T00:25:56Z", + "resourceType": "User", + "location": "http://localhost:8100/scim/Users/aaa3e1a2-3648-4453-b3a6-2195b6822e2d" + }, + "userType": "User", + "active": true, + "emails": [ + { + "value": "user1@example.com", + "primary": true + } + ], + "groups": [ + { + "value": "4ac05ed8-9e3b-4159-96c0-ad19e3b93658", + "display": "Default", + "type": "direct", + "$ref": "Groups/4ac05ed8-9e3b-4159-96c0-ad19e3b93658" + } + ], + "roles": [ + { + "value": "e9282e22-416b-11ea-a16e-57ee1bb61d18", + "display": "User", + "type": "User" + }, + { + "value": "cf75d7c2-416b-11ea-af5e-53c3b1a4efd8", + "display": "Administrator", + "type": "Administrator" + } + ] + } + ] +} +``` + +## Configuration + +### PactFlow URL (Required) + +**Variable:** `PACTFLOW_URL`
+ +This sets the URL that the PactFlow instance is accessed from. + +### Log Level + +**Variable:** `LOGGING_LEVEL_ROOT`
+**Default:** `INFO`
+**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`
+ +This sets the base log level for the SCIM API container. + +**WARNING: Setting the log level to `DEBUG` will cause all HTTP interactions between the SCIM API and PactFlow to be be logged, +which will include the API tokens in clear text.** To disable logging of the HTTP interactions, set +`LOGGING_LEVEL_ORG_APACHE_HC_CLIENT5_HTTP_WIRE` to `INFO` or greater. + +### Context Path + +**Variable:** `SERVER_SERVLET_CONTEXT_PATH`
+**Default:** `/scim`
+ +This sets the context path that the SCIM API is mounted at. diff --git a/website/docs/docs/on-premises-2x/security-audit-report.md b/website/docs/docs/on-premises-2x/security-audit-report.md new file mode 100644 index 00000000..fb44053f --- /dev/null +++ b/website/docs/docs/on-premises-2x/security-audit-report.md @@ -0,0 +1,199 @@ +--- +title: Security audit report +--- + +## Vulnerability scanning + +PactFlow uses the following tools to ensure the On-Premises image is kept as secure as possible. + +* Bundler Audit +* NPM audit +* Trivy +* Quay Security Scanner +* Amazon ECR Image scanning + +## Reporting vulnerabilities + +To report a vulnerability, please [contact security](https://smartbear.com/security/) and ensure you include the relevant CVE, and the name and/or path to the vulnerable component. + +## Identifying the correct Ruby version + +Many scanning tools have trouble identifying the correct version of Ruby installed on an image because Ruby stores its gems in a directory path that uses the minor version of Ruby (eg. `2.7.0`) rather than the patch version (eg. `2.7.6`). This can be demonstrated by running the following command: + +```shell +docker run --rm -it --entrypoint gem quay.io/pactflow/enterprise:latest environment +``` + +Example output (note the `RUBY VERSION` of `2.7.6` while the `GEM PATHS` use `2.7.0`): + +```shell +RubyGems Environment: + - RUBYGEMS VERSION: 3.1.6 + - RUBY VERSION: 2.7.6 (2022-04-12 patchlevel 219) [x86_64-linux-musl] + - INSTALLATION DIRECTORY: /usr/local/bundle + - USER INSTALLATION DIRECTORY: /root/.gem/ruby/2.7.0 + - RUBY EXECUTABLE: /usr/local/bin/ruby + - GIT EXECUTABLE: + - EXECUTABLE DIRECTORY: /usr/local/bundle/bin + - SPEC CACHE DIRECTORY: /root/.gem/specs + - SYSTEM CONFIGURATION DIRECTORY: /usr/local/etc + - RUBYGEMS PLATFORMS: + - ruby + - x86_64-linux-musl + - GEM PATHS: + - /usr/local/bundle + - /root/.gem/ruby/2.7.0 + - /usr/local/lib/ruby/gems/2.7.0 + - GEM CONFIGURATION: + - :update_sources => true + - :verbose => true + - :backtrace => false + - :bulk_threshold => 1000 + - "install" => "--no-document" + - "update" => "--no-document" + - REMOTE SOURCES: + - https://rubygems.org/ + - SHELL PATH: + - /usr/local/bundle/bin + - /usr/local/sbin + - /usr/local/bin + - /usr/sbin + - /usr/bin + - /sbin + - /bin +``` + +The difficulty that tools have in identifying the correct version of Ruby can lead to false positives being reported. Please check the version of Ruby before submitting a vulnerability report. + +## Identifying the installed gem versions + +To list the gems installed on the PactFlow image run: + +``` +docker run --rm -it --entrypoint gem quay.io/pactflow/enterprise:latest "list" +``` + +## Known vulnerabilities + +### CVE-2015-9284 + +#### Component + +omniauth gem + +#### CVE + +[https://nvd.nist.gov/vuln/detail/CVE-2015-9284](https://nvd.nist.gov/vuln/detail/CVE-2015-9284) + +#### Detectable in versions of PactFlow + +All. + +#### Status + +Non-exploitable. + +#### Notes + +This CVE is a CSRF vulnerability during sign in. This vulnerability is only exploitable if the initial request from the service provider to the identify provider is vulnerable to a CSRF attack because it uses a GET request without any CSRF protection. In PactFlow, this is not possible as PactFlow uses a POST request method with a CSRF token for the initial request to the IDP, as per the mitigation instructions [here](https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284). + +This can be observed by viewing the source of the login form. + +```html +
+ + +
+``` + +### CVE-2022-2625 + +#### Description + +Given certain prerequisites, this vulnerability allows arbitrary code to be run. + +#### Component + +postgresql14-dev package for Alpine + +#### CVE + +[https://nvd.nist.gov/vuln/detail/CVE-2022-2625](https://nvd.nist.gov/vuln/detail/CVE-2022-2625) + +#### Status + +Non-exploitable. + +#### Notes + +This vulnerability applies to the PostgreSQL server only. The PactFlow Docker image only uses the PostgreSQL client, and hence is not affected by this vulnerability. + +### CVE-2022-37434 + +#### Description + +A heap-based buffer over-read or buffer overflow in inflate in inflate.c via a large gzip header extra field. + +#### Component + +zlib package for Alpine + +#### CVE + +[https://nvd.nist.gov/vuln/detail/CVE-2022-37434](https://nvd.nist.gov/vuln/detail/CVE-2022-37434) + +#### Affected versions of PactFlow + +All. + +#### Status + +Unfixed. + +#### Notes + +As of 24 August 2022, there is no fix available. A patch release of PactFlow will be put out as soon as a fix is available. + +### CVE-2021-41816 + +#### Component + +The cgi library included in Ruby before 2.7.5 and 3.x before 3.0.3, and the [cgi gem](https://rubygems.org/gems/cgi) before 0.3.1. + +#### CVE + +[https://nvd.nist.gov/vuln/detail/CVE-2021-41816](https://nvd.nist.gov/vuln/detail/CVE-2021-41816) + +#### Status + +False positive. + +#### Notes + +This vulnerability only affects platforms that use a 4 byte long data type, typically Windows. The PactFlow base image uses 64 bit Alpine Linux, which uses an [8 byte long](https://www.ibm.com/docs/en/ibm-mq/9.0?topic=platforms-standard-data-types-unix-linux-windows). + +### CVE-2020-36599 + +#### Description + +lib/omniauth/failure_endpoint.rb in OmniAuth before 1.9.2 (and before 2.0) does not escape the message_key value. + +#### Component + +omniauth gem + +#### Status + +Non-exploitable. + +#### Detectable in versions of PactFlow + +Up to and including 1.19.2. + +#### Fixed versions + +1.19.3 and later. + +#### Notes + +PactFlow uses a custom failure endpoint so the vulnerable code is never executed. diff --git a/website/docs/docs/on-premises-2x/support-policy.md b/website/docs/docs/on-premises-2x/support-policy.md new file mode 100644 index 00000000..456b1f17 --- /dev/null +++ b/website/docs/docs/on-premises-2x/support-policy.md @@ -0,0 +1,58 @@ +--- +title: Support policy +--- + +## Versioning + +PactFlow On-Premises follows a [semantic versioning](https://semver.org/) policy for API changes. + +Further to this, any changes to the database schema or configuration that are backwards incompatible (eg. addition of a mandatory configuration setting with no default, or the deletion of a table) will only be introduced in a major version. Migration documentation will be included in the release notes for any major version, and any minor version that introduces optional configuration. + +### Base image upgrades + +Upgrades of the Docker base image will be performed in minor releases (eg. from `alpine3.14` to `alpine 3.15`). PactFlow images will only be supported for Docker versions that are currently [in support](https://docs.docker.com/engine/install/#support) themselves (20.10.0 and later). + +## Support period + +PactFlow application bug fixes will be applied to the latest minor release only. + +Minor versions will receive patches for security vulnerabilities for a period 9 months from the release date. + +## Releases + +Minor version releases are performed at 1-2 month intervals. Major and patch version releases are performed as required according to our versioning policy. + +## Subscribing to updates + +Subscribe to our [RSS](/notices/rss.xml), [Atom](/notices/atom.xml) or [JSON](/notices/feed.json) feeds for updates on new on-premises releases and important security announcements. + +## Asking for help + +Current customers may open a [support ticket](https://support.smartbear.com/pactflow/message/) with the following information: + +* The current version of your PactFlow instance (the version of your application is displayed in the footer. If the application is not able to start, the version of the docker image you are running is sufficient) +* A detailed description of what you're trying to achieve, what your expected outcome is, and what the actual behaviour is. +* The current configuration given to your application +* A log file taken from when the problem occurred, where the application log level has been set to `DEBUG` +* If you're trying to demonstrate a problem or diagnose a bug, the best possible thing you can do is provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). +* Any other information you think could help us diagnose the issue + +### Scope of PactFlow support + +PactFlow is distributed via an industry standard Docker image, meaning that it can be deployed to a wide variety of orchestration tools such as Kubernetes and OpenShift, and runtime environments such as AWS, GCP or Azure. + +Given this flexibility, we are unable to provide support for components that live outside of the PactFlow application as there are too many factors outside of our control to be able to advise you appropriately. + +**Examples of things we can help you with** + +* Application configuration issues +* Interpreting and clarifying application logs +* Diagnosing issues with the application behaviour + +**Examples of things we can't help you with** + +* Networking issues +* Docker orchestration setup (e.g. Helm charts, EKS) +* Cloud or infrastructure automation tools (e.g. Cloudformation, Terraform, Ansible) + +Of course, there are areas where the boundaries are not so clear - such as security reports highlighted by an infosec tool, or issues relating to your IDP or database. This is an area of our shared responsibility and we will do our best to support you. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/system-requirements.md b/website/docs/docs/on-premises-2x/system-requirements.md new file mode 100644 index 00000000..e5f2b2d8 --- /dev/null +++ b/website/docs/docs/on-premises-2x/system-requirements.md @@ -0,0 +1,135 @@ +--- +title: System requirements +--- + +## Application server instance + +### OS + +Linux + +### Minimum CPU/Memory + +4.0 GiB Memory, 4 vCPUs + +### Disk space usage + +4.0 GiB + +### Docker version + +20.10.0 or later + +## Postgres database instance + +### HA Configuration + +### Configuration + +We would recommend running Postgres as an Active/Passive setup with [streaming replication](https://wiki.postgresql.org/wiki/Replication,_Clustering,_and_Connection_Pooling), or Active/Active setup for the best availability. + +For reference, pactflow.io runs on AWS RDS in [active/passive mode across multiple logical networks](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html), and fails over to the replica when in a failure mode. + +### Minimum CPU/Memory + +4.0 GiB Memory, 4 vCPUs + +### Storage + +5GiB (minimum) +25GiB (recommended) + +### I/O Performance + +* 10 read/s +* 25 write/s + +## Load Balancing + +We recommend running PactFlow on load-balanced infrastructure in at least a 2 node setup to enable high availability and greater throughput. So for clarity, we would recommend running two servers both with 4GiB memory and 4 CPUs for a total capacity of 8GiB Memory and 8 CPUs. + +The PactFlow application is stateless, and therefore sticky sessions do not need to be configured. Use round-robin or least outstanding requests to route to the application servers. + +_NOTE_: Most Pact tooling has retries built-in to handle minor outages communicating to a broker. + +## Scaling and Monitoring + +Below are the key scaling considerations. + +First, make sure you've identified the baseline load and have performed a [load test](installation/load-testing). This will help you to set you boundaries for your scale out and scale in parameters. + +PactFlow is a database intensive application, with the I/O performance of the database being the most critical factor in determining overall system performance. You should setup monitoring for the following metrics: + +* CPU +* Memory +* I/O latency +* Query latency +* Remaining storage space + +Application servers tend to be more CPU bound, but you should look to monitor and scale at least: + +* CPU +* Memory + + +## Benchmarking and Forecasting + +The usage patterns of every customer is different. For example, we have several customers who are among top users of our SaaS platform with less than 30 integrations. + +Things that will affect how the system scales include: + +* Concurrent usage i.e. requests per second (usually by automation systems such as CI/CD) +* CI implementation patterns (e.g. integrations to PactFlow, the use of polling vs webhooks) +* Developer habits (continuous check-in vs bigger commits) causing more or less builds +* Whether you run regular database cleanups (to reduce database storage requirements, and speed up queries) +* The size, variation and stability of contracts +* The interconnectedness of your system +* Database growth + +and so on. These types of data are very hard to collect, measure and predict. + +For forecasting purposes we've created a standard model you can use for projecting storage and compute costs as you grow, which is based on the number of active users* you have on the system. + +_NOTE_: We still recommend using the monitoring and scaling approach (defined above) to automatically scale up/down your system as required. + +_* Active users is defined as a developer that either logs into PactFlow daily or commits code that would trigger a CI build that integrates with Pactflow_ +### Standard Units + +* 1 `compute unit` = 1 CPU, 256 MiB memory +* 1 `database unit` = 1 CPU, 256 MiB memory, 1 GiB storage (per week), 25 writes/s, 10 read/s + +For each 500 active users*, you should increment your total compute capacity by one (1) unit, and _each_ database server capacity by one (1) unit. + + +### Examples + +_**Scenario 1**: 1000 users in year 1_ + +Assuming our database uses active/passive mode and replication. + +Baseline capacity should be 2 x Application Servers each with 4 CPU and 4GiB memory, and a two Postgres database instances (one for the active and passive) each with 4CPU, 4GiB memory, 25GiB volume and 25/10 write/read per second. + +To calculate the number of standard units you need to add: + +``` +new units = expected users / 500 + = 1000 / 500 + = 2 units +``` + +You should therefore add 2 CPUs and 512 MiB to your total compute budget, and add 2 CPUs, 512 MiB of memory and 104 GiB storage capacity to each of your database instances in year 1, for a total budget: + +* **Compute**: 10 CPU, 8.5 GiB RAM (measured by total resources and not physical instances) +* **Database**: 2 x database servers each with 6 CPU, 4.5 GiB RAM, 75 writes/s, 30 read/s, 129 GiB storage + +_**Scenario 2**: Additional 1300 users in year 2_ + +``` +new units = expected users / 500 + = 1300 / 500 + = 3 units (rounded) +``` +You should therefore add 3 CPUs and 768 MiB to your total compute budget, and add 3 CPUs, 768 MiB of memory and 156 GiB storage capacity to each of your database instances in year 2, for a total budget: + +* **Compute**: 13 CPU, 9.25 GiB RAM (measured by total resources and not physical instances) +* **Database**: 2 x database servers each with 9 CPU, 5.25 GiB RAM, 150 writes/s, 60 read/s, 285 GiB storage \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/troubleshooting.md b/website/docs/docs/on-premises-2x/troubleshooting.md new file mode 100644 index 00000000..39c6c557 --- /dev/null +++ b/website/docs/docs/on-premises-2x/troubleshooting.md @@ -0,0 +1,47 @@ +--- +title: Troubleshooting +--- + +## Manually creating a new administrator + +It happens to the best of us. Perhaps you're locked out because your only Administrator has left, or maybe you disabled them. Whatever it is, here's how you can get back on track: + +1. Login to your Postgres database with the credentials you've setup +2. Find the ID of the user you wish to make an Administrator: + + `select * from saas_users;` + +Grab the ID for the user(s) you wish to make an Administrator. It may be simpler to just initially assign yourself as an Administrator, and then add others via the UI. + +3. Grab the ID of the Administrator role. It should have an ID of 1 and a uuid of `cf75d7c2-416b-11ea-af5e-53c3b1a4efd8`, but best to be sure: + + `select * from pactflow_roles;` + +4. Add a role mapping for the user: + + `insert into pactflow_user_roles ("user_id","role_id") values (, );` + +You are now an Administrator and - assuming you didn't tell anyone - have spared yourself shame and embarrassment. + +## Segmentation fault on launch + +```shell +/home/pact_broker_fork/lib/pact_broker/version.rb:2: [BUG] Segmentation fault at 0x00007efdfbffa000 +ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a) [x86_64-linux-musl] +-- Control frame information ----------------------------------------------- +c:0052 p:---- s:0316 e:000315 CFUNC :RGLoader_load +c:0051 p:0193 s:0311 e:000310 TOP /home/pact_broker_fork/lib/pact_broker/version.rb:2 [FINISH] +``` + +This most frequently happens when your license file isn't mounted correctly. ie. you're trying to mount a **file** as a **folder**, or vice-versa. Be sure to mount your license **file** as a **file** inside the running container. For example, in Docker Compose, you need to have: + +``` +version: "3" +services: + pactflow: + image: quay.io/pactflow/enterprise + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic +``` + +Adjust accordlingy depending on your container runtime. diff --git a/website/docs/docs/on-premises-2x/upgrading.md b/website/docs/docs/on-premises-2x/upgrading.md new file mode 100644 index 00000000..ef4886a7 --- /dev/null +++ b/website/docs/docs/on-premises-2x/upgrading.md @@ -0,0 +1,5 @@ +--- +title: Docker image +--- + +TBC diff --git a/website/docs/docs/on-premises-2x/upgrading/database-migrations.md b/website/docs/docs/on-premises-2x/upgrading/database-migrations.md new file mode 100644 index 00000000..df31afaa --- /dev/null +++ b/website/docs/docs/on-premises-2x/upgrading/database-migrations.md @@ -0,0 +1,70 @@ +--- +title: Database migrations +--- + +## Auto migration + +Schema migrations are run automatically on start up, unless the [PACTFLOW_DATABASE_AUTO_MIGRATE](../environment-variables#pactflow_database_auto_migrate) environment variable is set to `false`. Data migrations are also run automatically on start up, after the schema migrations, and ensure that any data inserted into the database by a previous version of the application are migrated. This allows you to perform no-downtime, rolling upgrades across your cluster, ensuring any data inserted into latest database schema by the nodes running the previous version of the application are safely migrated. + +Each schema migration will only ever be applied to the database once. Each data migration is executed during every application start up, as this provides the simplest mechanism for ensuring that all data is correctly migrated during rolling deployments. If this is undesirable, then manual migrations can be performed. + +## Manual migration + +The migrations can be run manually against the database before upgrading the PactFlow Docker image if desired. The `db-migrate` entrypoint will run both the schema and the data migrations. + +```sh +docker pull quay.io/pactflow/enterprise + +# Identify the current version before migrating, in case a rollback is required +docker run --rm \ + --env PACTFLOW_DATABASE_URL="postgres://username:password@host:port/database" \ + --entrypoint db-version \ + quay.io/pactflow/enterprise + +# Perform the migrations +docker run --rm \ + --env PACTFLOW_DATABASE_URL="postgres://username:password@host:port/database" \ + --entrypoint db-migrate \ + quay.io/pactflow/enterprise +``` + +To perform a manual no-downtime deployment that does not rely on the "auto migrate" feature: + +1. Execute the `db-migrate` entrypoint from the Docker image of the desired version. This will run both the schema and data migrations. +2. In the Pactflow application environment variables, set the `PACTFLOW_DATABASE_AUTO_MIGRATE` environment variable to `false`, and update the Pactflow image version to the desired tag. Allow your container management system to apply the rollout of the new Docker image. +3. Execute the `db-migrate` entrypoint again. This will run only the data migrations, as the schema migrations have already run. It is necessary to run the data migrations again to ensure that any data that was inserted into the new schema via the old API (during the rolling upgrade) is correctly migrated. + + +## Rollback + +To perform a manual rollback, first identify the number of the migration target using the PactFlow image with the tag you wish to rollback to. + +```sh +TAG="" +docker run --rm \ + --entrypoint /bin/sh \ + --volume $PWD/pactflow-onprem.lic:/home/pactflow-onprem.lic \ + quay.io/pactflow/enterprise:${TAG} \ + -c "ls /home/pact_broker_fork/db/migrations | grep \d | sort | tail -n 1 | cut -d '_' -f1" +``` + +Then, perform the rollback using the PactFlow image that belongs to the database version currently deployed. + +```sh +TAG="" +docker run --rm \ + --volume $PWD/pactflow-onprem.lic:/home/pactflow-onprem.lic \ + --env PACTFLOW_DATABASE_URL="postgres://username:password@host:port/database" \ + --env PACTFLOW_DATABASE_MIGRATION_TARGET="" \ + --entrypoint db-migrate \ + quay.io/pactflow/enterprise:${TAG} +``` + +## Minor and patch version upgrades + +Upgrades between any minor or patch versions with the same major versions do not need any migration path. + +## Major version upgrades + +For major version upgrades, please upgrade to the most recent patch version of the previous major version before upgrading to the next major version. + diff --git a/website/docs/docs/on-premises/releases/2.0.0.md b/website/docs/docs/on-premises/releases/2.0.0.md new file mode 100644 index 00000000..ee56092c --- /dev/null +++ b/website/docs/docs/on-premises/releases/2.0.0.md @@ -0,0 +1,43 @@ +--- +title: 2.0.0 +--- + +## Release date + +27 June 2025 + +## Introduction + +This major release introduces significant architectural changes and new features, including: + +1. A redesigned user interface +2. Migration to an Ubuntu Linux base image +3. Updated architecture using `HAProxy` for traffic routing and `supervisord` for process management +4. New caching and session management layers requiring a Redis-compatible service +5. Many additional features, fixes, and improvements + +For full details, including installation instructions, refer to the [2.x.x documentation](/docs/on-premises-2x). + +## Features + +- **Major UI update** + - Learn more about PactFlow's redesigned interface and improved navigation in the [UI migration guide](/docs/user-interface/migration/new). + +- **Bi-Directional Contract Testing** + - A new [comparison engine](https://github.com/pactflow/openapi-pact-comparator/) delivers up to 100× faster performance than the [previous engine](https://github.com/pactflow/swagger-mock-validator/). + - Support added for [configurable behavior](/docs/bi-directional-contract-testing/contracts/oas/configuration.md). + +- **Stub server updates** + - Now supports the Pact specification up to version 4. + - Includes additional [configuration options](/docs/stubs). + +## Migration notes + +Please review the following updates when migrating to version 2.0.0: + +1. A [Redis-compatible data store](/docs/on-premises-2x/redis) is now required. +2. `PACTFLOW_COOKIE_SECRET` must now be at least 64 characters. [More info](/docs/on-premises-2x/environment-variables#pactflow_cookie_secret). +3. The `PACTFLOW_LOG_FORMAT` environment variable is deprecated and has no effect. All logs are now output in JSON only. +4. The base image has changed from Alpine Linux to Ubuntu 24.04. If you have customized the image, review your setup and update any installed tools or libraries accordingly. + +> **Note:** There are no breaking API or database changes in this release. All existing API calls, SDKs, and CLI integrations will continue to work as expected. diff --git a/website/notices/2025-06-27-on-premises-2.0.0.md b/website/notices/2025-06-27-on-premises-2.0.0.md new file mode 100644 index 00000000..02761950 --- /dev/null +++ b/website/notices/2025-06-27-on-premises-2.0.0.md @@ -0,0 +1,7 @@ +--- +slug: 2025-06-27-on-premises-2.0.0 +title: On-premises release v2.0.0 +tags: [on-premises, release] +--- + +A new PactFlow on-premises release (2.0.0) is now available ([see details](/docs/on-premises/releases/2.0.0)). \ No newline at end of file diff --git a/website/sidebars.js b/website/sidebars.js index ad85c6a8..020eaa02 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -370,7 +370,7 @@ module.exports = { onprem: [ { type: "category", - label: "On-Premises", + label: "On-Premises 1.x", items: [ { type: "category", @@ -438,12 +438,73 @@ module.exports = { type: "category", label: "Troubleshooting", items: ["docs/on-premises/troubleshooting"], + } + ], + }, + { + type: "category", + label: "On-Premises 2.x", + items: [ + { + type: "category", + label: "Installation", + items: [ + "docs/on-premises-2x", + "docs/on-premises-2x/system-requirements", + "docs/on-premises-2x/docker-image-registry", + "docs/on-premises-2x/network-configuration", + "docs/on-premises-2x/installation/migrating", + "docs/on-premises-2x/database", + "docs/on-premises-2x/redis", + "docs/on-premises-2x/logging", + { + type: "category", + label: "Authentication", + items: [ + "docs/on-premises-2x/authentication/demo", + "docs/on-premises-2x/authentication/saml", + ], + }, + { + type: "category", + label: "Application configuration", + items: [ + "docs/on-premises-2x/environment-variables", + "docs/on-premises-2x/environment-variables/templates", + "docs/on-premises-2x/environment-variables/timezones", + "docs/on-premises-2x/license", + ], + }, + "docs/on-premises-2x/docker-compose-example", + "docs/on-premises-2x/installation/load-testing", + "docs/on-premises-2x/installation/checklist", + ], }, { type: "category", - label: "Releases", + label: "Upgrading", + items: ["docs/on-premises-2x/upgrading/database-migrations"], + }, + { + type: "category", + label: "Operation", + items: ["docs/on-premises-2x/authentication"], + }, + { + type: "category", + label: "Maintenance", + items: ["docs/on-premises-2x/maintenance/database"], + }, + { + type: "category", + label: "SCIM", + items: ["docs/on-premises-2x/scim"], + }, + { + type: "category", + label: "Security and support", items: [ - //on-prem-release-placeholder + 'docs/on-premises/releases/2.0.0', 'docs/on-premises/releases/1.36.1', "docs/on-premises/releases/1.36.0", "docs/on-premises/releases/1.35.0", @@ -500,7 +561,73 @@ module.exports = { "docs/on-premises/releases/1.4.0", ], }, + { + type: "category", + label: "Troubleshooting", + items: ["docs/on-premises-2x/troubleshooting"], + }, ], }, + { + type: "category", + label: "Releases", + items: [ + //on-prem-release-placeholder + "docs/on-premises/releases/2.0.0", + "docs/on-premises/releases/1.36.0", + "docs/on-premises/releases/1.35.0", + "docs/on-premises/releases/1.34.0", + "docs/on-premises/releases/1.33.0", + "docs/on-premises/releases/1.32.0", + "docs/on-premises/releases/1.31.0", + "docs/on-premises/releases/1.30.0", + "docs/on-premises/releases/1.29.0", + "docs/on-premises/releases/1.28.0", + "docs/on-premises/releases/1.27.0", + "docs/on-premises/releases/1.26.0", + "docs/on-premises/releases/1.25.0", + "docs/on-premises/releases/1.24.0", + "docs/on-premises/releases/1.23.1", + "docs/on-premises/releases/1.23.0", + "docs/on-premises/releases/1.22.1", + "docs/on-premises/releases/1.22.0", + "docs/on-premises/releases/1.21.1", + "docs/on-premises/releases/1.21.0", + "docs/on-premises/releases/1.20.0", + "docs/on-premises/releases/1.19.2", + "docs/on-premises/releases/1.19.1", + "docs/on-premises/releases/1.19.0", + "docs/on-premises/releases/1.18.0", + "docs/on-premises/releases/1.17.3", + "docs/on-premises/releases/1.17.2", + "docs/on-premises/releases/1.17.1", + "docs/on-premises/releases/1.17.0", + "docs/on-premises/releases/1.16.0", + "docs/on-premises/releases/1.15.0", + "docs/on-premises/releases/1.14.8", + "docs/on-premises/releases/1.14.7", + "docs/on-premises/releases/1.14.6", + "docs/on-premises/releases/1.14.5", + "docs/on-premises/releases/1.14.4", + "docs/on-premises/releases/1.14.3", + "docs/on-premises/releases/1.14.2", + "docs/on-premises/releases/1.14.1", + "docs/on-premises/releases/1.14.0", + "docs/on-premises/releases/1.13.1", + "docs/on-premises/releases/1.13.0", + "docs/on-premises/releases/1.12.0", + "docs/on-premises/releases/1.11.1", + "docs/on-premises/releases/1.11.0", + "docs/on-premises/releases/1.10.0", + "docs/on-premises/releases/1.9.0", + "docs/on-premises/releases/1.8.0", + "docs/on-premises/releases/1.7.0", + "docs/on-premises/releases/1.6.1", + "docs/on-premises/releases/1.6.0", + "docs/on-premises/releases/1.5.0", + "docs/on-premises/releases/1.4.1", + "docs/on-premises/releases/1.4.0", + ], + }, ], }; diff --git a/website/static/img/saas-architecture-2x.png b/website/static/img/saas-architecture-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5c00b9810b17d72a58c54d40ac073fc8befae836 GIT binary patch literal 253406 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

tv*>s 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 Date: Mon, 30 Jun 2025 14:20:05 +1000 Subject: [PATCH 2/2] wip: demonstrate the changed files for on-prem --- website/docs/docs/on-premises-2x.md | 57 -- .../docs/on-premises-2x/authentication.md | 16 - .../on-premises-2x/authentication/demo.md | 29 - .../on-premises-2x/authentication/oauth2.md | 48 -- .../on-premises-2x/authentication/saml.md | 128 ---- website/docs/docs/on-premises-2x/database.md | 60 -- .../on-premises-2x/docker-compose-example.md | 128 ---- .../on-premises-2x/docker-image-registry.md | 50 -- .../on-premises-2x/environment-variables.md | 646 ------------------ .../environment-variables/1.14-beta.md | 259 ------- .../environment-variables/jwt.md | 109 --- .../environment-variables/oauth2.md | 193 ------ .../environment-variables/templates.md | 75 -- .../environment-variables/timezones.md | 601 ---------------- .../on-premises-2x/installation/checklist.md | 43 -- .../installation/load-testing.md | 28 - .../migrating-from-pact-broker.md | 41 -- website/docs/docs/on-premises-2x/license.md | 66 -- website/docs/docs/on-premises-2x/logging.md | 15 - .../on-premises-2x/maintenance/database.md | 274 -------- .../on-premises-2x/network-configuration.md | 27 - .../docs/on-premises-2x/releases/1.10.0.md | 17 - .../docs/on-premises-2x/releases/1.11.0.md | 72 -- .../docs/on-premises-2x/releases/1.11.1.md | 11 - .../docs/on-premises-2x/releases/1.12.0.md | 14 - .../docs/on-premises-2x/releases/1.13.0.md | 11 - .../docs/on-premises-2x/releases/1.13.1.md | 11 - .../docs/on-premises-2x/releases/1.14.0.md | 30 - .../docs/on-premises-2x/releases/1.14.1.md | 11 - .../docs/on-premises-2x/releases/1.14.2.md | 15 - .../docs/on-premises-2x/releases/1.14.3.md | 15 - .../docs/on-premises-2x/releases/1.14.4.md | 17 - .../docs/on-premises-2x/releases/1.14.5.md | 15 - .../docs/on-premises-2x/releases/1.14.6.md | 19 - .../docs/on-premises-2x/releases/1.14.7.md | 15 - .../docs/on-premises-2x/releases/1.14.8.md | 15 - .../docs/on-premises-2x/releases/1.15.0.md | 18 - .../docs/on-premises-2x/releases/1.16.0.md | 15 - .../docs/on-premises-2x/releases/1.17.0.md | 15 - .../docs/on-premises-2x/releases/1.17.1.md | 12 - .../docs/on-premises-2x/releases/1.17.2.md | 11 - .../docs/on-premises-2x/releases/1.17.3.md | 11 - .../docs/on-premises-2x/releases/1.18.0.md | 28 - .../docs/on-premises-2x/releases/1.19.0.md | 20 - .../docs/on-premises-2x/releases/1.19.1.md | 12 - .../docs/on-premises-2x/releases/1.19.2.md | 11 - .../docs/on-premises-2x/releases/1.20.0.md | 18 - .../docs/on-premises-2x/releases/1.21.0.md | 16 - .../docs/on-premises-2x/releases/1.21.1.md | 11 - .../docs/on-premises-2x/releases/1.22.0.md | 26 - .../docs/on-premises-2x/releases/1.22.1.md | 16 - .../docs/on-premises-2x/releases/1.23.0.md | 16 - .../docs/on-premises-2x/releases/1.23.1.md | 11 - .../docs/on-premises-2x/releases/1.24.0.md | 25 - .../docs/on-premises-2x/releases/1.25.0.md | 22 - .../docs/on-premises-2x/releases/1.26.0.md | 51 -- .../docs/on-premises-2x/releases/1.27.0.md | 27 - .../docs/on-premises-2x/releases/1.28.0.md | 27 - .../docs/on-premises-2x/releases/1.29.0.md | 25 - .../docs/on-premises-2x/releases/1.30.0.md | 25 - .../docs/on-premises-2x/releases/1.31.0.md | 31 - .../docs/on-premises-2x/releases/1.32.0.md | 25 - .../docs/on-premises-2x/releases/1.33.0.md | 21 - .../docs/on-premises-2x/releases/1.34.0.md | 27 - .../docs/on-premises-2x/releases/1.35.0.md | 29 - .../docs/on-premises-2x/releases/1.36.0.md | 23 - .../docs/on-premises-2x/releases/1.4.0.md | 10 - .../docs/on-premises-2x/releases/1.4.1.md | 7 - .../docs/on-premises-2x/releases/1.5.0.md | 8 - .../docs/on-premises-2x/releases/1.6.0.md | 10 - .../docs/on-premises-2x/releases/1.6.1.md | 7 - .../docs/on-premises-2x/releases/1.7.0.md | 11 - .../docs/on-premises-2x/releases/1.8.0.md | 16 - .../docs/on-premises-2x/releases/1.9.0.md | 18 - website/docs/docs/on-premises-2x/scim.md | 288 -------- .../on-premises-2x/security-audit-report.md | 199 ------ .../docs/on-premises-2x/support-policy.md | 58 -- .../on-premises-2x/system-requirements.md | 135 ---- .../docs/on-premises-2x/troubleshooting.md | 47 -- website/docs/docs/on-premises-2x/upgrading.md | 5 - .../upgrading/database-migrations.md | 70 -- website/docs/docs/on-premises.md | 17 +- .../on-premises/docker-compose-example.md | 29 +- .../docs/on-premises/docker-image-registry.md | 4 +- .../docs/on-premises/environment-variables.md | 25 +- .../on-premises/installation/checklist.md | 4 +- website/docs/docs/on-premises/logging.md | 4 +- .../docs/on-premises/network-configuration.md | 7 +- .../{on-premises-2x => on-premises}/redis.md | 13 +- .../docs/docs/on-premises/releases/1.36.1.md | 21 - .../docs/docs/on-premises/releases/2.0.0.md | 16 +- website/docs/docs/on-premises/scim.md | 46 +- .../docs/on-premises/security-audit-report.md | 50 +- website/sidebars.js | 127 ---- .../static/img/on-prem-architecture-2x.png | Bin 0 -> 274905 bytes 95 files changed, 105 insertions(+), 4953 deletions(-) delete mode 100644 website/docs/docs/on-premises-2x.md delete mode 100644 website/docs/docs/on-premises-2x/authentication.md delete mode 100644 website/docs/docs/on-premises-2x/authentication/demo.md delete mode 100644 website/docs/docs/on-premises-2x/authentication/oauth2.md delete mode 100644 website/docs/docs/on-premises-2x/authentication/saml.md delete mode 100644 website/docs/docs/on-premises-2x/database.md delete mode 100644 website/docs/docs/on-premises-2x/docker-compose-example.md delete mode 100644 website/docs/docs/on-premises-2x/docker-image-registry.md delete mode 100644 website/docs/docs/on-premises-2x/environment-variables.md delete mode 100644 website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md delete mode 100644 website/docs/docs/on-premises-2x/environment-variables/jwt.md delete mode 100644 website/docs/docs/on-premises-2x/environment-variables/oauth2.md delete mode 100644 website/docs/docs/on-premises-2x/environment-variables/templates.md delete mode 100644 website/docs/docs/on-premises-2x/environment-variables/timezones.md delete mode 100644 website/docs/docs/on-premises-2x/installation/checklist.md delete mode 100644 website/docs/docs/on-premises-2x/installation/load-testing.md delete mode 100644 website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md delete mode 100644 website/docs/docs/on-premises-2x/license.md delete mode 100644 website/docs/docs/on-premises-2x/logging.md delete mode 100644 website/docs/docs/on-premises-2x/maintenance/database.md delete mode 100644 website/docs/docs/on-premises-2x/network-configuration.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.10.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.11.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.11.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.12.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.13.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.13.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.2.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.3.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.4.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.5.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.6.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.7.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.14.8.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.15.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.16.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.17.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.17.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.17.2.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.17.3.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.18.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.19.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.19.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.19.2.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.20.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.21.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.21.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.22.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.22.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.23.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.23.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.24.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.25.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.26.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.27.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.28.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.29.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.30.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.31.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.32.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.33.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.34.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.35.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.36.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.4.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.4.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.5.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.6.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.6.1.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.7.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.8.0.md delete mode 100644 website/docs/docs/on-premises-2x/releases/1.9.0.md delete mode 100644 website/docs/docs/on-premises-2x/scim.md delete mode 100644 website/docs/docs/on-premises-2x/security-audit-report.md delete mode 100644 website/docs/docs/on-premises-2x/support-policy.md delete mode 100644 website/docs/docs/on-premises-2x/system-requirements.md delete mode 100644 website/docs/docs/on-premises-2x/troubleshooting.md delete mode 100644 website/docs/docs/on-premises-2x/upgrading.md delete mode 100644 website/docs/docs/on-premises-2x/upgrading/database-migrations.md rename website/docs/docs/{on-premises-2x => on-premises}/redis.md (80%) delete mode 100644 website/docs/docs/on-premises/releases/1.36.1.md create mode 100644 website/static/img/on-prem-architecture-2x.png diff --git a/website/docs/docs/on-premises-2x.md b/website/docs/docs/on-premises-2x.md deleted file mode 100644 index f0ead206..00000000 --- a/website/docs/docs/on-premises-2x.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: PactFlow On-Premises Architecture -sidebar_label: Architecture ---- - -## System architecture - -### Minimum requirements - -* An application server capable of running Docker -* PostgreSQL database -* Redis cache -* SAML IDP for SSO -* PactFlow license file - -### Recommended architecture - -* Deploy to a service designed for Docker container orchestration (ECS, Fargate, Kubernetes etc.) - -### Example AWS deployment using ECS - -![System architecture](/img/saas-architecture-2x.png) - -## Internal architecture - -The PactFlow On-Premises application is distributed as a Docker image. It is based on the open source [Pact Broker](https://github.com/pact-foundation/pact_broker), which is a Ruby application. - -### Application user requirements - -The PactFlow application does not need any elevated privileges to run. It runs under the user `app`. - -### Application port - -The PactFlow application runs on port `9292` by default. This can be configured by setting the [PACTFLOW_HTTP_PORT](/docs/on-premises/environment-variables#pactflow_http_port) environment variable. - -### Healthcheck endpoint - -A healthcheck endpoint for use by a Docker container managment service is available at `http:///diagnostic/status/heartbeat`. No authentication is required. This endpoint does not make a connection to the database. You can use this check to confirm your load balancer targets are healthy. - -If the healthcheck is running from inside the container, make sure to use the port defined in the environment variable `$PACTFLOW_HTTP_PORT`, which defaults to `9292`. You can use `supervisorctl` to perform the healthcheck request. - -An example healthcheck configuration for Docker Compose: - -```yaml -healthcheck: - test: ["supervisorctl", "status", "haproxy", "marko", "pactflow"] - interval: 30s - timeout: 10s - retries: 3 -``` - -To check the connection to the database, use the endpoint `/diagnostic/status/dependencies`. This endpoint should not be used by Docker container managment services, as unrelated database issues might cause the Docker container to churn. - -### License file - -PactFlow on-premises version requires a license file to run. [Contact us](https://support.smartbear.com/pactflow/message/) if you have not -received one when your account was setup. See the [section on licenses for installation instructions](/docs/on-premises/license). diff --git a/website/docs/docs/on-premises-2x/authentication.md b/website/docs/docs/on-premises-2x/authentication.md deleted file mode 100644 index 3684ff6a..00000000 --- a/website/docs/docs/on-premises-2x/authentication.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Authentication ---- - -## User interface - -The PactFlow On-Premises application currently supports single sign for SAML identity providers. It supports both IDP and SP initiated log in. - -Any user who is able to authenticate to the configured IDP is allowed access to PactFlow. - -The SAML IDP is configured via [environment variables](environment-variables#saml-authentication). - -## API - -The API is accessed using a bearer token that is set in the HTTP header of the request (eg. `Authorization: Bearer `). The tokens are administered on a per user basis in the [settings page](/docs/user-interface/settings/api-tokens) of the PactFlow application. - diff --git a/website/docs/docs/on-premises-2x/authentication/demo.md b/website/docs/docs/on-premises-2x/authentication/demo.md deleted file mode 100644 index c9544f14..00000000 --- a/website/docs/docs/on-premises-2x/authentication/demo.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Demo Auth ---- - -To allow experimentation with PactFlow without the need to configure an external identity provider, the "demo" authentication provider can be enabled. With demo auth enabled, any user can log in to PactFlow by providing a name and email address. No password is used to authenticate the user. - -The first user to log in will be assigned the [Administrator](/docs/permissions/predefined-roles#administrator) role, and every user thereafter will receive the default ([User](/docs/permissions/predefined-roles#user)) role. - -After a user has logged in, they may perform all the actions their role allows, as if they were a user created via a real identify provider. - -:::caution - -This method of authentication is NOT secure and should not be used in production. - -::: - -Demo auth replaces the basic auth capability that was previously used for this purpose. - -## Configuration - -See the [Demo](/docs/on-premises-2x/environment-variables#demo_auth_enabled) section of the environment variables page. Demo auth cannot be enabled at the same time as any other method of authentication (ie. SAML). - -## Converting to a production IDP - -Demo authentication cannot be enabled at the same time as a real authentication provider (eg. SAML). We recommend starting with a clean database when installing PactFlow for production use. This will ensure no demo users remain in the system. - -## Docker Compose example - -This [Docker Compose example](/docs/on-premises-2x/docker-compose-example) is configured using Demo Auth. diff --git a/website/docs/docs/on-premises-2x/authentication/oauth2.md b/website/docs/docs/on-premises-2x/authentication/oauth2.md deleted file mode 100644 index 81aea089..00000000 --- a/website/docs/docs/on-premises-2x/authentication/oauth2.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: OAuth2 ---- - -## Configuration - -An OAuth2 identify provider is configured by a set of environment variables prefixed with `PACTFLOW_TEST_OAUTH2_`, or using the `test_oauth2` key in a YAML configuration file. See the [Test OAuth2](/docs/on-premises-2x/environment-variables/1.14-beta) section of the environment variables page for the full list. - -## Callback URL - -The callback URL is `https:///auth/oauth2/callback`. This must be configured in the settings for the PactFlow client in your Identify Provider. - -## Authorize params - -The following parameters are sent to the Identity Provider's configured [`authorize_url`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__authorize_url) during the request phase. - -| Parameter | Description | -|-----------|-------------| -| scope | `openid profile email` | -| response_type | `code` | -| response_mode | `form_post` | -| state | A randomly generated hex string | -| client_id | The configured [client_id](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__client_id) | -| redirect_uri | The [callback URL](#callback-url) as documented above | - -The parameters configured in the [`custom_authorize_params`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__custom_authorize_params__key) are also merged into these default parameters. - -## Token params - -The following parameters are sent to the Identity Provider's configured [`token_url`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__token_url). - -| Parameter | Description | -|-----------|-------------| -| code | The `code` returned by the IDP during the callback phase. | -| grant_type | `authorization_code` | -| client_id | The configured [client_id](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__client_id) | -| client_secret | The configured [client_secret](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__client_secret) | -| redirect_uri | The [callback URL](#callback-url) as documented above | - -The parameters configured in the [`custom_token_params`](/docs/on-premises-2x/environment-variables/1.14-beta#pactflow_test_oauth2__custom_token_params__key) are also merged into these default parameters. - -## Custom Auth handler - -At the end of the OAuth2 login flow, a JWT is retrieved by PactFlow from the customer's Identify Provider. A custom Ruby auth handler configuration file will be supplied by PactFlow to map claims from the JWT to PactFlow roles and teams. The auth handler configuration file must be mounted as a volume on the PactFlow container, in the directory `/home/pactflow/extensions/` eg. `/home/pactflow/extensions/auth_ext_script.rb`. - -## Debugging - -The URLs and headers of the HTTP interactions with the Identity Provider will be logged at `info` level in the PactFlow logs. To see the request and response bodies, set the `PACTFLOW_LOG_LEVEL` to `debug`. Note that this will log sensitive information, so do not leave the logging at this level permanently. diff --git a/website/docs/docs/on-premises-2x/authentication/saml.md b/website/docs/docs/on-premises-2x/authentication/saml.md deleted file mode 100644 index b3840c69..00000000 --- a/website/docs/docs/on-premises-2x/authentication/saml.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: SAML ---- - -PactFlow supports single sign on using the SAML authentication protocol. - -Once SAML has been configured, if the database contains no users, the first user to log in will be assigned the [Administrator](/docs/permissions/predefined-roles#administrator) role, and every user thereafter will receive the default ([User](/docs/permissions/predefined-roles#user)) role. - -## Configuration - -A SAML provider is configured by a set of environment variables prefixed with `PACTFLOW_SAML_`. See the [SAML](/docs/on-premises-2x/environment-variables#saml-authentication) section of the environment variables page for the full list. - -## Assertion Consumer URL - -This is the endpoint to which the IDP will post the SAML assertion after the user is authenticated. It is also called the "sign on URL", "reply URL", and "callback URL", depending on your IDP. You will need to configure this value in your IDP when you set up the PactFlow service provider. - -The URL is `https:///auth/saml/callback`. - -## Metadata URL - -The PactFlow SAML service provider metadata URL is available at `https:///auth/saml/metadata`. - -## Configuring multiple SAML providers - -In PactFlow 1.7.0 and later, multiple SAML providers may be configured. To configure a second SAML provider, create another set of the [SAML environment variables](/docs/on-premises-2x/environment-variables#saml-authentication) with the prefix `PACTFLOW_SAML_2_` (and `PACTFLOW_SAML_3_` for the third, etc). The `PACTFLOW_SAML_ISSUER` does not need to be specified again, as it is shared between all SAML providers. - -The callback path for the second provider is `/auth/saml/2/callback`, and for the third `/auth/saml/3/callback` etc. The path for the metadata for subsequent SAML providers will be `/auth/saml/2/metadata`, `/auth/saml/3/metadata` etc. - -## Configuring Azure Active Directory - -### Create a non gallery application - -* Follow the [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/add-non-gallery-app) for creating a non gallery application. - * Choose `Non-gallery application` at the `Add your own app` screen. - * Set the name to `PactFlow On-Premesis` when prompted. - -* When the application has been created, assign the users that should be allowed to login to PactFlow. - -* Once the users have been assigned, select the `Single sign-on` tab. Select `SAML`. - -* Set the Identifier (Entity ID) to `https://pactflow.` eg. `https://pactflow.mycompany.com`. This field must match the [PACTFLOW_SAML_ISSUER]../(environment-variables#pactflow_saml_issuer) environment variable. - -* Set the Reply URL to `https:///auth/saml/callback` - -* Leave the Sign On URL, Relay State and Logout Url fields blank. - -### Configure the PactFlow environment variables - -You can find a template for the required environment variables [here](/docs/on-premises-2x/environment-variables/templates#azure-active-directory). - -* Set the [PACTFLOW_SAML_ISSUER](/docs/on-premises-2x/environment-variables#pactflow_saml_issuer) to the `Identifier (Entity ID)`. -* Set the [PACTFLOW_SAML_IDP_SSO_TARGET_URL](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_sso_target_url) to the `Login URL`. -* Set the [PACTFLOW_SAML_IDP_ENTITY_ID](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_entity_id) to the `Azure AD Identifier` -* Set the [PACTFLOW_SAML_IDP_CERT_FINGERPRINT](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_cert_fingerprint) to the `Thumbprint` -* Set the [PACTFLOW_SAML_IDP_NAME](/docs/on-premises-2x/environment-variables#pactflow_saml_idp_name) to your choice - this is a display name for the login button. -* Set the identifier, email and name attributes as per the [template](/docs/on-premises-2x/environment-variables#/templates#azure-active-directory). - - -## Docker Compose Example - -Follow [steps 1 and 2](/docs/on-premises-2x/docker-compose-example) from the Docker Compose example that uses Demo Auth, then use the following `docker-compose.yml` file to run your services. - -``` -version: "3" - -services: - simplesaml: - image: kristophjunge/test-saml-idp - logging: - driver: none # comment out the logging config to see the SAML server logs - ports: - - "8080:8080" - - "8443:8443" - environment: - - SIMPLESAMLPHP_SP_ENTITY_ID=https://pactflow.io - - SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost/auth/saml/callback - - pactflow: - image: quay.io/pactflow/enterprise - depends_on: - - postgres - environment: - - PACTFLOW_HTTP_PORT=9292 - - PACTFLOW_BASE_URL=http://localhost - - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres - # insecure settings only for the purposes of this demo! Not to be used in production. - - PACTFLOW_DATABASE_SSLMODE=disable - - PACTFLOW_REQUIRE_HTTPS=false - - PACTFLOW_LOG_FORMAT=short # normally this would be set to json, use short for demo only - - PACTFLOW_ADMIN_API_KEY=admin - - PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY=thisissomerandombytes - - PACTFLOW_SAML_AUTH_ENABLED=true - - PACTFLOW_SAML_IDP_NAME=Simple SAML - - PACTFLOW_SAML_IDP_SSO_TARGET_URL=http://localhost:8080/simplesaml/saml2/idp/SSOService.php - - PACTFLOW_SAML_IDP_CERT_FINGERPRINT=11:9B:9E:02:79:59:CD:B7:C6:62:CF:D0:75:D9:E2:EF:38:4E:44:5F - - PACTFLOW_SAML_IDP_ID_ATTRIBUTE=uid - - PACTFLOW_SAML_EMAIL_ATTRIBUTE=email - - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- - - PACT_BROKER_ADMIN_API_KEY=admin - - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ - ports: - - "80:9292" - healthcheck: - test: ["CMD", "wget", "-nv", "-t1", "--spider", "http://localhost:9292/diagnostic/status/heartbeat"] - interval: 30s - timeout: 10s - retries: 3 - entrypoint: dockerize - command: -wait tcp://postgres:5432 docker-entrypoint - volumes: - - ./pactflow-onprem.lic:/home/pactflow-onprem.lic - - postgres: - image: postgres:13-alpine - healthcheck: - test: psql postgres --command "select 1" -U postgres - ports: - - "5432:5432" - volumes: - - postgres-volume:/var/lib/postgresql/data - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - POSTGRES_DB: postgres - -volumes: - postgres-volume: -``` diff --git a/website/docs/docs/on-premises-2x/database.md b/website/docs/docs/on-premises-2x/database.md deleted file mode 100644 index 7716694e..00000000 --- a/website/docs/docs/on-premises-2x/database.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Database ---- - -A PostgreSQL database is required for storage of the application data. - -:::info - If you would like to migrate an existing PostgreSQL database, skip this section and instead follow the guide [**here**](/docs/on-premises-2x/installation/migrating). -::: - -## Supported versions - -PostgreSQL version 10.6 and later are supported. - -## Database creation - -Log in as your database administrator, and execute the following statements in an SQL session. - -```sql -CREATE USER pactflow_user WITH PASSWORD ''; -CREATE DATABASE pactflow; -GRANT ALL PRIVILEGES ON DATABASE pactflow TO pactflow_user; -REVOKE ALL ON DATABASE pactflow FROM PUBLIC; -``` - -## SSL - -The application's PostgreSQL SSL mode is set to `require` by default, which means it requires the connection to the database to be encrypted, but does not verify the server's certificate. See the documentation for the [PACTFLOW_DATABASE_SSLMODE](environment-variables#pactflow_database_sslmode) environment variable for more options. It is not recommended to use any option weaker than `require`. - -## Authentication - -## Username/password authentication - -Database access between the PactFlow application and Postgres instance can be secured using a [username](/docs/on-premises-2x/environment-variables#pactflow_database_username) and [password](/docs/on-premises-2x/environment-variables#pactflow_database_password), configured via environment variables. - -## AWS IAM authentication - -When deploying PactFlow on AWS Cloud infrastructure, database access between the PactFlow application and the RDS Postgres instance can be secured using IAM. Please see the [AWS RDS IAM documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAM.html) for more information. - -The following environmet variables must be set for the PactFlow application: - -* [`PACTFLOW_DATABASE_ADAPTER="postgresiam"`](/docs/on-premises-2x/environment-variables#pactflow_database_adapter) -* [`PACTFLOW_DATABASE_USERNAME`](/docs/on-premises-2x/environment-variables#pactflow_database_username) -* [`PACTFLOW_DATABASE_HOST`](/docs/on-premises-2x/environment-variables#pactflow_database_host) -* [`PACTFLOW_DATABASE_PORT`](/docs/on-premises-2x/environment-variables#pactflow_database_port) -* [`PACTFLOW_DATABASE_NAME`](/docs/on-premises-2x/environment-variables#pactflow_database_name) -* [`PACTFLOW_DATABASE_SSLMODE="require"`](/docs/on-premises-2x/environment-variables#pactflow_database_sslmode) -* [`AWS_REGION`](/docs/on-premises-2x/environment-variables#aws_region) - -## Schema migrations - -The database schema migrations will be run automatically on start up. See the documentation on [Database migrations](upgrading/database-migrations) for more information. - -### Migrating from OSS Pact Broker to PactFlow - -If you have been hosting your own instance of the open source Pact Broker, you can point the new PactFlow On-Premises application at the same database, and the missing migrations will be applied. - -## Schema - -![Database schema](/on-premises/schema.png) diff --git a/website/docs/docs/on-premises-2x/docker-compose-example.md b/website/docs/docs/on-premises-2x/docker-compose-example.md deleted file mode 100644 index 2b5cd739..00000000 --- a/website/docs/docs/on-premises-2x/docker-compose-example.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Docker Compose example ---- - -In this guide, we'll provide an example `docker compose` setup so that you can see how all of the bits hang together. We will demonstrate: - -* Authenticating to Quay.io -* Running the PactFlow enterprise container -* Persistent storage with a postgres database - -**Pre-requsites** -* [Docker](https://docs.docker.com/engine/install/) -* [Docker Compose](https://docs.docker.com/compose/install/) -* A working *nix environment and access to a terminal -* Valid credentials to authenticate to our [Docker image registry](docker-image-registry) -* PactFlow license file - -## 1. Authenticating to Quay.io - -After obtaining valid robot credentials, you need to authenticate to Quay.io so that the docker engine is able to fetch our images. - -``` -docker login -u="" -p="" quay.io -docker pull quay.io/pactflow/enterprise -``` - -After this, you should have the latest PactFlow enterprise image on your machine. You can verify by executing - -```sh -docker images quay.io/pactflow/enterprise -``` - -Which should produce an output such as: - -```sh -> docker images quay.io/pactflow/enterprise -REPOSITORY TAG IMAGE ID CREATED SIZE -quay.io/pactflow/enterprise 2.0.0 32db429fda01 1 day ago 462MB # <- this guide applies to 2.x.x version -quay.io/pactflow/enterprise latest 32db429fda01 1 day ago 462MB -quay.io/pactflow/enterprise 1.36.0 7f9b3c3aa50e 7 weeks ago 454MB -``` - -## 2. PactFlow license file - -The PactFlow on-premises version requires a license file to run. You should have received this from us during the -on-boarding process. If not, please contact your Account Manager. - -Save the license file into a temporary directory with the name `pactflow-onprem.lic` (it needs to be the same directory as used in step 3). - -## 3. Startup PactFlow and supporting services - -Save the below file as `docker-compose.yml` in the same directory as the license file and then run `docker-compose up`: - -```yaml -version: "3" - -services: - pactflow: - image: quay.io/pactflow/enterprise:2.0.0 - depends_on: - - postgres - - redis - environment: - # This is set to localhost for this example but in a real deployment, this needs to be set to the actual URL of the application - - PACTFLOW_BASE_URL=http://localhost - # Insecure setting only for the purposes of this demo! Not to be used in production. - - PACTFLOW_DATABASE_SSLMODE=disable - # Insecure setting only for the purposes of this demo! Not to be used in production. - - PACTFLOW_REQUIRE_HTTPS=false - # Demo auth should only be used for demo purposes. Not to be used in production. - - PACTFLOW_DEMO_AUTH_ENABLED=true - # 'Allow all' for the webhook host whitelist should only be used for demo purposes. See docs for configuring this in production. - - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ - - PACTFLOW_HTTP_PORT=9292 - # Link to the postgres database - - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres - - PACTFLOW_LOG_LEVEL=info - - PACTFLOW_ADMIN_API_KEY=admin - - PACTFLOW_MASTER_ENCRYPTION_KEY=thisissomerandombytes - - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- - - PACT_BROKER_ADMIN_API_KEY=admin - - PACTFLOW_HTTP_LOGGING_ENABLED=true - # Link to the redis cache - - REDIS_URL=redis://redis:6379 - ports: - - "80:9292" - healthcheck: - test: ["CMD", "supervisorctl", "status", "haproxy", "marko", "pactflow"] - interval: 30s - timeout: 10s - retries: 3 - volumes: - - ./pactflow-onprem.lic:/home/pactflow-onprem.lic - - postgres: - image: postgres:13-alpine - healthcheck: - test: psql postgres --command "select 1" -U postgres - volumes: - - postgres-volume:/var/lib/postgresql/data - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - POSTGRES_DB: postgres - - redis: - image: redis:latest - -volumes: - postgres-volume: -``` - -You can verify all services by running `docker ps`: - -``` -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -1cefdf8b1e1b quay.io/pactflow/enterprise:2.0.0 "docker-entrypoint" 24 minutes ago Up 24 minutes (healthy) 0.0.0.0:80->9292/tcp tmp_pactflow_1 -6bedae5936dc redis:latest "docker-entrypoint.s…" 2 hours ago Up 24 minutes 6379/tcp tmp_redis_1 -8b393d35a20c postgres:13-alpine "docker-entrypoint.s…" 9 days ago Up 24 minutes (healthy) 5432/tcp tmp_postgres_1 -``` - -## 3. Login to PactFlow - -Head to [http://localhost](http://localhost) in your browser, and choose to login with "PACTFLOW DEMO AUTH". Provide a name and email address to create your account and login. (The details don't need to be valid, and won't be used to send any emails.) - -That's it 🎉. - -For production use, you'll need to replicate this setup using a proper container orchestration tool, such as Kubernetes, AWS ECS/Fargate, AKS, GKE, Mesos etc, and your real Identity Provider. diff --git a/website/docs/docs/on-premises-2x/docker-image-registry.md b/website/docs/docs/on-premises-2x/docker-image-registry.md deleted file mode 100644 index 8a2f6880..00000000 --- a/website/docs/docs/on-premises-2x/docker-image-registry.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Docker image registry ---- - -## Accessing the Enterprise PactFlow container registry - -Docker images for our self-hosted PactFlow Enterprise product are hosted at [Quay](http://quay.io). We will provide Quay.io access for you when signing up to the product. - -### User Account Access - -:::note -If you are on a PactFlow trial, creating a RedHat account is **not** required. You will be issued a separate set of credentials (see [CI Access](#ci-access) below) by your Account Manager for the duration of the trial. -::: - -To set you up with console access, you will need to create a [RedHat account](https://quay.io/signin/). Choose "Register for a RedHat account" and once comwpleted, provide the username/email address to us to add you to the registry. - -Once we have granted access to your given email address, you should receive an email from Red Hat Quay confirming access to the PactFlow organization. - -### CI Access - -In additional to user access, we will create you one or more [Robot Accounts](https://docs.quay.io/glossary/robot-accounts.html) for use in CI. - -## Getting started - -Once we have created you a new user, you will receive an email from Quay.io inviting you to join a new team and a license file from us. You can setup the new account as follows: - -1. Make sure you have received a PactFlow on-premises license file from your Account Manager -1. You should receive an email from Red Hat Quay, requesting you join a team `pactflow/`: - - ![Join PactFlow repository email](/on-premises/quay-join-team-email.png) - -1. Follow the link in your email to login to an existing accoun - - -1. You will be added to the correct team and you should then see our Enterprise repository (click [Repositories](https://quay.io/repository/) in the menu bar to see this): - - ![Completed signup](/on-premises/quay-completed.png) - -1. You should now have access to the `enterprise` repository in the `pactflow` organization. - -1. You can now sign in with your account (in addition to your Robot Account) to quay to pull docker images. See [getting started with Quay.io](https://docs.quay.io/solution/getting-started.html) for more on this. - -## Downloading the image - -With your personal credentials or Robot token (provided by your PactFlow Account Manager), you can login to your docker management system and pull the image: - -```sh -docker login -u="" -p="" quay.io # you can use either the robot token or your user credentials here -docker pull quay.io/pactflow/enterprise -``` diff --git a/website/docs/docs/on-premises-2x/environment-variables.md b/website/docs/docs/on-premises-2x/environment-variables.md deleted file mode 100644 index c8a60327..00000000 --- a/website/docs/docs/on-premises-2x/environment-variables.md +++ /dev/null @@ -1,646 +0,0 @@ ---- -title: Environment variables ---- - - - - - -## Logging - -


- - - -### PACTFLOW_LOG_LEVEL - -The PactFlow application log level - -**Required:** false
-**Default:** `INFO`
-**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
- -### PACTFLOW_HTTP_LOGGING_ENABLED - -When true, HTTP request details and response status and duration will be logged to stdout in json format - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -## Monitoring - -
- - - -### NEW_RELIC_AGENT_ENABLED - -Set this to true to enable New Relic application monitoring. The New Relic config file should be mounted at /home/pactflow/config/newrelic.yml - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -## Database - -
- - - -### PACTFLOW_DATABASE_URL - -The fully qualified database connection string. If using Postgres on RDS with IAM authentication, the scheme must be `postgresiam` and the port must also be set. - -**Required:** if separate host, name, username, password environment variables are not set
-**Example:** `postgresql://username:password@host:port/database`
- -### PACTFLOW_DATABASE_ADAPTER - -The database adapter to use. Use `postgresiam` when using Postgres on RDS with IAM authentication (rather than username/password authentication). - -**Required:** false
-**Default:** `postgres`
-**Allowed values:** `postgres`, `postgresiam`
- -### PACTFLOW_DATABASE_USERNAME - -The database username - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -### PACTFLOW_DATABASE_PASSWORD - -The database password - -**Required:** if PACTFLOW_DATABASE_URL is not set, unless using Postgres on RDS with IAM authentication
- -### PACTFLOW_DATABASE_HOST - -The database host - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -### PACTFLOW_DATABASE_PORT - -The database port - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -### PACTFLOW_DATABASE_NAME - -The database name - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -### PACTFLOW_DATABASE_SSLMODE - -The Postgresql ssl mode. Note, if using Postgres on AWS RDS with IAM authentication, this must be `require`. - -**Required:** false
-**Default:** `require`
-**Allowed values:** `disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full`
-**More information:** https://ankane.org/postgres-sslmode-explained
- -### PACTFLOW_DATABASE_CONNECTION_VALIDATION_TIMEOUT - -The number of seconds after which to check the health of a connection from a connection pool before passing it to the application. - -`-1` means that connections will be validated every time, which avoids errors -when databases are restarted and connections are killed. This has a performance -penalty, so consider increasing this timeout if building a frequently accessed service. - -**Required:** false
-**Default:** `3600`
-**Allowed values:** -1 or any positive integer.
-**More information:** https://sequel.jeremyevans.net/rdoc-plugins/files/lib/sequel/extensions/connection_validator_rb.html
- -### PACTFLOW_SQL_LOG_WARN_DURATION - -The duration in seconds, as a float, after which to log an SQL statement - -**Required:** false
-**Default:** `5`
- -### PACTFLOW_SQL_LOG_LEVEL - -The log level that will be specified when the SQL query statements are logged. - -**Required:** false
-**Default:** `NONE`
-**Allowed values:** `NONE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
- -### PACTFLOW_DATABASE_MAX_CONNECTIONS - -The maximum size of the connection pool per application instance. The total number of connections for the database must be calculated by multiplying this value by the number of instances (ie. running Docker containers). - -**Required:** false
-**Default:** `4`
-**Allowed values:** A positive integer value.
-**More information:** https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
- -### PACTFLOW_DATABASE_POOL_TIMEOUT - -The number of seconds to wait if a connection cannot be acquired before raising an error. - -**Required:** false
-**Default:** `5`
-**Allowed values:** A positive integer.
-**More information:** https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
- -### PACTFLOW_DATABASE_AUTO_MIGRATE - -Whether or not to automatically apply the schema and data migrations to the database on startup - -**Required:** false
-**Default:** `true`
-**Allowed values:** `true`, `false`
- -### AWS_REGION - -Required for running Postgres on RDS with IAM authentication. This must be set to the AWS region where the RDS database instance is running. - -**Required:** false
- -## Webhooks - -
- - - -### PACTFLOW_WEBHOOK_HOST_WHITELIST - -A space delimited list of hosts for which webhook response logging will be enabled. By default, all responses will be redacted for security purposes. To allow logging for all hosts, use the value `/.*/`. - -**Required:** false
-**Example:** `/.*\.foo\.com$/ github.com foo.slack.com`
-**More information:** https://docs.pact.io/pact_broker/configuration#webhook-whitelists
- -### PACTFLOW_WEBHOOK_SCHEME_WHITELIST - -A space delimited list of allowed schemes for a webhook to use. - -**Required:** false
-**Default:** `https`
-**Allowed values:** `https`, `http`
-**More information:** https://docs.pact.io/pact_broker/configuration#webhook-whitelists
- -### PACTFLOW_WEBHOOK_HTTP_METHOD_WHITELIST - -A space delimited list of allowed http methods for a webhook to use. *It is strongly recommended to only allow POST requests for security purposes.* - -**Required:** false
-**Default:** `POST`
-**Allowed values:** `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
-**More information:** https://docs.pact.io/pact_broker/configuration#webhook-whitelists
- -### PACTFLOW_DISABLE_SSL_VERIFICATION - -Whether or not to disable SSL verificaton when executing webhooks. - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_WEBHOOK_CERTIFICATES - -A list of SSL certificate configuration objects with the properties `description`, and either `content` or `path`. These -certificates are used when a webhook needs to connect to a server that uses a self signed certificate. - -Each certificate configuration item accepts a chain of certificates in PEM format - there may be multiple 'BEGIN CERTIFICATE' and 'END CERTIFICATE' in the content of each item. - -The certificate configuration is not validated on startup. If any of the configured certificates cannot be loaded during the execution of a webhook, an error -will be logged, and they will be ignored. You can check if the configuration is working by testing the execution of -a webhook that connects to the server with the self signed certificate by following these instructions https://docs.pact.io/pact_broker/webhooks/debugging_webhooks#testing-webhook-execution - -When setting the path, the full path to the certificate file in PEM format must be specified. When using Docker, you must ensure the -certificate file is [mounted into the container](https://docs.docker.com/storage/volumes/). - -Each property of the certificate is described by an indexed environment variable in the format `PACTFLOW_WEBHOOK_CERTIFICATES____`. -Environment variables with the same index are grouped together to form the complete object. Note the use of the double underscores before the index and property. - -Example: - -```shell -PACTFLOW_WEBHOOK_CERTIFICATES__0__LABEL="An example self signed certificate with content" -PACTFLOW_WEBHOOK_CERTIFICATES__0__CONTENT="-----BEGIN CERTIFICATE----- - MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYKCZImiZPyLGQB - - jHT1Ty2CglM= - -----END CERTIFICATE-----" -PACTFLOW_WEBHOOK_CERTIFICATES__1__LABEL="An example self signed certificate with a path" -PACTFLOW_WEBHOOK_CERTIFICATES__1__PATH="/full/path/to/the/cert.pem" -``` - -**Supported versions:** From v1.14.0
-**Required:** false
- -## SAML authentication - -
- -To configure more than one SAML identity provider, specify another set of the following environment variables with a `_2` after the `PACTFLOW_SAML` prefix (and `_3` for the third etc.). The `PACTFLOW_SAML_ISSUER` is shared between all the SAML providers so does not need to be duplicated. - -eg. For the second SAML identity provider set `PACTFLOW_SAML_2_AUTH_ENABLED`, `PACTFLOW_SAML_2_IDP_NAME` etc and for the third `PACTFLOW_SAML_3_AUTH_ENABLED`, `PACTFLOW_SAML_3_IDP_NAME` etc. - - -### PACTFLOW_SAML_AUTH_ENABLED - -Whether or not to enable SAML authentication. - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_SAML_ISSUER - -The name of this application as it is known to the SAML IDP. - -**Required:** false
-**Default:** `https://pactflow.io`
-**Example:** `http://pactflow.mycompany.com`
- -### PACTFLOW_SAML_IDP_NAME - -The display name of the SAML IDP. This value will be used as the login button label. - -**Required:** true
- -### PACTFLOW_SAML_IDP_LOGO - -URL of a logo for IDP, to be displayed next to the login button. - -**Required:** false
- -### PACTFLOW_SAML_IDP_SSO_TARGET_URL - -The URL to which the authentication request should be sent. This endpoint is on the identity provider. - -**Required:** if PACTFLOW_SAML_IDP_METADATA_URL is not set
-**More information:** https://github.com/omniauth/omniauth-saml#options
- -### PACTFLOW_SAML_IDP_CERT_FINGERPRINT - -The SHA1 fingerprint of the certificate, e.g. "90:CC:16:F0:8D:...". This is provided from the identity provider when setting up the relationship. - -**Required:** if PACTFLOW_SAML_IDP_METADATA_URL is not set
-**More information:** https://github.com/omniauth/omniauth-saml#options
- -### PACTFLOW_SAML_IDP_ID_ATTRIBUTE - -The name of the SAML response attribute that uniquely and permanently identifies a user for the IDP. - -**Required:** true
- -### PACTFLOW_SAML_EMAIL_ATTRIBUTE - -The name of the SAML response attribute that contains the email address. - -**Required:** true
- -### PACTFLOW_SAML_NAME_ATTRIBUTE - -The name of the SAML response attribute that contains the full name. - -**Required:** true
- -### PACTFLOW_SAML_FIRST_NAME_ATTRIBUTE - -The name of the SAML response attribute that contains the first name. - -**Required:** false
- -### PACTFLOW_SAML_LAST_NAME_ATTRIBUTE - -The name of the SAML response attribute that contains the last name. - -**Required:** false
- -### PACTFLOW_SAML_IDP_METADATA_URL - -The URL of the IDP's metadata endpoint. If this is set, then the PACTFLOW_SAML_IDP_SSO_TARGET_URL and PACTFLOW_SAML_IDP_CERT_FINGERPRINT can be skipped. - -**Required:** false
-**More information:** https://github.com/omniauth/omniauth-saml#idp-metadata
- -### PACTFLOW_SAML_NAME_IDENTIFIER_FORMAT - -Used during SP-initiated SSO. Describes the format of the username required by this application. - -**Required:** false
-**Default:** `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`
-**Allowed values:** `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`, `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`
- -### PACTFLOW_SAML_ALLOWED_CLOCK_DRIFT - -To allow for a small amount of clock drift between PactFlow and the Identity Provider, the allowed clock drift may be specified. Its value must be given in a number (and/or fraction) of seconds. The value is added to the current time at which the response is validated, before it is tested against the NotBefore assertion. - -**Required:** false
-**Default:** `0`
- -## Demo authentication - -
- - - -### PACTFLOW_DEMO_AUTH_ENABLED - -Whether or not to enable authentication for demo users. For demonstration purposes only - not to be set to `true` for production use. - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -## Encryption - -
- - - -### PACTFLOW_MASTER_ENCRYPTION_KEY - -A randomly generated string which will be the master key for encrypting secrets and API tokens. Renamed from `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY`. - -Do not change or lose the value of this key. All encrypted data (secrets and API keys) will be unretrievable if this key is lost. Rotation is not currently supported but will be added in a future release. - -To generate an appropriate value, run the following on Linux/Mac: - -``` -env LC_CTYPE=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 32 | head -n 1 -``` - -**Required:** true
-**Example:** `eLM5xPxPu9ftDhA34ZUw2ry2okpMnOPCrA-twxLBUUk`
- -## Secrets - -
- - - -### PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY - -Deprecated in favour of `PACTFLOW_MASTER_ENCRYPTION_KEY`. If you have a previous installation of PactFlow with `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY` set, please rename it to `PACTFLOW_MASTER_ENCRYPTION_KEY`. - -**Required:** false
- -## Content Security - -
- - - -### PACTFLOW_CSP_ALLOWED_SOURCES - -Space separated list of allowed content sources that should be allowed in addition to the hosts configured in the identity provider settings (eg. `PACTFLOW_SAML_IDP_SSO_TARGET_URL`). This may be useful if you need additional assets on your instance of PactFlow. For example, if you need to support multiple redirects for SAML authentication, you need to add them here for PactFlow to generate the appropriate Content-Security-Policy to allow that to happen. - -**Required:** false
-**Example:** `https://my-intermediate-idp-host.com`
- -## User administration - -
- - - -### PACTFLOW_ADMIN_API_KEY - -The value of the X-Api-Key header required to make the HTTP call to provision the admin user. - -To generate an appropriate value, run the following on Linux/Mac: - -``` -env LC_CTYPE=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 32 | head -n 1 -``` - -**Required:** true
-**Allowed values:** `A-Za-z0-9!#$%&*+-^_``|~.`
-**Example:** `4wmplZfucVG-LdIHD9L`
-**More information:** https://tools.ietf.org/html/rfc7230#section-3.2.6
- -## Domain - -
- - - -### PACTFLOW_ALLOW_DANGEROUS_CONTRACT_MODIFICATION - -Whether or not to allow the pact content for an existing consumer version to be modified. It is strongly recommended that this is set to false, -as allowing modification makes the results of can-i-deploy unreliable. When this is set to false as recommended, each commit must publish pacts -with a unique version number. - -**Supported versions:** From v1.14.0
-**Required:** false
-**Default:** For new installations of v1.14.0 and later, this defaults to `false`.
-**Allowed values:** `true`, `false`
-**More information:** https://docs.pact.io/versioning
- -### PACTFLOW_USE_FIRST_TAG_AS_BRANCH - -When the value is `true`, the first tag applied to a version (within 10 seconds) -will be used to populate the `branch` property of the version. - -This is to assist in the migration from using tags to track branches to using the branches feature. - -**Required:** false
-**Default:** `true`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_CREATE_DEPLOYED_VERSIONS_FOR_TAGS - -When the value is `true` and a tag is created, if there is an environment with the name of the newly created tag, a deployed version is -also created for the pacticipant version. - -This is to assist in the migration from using tags to track deployments to using the deployed and released versions feature. - -**Supported versions:** From v1.14.0
-**Required:** false
-**Default:** `true`
-**Allowed values:** `true`, `false`
-**More information:** https://docs.pact.io/pact_broker/recording_deployments_and_releases/
- -## Badges - -
- - - -### PACTFLOW_SHIELDS_IO_BASE_URL - -The URL of the free service that is used to generate the build badges. Note that the badge files are served via a redirect in the browser, so there is no request made from the PactFlow application to the shields server. - -**Required:** false
-**Default:** `https://img.shields.io`
-**More information:** https://shields.io
- -## Resources - -
- - - -### PACTFLOW_BASE_URL - -The base url, including HTTP scheme and any application context path, at which the PactFlow application will be publicly -accessible. It should not include a trailing slash. If there are multiple interfaces on which the application will be addressed, -list all the base URLs separated by spaces. - - -**Required:** true
-**Example:** `https://pactflow.mycompany.com https://pactflow.internal.mycompany.com`
- -### PACTFLOW_HTTP_PORT - -The HTTP port on which the PactFlow application will be exposed on the Docker container. Must be greater than 1024. - -**Required:** false
-**Default:** `9292`
- -### PACTFLOW_SESSION_LENGTH - -The number of seconds after which the user needs to re-authenticate with the IDP. Default is 1 week. - -**Required:** false
-**Default:** `604800`
- -### PACTFLOW_SESSION_INACTIVITY_TIMEOUT - -The number of seconds of inactivity after which the user needs to re-authenticate with the IDP. By default, this will be set to the value of the `PACTFLOW_SESSION_LENGTH`, effectively disabling the feature, unless a value is specified by the user. - -**Required:** false
-**Default:** `604800`
- -### PACTFLOW_COOKIE_SECRET - -The secret used to encrypt the rack.session cookie. -To generate an appropriate value, run the following on Linux/Mac: - -``` -env LC_ALL=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 64 | head -n 1 -``` - -**Required:** true
-**Example:** `X-sbeCpAUgO-8FRtKxYrVhgZ2hIJhPuzCh_89PypYrI`
- -### PACTFLOW_OLD_COOKIE_SECRET - -The previous secret - used when rotating the rack.session cookie secret. - -**Required:** false
- -### PACTFLOW_REQUIRE_HTTPS - -When set to `true`, the header `Strict-Transport-Security: max-age=31536000 ; includeSubDomains` is added to ensure connections are made over HTTPS, and the `PACTFLOW_BASE_URL` is validated to ensure it starts with https. - -This value should never be set to false in a production environment. It should only ever be set to false for local testing or demonstration purposes where an SSL certificate is not available. - - -**Required:** false
-**Default:** `true`
-**Allowed values:** `true`, `false`
- -### SSL_CERT_FILE - -The PEM certificate file to use if the webhooks have to connect to servers that use self signed certificates. - -**Required:** false
- -### SSL_CERT_DIR - -The PEM certificate directory to use if the webhooks have to connect to servers that use self signed certificates. - -**Required:** false
- -### http_proxy - -HTTP proxy used when making outgoing HTTP requests - -**Required:** false
- -### https_proxy - -HTTPS proxy used when making outgoing HTTP requests - -**Required:** false
- -### no_proxy - -The hosts for which to not use a proxy - -**Required:** false
- -### PACTFLOW_USE_HAL_BROWSER - -Whether or not to enable the embedded HAL Browser. - -**Required:** false
-**Default:** `true`
-**Allowed values:** `true`, `false`
-**More information:** https://github.com/mikekelly/hal-browser
- -## Miscellaneous - -
- - - -### TZ - -The timezone in which to display dates for server side rendered pages. - -**Required:** true
-**More information:** [Valid timezones](/docs/on-premises-2x/environment-variables/timezones)
- -## API Tokens - -
- - - -### PACTFLOW_API_TOKEN_AUTH_ENABLED - -Whether or not to enable the inbuilt PactFlow API tokens used for bearer authentication. Used to disable API tokens if an external Identify Provider is configured for API authentication. - -**Required:** false
-**Default:** `true`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED - -Enables encryption of API token values in the database. Requires `PACTFLOW_API_TOKEN_IV` and `PACTFLOW_MASTER_ENCRYPTION_KEY` to also be set. - -**Required:** false
- -### PACTFLOW_API_TOKEN_IV - -If `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` is set to `true`, then this value must contain a base 64 encoded string of random 16 bytes for the -encryption initialization vector. - -To generate an appropriate value, run the following on Linux/Mac: - -``` -head < /dev/random -c 16 | base64 -``` - -**Required:** if `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` is set to `true`
-**Example:** `JUVDdnRzLXZyWHA7UF93RAo=`
- -## User Interface - -
- - - -### PACTFLOW_CLARITY_DISABLED - -Disables the new user interface introduced in version 2.0.0. When this environment variable is set, the legacy interface becomes the default and users cannot switch to the new UI. - -**Required:** false
-**Default:** unset
-**Allowed values:** `true`
\ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md b/website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md deleted file mode 100644 index d8ae64d4..00000000 --- a/website/docs/docs/on-premises-2x/environment-variables/1.14-beta.md +++ /dev/null @@ -1,259 +0,0 @@ -# PactFlow Environment Variables - 1.14 beta features - -This page contains documentation for the usage of the JWT and OAuth2 features that are in beta release in PactFlow 1.14 - -## Test JWT bearer authentication - -
-These settings can be configured in a YAML file, as per this example. - -```yaml -test_jwt_bearer_token_auth_enabled: true -test_jwt_bearer_token: - iss: https://idp - exp_leeway: 60 - jwks_url: https://idp/jwks - aud: some-aud - auth_config_handler: auth_ext_script.rb - claim_mappings: - idp_id: SomeUniqueIdentifier - email: EmailAddress - name: DisplayName - first_name: FirstName - last_name: LastName - ``` - - -### PACTFLOW_TEST_JWT_BEARER_TOKEN_AUTH_ENABLED - -Whether or not to enable JWT bearer token authentication for testing purposes. This is not yet ready for production use. - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_TEST_JWT_BEARER_TOKEN__JWKS_URL - -The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT used as the bearer token. - -**Required:** false
- -### PACTFLOW_TEST_JWT_BEARER_TOKEN__AUD - -The expected token audience ("aud") of the JWT. - -**Required:** false
- -### PACTFLOW_TEST_JWT_BEARER_TOKEN__ISS - -The expected token issuer ("iss") of the JWT. - -**Required:** false
- -### PACTFLOW_TEST_JWT_BEARER_TOKEN__EXP_LEEWAY - -The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. - -**Required:** false
-**Default:** `0`
- -### PACTFLOW_TEST_JWT_BEARER_TOKEN__AUTH_CONFIG_HANDLER - -The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. - -**Required:** false
- -### PACTFLOW_TEST_JWT\_\_CLAIM_MAPPINGS__{KEY} - -This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. -At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. -The other recommended keys are `name`, `email`, `first_name` and `last_name`. - -eg. - -```yaml -test_jwt_bearer_token: - # other configurations here ... - claim_mappings: - idp_id: "SomeUniqueIdentifier" - name: "Name" - email: "Email" - first_name: "FirstName" - last_name: "LastName" -``` - -When setting the claim mappings using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_JWT__CLAIM_MAPPINGS__` eg. `PACTFLOW_TEST_JWT__CLAIM_MAPPINGS__EMAIL=Email`. This will be mapped to a lower case `{ "email": "Email" }` internally. - -**Required:** false
- -
- -## Test OAuth2 authentication - -
-These settings can be configured in a YAML file, as per this example. - -```yaml -test_oauth2_auth_enabled: true -test_oauth2: - client_id: "..." - client_secret: "..." - idp_url: "https://idp" - authorize_url: "https://idp/authorize" - token_url: "https://idp/token" - jwks_url: "https://idp/jwks" - token_issuer: "https://idp" - token_audience: "..." - token_exp_leeway: 60 - auth_config_handler: "auth_ext_script.rb" - custom_authorize_params: - resource: "SomeResource" - claim_mappings: - idp_id: "SomeUniqueIdentifier" - email: "Email" - name: "DisplayName" - first_name: "FirstName" - last_name: "LastName" -``` - - -### PACTFLOW_TEST_OAUTH2_AUTH_ENABLED - -Whether or not to enable OAuth2 authentication for testing purposes. This is not yet ready for production use. - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_TEST_OAUTH2__CLIENT_ID - -The unique identier by which the PactFlow application is known to the identity provider. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__CLIENT_SECRET - -The client secret which the PactFlow application shares with the identity provider. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__IDP_URL - -The identity provider's URL. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__AUTHORIZE_URL - -The authorize endpoint of the OAuth2 provider. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__TOKEN_URL - -The endpoint at which PactFlow can retrieve the JWT containing the user's information. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__JWKS_URL - -The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT returned by the token endpoint. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__TOKEN_ISSUER - -The expected token issuer ("iss") of the JWT. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__TOKEN_AUDIENCE - -The expected token audience ("aud") of the JWT. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2__TOKEN_EXP_LEEWAY - -The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. - -**Required:** false
-**Default:** `0`
- -### PACTFLOW_TEST_OAUTH2__AUTH_CONFIG_HANDLER - -The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2\_\_CUSTOM_AUTHORIZE_PARAMS__{KEY} - -Allows custom authorize parameters to be set. These will be sent to the IDP in the request phase along with the default authorize parameters. - -eg. - -```yaml -test_oauth2: - custom_authorize_params: - resource: "SomeResource" -``` - -When setting the custom authorize params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_OAUTH2__CUSTOM_AUTHORIZE_PARAMS__` -eg. `PACTFLOW_TEST_OAUTH2__CLAIM_MAPPINGS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2\_\_CUSTOM_TOKEN_PARAMS__{KEY} - -Allows custom token parameters to be set. These will be sent to the token endpoint along with the default token parameters. - -eg. - -```yaml -test_oauth2: - custom_token_params: - resource: "SomeResource" -``` - -When setting the custom token params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_OAUTH2__CUSTOM_TOKEN_PARAMS__` -eg. `PACTFLOW_TEST_OAUTH2__CUSTOM_TOKEN_PARAMS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. - -**Required:** false
- -### PACTFLOW_TEST_OAUTH2\_\_CLAIM_MAPPINGS__{KEY} - -This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. -At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. -The other recommended keys are `name`, `email`, `first_name` and `last_name`. - -eg. - -```yaml -test_oauth2: - # other configurations here ... - claim_mappings: - idp_id: "SomeUniqueIdentifier" - name: "Name" - email: "Email" - first_name: "FirstName" - last_name: "LastName" -``` - -When setting the claim mappings using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_TEST_OAUTH2__CLAIM_MAPPINGS__` -eg. `PACTFLOW_TEST_OAUTH2__CLAIM_MAPPINGS__EMAIL=Email`. This will be mapped to a lower case `{ "email": "Email" }` internally. - -**Required:** false
- -
- -## API Tokens - -
- - -### PACTFLOW_API_TOKENS__ENABLED - -Whether or not to enable the inbuilt PactFlow API tokens used for bearer authentication. Used to disable API tokens if an external Identify Provider is configured for API authentication. - -**Required:** false
-**Allowed values:** `true`, `false`
diff --git a/website/docs/docs/on-premises-2x/environment-variables/jwt.md b/website/docs/docs/on-premises-2x/environment-variables/jwt.md deleted file mode 100644 index dbdeffac..00000000 --- a/website/docs/docs/on-premises-2x/environment-variables/jwt.md +++ /dev/null @@ -1,109 +0,0 @@ -# Environment Variables - JWT - - - - - -## JWT bearer authentication - -
-These settings can be configured in a YAML file, as per this example. - -```yaml -jwt_bearer_token_auth_enabled: true -jwt_bearer_token: - issuer: https://idp - audience: some-aud - expiry_leeway: 60 - jwks_url: https://idp/jwks - auth_config_handler: auth_ext_script.rb - claim_mappings: - idp_id: SomeUniqueIdentifier - email: EmailAddress - name: DisplayName - first_name: FirstName - last_name: LastName - ``` - - -### PACTFLOW_JWT_BEARER_TOKEN_AUTH_ENABLED - -Whether or not to enable JWT bearer token authentication. - -**Supported versions:** From v1.16.0
-**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_JWT_BEARER_TOKEN\_\_JWKS_URL - -The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT used as the bearer token. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_JWT_BEARER_TOKEN\_\_AUDIENCE - -The expected token audience ("aud") of the JWT. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_JWT_BEARER_TOKEN\_\_ISSUER - -The expected token issuer ("iss") of the JWT. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_JWT_BEARER_TOKEN\_\_EXPIRY_LEEWAY - -The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. - -**Supported versions:** From v1.16.0
-**Required:** false
-**Default:** `0`
- -### PACTFLOW_JWT_BEARER_TOKEN\_\_AUTH_CONFIG_HANDLER - -The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. - -**Supported versions:** From v1.16.0
-**Required:** false
- -### PACTFLOW_JWT\_\_CLAIM_MAPPINGS\_\_{KEY} - -This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. -At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. -The other recommended keys are `name`, `email`, `first_name` and `last_name`. - -eg. - -```yaml -jwt_bearer_token_auth_enabled: true -jwt_bearer_token: - # other configurations here ... - claim_mappings: - idp_id: "SomeUniqueIdentifier" - name: "Name" - email: "Email" - first_name: "FirstName" - last_name: "LastName" -``` - -When setting the claim mappings using environment variables, a separate environment variable must be used for each claim mapping. -The key name must be uppercased and prefixed by `PACTFLOW_JWT__CLAIM_MAPPINGS__`. - -eg. - -```shell -PACTFLOW_JWT__CLAIM_MAPPINGS__IDP_ID="SomeUniqueIdentifier" -PACTFLOW_JWT__CLAIM_MAPPINGS__NAME="Name" -PACTFLOW_JWT__CLAIM_MAPPINGS__EMAIL="Email" -PACTFLOW_JWT__CLAIM_MAPPINGS__FIRST_NAME="FirstName" -PACTFLOW_JWT__CLAIM_MAPPINGS__LAST_NAME="LastName" -```` - -**Supported versions:** From v1.16.0
-**Required:** false
- diff --git a/website/docs/docs/on-premises-2x/environment-variables/oauth2.md b/website/docs/docs/on-premises-2x/environment-variables/oauth2.md deleted file mode 100644 index 7d9de85d..00000000 --- a/website/docs/docs/on-premises-2x/environment-variables/oauth2.md +++ /dev/null @@ -1,193 +0,0 @@ -# Environment Variables - OAuth2 - - - - - -## OAuth2 authentication - -
-These settings can be configured in a YAML file, as per this example. - -```yaml -oauth2_auth_enabled: true -oauth2: - client_id: "..." - client_secret: "..." - idp_name: "Some IDP" - idp_url: "https://idp" - authorize_url: "https://idp/authorize" - token_url: "https://idp/token" - jwks_url: "https://idp/jwks" - token_issuer: "https://idp" - token_audience: "..." - token_expiry_leeway: 60 - auth_config_handler: "auth_ext_script.rb" - custom_authorize_params: - resource: "SomeResource" - claim_mappings: - idp_id: "SomeUniqueIdentifier" - email: "Email" - name: "DisplayName" - first_name: "FirstName" - last_name: "LastName" -``` - - -### PACTFLOW_OAUTH2_AUTH_ENABLED - -Whether or not to enable OAuth2 authentication. - -**Supported versions:** From v1.16.0
-**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -### PACTFLOW_OAUTH2\_\_CLIENT_ID - -The unique identier by which the PactFlow application is known to the identity provider. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_CLIENT_SECRET - -The client secret which the PactFlow application shares with the identity provider. - -**Supported versions:** From v1.16.0
-**Required:** false
- -### PACTFLOW_OAUTH2\_\_IDP_NAME - -The identity provider's name. This value will appear on the login button. - -**Supported versions:** From v1.16.0
-**Required:** false
- -### PACTFLOW_OAUTH2\_\_IDP_URL - -The identity provider's URL. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_AUTHORIZE_URL - -The authorize endpoint of the OAuth2 provider. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_TOKEN_URL - -The endpoint at which PactFlow can retrieve the JWT containing the user's information. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_JWKS_URL - -The endpoint from which the JSON web key set can be retrieved to decode and verify the JWT returned by the token endpoint. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_TOKEN_ISSUER - -The expected token issuer ("iss") of the JWT. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_TOKEN_AUDIENCE - -The expected token audience ("aud") of the JWT. - -**Supported versions:** From v1.16.0
-**Required:** true
- -### PACTFLOW_OAUTH2\_\_TOKEN_EXPIRY_LEEWAY - -The number of seconds of leeway to allow when verifying the expiration of the JWT, to allow for click drift between Pactlow and the Identity Provider. - -**Supported versions:** From v1.16.0
-**Required:** false
-**Default:** `0`
- -### PACTFLOW_OAUTH2\_\_AUTH_CONFIG_HANDLER - -The name of a Ruby script which will parse the decoded JWT and extract the roles and teams associated with the user. The script must be mounted into the PactFlow Docker container in the directory `/home/pactflow/extensions`. - -**Supported versions:** From v1.16.0
-**Required:** false
- -### PACTFLOW_OAUTH2\_\_CUSTOM_AUTHORIZE_PARAMS\_\_{KEY} - -Allows custom authorize parameters to be set. These will be sent to the IDP in the request phase along with the default authorize parameters. - -eg. - -```yaml -oauth2: - custom_authorize_params: - resource: "SomeResource" -``` - -When setting the custom authorize params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_OAUTH2__CUSTOM_AUTHORIZE_PARAMS__` -eg. `PACTFLOW_OAUTH2__CUSTOM_AUTHORIZE_PARAMS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. - -**Supported versions:** From v1.16.0
-**Required:** false
- -### PACTFLOW_OAUTH2\_\_CUSTOM_TOKEN_PARAMS\_\_{KEY} - -Allows custom token parameters to be set. These will be sent to the token endpoint along with the default token parameters. - -eg. - -```yaml -oauth2: - custom_token_params: - resource: "SomeResource" -``` - -When setting the custom token params using environment variables, the key name must be uppercased and prefixed by `PACTFLOW_OAUTH2__CUSTOM_TOKEN_PARAMS__` -eg. `PACTFLOW_OAUTH2__CUSTOM_TOKEN_PARAMS__RESOURCE=SomeResource`. This will be mapped to a lower case `{ "resource": "SomeResource" }` internally. - -**Supported versions:** From v1.16.0
-**Required:** false
- -### PACTFLOW_OAUTH2\_\_CLAIM_MAPPINGS\_\_{KEY} - -This setting maps the IDP's claims in the JWT to the required PactFlow user attributes. This setting is best configured in the YAML file as a map. -At least one of the keys must be called `sub` or `idp_id`. This will be used by PactFlow to uniquely identify the user from the Identify Provider. -The other recommended keys are `name`, `email`, `first_name` and `last_name`. - -eg. - -```yaml -oauth2: - # other configurations here ... - claim_mappings: - idp_id: "SomeUniqueIdentifier" - name: "Name" - email: "Email" - first_name: "FirstName" - last_name: "LastName" -``` - -When setting the claim mappings using environment variables, a separate environment variable must be used for each claim mapping. -The key name must be uppercased and prefixed by `PACTFLOW_OAUTH2__CLAIM_MAPPINGS__`. - -eg. - -```shell -PACTFLOW_OAUTH2__CLAIM_MAPPINGS__IDP_ID="SomeUniqueIdentifier" -PACTFLOW_OAUTH2__CLAIM_MAPPINGS__NAME="Name" -PACTFLOW_OAUTH2__CLAIM_MAPPINGS__EMAIL="Email" -PACTFLOW_OAUTH2__CLAIM_MAPPINGS__FIRST_NAME="FirstName" -PACTFLOW_OAUTH2__CLAIM_MAPPINGS__LAST_NAME="LastName" -```` - -**Supported versions:** From v1.16.0
-**Required:** false
diff --git a/website/docs/docs/on-premises-2x/environment-variables/templates.md b/website/docs/docs/on-premises-2x/environment-variables/templates.md deleted file mode 100644 index 333de9c7..00000000 --- a/website/docs/docs/on-premises-2x/environment-variables/templates.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Configuration file templates ---- - -## Required environment variables - -```yml -- name: "PACTFLOW_DATABASE_URL" - value: "postgres://username:password@host:port/database" -- name: "PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY" - value: "" -- name: "PACTFLOW_COOKIE_SECRET" - value: "" -- name: "TZ" - value: "" -- name: "PACTFLOW_BASE_URL" - value: "" - -# SAML -- name: "PACTFLOW_SAML_IDP_NAME" - value: "" -- name: "PACTFLOW_SAML_ISSUER" - value: "" -- name: "PACTFLOW_SAML_NAME_IDENTIFIER_FORMAT" - value: "" -- name: "PACTFLOW_SAML_EMAIL_ATTRIBUTE" - value: "" -- name: "PACTFLOW_SAML_NAME_ATTRIBUTE" - value: "" -- name: "PACTFLOW_SAML_FIRST_NAME_ATTRIBUTE" - value: "" -- name: "PACTFLOW_SAML_LAST_NAME_ATTRIBUTE" - value: "" -- name: "PACTFLOW_SAML_IDP_SSO_TARGET_URL" - value: "" -- name: "PACTFLOW_SAML_IDP_CERT_FINGERPRINT" - value: "" -- name: "PACTFLOW_SAML_IDP_ID_ATTRIBUTE" - value: "" -``` - -## Recommended environment variables - -```yml -- name: "PACTFLOW_WEBHOOK_HOST_WHITELIST" - value: "" -``` - -## SAML -### Azure Active Directory - -```yml -- name: "PACTFLOW_SAML_ISSUER" - value: "eg. https://pactflow.mycompany.com" -- name: "PACTFLOW_SAML_IDP_NAME" - value: "eg. Azure AD" -- name: "PACTFLOW_SAML_IDP_SSO_TARGET_URL" - value: "eg. https://login.microsoftonline.com/abcd/saml2" -- name: "PACTFLOW_SAML_IDP_CERT_FINGERPRINT" - value: "eg. E97D948158F893A93827A0A4D70701A38AB1A499" -- name: "PACTFLOW_SAML_IDP_ENTITY_ID" - value: "eg. https://sts.windows.net/abcd/" -- name: "PACTFLOW_SAML_NAME_IDENTIFIER_FORMAT" - value: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" -- name: "PACTFLOW_SAML_IDP_ID_ATTRIBUTE" - value: "http://schemas.microsoft.com/identity/claims/objectidentifier" -- name: "PACTFLOW_SAML_EMAIL_ATTRIBUTE" - value: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -- name: "PACTFLOW_SAML_NAME_ATTRIBUTE" - value: "http://schemas.microsoft.com/identity/claims/displayname" -- name: "PACTFLOW_SAML_FIRST_NAME_ATTRIBUTE" - value: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" -- name: "PACTFLOW_SAML_LAST_NAME_ATTRIBUTE" - value: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" -``` diff --git a/website/docs/docs/on-premises-2x/environment-variables/timezones.md b/website/docs/docs/on-premises-2x/environment-variables/timezones.md deleted file mode 100644 index 9a039699..00000000 --- a/website/docs/docs/on-premises-2x/environment-variables/timezones.md +++ /dev/null @@ -1,601 +0,0 @@ ---- -title: Timezones ---- - -These are the valid values for the [TZ environment variable](/docs/on-premises-2x/environment-variables#tz). - -* Africa/Abidjan -* Africa/Accra -* Africa/Addis_Ababa -* Africa/Algiers -* Africa/Asmara -* Africa/Asmera -* Africa/Bamako -* Africa/Bangui -* Africa/Banjul -* Africa/Bissau -* Africa/Blantyre -* Africa/Brazzaville -* Africa/Bujumbura -* Africa/Cairo -* Africa/Casablanca -* Africa/Ceuta -* Africa/Conakry -* Africa/Dakar -* Africa/Dar_es_Salaam -* Africa/Djibouti -* Africa/Douala -* Africa/El_Aaiun -* Africa/Freetown -* Africa/Gaborone -* Africa/Harare -* Africa/Johannesburg -* Africa/Juba -* Africa/Kampala -* Africa/Khartoum -* Africa/Kigali -* Africa/Kinshasa -* Africa/Lagos -* Africa/Libreville -* Africa/Lome -* Africa/Luanda -* Africa/Lubumbashi -* Africa/Lusaka -* Africa/Malabo -* Africa/Maputo -* Africa/Maseru -* Africa/Mbabane -* Africa/Mogadishu -* Africa/Monrovia -* Africa/Nairobi -* Africa/Ndjamena -* Africa/Niamey -* Africa/Nouakchott -* Africa/Ouagadougou -* Africa/Porto-Novo -* Africa/Sao_Tome -* Africa/Timbuktu -* Africa/Tripoli -* Africa/Tunis -* Africa/Windhoek -* America/Adak -* America/Anchorage -* America/Anguilla -* America/Antigua -* America/Araguaina -* America/Argentina/Buenos_Aires -* America/Argentina/Catamarca -* America/Argentina/ComodRivadavia -* America/Argentina/Cordoba -* America/Argentina/Jujuy -* America/Argentina/La_Rioja -* America/Argentina/Mendoza -* America/Argentina/Rio_Gallegos -* America/Argentina/Salta -* America/Argentina/San_Juan -* America/Argentina/San_Luis -* America/Argentina/Tucuman -* America/Argentina/Ushuaia -* America/Aruba -* America/Asuncion -* America/Atikokan -* America/Atka -* America/Bahia -* America/Bahia_Banderas -* America/Barbados -* America/Belem -* America/Belize -* America/Blanc-Sablon -* America/Boa_Vista -* America/Bogota -* America/Boise -* America/Buenos_Aires -* America/Cambridge_Bay -* America/Campo_Grande -* America/Cancun -* America/Caracas -* America/Catamarca -* America/Cayenne -* America/Cayman -* America/Chicago -* America/Chihuahua -* America/Coral_Harbour -* America/Cordoba -* America/Costa_Rica -* America/Creston -* America/Cuiaba -* America/Curacao -* America/Danmarkshavn -* America/Dawson -* America/Dawson_Creek -* America/Denver -* America/Detroit -* America/Dominica -* America/Edmonton -* America/Eirunepe -* America/El_Salvador -* America/Ensenada -* America/Fort_Nelson -* America/Fort_Wayne -* America/Fortaleza -* America/Glace_Bay -* America/Godthab -* America/Goose_Bay -* America/Grand_Turk -* America/Grenada -* America/Guadeloupe -* America/Guatemala -* America/Guayaquil -* America/Guyana -* America/Halifax -* America/Havana -* America/Hermosillo -* America/Indiana/Indianapolis -* America/Indiana/Knox -* America/Indiana/Marengo -* America/Indiana/Petersburg -* America/Indiana/Tell_City -* America/Indiana/Vevay -* America/Indiana/Vincennes -* America/Indiana/Winamac -* America/Indianapolis -* America/Inuvik -* America/Iqaluit -* America/Jamaica -* America/Jujuy -* America/Juneau -* America/Kentucky/Louisville -* America/Kentucky/Monticello -* America/Knox_IN -* America/Kralendijk -* America/La_Paz -* America/Lima -* America/Los_Angeles -* America/Louisville -* America/Lower_Princes -* America/Maceio -* America/Managua -* America/Manaus -* America/Marigot -* America/Martinique -* America/Matamoros -* America/Mazatlan -* America/Mendoza -* America/Menominee -* America/Merida -* America/Metlakatla -* America/Mexico_City -* America/Miquelon -* America/Moncton -* America/Monterrey -* America/Montevideo -* America/Montreal -* America/Montserrat -* America/Nassau -* America/New_York -* America/Nipigon -* America/Nome -* America/Noronha -* America/North_Dakota/Beulah -* America/North_Dakota/Center -* America/North_Dakota/New_Salem -* America/Nuuk -* America/Ojinaga -* America/Panama -* America/Pangnirtung -* America/Paramaribo -* America/Phoenix -* America/Port-au-Prince -* America/Port_of_Spain -* America/Porto_Acre -* America/Porto_Velho -* America/Puerto_Rico -* America/Punta_Arenas -* America/Rainy_River -* America/Rankin_Inlet -* America/Recife -* America/Regina -* America/Resolute -* America/Rio_Branco -* America/Rosario -* America/Santa_Isabel -* America/Santarem -* America/Santiago -* America/Santo_Domingo -* America/Sao_Paulo -* America/Scoresbysund -* America/Shiprock -* America/Sitka -* America/St_Barthelemy -* America/St_Johns -* America/St_Kitts -* America/St_Lucia -* America/St_Thomas -* America/St_Vincent -* America/Swift_Current -* America/Tegucigalpa -* America/Thule -* America/Thunder_Bay -* America/Tijuana -* America/Toronto -* America/Tortola -* America/Vancouver -* America/Virgin -* America/Whitehorse -* America/Winnipeg -* America/Yakutat -* America/Yellowknife -* Antarctica/Casey -* Antarctica/Davis -* Antarctica/DumontDUrville -* Antarctica/Macquarie -* Antarctica/Mawson -* Antarctica/McMurdo -* Antarctica/Palmer -* Antarctica/Rothera -* Antarctica/South_Pole -* Antarctica/Syowa -* Antarctica/Troll -* Antarctica/Vostok -* Arctic/Longyearbyen -* Asia/Aden -* Asia/Almaty -* Asia/Amman -* Asia/Anadyr -* Asia/Aqtau -* Asia/Aqtobe -* Asia/Ashgabat -* Asia/Ashkhabad -* Asia/Atyrau -* Asia/Baghdad -* Asia/Bahrain -* Asia/Baku -* Asia/Bangkok -* Asia/Barnaul -* Asia/Beirut -* Asia/Bishkek -* Asia/Brunei -* Asia/Calcutta -* Asia/Chita -* Asia/Choibalsan -* Asia/Chongqing -* Asia/Chungking -* Asia/Colombo -* Asia/Dacca -* Asia/Damascus -* Asia/Dhaka -* Asia/Dili -* Asia/Dubai -* Asia/Dushanbe -* Asia/Famagusta -* Asia/Gaza -* Asia/Harbin -* Asia/Hebron -* Asia/Ho_Chi_Minh -* Asia/Hong_Kong -* Asia/Hovd -* Asia/Irkutsk -* Asia/Istanbul -* Asia/Jakarta -* Asia/Jayapura -* Asia/Jerusalem -* Asia/Kabul -* Asia/Kamchatka -* Asia/Karachi -* Asia/Kashgar -* Asia/Kathmandu -* Asia/Katmandu -* Asia/Khandyga -* Asia/Kolkata -* Asia/Krasnoyarsk -* Asia/Kuala_Lumpur -* Asia/Kuching -* Asia/Kuwait -* Asia/Macao -* Asia/Macau -* Asia/Magadan -* Asia/Makassar -* Asia/Manila -* Asia/Muscat -* Asia/Nicosia -* Asia/Novokuznetsk -* Asia/Novosibirsk -* Asia/Omsk -* Asia/Oral -* Asia/Phnom_Penh -* Asia/Pontianak -* Asia/Pyongyang -* Asia/Qatar -* Asia/Qostanay -* Asia/Qyzylorda -* Asia/Rangoon -* Asia/Riyadh -* Asia/Saigon -* Asia/Sakhalin -* Asia/Samarkand -* Asia/Seoul -* Asia/Shanghai -* Asia/Singapore -* Asia/Srednekolymsk -* Asia/Taipei -* Asia/Tashkent -* Asia/Tbilisi -* Asia/Tehran -* Asia/Tel_Aviv -* Asia/Thimbu -* Asia/Thimphu -* Asia/Tokyo -* Asia/Tomsk -* Asia/Ujung_Pandang -* Asia/Ulaanbaatar -* Asia/Ulan_Bator -* Asia/Urumqi -* Asia/Ust-Nera -* Asia/Vientiane -* Asia/Vladivostok -* Asia/Yakutsk -* Asia/Yangon -* Asia/Yekaterinburg -* Asia/Yerevan -* Atlantic/Azores -* Atlantic/Bermuda -* Atlantic/Canary -* Atlantic/Cape_Verde -* Atlantic/Faeroe -* Atlantic/Faroe -* Atlantic/Jan_Mayen -* Atlantic/Madeira -* Atlantic/Reykjavik -* Atlantic/South_Georgia -* Atlantic/St_Helena -* Atlantic/Stanley -* Australia/ACT -* Australia/Adelaide -* Australia/Brisbane -* Australia/Broken_Hill -* Australia/Canberra -* Australia/Currie -* Australia/Darwin -* Australia/Eucla -* Australia/Hobart -* Australia/LHI -* Australia/Lindeman -* Australia/Lord_Howe -* Australia/Melbourne -* Australia/NSW -* Australia/North -* Australia/Perth -* Australia/Queensland -* Australia/South -* Australia/Sydney -* Australia/Tasmania -* Australia/Victoria -* Australia/West -* Australia/Yancowinna -* Brazil/Acre -* Brazil/DeNoronha -* Brazil/East -* Brazil/West -* CET -* CST6CDT -* Canada/Atlantic -* Canada/Central -* Canada/Eastern -* Canada/Mountain -* Canada/Newfoundland -* Canada/Pacific -* Canada/Saskatchewan -* Canada/Yukon -* Chile/Continental -* Chile/EasterIsland -* Cuba -* EET -* EST -* EST5EDT -* Egypt -* Eire -* Etc/GMT -* Etc/GMT+0 -* Etc/GMT+1 -* Etc/GMT+10 -* Etc/GMT+11 -* Etc/GMT+12 -* Etc/GMT+2 -* Etc/GMT+3 -* Etc/GMT+4 -* Etc/GMT+5 -* Etc/GMT+6 -* Etc/GMT+7 -* Etc/GMT+8 -* Etc/GMT+9 -* Etc/GMT-0 -* Etc/GMT-1 -* Etc/GMT-10 -* Etc/GMT-11 -* Etc/GMT-12 -* Etc/GMT-13 -* Etc/GMT-14 -* Etc/GMT-2 -* Etc/GMT-3 -* Etc/GMT-4 -* Etc/GMT-5 -* Etc/GMT-6 -* Etc/GMT-7 -* Etc/GMT-8 -* Etc/GMT-9 -* Etc/GMT0 -* Etc/Greenwich -* Etc/UCT -* Etc/UTC -* Etc/Universal -* Etc/Zulu -* Europe/Amsterdam -* Europe/Andorra -* Europe/Astrakhan -* Europe/Athens -* Europe/Belfast -* Europe/Belgrade -* Europe/Berlin -* Europe/Bratislava -* Europe/Brussels -* Europe/Bucharest -* Europe/Budapest -* Europe/Busingen -* Europe/Chisinau -* Europe/Copenhagen -* Europe/Dublin -* Europe/Gibraltar -* Europe/Guernsey -* Europe/Helsinki -* Europe/Isle_of_Man -* Europe/Istanbul -* Europe/Jersey -* Europe/Kaliningrad -* Europe/Kiev -* Europe/Kirov -* Europe/Lisbon -* Europe/Ljubljana -* Europe/London -* Europe/Luxembourg -* Europe/Madrid -* Europe/Malta -* Europe/Mariehamn -* Europe/Minsk -* Europe/Monaco -* Europe/Moscow -* Europe/Nicosia -* Europe/Oslo -* Europe/Paris -* Europe/Podgorica -* Europe/Prague -* Europe/Riga -* Europe/Rome -* Europe/Samara -* Europe/San_Marino -* Europe/Sarajevo -* Europe/Saratov -* Europe/Simferopol -* Europe/Skopje -* Europe/Sofia -* Europe/Stockholm -* Europe/Tallinn -* Europe/Tirane -* Europe/Tiraspol -* Europe/Ulyanovsk -* Europe/Uzhgorod -* Europe/Vaduz -* Europe/Vatican -* Europe/Vienna -* Europe/Vilnius -* Europe/Volgograd -* Europe/Warsaw -* Europe/Zagreb -* Europe/Zaporozhye -* Europe/Zurich -* Factory -* GB -* GB-Eire -* GMT -* GMT+0 -* GMT-0 -* GMT0 -* Greenwich -* HST -* Hongkong -* Iceland -* Indian/Antananarivo -* Indian/Chagos -* Indian/Christmas -* Indian/Cocos -* Indian/Comoro -* Indian/Kerguelen -* Indian/Mahe -* Indian/Maldives -* Indian/Mauritius -* Indian/Mayotte -* Indian/Reunion -* Iran -* Israel -* Jamaica -* Japan -* Kwajalein -* Libya -* MET -* MST -* MST7MDT -* Mexico/BajaNorte -* Mexico/BajaSur -* Mexico/General -* NZ -* NZ-CHAT -* Navajo -* PRC -* PST8PDT -* Pacific/Apia -* Pacific/Auckland -* Pacific/Bougainville -* Pacific/Chatham -* Pacific/Chuuk -* Pacific/Easter -* Pacific/Efate -* Pacific/Enderbury -* Pacific/Fakaofo -* Pacific/Fiji -* Pacific/Funafuti -* Pacific/Galapagos -* Pacific/Gambier -* Pacific/Guadalcanal -* Pacific/Guam -* Pacific/Honolulu -* Pacific/Johnston -* Pacific/Kiritimati -* Pacific/Kosrae -* Pacific/Kwajalein -* Pacific/Majuro -* Pacific/Marquesas -* Pacific/Midway -* Pacific/Nauru -* Pacific/Niue -* Pacific/Norfolk -* Pacific/Noumea -* Pacific/Pago_Pago -* Pacific/Palau -* Pacific/Pitcairn -* Pacific/Pohnpei -* Pacific/Ponape -* Pacific/Port_Moresby -* Pacific/Rarotonga -* Pacific/Saipan -* Pacific/Samoa -* Pacific/Tahiti -* Pacific/Tarawa -* Pacific/Tongatapu -* Pacific/Truk -* Pacific/Wake -* Pacific/Wallis -* Pacific/Yap -* Poland -* Portugal -* ROC -* ROK -* Singapore -* Turkey -* UCT -* US/Alaska -* US/Aleutian -* US/Arizona -* US/Central -* US/East-Indiana -* US/Eastern -* US/Hawaii -* US/Indiana-Starke -* US/Michigan -* US/Mountain -* US/Pacific -* US/Pacific-New -* US/Samoa -* UTC -* Universal -* W-SU -* WET -* Zulu \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/installation/checklist.md b/website/docs/docs/on-premises-2x/installation/checklist.md deleted file mode 100644 index 3c6f148e..00000000 --- a/website/docs/docs/on-premises-2x/installation/checklist.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Installation checklist ---- - -## 1. PactFlow license file - -The PactFlow on-premises version requires a license file to run. You should have received this from us during the -on-boarding process. If not, please contact your Account Manager. - -## 2. Run Docker Compose example - -See the [Docker Compose example](/docs/on-premises-2x/docker-compose-example). - -## 3. Choose the domain name for your PactFlow On-Premises application - -eg. `https://pactflow.mycompany.com` - -You will need this for the next step. - -## 4. Configure identity provider - -Configure the PactFlow On-Premises application in your identity provider. See the [Azure Active Directory](/docs/on-premises-2x/authentication/saml#configuring-azure-active-directory) documentation. - -## 5. Deploy PactFlow On-Premises application stack - -* Configure the [PactFlow Docker image](/docs/on-premises-2x/docker-image-registry) to be pulled from Quay. -* Use the [environment variable templates](/docs/on-premises-2x/environment-variables/templates) to create the appropriate deployment configuration artifacts for the PactFlow Docker image (eg. Cloudformation template, Helm chart etc.) -* Ensure the [compute resources](/docs/on-premises-2x/system-requirements) have the appropriate specifications. -* Create a [PostgreSQL database](/docs/on-premises-2x/database) -* Setup a [Redis cache](/docs/on-premises-2x/redis) -* Ensure the [network](/docs/on-premises-2x/network-configuration) is configured appropriately. -* Ensure the [logs](/docs/on-premises-2x/logging) are forwarded to a log aggregation service. -* Make sure the [license file](/docs/on-premises-2x/license) is mounted into the running containers. -* Ensure you have [load tested](load-testing) the system and have confidence the system can handle your baseline load, and can scale with increased demand. - -## 6. Setup database cleaning - -Setup [database cleaning](/docs/on-premises-2x/maintenance/database) to ensure optimal PactFlow performance and reliability. - -:::warning this step is not optional -Failure to enable database cleaning is likely to result in a gradual decline in system performance and, eventually, query timeouts and system failure. -::: - diff --git a/website/docs/docs/on-premises-2x/installation/load-testing.md b/website/docs/docs/on-premises-2x/installation/load-testing.md deleted file mode 100644 index 3fcf7835..00000000 --- a/website/docs/docs/on-premises-2x/installation/load-testing.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Load Testing ---- - - -# Load testing - -Load testing is an important part of installation, it helps to give confidence that the system is setup and configured to scale with the needs of the organisation. - -It also helps us to identify the key scaling properties - e.g. is it CPU, I/O or network bound - in order to tune autoscaling, metrics and alarms. - -## Calculating base usage - -There is no easy answer on how many requests per second should the system be able to handle, but the simplest approach is to base it off the number of CI builds and releases you perform on your busiest day. - -If you can imagine a histogram of these builds with time as the x-axis, and number of builds on the y-axis, you can take the peak number and use that as your baseline "concurrent users" metric. - -A starting point of being able to handle 10 concurrent users (builds) is a good start, as each build will usually perform several API calls. - -It's worth pointing out that each real CI build will usually span multiple minutes, and only a fraction of the build time will be dedicated Pact and communicting with PactFlow directly. - -## Running a load test - -We have created a tool that you can use to run a load test on your platform. - -Using the metric from above, the load testing tool maps to a random scenario (which may perform multiple API calls to PactFlow), attempting to create a more realistic system load. - -You can download and run the tool from: https://github.com/pactflow/pactflow-load-test \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md b/website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md deleted file mode 100644 index a006ccf0..00000000 --- a/website/docs/docs/on-premises-2x/installation/migrating-from-pact-broker.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: migrating -title: Migrating from Pact Broker ---- - -# Migrating from Pact Broker - -If you have previously used the open source Pact Broker with a PostgreSQL database it is possible to migrate that data to PactFlow, keeping everything and making it available in PactFlow. The migration process uses the existing Pact Broker database. Database migrations are then performed to add additional tables and data used for PactFlow features. - -:::note -Migration is only supported for a Pact Broker running a PostgreSQL database. -::: - -## Single Pact Broker instance - -Follow existing [set up documentation](/docs/on-premises-2x) for setting up your new PactFlow. When you reach the section regarding setting up a [Database](/docs/on-premises-2x/database) follow these steps to migrate instead of creating a new database: - -1. Re-use your existing Pact Broker environment variables, updating the names to read `PACTFLOW_*` instead of `PACT_BROKER_*`. A full list of the PactFlow environment variables can be found [here](/docs/on-premises-2x/environment-variables). - -:::tip - -It is crucial that all `PACT_BROKER_DATABASE_*` environment variables are renamed to `PACTFLOW_DATABASE_*` while their `values` remain the same. This is because your existing Pact Broker database will be used, and updated for use with PactFlow as part of the process. -::: - -2. If you previously set the environment variables `PACT_BROKER_AUTO_MIGRATE_DB` and `PACT_BROKER_AUTO_MIGRATE_DB_DATA` remove these and replace them with a new environment variable named `PACTFLOW_DATABASE_AUTO_MIGRATE`. Set its value to `true`. This environment variable will allow your existing database to be updated with the required structures and data to support PactFlow, and maintain any existing data. -You do not need to add the new variable if you did not previously set `PACT_BROKER_AUTO_MIGRATE_DB` and `PACT_BROKER_AUTO_MIGRATE_DB_DATA`. - -4. When the PactFlow instance starts up the migrations will run automatically. The migrations can be run manually instead if needed. See details [here](/docs/on-premises-2x/upgrading/database-migrations) - -## Multiple Pact Broker instances - -It is not currently possible to combine multiple Pact Broker databases into a single database for use with PactFlow. Instead one Pact Broker database can be used in the migration, and the others ran in parallel with the new PactFlow instance until sufficient data is transferred. The PactFlow instance must contain all production versions of all services used in the contract test before it can safely take over all 'can-i-deploy' checks. - -The recommended steps are as follows: - -1. Select one of the Pact Broker databases to update and use going forwards. -2. Follow instructions above to set up PactFlow using this database. -3. The Pact Broker instances that was used in the upgrade process and be decommissioned, as the database and its contents are now available in PactFlow. -4. Run the PactFlow instance and any other existing Pact Broker instances in parallel. Duplicate the pact publication and pact verification tasks in your pipeline. The duplicated task should use the new PactFlow instance details. In this way all new data can gradually added to PactFlow while ensuring `can-i-deploy` still has access to production versions of all services. -5. Continue to run PactFlow and Pact Brokers in parallel. Once the PactFlow instance contains all the `production` versions for all the services used in the contract tests the old Pact Broker instances can be safely decommissioned. This will allow PactFlow to be the sole source of data for 'can-i-deploy' -6. Clean up any code and API calls that were used to run PactFlow and existing Pact Brokers in parallel. The pact publication and pact verification steps in your pipeline that used the old Pact Brokers can be removed. diff --git a/website/docs/docs/on-premises-2x/license.md b/website/docs/docs/on-premises-2x/license.md deleted file mode 100644 index 97640294..00000000 --- a/website/docs/docs/on-premises-2x/license.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: License file ---- - -The PactFlow on-premises version requires a license file to run. You should have received this from us during the -on-boarding process. If not, please contact your Account Manager. - -The license file needs to be mounted into the docker container at the `/home/pactflow-onprem.lic` path. This can -be done by either using a volume mount or building a new image with the license file in it. - -## Volume mounting the license file - -Refer to the docker documentation on using [volumes](https://docs.docker.com/storage/volumes/). - -For an example, you can use the docker CLI `-v` parameter to mount the license file (i.e. if the license file -is stored at `/opt/pactflow/pactflow-onprem.lic` on your server, then `-v /opt/pactflow/pactflow-onprem.lic/pactflow-onprem.lic:/home/pactflow-onprem.lic` will mount it). - -## Building a new image with the license file in - -You can also create a new docker file with the license file baked in. Here is an example docker build file that does that: - -```dockerfile -ARG ONPREM_IMAGE -FROM ${ONPREM_IMAGE} - -COPY --chown=app:app pactflow-onprem.lic $APP_HOME/../pactflow-onprem.lic -``` - -This can then be built with the following docker command: - -```console -$ docker build . --build-arg ONPREM_IMAGE=quay.io/pactflow/enterprise:1.10.0 -``` - -## Customising the location of the license file - -If mounting the license file in `/home` is not desirable, you can specify a custom directory using the `RG_LIC_PATH` environment variable. - -For example, to change the path to `/opt/pactflow/pactflow-onprem.lic` you would set the environment variable in the container to `RG_LIC_PATH=/opt/pactflow/`. - -## License enforcement - -The license provided encodes your designated subscription limits, such as your allocated number of users and the expiration date of your subscription. These limits are enforced by the application at runtime. In the event you have an invalid or incompatible license, the system will not boot and will provide an error in your system log file - - - -In the event the license does expire, the [health check endpoint](/docs/on-premises-2x#healthcheck-endpoint) will continue to remain operational. - -## FAQ - -### What happens when I reach my licenses user limit? - -New users will be unable to login and will receive a message indicating the user limit has been reached. - -You can rectify this by: - -1. Disabling any users that no longer require access to Pactflow -2. Upgrading your subscription to allow more users - -### What happens when my license expires? - -Well ahead of your license expiration you will be contacted from a SmartBear representative to help with ensuring a smooth transition from your expiring license to a new one. - -Pactflow will provide in-application notices when there are 30 days or less until expiry of the subscription. The notices will be displayed on both the login screen and in the footer. - -When the subscription reaches its end date, if the license has not been replaced you will lose access to Pactflow and the system will cease to function (with the exception of the [health check endpoint](/docs/on-premises-2x#healthcheck-endpoint)). diff --git a/website/docs/docs/on-premises-2x/logging.md b/website/docs/docs/on-premises-2x/logging.md deleted file mode 100644 index fca9cc15..00000000 --- a/website/docs/docs/on-premises-2x/logging.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Logging ---- - -## Output - -PactFlow application logs are sent to the standard output stream of the Docker container, with the expectation that the container orchestration service will collect and forward them to a log aggregation service. Both the UI and App logs will be interspersed here. They are distinguishable by the `application` property. UI will be `pactflow-ui` and API will be `pactflow-application`. - -## Format - -The log format is JSON. - -## Level - -The default log level is `INFO`. This can be changed by setting the [PACTFLOW_LOG_LEVEL](environment-variables#pactflow_log_level) environment variable. diff --git a/website/docs/docs/on-premises-2x/maintenance/database.md b/website/docs/docs/on-premises-2x/maintenance/database.md deleted file mode 100644 index ad6cbd9b..00000000 --- a/website/docs/docs/on-premises-2x/maintenance/database.md +++ /dev/null @@ -1,274 +0,0 @@ ---- -title: Database ---- - - - -## Automatic data clean up - -:::note -Automatic data clean up is available in PactFlow On-Premises version 1.23.0 and later. -::: - -Performance can degrade when too much data accumulates in the PactFlow database. Fortunately, a lot of the data in a PactFlow instance is "unreachable" and can be removed without affecting the way it operates functionally, as generally speaking, the application (pacticipant) versions that are referenced in the verification and can-i-deploy tasks are a very small subset of the total published dataset. - -### Categories of removable data - -* Overwritten data for application versions - * Overwritten consumer contracts: these are created when a consumer contract is published with the same consumer version but different content from a previous publication - it shouldn't happen if following best practice, and there is a configuration option to stop this occurring, but such data may exist in older PactFlow instances. - * Duplicate verifications: these are created when verification results for the same pact version content are published by the same provider version multiple times - this can happen quite often under normal operation. -* Historical webhook execution data. -* Old or superseded (ie. versions that are not the latest for their branch/tag) application versions and their associated tags/pacts/verifications/webhooks. - -### How the application version cleaning works - -To ensure that the data that is still in use is not deleted, a list of "keep" selectors must be configured to specify which application versions (and associated data) should be kept. Any application version not selected by one or more of the keep selectors will (eventually) be deleted. To ensure that the clean up task itself does not impact the performance of the Broker, a limit is placed on the number of application versions that will be deleted at one time. The task will first identify all the application versions to keep, exclude those records, and then delete the oldest \[configurable number\] of application versions and their associated contracts, verifications, tags, webhook executions, and any orphan contract versions. - -### Understanding the "keep" selectors - -The keep selectors operate in a very similar way to the [consumer version selectors](https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/) used during verification. Each selector can have the following properties: - -* `pacticipant`: the name of the pacticipant -* `branch`: the name of the branch as a string to indicate a particular branch, or a boolean `true` to indicate "any version associated with a branch" -* `tag`: the name of the tag as a string to indicate a particular tag, or a boolean `true` to indicate "any version with a tag" -* `latest`: if `true`, then the latest version matching the other selection properties is specified. If `false` or omitted, all versions matching the other selection properties are specified. -* `mainBranch`: if set to true, specifies all versions that belong to the pacticipant's configured main branch. -* `deployed`: if set to true, specifies all currently deployed pacticipant versions -* `released`: if set to true, specifies all released pacticipant versions that are currently in support -* `max_age`: the number of days since it was created, as an integer, for which to keep the application version. - -The `pacticipant` and `max_age` property may be used in combination with the other tags. The `max_age` and `latest` keys cannot be used together. - -:::note - -The selectors `{ "deployed": true }` and `{ "released": true }` will automatically be added to the keep selectors, meaning that all versions that have ever been deployed or released will be kept. - -::: - -#### Examples - -* keep all versions on the main branch of each pacticipant that are less than 30 days old: `{ "max_age": 30, "mainBranch": true }` -* keep the latest version from each pacticipant's branch: `{ "branch": true, "latest": true }` -* keep the latest version for each pacticipant/tag: `{ "latest": true, "tag": true }` -* keep all versions less than 30 days old: `{ "max_age": 30 }` -* keep all currently deployed versions: `{ "deployed": true }` -* keep all released and currently supported versions: `{ "released": true }` -* keep all versions for Foo app: `{ "pacticipant": "Foo" }` -* keep the latest version for each pacticipant: `{ "latest": true }` -* keep all versions tagged "develop" for Foo app: `{ "pacticipant": "Foo", "tag": "develop" }` - -The selectors combine by "OR", meaning that a version is kept if it matches any of the selectors. So `[{ "max_age": 30 }, { "branch": true, "latest": true }, { "deployed": true }]` would mean "keep every version younger than 30 days old, or is the latest version for its branch, or is currently deployed". - -#### Recommended starting configuration for keep selectors - -The following are the default keep selectors specified in the clean tool, and they are a good place to start. (Remember, only one of the selectors needs to be matched to keep the version). - -* Keep all versions under 90 days old - `{ "max_age": 90 }` -* Keep all versions that are the latest for their branch - `{ "branch": true, "latest": true }` -* Keep all versions that are the latest for their tag - `{ "tag": true, "latest": true }` -* Keep all the currently deployed versions - `{ "deployed": true }` -* Keep all the released and currently supported versions - `{ "released": true }` -* Keep the latest version for every pacticipant - `{ "latest": true }` - -Notes: - -* When you deploy an application to production, the relevant pacticipant version needs to be recorded as deployed in PactFlow, so you need to ensure that you keep any version that you're likely to deploy (or rollback to). Specify a `max_age` value that is at minimum the number of days it takes between a commit being created and that commit being deployed (with a very comfortable margin of error) and any branch that you deploy from. A reasonable max_age value might be 90 days for the `main` branch. eg. `{"max_age": 90, "mainBranch": true }` -* If an application is not under active development, a selector that keeps versions by age limit might not actually select any versions. To ensure that we don't lose those critical "latest" versions for our main line of development or our deployed environments, add a selector with `{"mainBranch": true, "latest": true }`, or keep the latest version from each branch by specifying `{"branch": true, "latest": true }`. - -### Execution - -The database clean tool comes built into the PactFlow On-Premises Docker image. The Docker container should be executed using a tool like Kubernetes CronJob or AWS Batch. It should run on a regular schedule (eg. daily) and be configured to delete at least as many application versions as are expected to be created between each clean execution. - -:::note - -The clean task must use the same Docker image tag as the currently running PactFlow application. - -::: - -To execute the clean task, run the Docker container with the appropriate environment variables (documented below), the PactFlow license mounted, and the entrypoint set to `db-clean`. - -eg. -```sh -docker run --rm \ - --entrypoint db-clean \ - --volume ./pactflow-onprem.lic:/home/pactflow-onprem.lic \ - --env PACTFLOW_DATABASE_URL="..." \ # appropriate environment variables here - quay.io/pactflow/enterprise -``` - -This example Docker Compose file shows an example configuration. It can be run by saving the contents as `docker-compose.yml` and then running `docker compose up` in the same directory. Note that a PactFlow license file is required to run the PactFlow container. - -There will be no data in the database to delete, but the logs will show that the clean process has run. - -```yml -version: "3" - -services: - postgres: - image: postgres:13-alpine - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - POSTGRES_DB: postgres - - clean: - image: quay.io/pactflow/enterprise - depends_on: - - postgres - environment: - PACTFLOW_DATABASE_URL: "postgres://postgres:password@postgres/postgres" - PACTFLOW_DATABASE_SSLMODE: "disable" # overriding default value of "require" for demo only - "disable" should never be used in production - PACTFLOW_DATABASE_CLEAN_DELETION_LIMIT: "500" - PACTFLOW_SQL_LOG_WARN_DURATION: "60" - # Keep the latest version for every pacticipant branch, and all versions less than 30 days old, and anything deployed or released - PACTFLOW_DATABASE_CLEAN_KEEP_VERSION_SELECTORS: "[{ \"branch\": true, \"latest\": true }, {\"max_age\": 30 }, {\"deployed\": true }, {\"released\": true }]" - PACTFLOW_LOG_LEVEL: "INFO" - PACTFLOW_SQL_LOG_LEVEL: "DEBUG" - entrypoint: dockerize - # There will be no data in the database to delete, but the logs will show that the clean process has run - command: -wait tcp://postgres:5432 sh -c 'db-migrate && db-clean' - volumes: - - ./pactflow-onprem.lic:/home/pactflow-onprem.lic - -``` - -#### Initial clean strategy - -If you have a very large database, and you are just now enabling the clean, the initial clean up might take some time. To ensure that the clean does not have an impact on the performance of PactFlow, it is recommended to set the cron schedule to something quite regular for the first day (eg. every 2 minutes), and set the clean limit quite low (eg. 100). Once the task has stopped deleting any more records, set the schedule back to something like once/twice a day, and make sure the clean limit is higher than the number of new versions you expect in that time period. - -### Configuration - - - - -#### PACTFLOW_LOG_LEVEL - -The PactFlow application log level - -**Required:** false
-**Default:** `INFO`
-**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
- -#### PACTFLOW_LOG_FORMAT - -The PactFlow application log format - -**Required:** false
-**Default:** `json`
-**Allowed values:** `json`, `default`, `color`
-**More information:** https://github.com/rocketjob/semantic_logger/tree/master/lib/semantic_logger/formatters
- -#### PACTFLOW_SQL_LOG_LEVEL - -The log level that will be specified when the SQL query statements are logged. - -**Required:** false
-**Default:** `NONE`
-**Allowed values:** `NONE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
- -#### PACTFLOW_DATABASE_URL - -The fully qualifed database connection string. If using Postgres on RDS with IAM authentication, the scheme must be `postgresiam` and the port must also be set. - -**Required:** if separate host, name, username, password environment variables are not set
-**Example:** `postgresql://username:password@host:port/database`
- -#### PACTFLOW_DATABASE_ADAPTER - -The database adapter to use. Use `postgresiam` when using Postgres on RDS with IAM authentication (rather than username/password authentication). - -**Required:** false
-**Default:** `postgres`
-**Allowed values:** `postgres`, `postgresiam`
- -#### PACTFLOW_DATABASE_USERNAME - -The database username - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -#### PACTFLOW_DATABASE_PASSWORD - -The database password - -**Required:** if PACTFLOW_DATABASE_URL is not set, unless using Postgres on RDS with IAM authentication
- -#### PACTFLOW_DATABASE_HOST - -The database host - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -#### PACTFLOW_DATABASE_PORT - -The database port - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -#### PACTFLOW_DATABASE_NAME - -The database name - -**Required:** if PACTFLOW_DATABASE_URL is not set
- -#### PACTFLOW_DATABASE_SSLMODE - -The Postgresql ssl mode. Note, if using Postgres on AWS RDS with IAM authentication, this must be `require`. - -**Required:** false
-**Default:** `require`
-**Allowed values:** `disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full`
-**More information:** https://ankane.org/postgres-sslmode-explained
- -#### PACTFLOW_DATABASE_CLEAN_DELETION_LIMIT - -Only required when running the `db-clean` entrypoint in the PactFlow Docker container. -The maximum number of records to delete at a time from each of the (categories of removable data)[#categories-of-removable-data]. -Should be set to a number higher than the expected number of application versions that will be created between each clean, -but not so high that it will impact on the performance of the application while it is running. You may need to run tests find the optimal number to use in your environment. - -**Required:** false
-**Default:** `500`
- -#### PACTFLOW_DATABASE_CLEAN_KEEP_VERSION_SELECTORS - -Only required when running the `db-clean` entrypoint in the PactFlow Docker container. -A JSON string containing a list of the "keep" selectors described in (Understanding the keep selectors)[#understanding-the-keep-selectors]. -To ensure the integity of the PactFlow data, the selectors `{ "deployed": true }` and `{ "released": true }` will be automatically added to the selector list if they are not specified. -Remember to escape the quotes if necessary in your configuration files. - -**Required:** false
-**Default:** `[{ "max_age": 90 }, { "branch": true, "latest": true }, { "tag": true, "latest": true }, { "deployed": true }, { "released": true }, { "latest": true }]`
- -#### PACTFLOW_DATABASE_CLEAN_OVERWRITTEN_DATA_MAX_AGE - -Only required when running the `db-clean` entrypoint in the PactFlow Docker container. -The maximum number of days to keep "overwritten" data as described in (categories of removable data)[#categories-of-removable-data] - -**Required:** false
-**Default:** `7`
- -#### PACTFLOW_DATABASE_CLEAN_DRY_RUN - -Only required when running the `db-clean` entrypoint in the PactFlow Docker container. -When set to `true`, the `db-clean` process will not delete any data, but will instead log the data that would be deleted if dry run was not enabled. -Use this to test that the container is configured correctly. - -**Required:** false
-**Default:** `false`
-**Allowed values:** `true`, `false`
- -#### AWS_REGION - -Required for running Postgres on RDS with IAM authentication. This must be set to the AWS region where the RDS database instance is running. - -**Required:** false
- - - diff --git a/website/docs/docs/on-premises-2x/network-configuration.md b/website/docs/docs/on-premises-2x/network-configuration.md deleted file mode 100644 index 4c0e2fa3..00000000 --- a/website/docs/docs/on-premises-2x/network-configuration.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Network configuration ---- - -## Firewall Configuration - -### Inbound - -#### Application port - -The PactFlow application runs on port `9292` by default. This can be configured by setting the [PACTFLOW_HTTP_PORT](/docs/on-premises-2x/environment-variables#pactflow_http_port) environment variable. - -### Outbound - -#### Webhooks - -The PactFlow application provides [webhooks](https://docs.pact.io/pact_broker/advanced_topics/webhooks) that are primarily designed for triggering builds in the **CI systems** of integrated applications. They may also be used to provide status updates to **source control systems** (eg. Github) or **team chat software** (eg. Slack). To enable PactFlow to operate correctly, network access should be configured to systems that are likely to be the targets of these webhooks. - -The host names of these services should also be whitelisted in the [PACTFLOW_WEBHOOK_HOST_WHITELIST](/docs/on-premises-2x/environment-variables/#pactflow_webhook_host_whitelist) environment variable. - -## Certificate and TLS termination - -The recommended configuration is to terminate TLS at the load balancer, communicating over HTTP to the target application servers, which in turn communicate over local sockets to applications within the container. - -If you would like to run PactFlow in a TLS-everywhere configuration, modify the HAProxy configuration file (`/tmp/haproxy.cfg`) to bind a certificate to the `frontend`, and ensure the certificate has been appropriately mounted/added to the container. - -Refer to the [HAProxy documentation](https://www.haproxy.com/documentation/haproxy-configuration-tutorials/security/ssl-tls/client-side-encryption/) for further information. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.10.0.md b/website/docs/docs/on-premises-2x/releases/1.10.0.md deleted file mode 100644 index 90460c95..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.10.0.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 1.10.0 ---- - -## Release date - -31 March 2021 - -## Notes - -* The on-premises version of PactFlow requires a license file to run. Contact your Account Manager if you have not received one. - -## Features - -* Update OSS broker to 2.79.0 -* Generate downloadable example projects for consumers and providers - diff --git a/website/docs/docs/on-premises-2x/releases/1.11.0.md b/website/docs/docs/on-premises-2x/releases/1.11.0.md deleted file mode 100644 index 9903ba26..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.11.0.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: 1.11.0 ---- - -## Release date - -5 July 2021 - -## Features - -- Allow a banner to be configured and displayed post-login. -- Support [user preferences](/docs/user-interface/settings/preferences#personal-preferences). -- Support [system preferences](/docs/user-interface/settings/preferences#system-preferences). -- Support [PACTFLOW_DATABASE_PORT](/docs/on-premises-2x/environment-variables#pactflow_database_port) environment variable. -- Allow API token expiry to be configured. -- Show warning in UI when API token is due to expire. -- Support database field level encryption of API tokens. -- Support [ignoring specified applications](https://docs.pact.io/pact_broker/client_cli/readme#can-i-deploy) when using can-i-deploy. -- Allow [secrets](/docs/user-interface/settings/secrets) and [webhooks](/docs/user-interface/settings/webhooks) to be assigned to, and managed by, a specific team. -- Improve [pending pacts and WIP pacts](https://github.com/pact-foundation/pact_broker/pull/432) logic. -- Add [pactbroker.azureDevOpsVerificationStatus webhook parameter](/docs/user-interface/settings/webhooks#pactflow). -- Validate that well formed JSON or YAML is used when publishing Base64 encoded provider contracts. -- Disallow the deletion of predefined roles. -- Add endpoint to [reset role/permissions assignments](/docs/permissions/predefined-roles#resetting-permissions-for-predefined-roles) for predefined roles. -- Deprecate `system:preference:read` permission. All logged in users may now read the system preferences. -- Allow team administrators to be assigned to teams. Team administrators can add and remove users and applications from teams. -- Add [`system_account:manage:team`](/docs/permissions#system_accountmanageteam) permission to allow team users to view/regenerate the API tokens for system account users that are assigned to their team. -- Update default permissions assigned to predefined roles to use [team scoped permissions](/docs/permissions/predefined-roles#user) where ever applicable. -- Renamed "Test Maintainer" role to ["User"](/docs/permissions/predefined-roles#user) for new installations. - -## Fixes - -- Ensure the SAML provider base URL is derived correctly when the login endpoint is specified in the metadata, not an environment variable -- Correctly record which SAML provider was used to log in when multiple SAML providers are configured -- Ensure api token values are not show in debug logging - -## Migration notes - -- If not already set, the `PACTFLOW_BASE_URL` should be set to mitigate cache poisoning vulnerabilities. -- The `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY` environment variable has been renamed to `PACTFLOW_MASTER_ENCRYPTION_KEY`. The old name will continue to work, but please update your configuration to avoid warnings. Do not change the value of this key. -- Steps to enable API token database field level encryption: - - - Please read the relevant documentation for each of the following environment variables, and update your configuration with the appropriate values. - - [`PACTFLOW_MASTER_ENCRYPTION_KEY`](/docs/on-premises-2x/environment-variables#pactflow_master_encryption_key) - renamed from `PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY`. Do not change the value of this key. - - [`PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED`](/docs/on-premises-2x/environment-variables#pactflow_api_token_encryption_enabled) - must be set to "true" - - [`PACTFLOW_API_TOKEN_IV`](/docs/on-premises-2x/environment-variables#pactflow_api_token_iv) - a random value must be assigned as per the documentation. - - Restart the PactFlow application. The API tokens will be encrypted during start up once the `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` environment variable has been set to true. - - Verify that the API tokens have been encrypted by running the SQL: - - ```sql - SELECT COUNT(*) FROM saas_api_tokens; - SELECT COUNT(*) FROM saas_api_tokens WHERE encrypted_value IS NOT NULL; - ``` - - Both counts should be the same. - - - Verify that users still have access to the API using their existing tokens executing the following curl command, or making the same request with Postman or equivalent: - - ```bash - curl -v https://{YOUR_PACTFLOW_DOMAIN} \ - -H "Authorization: Bearer {EXISTING_TOKEN_VALUE}" - ``` - - The response should be a 200 OK with a JSON body. - - - Once it has been confirmed that the now-encrypted API tokens are working correctly, please clear the unencrypted values from the database using the following SQL: - - ```sql - UPDATE saas_api_tokens SET value = NULL; - ``` - - - Once API token encryption has been enabled and the unencrypted values removed, encryption cannot be disabled again. diff --git a/website/docs/docs/on-premises-2x/releases/1.11.1.md b/website/docs/docs/on-premises-2x/releases/1.11.1.md deleted file mode 100644 index ca99878c..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.11.1.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.11.1 ---- - -## Release date - -9 July 2021 - -## Fixes - -* Fix runtime error generating validation message for can-i-deploy diff --git a/website/docs/docs/on-premises-2x/releases/1.12.0.md b/website/docs/docs/on-premises-2x/releases/1.12.0.md deleted file mode 100644 index b3350c04..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.12.0.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: 1.12.0 ---- - -## Release date - -21 September 2021 - -## Features - -* Add support for [PACTFLOW_SAML_ALLOWED_CLOCK_DRIFT](/docs/on-premises-2x/environment-variables#pactflow_saml_allowed_clock_drift) -* Validate encryption master key on startup -* Allow the default role and team to be configured in the system preferences -* Add [Guest role](/docs/permissions/predefined-roles#guest). diff --git a/website/docs/docs/on-premises-2x/releases/1.13.0.md b/website/docs/docs/on-premises-2x/releases/1.13.0.md deleted file mode 100644 index c1796a09..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.13.0.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.13.0 ---- - -## Release date - -23 September 2021 - -## Features - -* Add support for [PACTFLOW_HTTP_LOGGING_ENABLED](/docs/on-premises-2x/environment-variables#pactflow_http_logging_enabled) diff --git a/website/docs/docs/on-premises-2x/releases/1.13.1.md b/website/docs/docs/on-premises-2x/releases/1.13.1.md deleted file mode 100644 index 77d17db7..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.13.1.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.13.1 ---- - -## Release date - -27 September 2021 - -## Fixes - -* Correct missing default value for the database adapter which stops the application from starting up when the individual database connection attributes are used. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.0.md b/website/docs/docs/on-premises-2x/releases/1.14.0.md deleted file mode 100644 index 9672fb4c..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.0.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: 1.14.0 ---- - -## Release date - -2 December 2021 - -## Features - -- Add support for publishing pacts and verification results with [branches](https://docs.pact.io/pact_broker/branches). -- Add support for recording [deployments and releases](https://docs.pact.io/pact_broker/recording_deployments_and_releases). -- Add [global](/docs/permissions#deployment_and_releaserecord) and [team](/docs/permissions#deployment_and_releaserecordteam) scoped permissions for recording deployments and releases. -- Add support for the new [`contract_requiring_verification_published` webhook](https://docs.pact.io/blog/2021/10/11/contract-requiring-verification-published-webhook-event). -- Add support for disabling [dangerous pact modification](https://docs.pact.io/pact_broker/configuration/settings#allow_dangerous_contract_modification). -- Added support for the following configuration settings: - - [PACTFLOW_DATABASE_CONNECTION_VALIDATION_TIMEOUT](/docs/on-premises-2x/environment-variables#pactflow_database_connection_validation_timeout) - - [PACTFLOW_ALLOW_DANGEROUS_CONTRACT_MODIFICATION](/docs/on-premises-2x/environment-variables#pactflow_allow_dangerous_contract_modification) - - [PACTFLOW_USE_FIRST_TAG_AS_BRANCH](/docs/on-premises-2x/environment-variables#pactflow_use_first_tag_as_branch) - - [PACTFLOW_CREATE_DEPLOYED_VERSIONS_FOR_TAGS](/docs/on-premises-2x/environment-variables#pactflow_create_deployed_versions_for_tags) - - [PACTFLOW_USE_HAL_BROWSER](/docs/on-premises-2x/environment-variables#pactflow_use_hal_browser) - -## Fixes - -- Do not error when attempting to add a user or application to the default team as configured in the system preferences, and the default team no longer exists. - -## Migration notes - -- Update the PactFlow Docker image tag to `1.14.0` and redeploy the PactFlow application infrastructure. -- There are no configuration changes to be made. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.1.md b/website/docs/docs/on-premises-2x/releases/1.14.1.md deleted file mode 100644 index 090f470f..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.1.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.14.1 ---- - -## Release date - -7 December 2021 - -## Fixes - -* Display correct icon for pacts with status "failed_pending". diff --git a/website/docs/docs/on-premises-2x/releases/1.14.2.md b/website/docs/docs/on-premises-2x/releases/1.14.2.md deleted file mode 100644 index c8cd5431..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.2.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.14.2 ---- - -## Release date - -31 January 2022 - -## Fixes - -* Fix error raised when setting [`database_connection_validation_timeout`](/docs/on-premises-2x/environment-variables#pactflow_database_connection_validation_timeout). - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.3.md b/website/docs/docs/on-premises-2x/releases/1.14.3.md deleted file mode 100644 index 84c8252d..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.3.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.14.3 ---- - -## Release date - -1 February 2022 - -## Fixes - -* Fixed CVE-2021-23807 - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.4.md b/website/docs/docs/on-premises-2x/releases/1.14.4.md deleted file mode 100644 index 1e1c29d9..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.4.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 1.14.4 ---- - -## Release date - -3 February 2022 - -## Fixes - -* Updated Docker base image to `ruby:2.7.5-alpine3.13` -* Fixed `disable_ssl_verification` setting which was not being honoured in the webhook background process. -* Fixed `webhook_certificates` setting which was not being honoured in the webhook background process. - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.5.md b/website/docs/docs/on-premises-2x/releases/1.14.5.md deleted file mode 100644 index c574b88e..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.5.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.14.5 ---- - -## Release date - -7 February 2022 - -## Fixes - -* Fix CVE-2021-3918 - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.6.md b/website/docs/docs/on-premises-2x/releases/1.14.6.md deleted file mode 100644 index 9b4f3056..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.6.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: 1.14.6 ---- - -## Release date - -10 February 2022 - -## Fixes - -* Fix CVE-2018-20677 (bootstrap) -* Fix CVE-2018-20676 (bootstrap) -* Fix CVE-2018-14041 (bootstrap) -* Fix CVE-2021-23358 (underscore) -* Fix CVE-2021-31799 (rdoc) - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.7.md b/website/docs/docs/on-premises-2x/releases/1.14.7.md deleted file mode 100644 index b038761a..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.7.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.14.7 ---- - -## Release date - -11 February 2022 - -## Fixes - -* Add missing custom token params to JWT retrieval call. - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.14.8.md b/website/docs/docs/on-premises-2x/releases/1.14.8.md deleted file mode 100644 index 82bad596..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.14.8.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.14.8 ---- - -## Release date - -11 February 2022 - -## Fixes - -* Parse teams and roles from access token instead of id token. - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.15.0.md b/website/docs/docs/on-premises-2x/releases/1.15.0.md deleted file mode 100644 index 6d082f59..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.15.0.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: 1.15.0 ---- - -:::caution NOTE -Docker 19.03 support is dropped with this release. -::: - -## Release date - -15 February 2022 - - -## Migration notes - -This release upgrades the base image from alpine3.13 to alpine3.15. **Please note that Docker 19.03 is no longer supported** as it is EOL and alpine3.15 requires Docker 20.10.0 or later (see point 2 in the `faccessat2` section of the [Alpine 3.14 release notes](https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2) for more information). - -If you are already running PactFlow on Docker 20.10.0 or later, no action is required. Please update your PactFlow image version as normal. If you are running a version of Docker older than 20.10.0, please upgrade your Docker version to 20.10.0 or later before upgrading to PactFlow 1.15.0. diff --git a/website/docs/docs/on-premises-2x/releases/1.16.0.md b/website/docs/docs/on-premises-2x/releases/1.16.0.md deleted file mode 100644 index 8a4727ab..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.16.0.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.16.0 ---- - -## Release date - -18 February 2022 - -## Features - -* Added support for using AWS IAM authentication between the PactFlow application and an RDS Postgres instance. See documentation [here](/docs/on-premises-2x/database#aws-iam-authentication). - -## Migration notes - -N/A. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.17.0.md b/website/docs/docs/on-premises-2x/releases/1.17.0.md deleted file mode 100644 index 7ea5d873..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.17.0.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 1.17.0 ---- - -## Release date - -25 February 2022 - -## Features - -* Added support for server side session inactivity timeout, configurable via the environment variable [`PACTFLOW_SESSION_INACTIVITY_TIMEOUT`](/docs/on-premises-2x/environment-variables#pactflow_session_inactivity_timeout) - -## Migration notes - -By default, the `PACTFLOW_SESSION_INACTIVITY_TIMEOUT` will be set to the configured value of `PACTFLOW_SESSION_LENGTH`. This effectively disables the feature, for backwards compatibility purposes. If you would like to take advantage of this new feature, set the `PACTFLOW_SESSION_INACTIVITY_TIMEOUT` to the value of your choice. If you do not wish to use this feature, no change is required. diff --git a/website/docs/docs/on-premises-2x/releases/1.17.1.md b/website/docs/docs/on-premises-2x/releases/1.17.1.md deleted file mode 100644 index 12a9f10b..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.17.1.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: 1.17.1 ---- - -## Release date - -10 March 2022 - -## Fixes - -* Upgrade busybox to fix CVE-2021-42377 -* Fix error returned when viewing OSS server side rendered UI. diff --git a/website/docs/docs/on-premises-2x/releases/1.17.2.md b/website/docs/docs/on-premises-2x/releases/1.17.2.md deleted file mode 100644 index 3dad692e..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.17.2.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.17.2 ---- - -## Release date - -28 March 2022 - -## Fixes - -* Ensure commas in database and basic auth credential configurations do not cause the values to be parsed as arrays. diff --git a/website/docs/docs/on-premises-2x/releases/1.17.3.md b/website/docs/docs/on-premises-2x/releases/1.17.3.md deleted file mode 100644 index 4785d60a..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.17.3.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.17.3 ---- - -## Release date - -12 April 2022 - -## Fixes - -* CVE-2018-25032 diff --git a/website/docs/docs/on-premises-2x/releases/1.18.0.md b/website/docs/docs/on-premises-2x/releases/1.18.0.md deleted file mode 100644 index 44d03d3e..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.18.0.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 1.18.0 ---- - - - - -## Release date - -31 May 2022 - -## Features - -* Enable [bi-directional contracts](https://pactflow.io/blog/introducing-bi-directional-contract-testing/) feature. -* Add support for monitoring with [New Relic](/docs/on-premises-2x/environment-variables#new_relic_agent_enabled). -* Require that the `PACTFLOW_BASE_URL` specifies a `https` URL (rather than `http`) unless [`PACTFLOW_REQUIRE_HTTPS`](/docs/on-premises-2x/environment-variables#pactflow_require_https) is set to false. -* Check for potential duplicate pacticipants in publish contracts endpoint. -* Timeout long running pact content diff requests. -* Improve error message when request has non UTF-8 characters. - -## Fixes - -* Matrix - fix performance issue when querying matrix with one selector -* Ensure cookie secret set via environment variable is not parsed as an array when it contains commas. -* CVE-2018-25032 -* CVE-2022-29824 -* CVE-2022-30122 - diff --git a/website/docs/docs/on-premises-2x/releases/1.19.0.md b/website/docs/docs/on-premises-2x/releases/1.19.0.md deleted file mode 100644 index 995b74c9..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.19.0.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: 1.19.0 ---- - -## Release date - -1 August 2022 - -## Features - -* Return user email to ui for user with unknown names -* Allow configuration of [max_connections](https://docs.pactflow.io/docs/on-premises-2x/environment-variables/#pactflow_database_max_connections) and [pool_timeout](https://docs.pactflow.io/docs/on-premises-2x/environment-variables/#pactflow_database_pool_timeout) - -## Fixes - -* [Correctly apply the `deployment_and_release:record:team` permission](https://github.com/pactflow/roadmap/issues/71) when recording deployments and releases. -* Gracefully handle policy check when no contracts are defined in the request to publish contracts -* Apply the integrations limit to the publish contracts endpoint -* CVE-2022-30122 CVE-2022-30123 GHSA-cgx6-hpwq-fhv5 CVE-2022-29181 GHSA-xh29-r2w5-wx8m -* Update mechanize for CVE-2022-31033 diff --git a/website/docs/docs/on-premises-2x/releases/1.19.1.md b/website/docs/docs/on-premises-2x/releases/1.19.1.md deleted file mode 100644 index be751823..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.19.1.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: 1.19.1 ---- - -## Release date - -18 August 2022 - -## Fixes - -* Show correct cross contract comparison result in Matrix UI when comparisons exist for multiple consumer pacts -* Show correct contract deletion options in kebab menu when viewing the bi-directional contract details page \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.19.2.md b/website/docs/docs/on-premises-2x/releases/1.19.2.md deleted file mode 100644 index b6e8bcc3..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.19.2.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.19.2 ---- - -## Release date - -24 August 2022 - -## Fixes - -* Correctly use default value for PACTFLOW_SQL_LOG_LEVEL when the environment variable has not been set \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.20.0.md b/website/docs/docs/on-premises-2x/releases/1.20.0.md deleted file mode 100644 index 3164c587..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.20.0.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: 1.20.0 ---- - -## Release date - -2 September 2022 - -## Features - -* Added support for [demo authentication](/docs/on-premises-2x/authentication/demo). Note: using basic auth for demonstration mode is no longer supported. - -## Fixes - -* CVE-2020-36599 -* Fixed error message "unable to load resource, as it was not found" shown on user admin page. -* When deleting an integration, ensure a provider with an OAS is not deleted if another consumer has a pact with it. -* Correctly identify database version when schema_migrations table is empty. diff --git a/website/docs/docs/on-premises-2x/releases/1.21.0.md b/website/docs/docs/on-premises-2x/releases/1.21.0.md deleted file mode 100644 index f368b014..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.21.0.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 1.21.0 ---- - -## Release date - -21 October 2022 - -## Features - -* Display license expiry notices in the UI when there are fewer than 30 days until expiry. -* Implement pending logic for provider branches. - -## Fix - -* Fix performance issue when calculating the work in progress pacts for the "pacts for verification" endpoint. diff --git a/website/docs/docs/on-premises-2x/releases/1.21.1.md b/website/docs/docs/on-premises-2x/releases/1.21.1.md deleted file mode 100644 index efb40bfd..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.21.1.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.21.1 ---- - -## Release date - -4 Nov 2022 - -## Fix - -* Fix argument error when publishing pacts diff --git a/website/docs/docs/on-premises-2x/releases/1.22.0.md b/website/docs/docs/on-premises-2x/releases/1.22.0.md deleted file mode 100644 index ecb36dbb..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.22.0.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: 1.22.0 ---- - -## Release date - -13 Feb 2023 - -## Features - -* Pagination has been added to the Pacticipant end point -* Miscellaneous performance improvements - -## Fixes - -* Fix BDC incorrectly requiring consumer to be deployed to deploy the provider -* Restrict users from changing their own roles in PactFlow API -* Restrict users from updating their own roles via bulk actions -* Restrict users without required permissions from creating and updating other users -* Add validation to ensure an environment or to tag is specified for the /can-i-deploy endpoint -* Check that request body does not contain any invalid UTF-8 characters before JSON parsing - - -## Migration notes - -N/A. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/releases/1.22.1.md b/website/docs/docs/on-premises-2x/releases/1.22.1.md deleted file mode 100644 index 56a561af..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.22.1.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 1.22.1 ---- - -## Release date - -23 Feb 2023 - -## Fixes - -* Fix error raised for clean task when one keep selector has a max age, and another keep selector has a max age and branch. -* Fix incorrect "no" response for can-i-deploy when a provider with a provider contract has multiple consumers. - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.23.0.md b/website/docs/docs/on-premises-2x/releases/1.23.0.md deleted file mode 100644 index 8cef25a7..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.23.0.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 1.23.0 ---- - -## Release date - -23 Feb 2023 - -## Features - -* Improve pre-calculation of pact/provider contract comparisons to reduce chance of missing comparison when can-i-deploy is run. -* Add db-clean entrypoint to PactFlow Docker image to support [database maintenance](/docs/on-premises-2x/maintenance/database). - -## Migration notes - -N/A. diff --git a/website/docs/docs/on-premises-2x/releases/1.23.1.md b/website/docs/docs/on-premises-2x/releases/1.23.1.md deleted file mode 100644 index e86667d6..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.23.1.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.23.1 ---- - -## Release date - -22 May 2023 - -## Fixes - -* Fix vulnerabilities diff --git a/website/docs/docs/on-premises-2x/releases/1.24.0.md b/website/docs/docs/on-premises-2x/releases/1.24.0.md deleted file mode 100644 index 7f51a04a..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.24.0.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: 1.24.0 ---- - -## Release date - -6 June 2023 - -## Features - -* Upgrade to Ruby 3.2 -* Execute missing pact/OAS comparisons asynchronously to prevent can-i-deploy HTTP requests timing out. See [blog post](https://pactflow.io/blog/resilient-builds-with-can-i-deploy-2/). -* Allow pacticipants to be searched by name using the query string `?q={term}` -* Add pagination to teams endpoint -* Compress response payloads with gzip -* Upgrade to latest swagger-mock-validator -* When comparing a pact and OAS for a bi-directional contract, select OAS response schema based on accept and request schema based on content-type headers -* When comparing a pact and OAS for a bi-directional contract, support comparisons for [Pact V4 bodies](https://github.com/pact-foundation/pact-specification/tree/version-4#bodies) rather than treating the section as JSON. - -## Fixes - -* Fix error raised when querying the matrix for an integration using bi-directional contracts with a single selector and no 'deploy to' selector (tag, environment, or branch). -* Fix error raised when updating a team with a team member that has been marked as inactive. -* SCIM - allow externalIdpId and externalIdpUsername fields to be writable in the create user endpoint, to ensure provisioned user details are correctly matched with the newly logged in user details. -* Add missing validation for the provider version branch when fetching pacts for verification, to ensure that empty strings are disallowed diff --git a/website/docs/docs/on-premises-2x/releases/1.25.0.md b/website/docs/docs/on-premises-2x/releases/1.25.0.md deleted file mode 100644 index 68542329..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.25.0.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: 1.25.0 ---- - -## Release date - -28 June 2023 - -## Features - -* Add support for negative scenarios in bi-directional contracts. When the expected response code is >= 400, request parameters, headers, body and security requirements are ignored, and the expected response schema is selected for comparison. - -## Fixes - -* Address performance issues in the dashboard when large numbers of pacticipants are present. -* Improve performance of integrations list on dashboard by using pagination. -* Improve performance of API for network diagram by updating network discovery algorithm and limiting the number of applications that are included in the diagram. -* When deleting a team, disassociate webhooks and secrets to prevent foreign key errors. - -## Migration notes - -N/A diff --git a/website/docs/docs/on-premises-2x/releases/1.26.0.md b/website/docs/docs/on-premises-2x/releases/1.26.0.md deleted file mode 100644 index 30354c2c..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.26.0.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: 1.26.0 ---- - -## Release date - -07 August 2023 - -## Features - -* Support application/problem+json error response format for all non-200 responses -* [Major version upgrade of AJV](https://docs.pactflow.io/docs/bi-directional-contract-testing/contracts/oas/changelog) from v6 to v8 and Improve support for allOf, anyOf, oneOf, including polymorphic inheritance. -* Add new SCIM role to be assigned to the System Account that is used to access the PactFlow SCIM API. - -## Fixes - -* Fix error occuring when can-i-deploy badge is requested and no version is found -* Fix incorrect decoding of pact v4 bodies -* OAS now supports `exclusiveMinimum` and `exclusiveMaximum` correctly in request and response bodies -* Fix null pointer in role users endpoint - -## Migration notes - -### SCIM role migration - -These migration steps are only relevant if the PactFlow SCIM API is in use. - -1. Identify the System Account that is being used to access the SCIM API. - * Login to PactFlow as an Administrator. - * Click the Settings icon in the top right. - * Click the `Users` link in the left menu. - * Select `System Accounts` in the drop down box above the User list. - * Identify the relevant System Account and note the name. -2. Ensure that no role called `SCIM` exists. - * From the PactFlow Settings page, click the `Roles` link. - * If a role called `SCIM` exists, click the `EDIT` button, change the name (eg. `SCIM (Deprecated)`), and click `SAVE` -3. Perform the release as normal. -4. Assign the new SCIM role to the System Account identified in step 1. - * Login to PactFlow as an Administrator. - * Click the Settings icon in the top right. - * Click the `Users` link in the left menu. - * Select `System Accounts` in the drop down box above the User list. - * Locate the relevant System Account in the list. - * Click the `...` icon at the right of the row for the relevant System Account. - * Select `Edit roles`. - * Deselect the existing role. - * Select `SCIM`. - * Click `OK` -5. If there was a custom role previously used for the SCIM System Account, delete it. - * From the PactFlow Settings page, click the `Roles` link. - * Click the `DELETE` button next to the custom role. diff --git a/website/docs/docs/on-premises-2x/releases/1.27.0.md b/website/docs/docs/on-premises-2x/releases/1.27.0.md deleted file mode 100644 index 4fb0acf0..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.27.0.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: 1.27.0 ---- - -## Release date - -21 September 2023 - -## Features - -* Bi-directional contracts - add "all in one" endpoint for publishing provider contracts with branch and tags -* Bi-directional contracts Pact/OAS comparison tool (swagger-mock-validator) - * Support OAS schemas with nested `allOf` operators - * Set default `additionalProperties` in response to false - * Handle exclusiveMinimum/exclusiveMaximum in bodies - * Support polymorphic inheritance in request bodies - * Improve support for allOf, anyOf, oneOf -* Add branch endpoint supporting GET and DELETE -* Add pagination parameter validation to endpoints that support pagination. - -## Fixes - -* Do not raise an error when attempting to save a duplicate provider contract version -* Matrix - optimise long running query -* Bi-directional contracts Pact/OAS comparison tool (swagger-mock-validator) - correctly decode Pact v4 bodies - -## Migration notes diff --git a/website/docs/docs/on-premises-2x/releases/1.28.0.md b/website/docs/docs/on-premises-2x/releases/1.28.0.md deleted file mode 100644 index 3ed84761..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.28.0.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: 1.28.0 ---- - -## Release date - -28 November 2023 - -## Features - -* Add endpoint to list branches -* Removed "generate project" links -* Allow additional sources to be added to the Content-Security-Policy -* Pagination parameters `pageSize` and `pageNumber` have been renamed to `size` and `page`, but the older name is retained for backward compatibility -* Support ignoring applications for "can-i-deploy" with bi-directional contracts - -## Fixes - -* Fixed an issue when trying to read individual system preferences -* Add index to fix performance issue when deleting versions with many deployed or released versions. -* Fix null pointer error raised when no matching environment found when querying environments by name - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.29.0.md b/website/docs/docs/on-premises-2x/releases/1.29.0.md deleted file mode 100644 index 230d9cd1..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.29.0.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: 1.29.0 ---- - -## Release date - -31 January 2024 - -## Features - -* Add verification modes to the GET /integration endpoint -* Reduce time for a successful can-i-deploy result when using bi-directional contracts by reducing the number of historical branches to generate pact/OAS comparisons for - -## Fixes - -* Add validation to ensure a pacticipant cannot be created with an empty name when publishing a contract. -* Fix performance issues due to contention in the integrations table when publishing a large number of contracts (> 20) per request, in parallel -* Fix contention on the API tokens table when large numbers of parallel requests come in with the same token -* Correct the logic used to calculate the pactRevisionsPerConsumerVersion distribution in the metrics endpoint - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.30.0.md b/website/docs/docs/on-premises-2x/releases/1.30.0.md deleted file mode 100644 index 62b2de28..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.30.0.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: 1.30.0 ---- - -## Release date - -10 April 2024 - -## Features - -* Add team-specific metric details via an endpoint `/metrics/teams` - -## Fixes - -* Fix bug where a user with `environment:team:read` permission received a 403 when performing a GET request for an individual environment -* Ensure matrix and can-i-deploy use the latest revision of the pact when using bi-directional contracts and the pact for a consumer version is modified -* Fix bug where searching integrations in the dashboard would only search from the first 1000 integrations -* Improved performance of the `/admin/users` endpoint -* Disables “dangerous contract modification” by default for new installations. Existing on-premises installations are unaffected. See https://docs.pactflow.io/docs/troubleshooting/disabling-dangerous-contract-modification/#on-premesis-1 for more, and how to disable it for existing installations. - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.31.0.md b/website/docs/docs/on-premises-2x/releases/1.31.0.md deleted file mode 100644 index 1824fccc..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.31.0.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: 1.31.0 ---- - -## Release date - -22 August 2024 - -## Features - -* Added new `/labels` API that lists all labels - -## Fixes - -* Fixes an issue where the "next" embedded link was not documented in the response body of the `GET /audit` endpoint -* Fixes the `NoMethodError` for pacticipants PATCH request when request body contains embedded labels -* Documents the API `/pacticipants/:pacticipant_name/labels/:label_name` for managing labels for a pacticipant -* Fixed unique team name issue when updating team in settings -* Fix bug which caused a missing row in the matrix when there are a mix of classic Pact and bi-directional contracts -* Resolves the `UniqueConstraintViolation` issue when updating team users via a PUT request. -* Fixed incorrect type standardization for openapi -v 3.1.0 -* Team Administrators will now have permission to view environments -* Deprecated _embedded payload format in the team update APIs -* Fixes an issue where deleting an integration in the context of BDCT leads to the unintended deletion of provider contracts -* Added provider version number to webhook endpoint - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.32.0.md b/website/docs/docs/on-premises-2x/releases/1.32.0.md deleted file mode 100644 index 9ff3dcc1..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.32.0.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: 1.32.0 ---- - -## Release date - -09 September 2024 - -## Features - -N/A - -## Fixes - -* fixed the situation when a consumer-provider pair has both an OAS and traditional pact containing both HTTP and message interactions. Message interactions that haven't been validated at comparison time or when `can-i-deploy` is called, returns a new Message Verification Missing reason. -* Fixed vulnerability GHSA-4xqq-m2hx-25v8 ( rexml ) -* Fixed vulnerability GHSA-vg3r-rm7w-2xgh ( rexml ) -* Fixed vulnerability GHSA-vmwr-mc7x-5vc3 ( rexml ) -* Fixed vulnerability CVE-2024-6119 ( openssl-dev, libssl-dev, libcrypto3 ) - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.33.0.md b/website/docs/docs/on-premises-2x/releases/1.33.0.md deleted file mode 100644 index a6c57c5f..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.33.0.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: 1.33.0 ---- - -## Release date - -18 September 2024 - -## Features - -N/A - -## Fixes - -* CVEs GHSA-cvp8-5r8g-fhvq, GHSA-jw9c-mfg7-9rx2, GHSA-r55c-59qm-vjw6, GHSA-5866-49gr-22v4, GHSA-vmwr-mc7x-5vc3 - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.34.0.md b/website/docs/docs/on-premises-2x/releases/1.34.0.md deleted file mode 100644 index a57a6ad0..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.34.0.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: 1.34.0 ---- - -## Release date - -22 October 2024 - -## Features - -N/A - -## Fixes -* updated packages to fix multiple CVEs - - webrick ( GHSA-6f62-3596-g6w7 ) - - wget ( CVE-2024-38428 ) - - puma ( GHSA-9hf4-67fc-4vf4 ) - - openssl-dev ( CVE-2024-9143 ) - - libssl3 ( CVE-2024-9143 ) - - openssl ( CVE-2024-9143 ) - - libcrypto3 ( CVE-2024-9143 ) - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.35.0.md b/website/docs/docs/on-premises-2x/releases/1.35.0.md deleted file mode 100644 index c82b6214..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.35.0.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: 1.35.0 ---- - -## Release date - -18 November 2024 - -## Features - -* using time based sort when combining BDCT + classic pacts -* upgraded to ruby 3.2.6 - -## Fixes - -* updated packages to fix multiple CVEs - - cross-spawn ( CVE-2024-21538 ) - - rexml (GHSA-2rxp-v6pw-ch6m) - - postgresql14-dev (CVE-2024-10979) - - libpq (CVE-2024-10979) - - libecpg-dev (CVE-2024-10979) - - libecpg (CVE-2024-10979) - - libpq-dev (CVE-2024-10979) - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.36.0.md b/website/docs/docs/on-premises-2x/releases/1.36.0.md deleted file mode 100644 index 35f3cd36..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.36.0.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: 1.36.0 ---- - -## Release date - -17 January 2025 - -## Features - -* New AI user permission (NOTE: AI features are not yet available to on-premises customers) - -## Fixes - -* Added validation to publish provider contract endpoint to prevent invalid data -* Support x-www-form-urlencoded validation in bi-directional contract testing - - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises-2x/releases/1.4.0.md b/website/docs/docs/on-premises-2x/releases/1.4.0.md deleted file mode 100644 index 32f0aad7..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.4.0.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: 1.4.0 ---- - -## Features - -* Provide an [API stub](https://pactflow.io/blog/hosted-stubs/) for every pact. -* Automatically assign first user to log in as the administrator. -* Allow administrators to assign and unassign the administrator role to other users. -* Allow administrators to disable and enable users. diff --git a/website/docs/docs/on-premises-2x/releases/1.4.1.md b/website/docs/docs/on-premises-2x/releases/1.4.1.md deleted file mode 100644 index 2d0bf290..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.4.1.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: 1.4.1 ---- - -## Fixes - -* Fixed the users screen to not overflow text with long email addresses diff --git a/website/docs/docs/on-premises-2x/releases/1.5.0.md b/website/docs/docs/on-premises-2x/releases/1.5.0.md deleted file mode 100644 index 8a05a7fa..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.5.0.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: 1.5.0 ---- - -## Features - -* Allow users and applications to be assigned to teams -* Allow applications on dashboard to be filtered by selecting a team diff --git a/website/docs/docs/on-premises-2x/releases/1.6.0.md b/website/docs/docs/on-premises-2x/releases/1.6.0.md deleted file mode 100644 index ed55367e..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.6.0.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: 1.6.0 ---- - -## Features - -- Add all new users and applications to a [Default team](/docs/user-interface/settings/teams#the-default-team). -- Support [Test Maintainer](/docs/permissions/predefined-roles#test-maintainer), [CI/CD](/docs/permissions/predefined-roles#cicd) and [Viewer](/docs/permissions/predefined-roles#viewer) roles. -- Add ["team" scoped permissions](/docs/permissions/#contract_datamanageteam) that allow a user to manage applications that are assigned to their team(s). -- Alter the "Test Maintainer" role to use the new "team" scoped permissions. diff --git a/website/docs/docs/on-premises-2x/releases/1.6.1.md b/website/docs/docs/on-premises-2x/releases/1.6.1.md deleted file mode 100644 index aa0c452c..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.6.1.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: 1.6.1 ---- - -## Fixes - -* Remove unused vulnerable version of Bundler from base Docker image diff --git a/website/docs/docs/on-premises-2x/releases/1.7.0.md b/website/docs/docs/on-premises-2x/releases/1.7.0.md deleted file mode 100644 index 49b45869..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.7.0.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 1.7.0 ---- - -## Release date - -8 December 2020 - -## Features - -* Allow configuration of [multiple SAML providers](/docs/on-premises-2x/authentication/saml#configuring-multiple-saml-providers) diff --git a/website/docs/docs/on-premises-2x/releases/1.8.0.md b/website/docs/docs/on-premises-2x/releases/1.8.0.md deleted file mode 100644 index a502b0d0..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.8.0.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 1.8.0 ---- - -## Release date - -18 December 2020 - -## Features - -* Add [menus](/docs/user-interface/dashboard/#version-tag-menus) to application version tags to allow copying of relevant URLs and deletion of associated resources. -* Add screens to display webhook execution logs. - -## Fixes - -* Fix vulnerabilities in base image. diff --git a/website/docs/docs/on-premises-2x/releases/1.9.0.md b/website/docs/docs/on-premises-2x/releases/1.9.0.md deleted file mode 100644 index 415bea5f..00000000 --- a/website/docs/docs/on-premises-2x/releases/1.9.0.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: 1.9.0 ---- - -## Release date - -1 February 2021 - -## Features - -* Support [deleting verification results](/docs/how_to#delete-verification-results) through the UI. -* Add Pact Broker/PactFlow version to UI. - -## Fixes - -* Fix cache poisoning vulnerability -* Updated JQuery and Bootstrap libraries -* Fix missing request path in audit logs diff --git a/website/docs/docs/on-premises-2x/scim.md b/website/docs/docs/on-premises-2x/scim.md deleted file mode 100644 index c46ea17e..00000000 --- a/website/docs/docs/on-premises-2x/scim.md +++ /dev/null @@ -1,288 +0,0 @@ ---- -title: On-Premises SCIM API ---- - -The PactFlow SCIM API can be added as a façade to your on-premises PactFlow instance. It runs in its own -docker container and access the PactFlow APIs using a system account API token. - -For details on the PactFlow SCIM API, refer to the [main SCIM documentation](/docs/scim/main). - -## Installation - -### First - -Before running the SCIM API, you must have a correctly running PactFlow instance that is version 1.26.0 or later. Follow the -[PactFlow On-Premises installation instructions](/docs/on-premises-2x/installation/checklist). - -### Then - -* Configure the SCIM Docker image to be pulled from Quay. Follow the [Docker image registry instructions](/docs/on-premises-2x/docker-image-registry) - to get access to the Quay registry and then run `docker pull quay.io/pactflow/scim-api` to pull down the latest SCIM API image. -* You can then deploy the docker container to your docker orchestration service (AWS ECS, K8, etc.). You need to provide the external URL of -your PactFlow instance as the `PACTFLOW_URL` environment variable to the running container. - -**NOTE: The SCIM API has to access your PactFlow instance using the URL/one of the URLs listed in the [PACTFLOW_BASE_URL](/docs/on-premises-2x/environment-variables#pactflow_base_url) environment variable used for the PactFlow application.** This is due to PactFlow using the HAL media format which uses embedded links in the responses. - -For instance, if your PactFlow instance is running as `https://pactflow.mycompany.com` then you need to the set the -`PACTFLOW_URL` environment variable for the SCIM API to that address. - -### Next - -You can now test the running SCIM API by using a tool like `curl`. First, login to your PactFlow instance and create [a -system account](/docs/user-interface/settings/users#system-accounts) with the [SCIM role](/docs/permissions/predefined-roles#scim) and then copy the system account API token. - -For instance, assuming your PactFlow instance is running as `https://pactflow.mycompany.com` and your SCIM API is -running as `https://pactflow-scim.mycompany.com` with its `PACTFLOW_URL` environment variable set to `https://pactflow.mycompany.com` and -you have copied the SCIM system account API token, you can then run `curl -H 'Authorization: Bearer ' https://pactflow-scim.mycompany.com/Users` -to fetch the users as a SCIM request. - -## Docker Compose example - -Here is an example docker compose setup (modified from the [PactFlow Docker Compose example](/docs/on-premises-2x/docker-compose-example)) -to show how the SCIM API can be setup alongside the PactFlow instance. Run through the [PactFlow Docker Compose example](/docs/on-premises-2x/docker-compose-example) -first, and when that is working you can use this docker compose file to add SCIM as a façade. - -### 1. Authenticating to Quay.io - -Authenticate to Quay.io so that the docker engine is able to fetch our images. - -``` -docker login -u="" -p="" quay.io -docker pull quay.io/pactflow/scim-api -``` - -### 2. Startup PactFlow with SCIM API - -Save the below file as `docker-compose.yml` into a temporary directory and then run `docker-compose up`. Make sure you -have setup the PactFlow license file correctly as per [2. PactFlow license file](/docs/on-premises-2x/docker-compose-example#2-pactflow-license-file). - -```yaml -version: "3" - -services: - simplesaml: - image: kristophjunge/test-saml-idp - logging: - driver: none # comment out the logging config to see the SAML server logs - ports: - - "8080:8080" - - "8443:8443" - environment: - - SIMPLESAMLPHP_SP_ENTITY_ID=https://pactflow.io - - SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost/auth/saml/callback - - pactflow: - image: quay.io/pactflow/enterprise:2.0.0 - depends_on: - - postgres - - redis - environment: - # This is set to localhost for this example but in a real deployment, this needs to be set to the actual URL of the application - - PACTFLOW_BASE_URL=http://localhost - # Insecure setting only for the purposes of this demo! Not to be used in production. - - PACTFLOW_DATABASE_SSLMODE=disable - # Insecure setting only for the purposes of this demo! Not to be used in production. - - PACTFLOW_REQUIRE_HTTPS=false - # Demo auth should only be used for demo purposes. Not to be used in production. - - PACTFLOW_DEMO_AUTH_ENABLED=true - # 'Allow all' for the webhook host whitelist should only be used for demo purposes. See docs for configuring this in production. - - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ - - PACTFLOW_HTTP_PORT=9292 - # Link to the postgres database - - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres - - PACTFLOW_LOG_LEVEL=info - - PACTFLOW_ADMIN_API_KEY=admin - - PACTFLOW_MASTER_ENCRYPTION_KEY=thisissomerandombytes - - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- - - PACT_BROKER_ADMIN_API_KEY=admin - - PACTFLOW_HTTP_LOGGING_ENABLED=true - # Link to the redis cache - - REDIS_URL=redis://redis:6379 - # SAML settings - - PACTFLOW_SAML_AUTH_ENABLED=true - - PACTFLOW_SAML_IDP_NAME=Simple SAML - - PACTFLOW_SAML_IDP_SSO_TARGET_URL=http://localhost:8080/simplesaml/saml2/idp/SSOService.php - - PACTFLOW_SAML_IDP_CERT_FINGERPRINT=11:9B:9E:02:79:59:CD:B7:C6:62:CF:D0:75:D9:E2:EF:38:4E:44:5F - - PACTFLOW_SAML_IDP_ID_ATTRIBUTE=uid - - PACTFLOW_SAML_EMAIL_ATTRIBUTE=email - ports: - - "80:9294" - healthcheck: - test: ["CMD", "supervisorctl", "status", "haproxy", "marko", "pactflow"] - interval: 30s - timeout: 10s - retries: 3 - volumes: - - ./pactflow-onprem.lic:/home/pactflow-onprem.lic - ports: - - "80:9292" - healthcheck: - test: ["CMD", "wget", "-nv", "-t1", "--spider", "http://localhost:9292/diagnostic/status/heartbeat"] - interval: 30s - timeout: 10s - retries: 3 - entrypoint: dockerize - command: -wait tcp://postgres:5432 docker-entrypoint - volumes: - - ./pactflow-onprem.lic:/home/pactflow-onprem.lic - - postgres: - image: postgres - healthcheck: - test: psql postgres --command "select 1" -U postgres - ports: - - "5432:5432" - volumes: - - postgres-volume:/var/lib/postgresql/data - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - POSTGRES_DB: postgres - - scim-api: - image: quay.io/pactflow/scim-api - depends_on: - - pactflow - environment: - PACTFLOW_URL: "http://pactflow:9292" - LOGGING_LEVEL_ROOT: DEBUG - LOGGING_LEVEL_ORG_APACHE_HC_CLIENT5_HTTP_WIRE: INFO - ports: - - "8100:8080" - - redis: - image: redis:latest - -volumes: - postgres-volume: - -``` - -## 3. Login to PactFlow - -Head to http://localhost in your browser, and choose to login with "SIMPLE SAML", with the username `user1` and password `user1pass`. -Then go to Settings -> API Tokens and COPY an API token. - -## 4. Use Curl and JQ to test access to the SCIM API - -Replace `` below with the API token copied from the last step. - -```console -❯ curl -H 'Authorization: Bearer ' http://localhost:8100/scim/Users | jq - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 1530 100 1530 0 0 3026 0 --:--:-- --:--:-- --:--:-- 3029 -{ - "schemas": [ - "urn:ietf:params:scim:api:messages:2.0:ListResponse" - ], - "totalResults": 2, - "Resources": [ - { - "schemas": [ - "urn:ietf:params:scim:schemas:core:2.0:User" - ], - "id": "61cfa5ff-1be6-4e7e-a620-7efac4a370df", - "meta": { - "created": "2022-12-06T03:49:22Z", - "lastModified": "2022-12-06T03:49:29Z", - "resourceType": "User", - "location": "http://localhost:8100/scim/Users/61cfa5ff-1be6-4e7e-a620-7efac4a370df" - }, - "name": { - "formatted": "SCIM" - }, - "displayName": "SCIM", - "userType": "System Account", - "active": true, - "groups": [ - { - "value": "4ac05ed8-9e3b-4159-96c0-ad19e3b93658", - "display": "Default", - "type": "direct", - "$ref": "Groups/4ac05ed8-9e3b-4159-96c0-ad19e3b93658" - } - ], - "roles": [ - { - "value": "c1878b8e-d09e-11ea-8fde-af02c4677eb7", - "display": "CI/CD", - "type": "CI/CD" - }, - { - "value": "cf75d7c2-416b-11ea-af5e-53c3b1a4efd8", - "display": "Administrator", - "type": "Administrator" - } - ] - }, - { - "schemas": [ - "urn:ietf:params:scim:schemas:core:2.0:User" - ], - "id": "aaa3e1a2-3648-4453-b3a6-2195b6822e2d", - "meta": { - "created": "2022-12-06T00:25:56Z", - "lastModified": "2022-12-06T00:25:56Z", - "resourceType": "User", - "location": "http://localhost:8100/scim/Users/aaa3e1a2-3648-4453-b3a6-2195b6822e2d" - }, - "userType": "User", - "active": true, - "emails": [ - { - "value": "user1@example.com", - "primary": true - } - ], - "groups": [ - { - "value": "4ac05ed8-9e3b-4159-96c0-ad19e3b93658", - "display": "Default", - "type": "direct", - "$ref": "Groups/4ac05ed8-9e3b-4159-96c0-ad19e3b93658" - } - ], - "roles": [ - { - "value": "e9282e22-416b-11ea-a16e-57ee1bb61d18", - "display": "User", - "type": "User" - }, - { - "value": "cf75d7c2-416b-11ea-af5e-53c3b1a4efd8", - "display": "Administrator", - "type": "Administrator" - } - ] - } - ] -} -``` - -## Configuration - -### PactFlow URL (Required) - -**Variable:** `PACTFLOW_URL`
- -This sets the URL that the PactFlow instance is accessed from. - -### Log Level - -**Variable:** `LOGGING_LEVEL_ROOT`
-**Default:** `INFO`
-**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`
- -This sets the base log level for the SCIM API container. - -**WARNING: Setting the log level to `DEBUG` will cause all HTTP interactions between the SCIM API and PactFlow to be be logged, -which will include the API tokens in clear text.** To disable logging of the HTTP interactions, set -`LOGGING_LEVEL_ORG_APACHE_HC_CLIENT5_HTTP_WIRE` to `INFO` or greater. - -### Context Path - -**Variable:** `SERVER_SERVLET_CONTEXT_PATH`
-**Default:** `/scim`
- -This sets the context path that the SCIM API is mounted at. diff --git a/website/docs/docs/on-premises-2x/security-audit-report.md b/website/docs/docs/on-premises-2x/security-audit-report.md deleted file mode 100644 index fb44053f..00000000 --- a/website/docs/docs/on-premises-2x/security-audit-report.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Security audit report ---- - -## Vulnerability scanning - -PactFlow uses the following tools to ensure the On-Premises image is kept as secure as possible. - -* Bundler Audit -* NPM audit -* Trivy -* Quay Security Scanner -* Amazon ECR Image scanning - -## Reporting vulnerabilities - -To report a vulnerability, please [contact security](https://smartbear.com/security/) and ensure you include the relevant CVE, and the name and/or path to the vulnerable component. - -## Identifying the correct Ruby version - -Many scanning tools have trouble identifying the correct version of Ruby installed on an image because Ruby stores its gems in a directory path that uses the minor version of Ruby (eg. `2.7.0`) rather than the patch version (eg. `2.7.6`). This can be demonstrated by running the following command: - -```shell -docker run --rm -it --entrypoint gem quay.io/pactflow/enterprise:latest environment -``` - -Example output (note the `RUBY VERSION` of `2.7.6` while the `GEM PATHS` use `2.7.0`): - -```shell -RubyGems Environment: - - RUBYGEMS VERSION: 3.1.6 - - RUBY VERSION: 2.7.6 (2022-04-12 patchlevel 219) [x86_64-linux-musl] - - INSTALLATION DIRECTORY: /usr/local/bundle - - USER INSTALLATION DIRECTORY: /root/.gem/ruby/2.7.0 - - RUBY EXECUTABLE: /usr/local/bin/ruby - - GIT EXECUTABLE: - - EXECUTABLE DIRECTORY: /usr/local/bundle/bin - - SPEC CACHE DIRECTORY: /root/.gem/specs - - SYSTEM CONFIGURATION DIRECTORY: /usr/local/etc - - RUBYGEMS PLATFORMS: - - ruby - - x86_64-linux-musl - - GEM PATHS: - - /usr/local/bundle - - /root/.gem/ruby/2.7.0 - - /usr/local/lib/ruby/gems/2.7.0 - - GEM CONFIGURATION: - - :update_sources => true - - :verbose => true - - :backtrace => false - - :bulk_threshold => 1000 - - "install" => "--no-document" - - "update" => "--no-document" - - REMOTE SOURCES: - - https://rubygems.org/ - - SHELL PATH: - - /usr/local/bundle/bin - - /usr/local/sbin - - /usr/local/bin - - /usr/sbin - - /usr/bin - - /sbin - - /bin -``` - -The difficulty that tools have in identifying the correct version of Ruby can lead to false positives being reported. Please check the version of Ruby before submitting a vulnerability report. - -## Identifying the installed gem versions - -To list the gems installed on the PactFlow image run: - -``` -docker run --rm -it --entrypoint gem quay.io/pactflow/enterprise:latest "list" -``` - -## Known vulnerabilities - -### CVE-2015-9284 - -#### Component - -omniauth gem - -#### CVE - -[https://nvd.nist.gov/vuln/detail/CVE-2015-9284](https://nvd.nist.gov/vuln/detail/CVE-2015-9284) - -#### Detectable in versions of PactFlow - -All. - -#### Status - -Non-exploitable. - -#### Notes - -This CVE is a CSRF vulnerability during sign in. This vulnerability is only exploitable if the initial request from the service provider to the identify provider is vulnerable to a CSRF attack because it uses a GET request without any CSRF protection. In PactFlow, this is not possible as PactFlow uses a POST request method with a CSRF token for the initial request to the IDP, as per the mitigation instructions [here](https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284). - -This can be observed by viewing the source of the login form. - -```html -
- - -
-``` - -### CVE-2022-2625 - -#### Description - -Given certain prerequisites, this vulnerability allows arbitrary code to be run. - -#### Component - -postgresql14-dev package for Alpine - -#### CVE - -[https://nvd.nist.gov/vuln/detail/CVE-2022-2625](https://nvd.nist.gov/vuln/detail/CVE-2022-2625) - -#### Status - -Non-exploitable. - -#### Notes - -This vulnerability applies to the PostgreSQL server only. The PactFlow Docker image only uses the PostgreSQL client, and hence is not affected by this vulnerability. - -### CVE-2022-37434 - -#### Description - -A heap-based buffer over-read or buffer overflow in inflate in inflate.c via a large gzip header extra field. - -#### Component - -zlib package for Alpine - -#### CVE - -[https://nvd.nist.gov/vuln/detail/CVE-2022-37434](https://nvd.nist.gov/vuln/detail/CVE-2022-37434) - -#### Affected versions of PactFlow - -All. - -#### Status - -Unfixed. - -#### Notes - -As of 24 August 2022, there is no fix available. A patch release of PactFlow will be put out as soon as a fix is available. - -### CVE-2021-41816 - -#### Component - -The cgi library included in Ruby before 2.7.5 and 3.x before 3.0.3, and the [cgi gem](https://rubygems.org/gems/cgi) before 0.3.1. - -#### CVE - -[https://nvd.nist.gov/vuln/detail/CVE-2021-41816](https://nvd.nist.gov/vuln/detail/CVE-2021-41816) - -#### Status - -False positive. - -#### Notes - -This vulnerability only affects platforms that use a 4 byte long data type, typically Windows. The PactFlow base image uses 64 bit Alpine Linux, which uses an [8 byte long](https://www.ibm.com/docs/en/ibm-mq/9.0?topic=platforms-standard-data-types-unix-linux-windows). - -### CVE-2020-36599 - -#### Description - -lib/omniauth/failure_endpoint.rb in OmniAuth before 1.9.2 (and before 2.0) does not escape the message_key value. - -#### Component - -omniauth gem - -#### Status - -Non-exploitable. - -#### Detectable in versions of PactFlow - -Up to and including 1.19.2. - -#### Fixed versions - -1.19.3 and later. - -#### Notes - -PactFlow uses a custom failure endpoint so the vulnerable code is never executed. diff --git a/website/docs/docs/on-premises-2x/support-policy.md b/website/docs/docs/on-premises-2x/support-policy.md deleted file mode 100644 index 456b1f17..00000000 --- a/website/docs/docs/on-premises-2x/support-policy.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Support policy ---- - -## Versioning - -PactFlow On-Premises follows a [semantic versioning](https://semver.org/) policy for API changes. - -Further to this, any changes to the database schema or configuration that are backwards incompatible (eg. addition of a mandatory configuration setting with no default, or the deletion of a table) will only be introduced in a major version. Migration documentation will be included in the release notes for any major version, and any minor version that introduces optional configuration. - -### Base image upgrades - -Upgrades of the Docker base image will be performed in minor releases (eg. from `alpine3.14` to `alpine 3.15`). PactFlow images will only be supported for Docker versions that are currently [in support](https://docs.docker.com/engine/install/#support) themselves (20.10.0 and later). - -## Support period - -PactFlow application bug fixes will be applied to the latest minor release only. - -Minor versions will receive patches for security vulnerabilities for a period 9 months from the release date. - -## Releases - -Minor version releases are performed at 1-2 month intervals. Major and patch version releases are performed as required according to our versioning policy. - -## Subscribing to updates - -Subscribe to our [RSS](/notices/rss.xml), [Atom](/notices/atom.xml) or [JSON](/notices/feed.json) feeds for updates on new on-premises releases and important security announcements. - -## Asking for help - -Current customers may open a [support ticket](https://support.smartbear.com/pactflow/message/) with the following information: - -* The current version of your PactFlow instance (the version of your application is displayed in the footer. If the application is not able to start, the version of the docker image you are running is sufficient) -* A detailed description of what you're trying to achieve, what your expected outcome is, and what the actual behaviour is. -* The current configuration given to your application -* A log file taken from when the problem occurred, where the application log level has been set to `DEBUG` -* If you're trying to demonstrate a problem or diagnose a bug, the best possible thing you can do is provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). -* Any other information you think could help us diagnose the issue - -### Scope of PactFlow support - -PactFlow is distributed via an industry standard Docker image, meaning that it can be deployed to a wide variety of orchestration tools such as Kubernetes and OpenShift, and runtime environments such as AWS, GCP or Azure. - -Given this flexibility, we are unable to provide support for components that live outside of the PactFlow application as there are too many factors outside of our control to be able to advise you appropriately. - -**Examples of things we can help you with** - -* Application configuration issues -* Interpreting and clarifying application logs -* Diagnosing issues with the application behaviour - -**Examples of things we can't help you with** - -* Networking issues -* Docker orchestration setup (e.g. Helm charts, EKS) -* Cloud or infrastructure automation tools (e.g. Cloudformation, Terraform, Ansible) - -Of course, there are areas where the boundaries are not so clear - such as security reports highlighted by an infosec tool, or issues relating to your IDP or database. This is an area of our shared responsibility and we will do our best to support you. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/system-requirements.md b/website/docs/docs/on-premises-2x/system-requirements.md deleted file mode 100644 index e5f2b2d8..00000000 --- a/website/docs/docs/on-premises-2x/system-requirements.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: System requirements ---- - -## Application server instance - -### OS - -Linux - -### Minimum CPU/Memory - -4.0 GiB Memory, 4 vCPUs - -### Disk space usage - -4.0 GiB - -### Docker version - -20.10.0 or later - -## Postgres database instance - -### HA Configuration - -### Configuration - -We would recommend running Postgres as an Active/Passive setup with [streaming replication](https://wiki.postgresql.org/wiki/Replication,_Clustering,_and_Connection_Pooling), or Active/Active setup for the best availability. - -For reference, pactflow.io runs on AWS RDS in [active/passive mode across multiple logical networks](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html), and fails over to the replica when in a failure mode. - -### Minimum CPU/Memory - -4.0 GiB Memory, 4 vCPUs - -### Storage - -5GiB (minimum) -25GiB (recommended) - -### I/O Performance - -* 10 read/s -* 25 write/s - -## Load Balancing - -We recommend running PactFlow on load-balanced infrastructure in at least a 2 node setup to enable high availability and greater throughput. So for clarity, we would recommend running two servers both with 4GiB memory and 4 CPUs for a total capacity of 8GiB Memory and 8 CPUs. - -The PactFlow application is stateless, and therefore sticky sessions do not need to be configured. Use round-robin or least outstanding requests to route to the application servers. - -_NOTE_: Most Pact tooling has retries built-in to handle minor outages communicating to a broker. - -## Scaling and Monitoring - -Below are the key scaling considerations. - -First, make sure you've identified the baseline load and have performed a [load test](installation/load-testing). This will help you to set you boundaries for your scale out and scale in parameters. - -PactFlow is a database intensive application, with the I/O performance of the database being the most critical factor in determining overall system performance. You should setup monitoring for the following metrics: - -* CPU -* Memory -* I/O latency -* Query latency -* Remaining storage space - -Application servers tend to be more CPU bound, but you should look to monitor and scale at least: - -* CPU -* Memory - - -## Benchmarking and Forecasting - -The usage patterns of every customer is different. For example, we have several customers who are among top users of our SaaS platform with less than 30 integrations. - -Things that will affect how the system scales include: - -* Concurrent usage i.e. requests per second (usually by automation systems such as CI/CD) -* CI implementation patterns (e.g. integrations to PactFlow, the use of polling vs webhooks) -* Developer habits (continuous check-in vs bigger commits) causing more or less builds -* Whether you run regular database cleanups (to reduce database storage requirements, and speed up queries) -* The size, variation and stability of contracts -* The interconnectedness of your system -* Database growth - -and so on. These types of data are very hard to collect, measure and predict. - -For forecasting purposes we've created a standard model you can use for projecting storage and compute costs as you grow, which is based on the number of active users* you have on the system. - -_NOTE_: We still recommend using the monitoring and scaling approach (defined above) to automatically scale up/down your system as required. - -_* Active users is defined as a developer that either logs into PactFlow daily or commits code that would trigger a CI build that integrates with Pactflow_ -### Standard Units - -* 1 `compute unit` = 1 CPU, 256 MiB memory -* 1 `database unit` = 1 CPU, 256 MiB memory, 1 GiB storage (per week), 25 writes/s, 10 read/s - -For each 500 active users*, you should increment your total compute capacity by one (1) unit, and _each_ database server capacity by one (1) unit. - - -### Examples - -_**Scenario 1**: 1000 users in year 1_ - -Assuming our database uses active/passive mode and replication. - -Baseline capacity should be 2 x Application Servers each with 4 CPU and 4GiB memory, and a two Postgres database instances (one for the active and passive) each with 4CPU, 4GiB memory, 25GiB volume and 25/10 write/read per second. - -To calculate the number of standard units you need to add: - -``` -new units = expected users / 500 - = 1000 / 500 - = 2 units -``` - -You should therefore add 2 CPUs and 512 MiB to your total compute budget, and add 2 CPUs, 512 MiB of memory and 104 GiB storage capacity to each of your database instances in year 1, for a total budget: - -* **Compute**: 10 CPU, 8.5 GiB RAM (measured by total resources and not physical instances) -* **Database**: 2 x database servers each with 6 CPU, 4.5 GiB RAM, 75 writes/s, 30 read/s, 129 GiB storage - -_**Scenario 2**: Additional 1300 users in year 2_ - -``` -new units = expected users / 500 - = 1300 / 500 - = 3 units (rounded) -``` -You should therefore add 3 CPUs and 768 MiB to your total compute budget, and add 3 CPUs, 768 MiB of memory and 156 GiB storage capacity to each of your database instances in year 2, for a total budget: - -* **Compute**: 13 CPU, 9.25 GiB RAM (measured by total resources and not physical instances) -* **Database**: 2 x database servers each with 9 CPU, 5.25 GiB RAM, 150 writes/s, 60 read/s, 285 GiB storage \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/troubleshooting.md b/website/docs/docs/on-premises-2x/troubleshooting.md deleted file mode 100644 index 39c6c557..00000000 --- a/website/docs/docs/on-premises-2x/troubleshooting.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Troubleshooting ---- - -## Manually creating a new administrator - -It happens to the best of us. Perhaps you're locked out because your only Administrator has left, or maybe you disabled them. Whatever it is, here's how you can get back on track: - -1. Login to your Postgres database with the credentials you've setup -2. Find the ID of the user you wish to make an Administrator: - - `select * from saas_users;` - -Grab the ID for the user(s) you wish to make an Administrator. It may be simpler to just initially assign yourself as an Administrator, and then add others via the UI. - -3. Grab the ID of the Administrator role. It should have an ID of 1 and a uuid of `cf75d7c2-416b-11ea-af5e-53c3b1a4efd8`, but best to be sure: - - `select * from pactflow_roles;` - -4. Add a role mapping for the user: - - `insert into pactflow_user_roles ("user_id","role_id") values (, );` - -You are now an Administrator and - assuming you didn't tell anyone - have spared yourself shame and embarrassment. - -## Segmentation fault on launch - -```shell -/home/pact_broker_fork/lib/pact_broker/version.rb:2: [BUG] Segmentation fault at 0x00007efdfbffa000 -ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a) [x86_64-linux-musl] --- Control frame information ----------------------------------------------- -c:0052 p:---- s:0316 e:000315 CFUNC :RGLoader_load -c:0051 p:0193 s:0311 e:000310 TOP /home/pact_broker_fork/lib/pact_broker/version.rb:2 [FINISH] -``` - -This most frequently happens when your license file isn't mounted correctly. ie. you're trying to mount a **file** as a **folder**, or vice-versa. Be sure to mount your license **file** as a **file** inside the running container. For example, in Docker Compose, you need to have: - -``` -version: "3" -services: - pactflow: - image: quay.io/pactflow/enterprise - volumes: - - ./pactflow-onprem.lic:/home/pactflow-onprem.lic -``` - -Adjust accordlingy depending on your container runtime. diff --git a/website/docs/docs/on-premises-2x/upgrading.md b/website/docs/docs/on-premises-2x/upgrading.md deleted file mode 100644 index ef4886a7..00000000 --- a/website/docs/docs/on-premises-2x/upgrading.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Docker image ---- - -TBC diff --git a/website/docs/docs/on-premises-2x/upgrading/database-migrations.md b/website/docs/docs/on-premises-2x/upgrading/database-migrations.md deleted file mode 100644 index df31afaa..00000000 --- a/website/docs/docs/on-premises-2x/upgrading/database-migrations.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Database migrations ---- - -## Auto migration - -Schema migrations are run automatically on start up, unless the [PACTFLOW_DATABASE_AUTO_MIGRATE](../environment-variables#pactflow_database_auto_migrate) environment variable is set to `false`. Data migrations are also run automatically on start up, after the schema migrations, and ensure that any data inserted into the database by a previous version of the application are migrated. This allows you to perform no-downtime, rolling upgrades across your cluster, ensuring any data inserted into latest database schema by the nodes running the previous version of the application are safely migrated. - -Each schema migration will only ever be applied to the database once. Each data migration is executed during every application start up, as this provides the simplest mechanism for ensuring that all data is correctly migrated during rolling deployments. If this is undesirable, then manual migrations can be performed. - -## Manual migration - -The migrations can be run manually against the database before upgrading the PactFlow Docker image if desired. The `db-migrate` entrypoint will run both the schema and the data migrations. - -```sh -docker pull quay.io/pactflow/enterprise - -# Identify the current version before migrating, in case a rollback is required -docker run --rm \ - --env PACTFLOW_DATABASE_URL="postgres://username:password@host:port/database" \ - --entrypoint db-version \ - quay.io/pactflow/enterprise - -# Perform the migrations -docker run --rm \ - --env PACTFLOW_DATABASE_URL="postgres://username:password@host:port/database" \ - --entrypoint db-migrate \ - quay.io/pactflow/enterprise -``` - -To perform a manual no-downtime deployment that does not rely on the "auto migrate" feature: - -1. Execute the `db-migrate` entrypoint from the Docker image of the desired version. This will run both the schema and data migrations. -2. In the Pactflow application environment variables, set the `PACTFLOW_DATABASE_AUTO_MIGRATE` environment variable to `false`, and update the Pactflow image version to the desired tag. Allow your container management system to apply the rollout of the new Docker image. -3. Execute the `db-migrate` entrypoint again. This will run only the data migrations, as the schema migrations have already run. It is necessary to run the data migrations again to ensure that any data that was inserted into the new schema via the old API (during the rolling upgrade) is correctly migrated. - - -## Rollback - -To perform a manual rollback, first identify the number of the migration target using the PactFlow image with the tag you wish to rollback to. - -```sh -TAG="" -docker run --rm \ - --entrypoint /bin/sh \ - --volume $PWD/pactflow-onprem.lic:/home/pactflow-onprem.lic \ - quay.io/pactflow/enterprise:${TAG} \ - -c "ls /home/pact_broker_fork/db/migrations | grep \d | sort | tail -n 1 | cut -d '_' -f1" -``` - -Then, perform the rollback using the PactFlow image that belongs to the database version currently deployed. - -```sh -TAG="" -docker run --rm \ - --volume $PWD/pactflow-onprem.lic:/home/pactflow-onprem.lic \ - --env PACTFLOW_DATABASE_URL="postgres://username:password@host:port/database" \ - --env PACTFLOW_DATABASE_MIGRATION_TARGET="" \ - --entrypoint db-migrate \ - quay.io/pactflow/enterprise:${TAG} -``` - -## Minor and patch version upgrades - -Upgrades between any minor or patch versions with the same major versions do not need any migration path. - -## Major version upgrades - -For major version upgrades, please upgrade to the most recent patch version of the previous major version before upgrading to the next major version. - diff --git a/website/docs/docs/on-premises.md b/website/docs/docs/on-premises.md index 1adaa63d..9b5c5df9 100644 --- a/website/docs/docs/on-premises.md +++ b/website/docs/docs/on-premises.md @@ -9,6 +9,7 @@ sidebar_label: Architecture * An application server capable of running Docker * PostgreSQL database +* Redis Serialization Protocol (RESP)-compatible key/value cache * SAML IDP for SSO * PactFlow license file @@ -18,7 +19,7 @@ sidebar_label: Architecture ### Example AWS deployment using ECS -![System architecture](/img/saas-architecture-aws.png) +![System architecture](/img/on-prem-architecture-2x.png) ## Internal architecture @@ -26,7 +27,7 @@ The PactFlow On-Premises application is distributed as a Docker image. It is bas ### Application user requirements -The PactFlow application does not need any elevated privileges to run. It runs under the user `app:app`. +You can run the application without elevated privileges. It runs under the user `app`. ### Application port @@ -34,15 +35,21 @@ The PactFlow application runs on port `9292` by default. This can be configured ### Healthcheck endpoint -A healthcheck endpoint for use by a Docker container managment service is available at `http:///diagnostic/status/heartbeat`. No authentication is required. This endpoint does not make a connection to the database. +There's a healthcheck endpoint at `http:///diagnostic/status/heartbeat` meant for Docker container management tools. -If the healthcheck is running from inside the container, make sure to use the port defined in the environment variable `$PACTFLOW_HTTP_PORT`, which defaults to 9292. You can use `wget` to perform the healthcheck request. +- It doesn't need authentication. +- It doesn't touch the database. +- You can use it to check if load balancer targets are working properly. + +If you're running the healthcheck from inside the container, be sure to use the port specified by the `$PACTFLOW_HTTP_PORT` environment variable (defaults to `9292` if not set). + +You can use `supervisorctl` to send the healthcheck request. An example healthcheck configuration for Docker Compose: ```yaml healthcheck: - test: ["CMD", "wget", "-nv", "-t1", "--spider", "http://localhost:9292/diagnostic/status/heartbeat"] + test: ["supervisorctl", "status", "haproxy", "marko", "pactflow"] interval: 30s timeout: 10s retries: 3 diff --git a/website/docs/docs/on-premises/docker-compose-example.md b/website/docs/docs/on-premises/docker-compose-example.md index 5818052e..64d0cdb1 100644 --- a/website/docs/docs/on-premises/docker-compose-example.md +++ b/website/docs/docs/on-premises/docker-compose-example.md @@ -35,9 +35,9 @@ Which should produce an output such as: ```sh > docker images quay.io/pactflow/enterprise REPOSITORY TAG IMAGE ID CREATED SIZE -quay.io/pactflow/enterprise 1.9.0 32db429fda01 7 weeks ago 454MB -quay.io/pactflow/enterprise latest 32db429fda01 7 weeks ago 454MB -quay.io/pactflow/enterprise 1.8.0 7f9b3c3aa50e 3 months ago 462MB +quay.io/pactflow/enterprise 2.0.0 32db429fda01 1 day ago 462MB # <- this guide applies to 2.x.x version +quay.io/pactflow/enterprise latest 32db429fda01 1 day ago 462MB +quay.io/pactflow/enterprise 1.36.0 7f9b3c3aa50e 7 weeks ago 454MB ``` ## 2. PactFlow license file @@ -56,9 +56,10 @@ version: "3" services: pactflow: - image: quay.io/pactflow/enterprise + image: quay.io/pactflow/enterprise:latest depends_on: - postgres + - redis environment: # This is set to localhost for this example but in a real deployment, this needs to be set to the actual URL of the application - PACTFLOW_BASE_URL=http://localhost @@ -71,24 +72,23 @@ services: # 'Allow all' for the webhook host whitelist should only be used for demo purposes. See docs for configuring this in production. - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ - PACTFLOW_HTTP_PORT=9292 + # Link to the postgres database - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres - - Short log format only for demo purposes. Use json in production. - - PACTFLOW_LOG_FORMAT=short - PACTFLOW_LOG_LEVEL=info - PACTFLOW_ADMIN_API_KEY=admin - PACTFLOW_MASTER_ENCRYPTION_KEY=thisissomerandombytes - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- - PACT_BROKER_ADMIN_API_KEY=admin - PACTFLOW_HTTP_LOGGING_ENABLED=true + # Link to the redis cache + - REDIS_URL=redis://redis:6379 ports: - "80:9292" healthcheck: - test: ["CMD", "wget", "-nv", "-t1", "--spider", "http://localhost:9292/diagnostic/status/heartbeat"] + test: ["CMD", "supervisorctl", "status", "haproxy", "marko", "pactflow"] interval: 30s timeout: 10s retries: 3 - entrypoint: dockerize - command: -wait tcp://postgres:5432 docker-entrypoint volumes: - ./pactflow-onprem.lic:/home/pactflow-onprem.lic @@ -103,6 +103,9 @@ services: POSTGRES_PASSWORD: password POSTGRES_DB: postgres + redis: + image: redis:latest + volumes: postgres-volume: ``` @@ -110,10 +113,10 @@ volumes: You can verify all services by running `docker ps`: ``` -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -8318130fa98a quay.io/pactflow/enterprise "docker-entrypoint" 18 seconds ago Up 17 seconds (health: starting) 9292/tcp, 0.0.0.0:80->9292/tcp tmp_pactflow_1 -7ba5d1679d09 kristophjunge/test-saml-idp "docker-php-entrypoi…" 7 minutes ago Up 17 seconds 0.0.0.0:8080->8080/tcp, 80/tcp, 0.0.0.0:8443->8443/tcp tmp_simplesaml_1 -c0e3059fa37c postgres "docker-entrypoint.s…" 7 minutes ago Up 17 seconds (health: starting) 0.0.0.0:5432->5432/tcp tmp_postgres_1 +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +1cefdf8b1e1b quay.io/pactflow/enterprise:2.0.0 "docker-entrypoint" 24 minutes ago Up 24 minutes (healthy) 0.0.0.0:80->9292/tcp tmp_pactflow_1 +6bedae5936dc redis:latest "docker-entrypoint.s…" 2 hours ago Up 24 minutes 6379/tcp tmp_redis_1 +8b393d35a20c postgres:13-alpine "docker-entrypoint.s…" 9 days ago Up 24 minutes (healthy) 5432/tcp tmp_postgres_1 ``` ## 3. Login to PactFlow diff --git a/website/docs/docs/on-premises/docker-image-registry.md b/website/docs/docs/on-premises/docker-image-registry.md index 425b55df..8a2f6880 100644 --- a/website/docs/docs/on-premises/docker-image-registry.md +++ b/website/docs/docs/on-premises/docker-image-registry.md @@ -14,7 +14,7 @@ If you are on a PactFlow trial, creating a RedHat account is **not** required. Y To set you up with console access, you will need to create a [RedHat account](https://quay.io/signin/). Choose "Register for a RedHat account" and once comwpleted, provide the username/email address to us to add you to the registry. -Once we have granted access to your given email address, you should receive an email from Red Hat Quay confirming access to the PactFlow organisation. +Once we have granted access to your given email address, you should receive an email from Red Hat Quay confirming access to the PactFlow organization. ### CI Access @@ -36,7 +36,7 @@ Once we have created you a new user, you will receive an email from Quay.io invi ![Completed signup](/on-premises/quay-completed.png) -1. You should now have access to the `enterprise` repository in the `pactflow` organisation. +1. You should now have access to the `enterprise` repository in the `pactflow` organization. 1. You can now sign in with your account (in addition to your Robot Account) to quay to pull docker images. See [getting started with Quay.io](https://docs.quay.io/solution/getting-started.html) for more on this. diff --git a/website/docs/docs/on-premises/environment-variables.md b/website/docs/docs/on-premises/environment-variables.md index 6bdaaad4..f9caad3b 100644 --- a/website/docs/docs/on-premises/environment-variables.md +++ b/website/docs/docs/on-premises/environment-variables.md @@ -24,15 +24,6 @@ The PactFlow application log level **Default:** `INFO`
**Allowed values:** `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
-### PACTFLOW_LOG_FORMAT - -The PactFlow application log format - -**Required:** false
-**Default:** `json`
-**Allowed values:** `json`, `default`, `color`
-**More information:** https://github.com/rocketjob/semantic_logger/tree/master/lib/semantic_logger/formatters
- ### PACTFLOW_HTTP_LOGGING_ENABLED When true, HTTP request details and response status and duration will be logged to stdout in json format @@ -531,7 +522,7 @@ The secret used to encrypt the rack.session cookie. To generate an appropriate value, run the following on Linux/Mac: ``` -env LC_CTYPE=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 32 | head -n 1 +LC_ALL=C tr -dc '_A-Z-a-z-0-9!#$%&*+-\\.^_|~' < /dev/urandom | fold -w 64 | head -n 1 ``` **Required:** true
@@ -639,3 +630,17 @@ head < /dev/random -c 16 | base64 **Required:** if `PACTFLOW_API_TOKEN_ENCRYPTION_ENABLED` is set to `true`
**Example:** `JUVDdnRzLXZyWHA7UF93RAo=`
+ +## User Interface + +
+ + + +### PACTFLOW_CLARITY_DISABLED + +Disables the new user interface introduced in version 2.0.0. When this environment variable is set, the legacy interface becomes the default and users cannot switch to the new UI. + +**Required:** false
+**Default:** unset
+**Allowed values:** `true`
\ No newline at end of file diff --git a/website/docs/docs/on-premises/installation/checklist.md b/website/docs/docs/on-premises/installation/checklist.md index 92b4ee47..8e61a005 100644 --- a/website/docs/docs/on-premises/installation/checklist.md +++ b/website/docs/docs/on-premises/installation/checklist.md @@ -27,6 +27,7 @@ Configure the PactFlow On-Premises application in your identity provider. See th * Use the [environment variable templates](/docs/on-premises/environment-variables/templates) to create the appropriate deployment configuration artifacts for the PactFlow Docker image (eg. Cloudformation template, Helm chart etc.) * Ensure the [compute resources](/docs/on-premises/system-requirements) have the appropriate specifications. * Create a [PostgreSQL database](/docs/on-premises/database) +* Setup a [Redis cache](/docs/on-premises/redis) * Ensure the [network](/docs/on-premises/network-configuration) is configured appropriately. * Ensure the [logs](/docs/on-premises/logging) are forwarded to a log aggregation service. * Make sure the [license file](/docs/on-premises/license) is mounted into the running containers. @@ -38,4 +39,5 @@ Setup [database cleaning](/docs/on-premises/maintenance/database) to ensure opti :::warning this step is not optional Failure to enable database cleaning is likely to result in a gradual decline in system performance and, eventually, query timeouts and system failure. -::: \ No newline at end of file +::: + diff --git a/website/docs/docs/on-premises/logging.md b/website/docs/docs/on-premises/logging.md index 382c4b78..fca9cc15 100644 --- a/website/docs/docs/on-premises/logging.md +++ b/website/docs/docs/on-premises/logging.md @@ -4,11 +4,11 @@ title: Logging ## Output -PactFlow application logs are sent to the standard output stream of the Docker container, with the expectation that the container orchestration service will collect and forward them to a log aggregation service. +PactFlow application logs are sent to the standard output stream of the Docker container, with the expectation that the container orchestration service will collect and forward them to a log aggregation service. Both the UI and App logs will be interspersed here. They are distinguishable by the `application` property. UI will be `pactflow-ui` and API will be `pactflow-application`. ## Format -The default log format is JSON. This can be changed by setting the [PACTFLOW_LOG_FORMAT](environment-variables#pactflow_log_format) environment variable. +The log format is JSON. ## Level diff --git a/website/docs/docs/on-premises/network-configuration.md b/website/docs/docs/on-premises/network-configuration.md index 7cafece2..450cbfd0 100644 --- a/website/docs/docs/on-premises/network-configuration.md +++ b/website/docs/docs/on-premises/network-configuration.md @@ -20,9 +20,8 @@ The host names of these services should also be whitelisted in the [PACTFLOW_WEB ## Certificate and TLS termination -The recommended configuration is to terminate TLS at the load balancer, communicating over HTTP to the target application servers. +The recommended configuration is to terminate TLS at the load balancer, communicating over HTTP to the target application servers, which in turn communicate over local sockets to applications within the container. -If you would like to run PactFlow in a TLS-everywhere configuration there are several options: +If you would like to run PactFlow in a TLS-everywhere configuration, modify the HAProxy configuration file (`/tmp/haproxy.cfg`) to bind a certificate to the `frontend`, and ensure the certificate has been appropriately mounted/added to the container. -* Run the PactFlow container with a sidecar reverse proxy such as nginx configured with the TLS configuration of your choosing -* Raise a feature request with us so that we can add it to our backlog, and support it natively with the underlying application server (Puma) +Refer to the [HAProxy documentation](https://www.haproxy.com/documentation/haproxy-configuration-tutorials/security/ssl-tls/client-side-encryption/) for further information. \ No newline at end of file diff --git a/website/docs/docs/on-premises-2x/redis.md b/website/docs/docs/on-premises/redis.md similarity index 80% rename from website/docs/docs/on-premises-2x/redis.md rename to website/docs/docs/on-premises/redis.md index f926b955..e9e13ad0 100644 --- a/website/docs/docs/on-premises-2x/redis.md +++ b/website/docs/docs/on-premises/redis.md @@ -1,13 +1,13 @@ --- -title: Redis Cache +title: Cache --- ## Introduction -PactFlow requires a Redis-compatible storage for the following functions: +PactFlow requires a Redis Serialization Protocol (RESP)-compatible storage engine to support the following functions: - User session management -- UI caching for performance +- UI caching for improved performance ## Session management @@ -35,4 +35,9 @@ As a fallback, the PactFlow UI follows HTTP cache-control conventions. If a user ## Supported versions -Redis 7.0 and later is supported. \ No newline at end of file +Engines that implement the [Redis Serialization Protocol (RESP) version 3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md) are supported. + +Example implementations include: + +- Redis +- Valkey \ No newline at end of file diff --git a/website/docs/docs/on-premises/releases/1.36.1.md b/website/docs/docs/on-premises/releases/1.36.1.md deleted file mode 100644 index 9cfb9b25..00000000 --- a/website/docs/docs/on-premises/releases/1.36.1.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: 1.36.1 ---- - -## Release date - -20 June 2025 - -## Features - -N/A - -## Fixes - -Fixed intermittent 401 when running custom extension auth_ext_script. - -## Migration notes - -N/A - - diff --git a/website/docs/docs/on-premises/releases/2.0.0.md b/website/docs/docs/on-premises/releases/2.0.0.md index ee56092c..182f90ce 100644 --- a/website/docs/docs/on-premises/releases/2.0.0.md +++ b/website/docs/docs/on-premises/releases/2.0.0.md @@ -10,13 +10,13 @@ title: 2.0.0 This major release introduces significant architectural changes and new features, including: -1. A redesigned user interface -2. Migration to an Ubuntu Linux base image -3. Updated architecture using `HAProxy` for traffic routing and `supervisord` for process management -4. New caching and session management layers requiring a Redis-compatible service -5. Many additional features, fixes, and improvements +1. A redesigned user interface. +2. Migration to an Ubuntu Linux base image. +3. Updated architecture using `HAProxy` for traffic routing and `supervisord` for process management. +4. New caching and session management layers requiring a Redis Serialization Protocol (RESP)-compatible key/value storage engine. +5. Many additional features, fixes, and improvements. -For full details, including installation instructions, refer to the [2.x.x documentation](/docs/on-premises-2x). +For full details, including installation instructions, refer to the [2.x.x documentation](/docs/on-premises). ## Features @@ -35,8 +35,8 @@ For full details, including installation instructions, refer to the [2.x.x docum Please review the following updates when migrating to version 2.0.0: -1. A [Redis-compatible data store](/docs/on-premises-2x/redis) is now required. -2. `PACTFLOW_COOKIE_SECRET` must now be at least 64 characters. [More info](/docs/on-premises-2x/environment-variables#pactflow_cookie_secret). +1. A [Redis-compatible data store](/docs/on-premises/redis) is now required. +2. `PACTFLOW_COOKIE_SECRET` must now be at least 64 characters. [More info](/docs/on-premises/environment-variables#pactflow_cookie_secret). 3. The `PACTFLOW_LOG_FORMAT` environment variable is deprecated and has no effect. All logs are now output in JSON only. 4. The base image has changed from Alpine Linux to Ubuntu 24.04. If you have customized the image, review your setup and update any installed tools or libraries accordingly. diff --git a/website/docs/docs/on-premises/scim.md b/website/docs/docs/on-premises/scim.md index 86f7df1c..715e2929 100644 --- a/website/docs/docs/on-premises/scim.md +++ b/website/docs/docs/on-premises/scim.md @@ -72,29 +72,48 @@ services: - SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost/auth/saml/callback pactflow: - image: quay.io/pactflow/enterprise + image: quay.io/pactflow/enterprise:2.0.0 depends_on: - postgres + - redis environment: - - PACTFLOW_HTTP_PORT=9292 - - PACTFLOW_BASE_URL=http://localhost http://pactflow:9292 - - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres - # insecure settings only for the purposes of this demo! Not to be used in production. + # This is set to localhost for this example but in a real deployment, this needs to be set to the actual URL of the application + - PACTFLOW_BASE_URL=http://localhost + # Insecure setting only for the purposes of this demo! Not to be used in production. - PACTFLOW_DATABASE_SSLMODE=disable + # Insecure setting only for the purposes of this demo! Not to be used in production. - PACTFLOW_REQUIRE_HTTPS=false - - PACTFLOW_SECURE_COOKIES=false - - PACTFLOW_LOG_FORMAT=short # normally this would be set to json, use short for demo only + # Demo auth should only be used for demo purposes. Not to be used in production. + - PACTFLOW_DEMO_AUTH_ENABLED=true + # 'Allow all' for the webhook host whitelist should only be used for demo purposes. See docs for configuring this in production. + - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ + - PACTFLOW_HTTP_PORT=9292 + # Link to the postgres database + - PACTFLOW_DATABASE_URL=postgres://postgres:password@postgres/postgres + - PACTFLOW_LOG_LEVEL=info - PACTFLOW_ADMIN_API_KEY=admin - - PACTFLOW_MASTER_SECRETS_ENCRYPTION_KEY=thisissomerandombytes + - PACTFLOW_MASTER_ENCRYPTION_KEY=thisissomerandombytes + - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- + - PACT_BROKER_ADMIN_API_KEY=admin + - PACTFLOW_HTTP_LOGGING_ENABLED=true + # Link to the redis cache + - REDIS_URL=redis://redis:6379 + # SAML settings - PACTFLOW_SAML_AUTH_ENABLED=true - PACTFLOW_SAML_IDP_NAME=Simple SAML - PACTFLOW_SAML_IDP_SSO_TARGET_URL=http://localhost:8080/simplesaml/saml2/idp/SSOService.php - PACTFLOW_SAML_IDP_CERT_FINGERPRINT=11:9B:9E:02:79:59:CD:B7:C6:62:CF:D0:75:D9:E2:EF:38:4E:44:5F - PACTFLOW_SAML_IDP_ID_ATTRIBUTE=uid - - PACTFLOW_SAML_EMAIL_ATTRIBUTE=email - - PACTFLOW_COOKIE_SECRET=at-least-64-char-secret---------at-least-64-char-secret--------- - - PACT_BROKER_ADMIN_API_KEY=admin - - PACTFLOW_WEBHOOK_HOST_WHITELIST=/.*/ + - PACTFLOW_SAML_EMAIL_ATTRIBUTE=email + ports: + - "80:9294" + healthcheck: + test: ["CMD", "supervisorctl", "status", "haproxy", "marko", "pactflow"] + interval: 30s + timeout: 10s + retries: 3 + volumes: + - ./pactflow-onprem.lic:/home/pactflow-onprem.lic ports: - "80:9292" healthcheck: @@ -130,6 +149,9 @@ services: LOGGING_LEVEL_ORG_APACHE_HC_CLIENT5_HTTP_WIRE: INFO ports: - "8100:8080" + + redis: + image: redis:latest volumes: postgres-volume: diff --git a/website/docs/docs/on-premises/security-audit-report.md b/website/docs/docs/on-premises/security-audit-report.md index fb44053f..c85bb07e 100644 --- a/website/docs/docs/on-premises/security-audit-report.md +++ b/website/docs/docs/on-premises/security-audit-report.md @@ -106,54 +106,6 @@ This can be observed by viewing the source of the login form. ``` -### CVE-2022-2625 - -#### Description - -Given certain prerequisites, this vulnerability allows arbitrary code to be run. - -#### Component - -postgresql14-dev package for Alpine - -#### CVE - -[https://nvd.nist.gov/vuln/detail/CVE-2022-2625](https://nvd.nist.gov/vuln/detail/CVE-2022-2625) - -#### Status - -Non-exploitable. - -#### Notes - -This vulnerability applies to the PostgreSQL server only. The PactFlow Docker image only uses the PostgreSQL client, and hence is not affected by this vulnerability. - -### CVE-2022-37434 - -#### Description - -A heap-based buffer over-read or buffer overflow in inflate in inflate.c via a large gzip header extra field. - -#### Component - -zlib package for Alpine - -#### CVE - -[https://nvd.nist.gov/vuln/detail/CVE-2022-37434](https://nvd.nist.gov/vuln/detail/CVE-2022-37434) - -#### Affected versions of PactFlow - -All. - -#### Status - -Unfixed. - -#### Notes - -As of 24 August 2022, there is no fix available. A patch release of PactFlow will be put out as soon as a fix is available. - ### CVE-2021-41816 #### Component @@ -170,7 +122,7 @@ False positive. #### Notes -This vulnerability only affects platforms that use a 4 byte long data type, typically Windows. The PactFlow base image uses 64 bit Alpine Linux, which uses an [8 byte long](https://www.ibm.com/docs/en/ibm-mq/9.0?topic=platforms-standard-data-types-unix-linux-windows). +This vulnerability only affects platforms that use a 4 byte long data type, typically Windows. The PactFlow base image uses 64 bit Ubuntu Linux, which uses an [8 byte long](https://www.ibm.com/docs/en/ibm-mq/9.0?topic=platforms-standard-data-types-unix-linux-windows). ### CVE-2020-36599 diff --git a/website/sidebars.js b/website/sidebars.js index 020eaa02..ff3350a7 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -441,133 +441,6 @@ module.exports = { } ], }, - { - type: "category", - label: "On-Premises 2.x", - items: [ - { - type: "category", - label: "Installation", - items: [ - "docs/on-premises-2x", - "docs/on-premises-2x/system-requirements", - "docs/on-premises-2x/docker-image-registry", - "docs/on-premises-2x/network-configuration", - "docs/on-premises-2x/installation/migrating", - "docs/on-premises-2x/database", - "docs/on-premises-2x/redis", - "docs/on-premises-2x/logging", - { - type: "category", - label: "Authentication", - items: [ - "docs/on-premises-2x/authentication/demo", - "docs/on-premises-2x/authentication/saml", - ], - }, - { - type: "category", - label: "Application configuration", - items: [ - "docs/on-premises-2x/environment-variables", - "docs/on-premises-2x/environment-variables/templates", - "docs/on-premises-2x/environment-variables/timezones", - "docs/on-premises-2x/license", - ], - }, - "docs/on-premises-2x/docker-compose-example", - "docs/on-premises-2x/installation/load-testing", - "docs/on-premises-2x/installation/checklist", - ], - }, - { - type: "category", - label: "Upgrading", - items: ["docs/on-premises-2x/upgrading/database-migrations"], - }, - { - type: "category", - label: "Operation", - items: ["docs/on-premises-2x/authentication"], - }, - { - type: "category", - label: "Maintenance", - items: ["docs/on-premises-2x/maintenance/database"], - }, - { - type: "category", - label: "SCIM", - items: ["docs/on-premises-2x/scim"], - }, - { - type: "category", - label: "Security and support", - items: [ - 'docs/on-premises/releases/2.0.0', - 'docs/on-premises/releases/1.36.1', - "docs/on-premises/releases/1.36.0", - "docs/on-premises/releases/1.35.0", - "docs/on-premises/releases/1.34.0", - "docs/on-premises/releases/1.33.0", - "docs/on-premises/releases/1.32.0", - "docs/on-premises/releases/1.31.0", - "docs/on-premises/releases/1.30.0", - "docs/on-premises/releases/1.29.0", - "docs/on-premises/releases/1.28.0", - "docs/on-premises/releases/1.27.0", - "docs/on-premises/releases/1.26.0", - "docs/on-premises/releases/1.25.0", - "docs/on-premises/releases/1.24.0", - "docs/on-premises/releases/1.23.1", - "docs/on-premises/releases/1.23.0", - "docs/on-premises/releases/1.22.1", - "docs/on-premises/releases/1.22.0", - "docs/on-premises/releases/1.21.1", - "docs/on-premises/releases/1.21.0", - "docs/on-premises/releases/1.20.0", - "docs/on-premises/releases/1.19.2", - "docs/on-premises/releases/1.19.1", - "docs/on-premises/releases/1.19.0", - "docs/on-premises/releases/1.18.0", - "docs/on-premises/releases/1.17.3", - "docs/on-premises/releases/1.17.2", - "docs/on-premises/releases/1.17.1", - "docs/on-premises/releases/1.17.0", - "docs/on-premises/releases/1.16.0", - "docs/on-premises/releases/1.15.0", - "docs/on-premises/releases/1.14.8", - "docs/on-premises/releases/1.14.7", - "docs/on-premises/releases/1.14.6", - "docs/on-premises/releases/1.14.5", - "docs/on-premises/releases/1.14.4", - "docs/on-premises/releases/1.14.3", - "docs/on-premises/releases/1.14.2", - "docs/on-premises/releases/1.14.1", - "docs/on-premises/releases/1.14.0", - "docs/on-premises/releases/1.13.1", - "docs/on-premises/releases/1.13.0", - "docs/on-premises/releases/1.12.0", - "docs/on-premises/releases/1.11.1", - "docs/on-premises/releases/1.11.0", - "docs/on-premises/releases/1.10.0", - "docs/on-premises/releases/1.9.0", - "docs/on-premises/releases/1.8.0", - "docs/on-premises/releases/1.7.0", - "docs/on-premises/releases/1.6.1", - "docs/on-premises/releases/1.6.0", - "docs/on-premises/releases/1.5.0", - "docs/on-premises/releases/1.4.1", - "docs/on-premises/releases/1.4.0", - ], - }, - { - type: "category", - label: "Troubleshooting", - items: ["docs/on-premises-2x/troubleshooting"], - }, - ], - }, { type: "category", label: "Releases", diff --git a/website/static/img/on-prem-architecture-2x.png b/website/static/img/on-prem-architecture-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..21d68fce91928dd346e18bd02d7949b9ed054d77 GIT binary patch literal 274905 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

(!j5D23(Fx+3`EZK!+(7E`nmm(rq! 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 BRoVam literal 0 HcmV?d00001