# Enterprise Installs

This document covers advanced configuration and administration for Quilt Enterprise installations.

> For installation instructions, see [Installation](/quilt-python-sdk/installation.md). For architecture details, see [Architecture](/architecture.md).

## Health and Monitoring

To check the status of your Quilt stack after bring-up or update, check the stack health in the CloudFormation console.

### Elasticsearch Cluster

If you notice slow or incomplete search results, check the status of the Quilt Elasticsearch cluster. To find the Quilt search cluster from CloudFormation, click on the Quilt stack, then "Resources." Click on the "Search" resource.

If your cluster status is not "Green" (healthy), please contact Quilt support. Causes of unhealthy search clusters include:

* Running out of storage space
* High index rates (e.g., caused by adding or updating very large numbers of files in S3)

### Service Limits

This deployment does not require an increase in limits for your AWS Account.

### External Dependencies

In addition to containers running in Fargate, Quilt includes a set of AWS Lambda functions. These lambda functions are not scanned by AWS Marketplace. The [code for the lambda functions](https://github.com/quiltdata/quilt/tree/master/lambdas) is open-source and has been verified through an independent security audit.

## Advanced configuration

The default Quilt settings are adequate for most use cases. The following section covers advanced customization options.

### Setting the default role

**The Quilt admin must log in and set the default role** in order for new users to be able to sign up.

![](/files/bHdgRSmaXDxg8aV5abS6)

## Single sign-on (SSO)

### Google

You can enable users on your Google domain to sign in to Quilt. Refer to [Google's instructions on OAuth2 user agents](https://developers.google.com/identity/protocols/OAuth2UserAgent) and create authorization credentials to identify your Quilt stack to Google's OAuth 2.0 server.

![](/files/-MK0AF_GTeFmrpZEtl7r)

Copy the `Client ID` and `Client secret` to a safe place. Add `<QuiltWebHost>/oauth-callback` to *authorized redirect URIs*.

### Microsoft Entra ID (Azure Active Directory)

1. Go to [Microsoft Entra admin center](https://entra.microsoft.com) → **Microsoft Entra ID → Applications → App registrations → New registration**.
2. Name the app, select the supported account types, and click **Register**. Note the **Application (client) ID** and **Directory (tenant) ID**.
3. Go to **Authentication → Add a platform → Web**. Add the redirect URI `<QuiltWebHost>/oauth-callback`. Under **Implicit grant and hybrid flows**, enable **ID tokens** (required — login will fail without it). Click **Save**.
4. Go to **Certificates & secrets → New client secret**. Copy the **Value** immediately — it is not shown again. (Do not use the Secret ID.)
5. Go to **API permissions → Add a permission → Microsoft Graph → Delegated**. Add `openid`, `profile`, `email`, `offline_access`, and `User.Read`, then click **Grant admin consent**. Without admin consent, each user is typically prompted to grant these permissions on their first login; granting admin consent approves them tenant-wide (subject to your org's policies) and avoids end-user prompts.
6. Your `AzureBaseUrl` is `https://login.microsoftonline.com/<TENANT_ID>/v2.0`. Reference [Microsoft identity platform and OpenID Connect protocol](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc) and [National clouds](https://learn.microsoft.com/en-us/entra/identity-platform/authentication-national-cloud) for non-standard endpoints.

   > **`AzureBaseUrl` must end in `/v2.0`. Append it if missing.**
7. For SSO Permissions Mapping:
   * Create security groups in Entra and assign users.
   * In the app registration, go to **Token configuration → Add groups claim** (or **Edit** if it already exists) and configure it to emit **Group IDs** in the **ID token**.
   * Create a [configuration file](/quilt-platform-administrator/advanced/sso-permissions.md) to map Entra Group IDs to Quilt roles.
8. Proceed to [Enabling SSO](#enabling-sso).

### Okta

1. Go to Okta > Admin > Applications > Applications

   ![](/files/eeoPmYqZFu79NzZdCa3Y)
2. Click `Create App Integration`. A new modal window opens.
3. Assign `Sign-in method` radio button to `OIDC - OpenID Connect`.
4. Assign `Application type` radio button to `Web Application`.

   ![](/files/1J0yM0Pr674Co2vq8asI)
5. Click the `Next` button.
6. Rename the default `App integration name` to `Quilt` or something distinctive for your organization to identify it.
7. Add the [Quilt logo](https://user-images.githubusercontent.com/1322715/198700580-da72bd8d-b460-4125-ba31-a246965e3de8.png) for user recognition.
8. Configure the new web app integration as follows:
   1. For `Grant type` check the following: `Authorization Code`, `Refresh Token`, and `Implicit (hybrid)`.

      > **Important:** `Refresh Token` must be checked. Without it, the Quilt registry cannot complete the sign-in flow and will return a 401 error.
   2. To the `Sign-in redirect URIs` add `<QuiltWebHost>/oauth-callback` URL.
   3. Leave the `Allow wildcard * in the login URI redirect` checkbox **unchecked** unless you need wildcard redirect URIs (e.g., for multiple subdomains). Note that wildcards only match a single subdomain level: `*.example.com` matches `app.example.com` but NOT `app.dev.example.com`.
   4. Optionally add to the `Sign-out redirect URIs` (if desired by your organization).
   5. **Uncheck "Enable immediate access"** (also called Federation Broker Mode). This setting is on by default and will cause SSO to fail with `access_denied — Identity Provider: Unknown`. When unchecked, you can assign users directly.
   6. For the `Assignments > Controlled Access` selection, choose the option desired by your organization. Ensure at least one user or group is assigned to the app.
9. Once you click the `Save` button you will have a new application integration to review.
   1. If it's undefined, update the `Initiate login URI` to your `<QuiltWebHost>` URL.
   2. Copy the `Client ID`, `Secret`, and `Base URL` to a safe place
10. **Configure the authentication policy.** Go to **Security > Authentication Policies** and check which policy your new app is assigned to. The default policy ("Any two factors") requires MFA, which will block sign-in unless all users have MFA enrolled. Create or use a policy that allows password-only authentication. When creating a new policy, also edit the **Catch-all Rule** — it defaults to 2 factor types.
11. Go to **Okta > Security > API > Authorization servers**
    1. You should see a `default` entry with the `Audience` value set to `api://default`, and an `Issuer URI` that looks like the following:

       ```
       <MY_COMPANY>.okta.com/oauth2/default
       ```
    2. Click on the `default` authorization server. Go to the **Access Policies** tab and ensure there is at least one **rule** that grants tokens for Authorization Code flow. A policy with no rules will silently deny all token requests, causing sign-in to fail.
    3. See [Okta authorization servers](https://developer.okta.com/docs/concepts/auth-servers/#which-authorization-server-should-you-use) for more.
12. Proceed to [Enabling SSO](#enabling-sso)

### OneLogin

1. Go to Administration > Applications > Custom Connectors
2. Click `New Connector`
   1. Name the connector *Quilt Connector* or something similar
   2. Set `Sign on method` to `OpenID Connect`
   3. Set `Login URL` to `<QuiltWebHost>/oauth-callback`
   4. Click "Save"
3. Go back to Applications > Custom Connectors
4. Click `Add App to Connector`
5. Save the app (be sure to save it for the Organization)
6. Go to Applications > Applications > *Your new app* > SSO

   1. Click SSO. Copy the `Client ID`, `ClientSecret` and `Issuer URL` to a safe place.
   2. "Application Type" should be set to `Web`.
   3. "Token Endpoint" should be set to `POST`.

   ![](/files/M8k0WwnBUOGzZPCnpX2x)
7. Add *Your new app* to the users who need to access Quilt:

   ![](/files/-MK0AF_OHVC7UYi8uNmz)
8. Proceed to [Enabling SSO](#enabling-sso).

### Enabling SSO

The SSO parameter names in your stack depend on how the CloudFormation template was built — not on whether you use the Console, CLI, or Terraform to deploy it. To determine which applies, look at your stack's parameters in CloudFormation:

* **`SingleSignOnProvider` dropdown present** → your stack uses single-provider SSO; follow the [single-provider instructions](#single-provider-sso) below.
* **`GoogleAuth`, `AzureAuth`, etc. present** → your stack uses multi-provider SSO; follow the [multi-provider instructions](#multi-provider-sso) below.

#### Single-provider SSO

Set `PasswordAuth` to `Enabled` in the Quilt template (AWS Console > CloudFormation > *Quilt stack* > Update > Use current template > Next > Specify stack details), then select your provider from the `SingleSignOnProvider` dropdown (Google, Okta, OneLogin, or Azure).

![](/files/Byqh2QrtyldSxeg0yKTt)

Use the following settings for the remaining parameters:

| CFT Parameter              | Google SSO    | Okta SSO  | OneLogin SSO | Azure SSO               |
| -------------------------- | ------------- | --------- | ------------ | ----------------------- |
| `SingleSignOnClientId`     | Client ID     | Client ID | Client ID    | Application (client) ID |
| `SingleSignOnClientSecret` | Client secret | Secret    | ClientSecret | Client secret Value     |
| `SingleSignOnBaseUrl`      | N/A           | Base URL  | Issuer URL   | AzureBaseUrl            |

> Be sure to set the [default role](#setting-the-default-role) as indicated above.

#### Multi-provider SSO

Stacks built with multi-provider SSO use per-provider parameters instead of the shared `SingleSignOnProvider` dropdown, allowing multiple providers to be enabled simultaneously. These parameters are passed the same way regardless of deployment method — Console, CLI, or Terraform. See [Authentication Examples](https://github.com/quiltdata/iac/blob/main/EXAMPLES.md#authentication-examples) for examples using the [Quilt IAC Terraform module](https://github.com/quiltdata/iac).

| Function      | Google               | Okta               | OneLogin               | Azure               |
| ------------- | -------------------- | ------------------ | ---------------------- | ------------------- |
| Enable        | `GoogleAuth`         | `OktaAuth`         | `OneLoginAuth`         | `AzureAuth`         |
| Client ID     | `GoogleClientId`     | `OktaClientId`     | `OneLoginClientId`     | `AzureClientId`     |
| Client Secret | `GoogleClientSecret` | `OktaClientSecret` | `OneLoginClientSecret` | `AzureClientSecret` |
| Base URL      | N/A                  | `OktaBaseUrl`      | `OneLoginBaseUrl`      | `AzureBaseUrl`      |

### Preparing an AWS Role for use with Quilt

These instructions document how to set up an existing role for use with Quilt. If the role you want to use doesn't exist yet, create it now. For guidance creating IAM roles, see: [IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html), and the [Principle of Least Privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)

Go to your Quilt stack in CloudFormation. Go to `Outputs`, then find `RegistryRoleARN` and copy its value. It should look something like this: `arn:aws:iam::000000000000:role/stackname-ecsTaskExecutionRole`.

Go to the IAM console and navigate to `Roles`. Select the role you want to use. Go to the `Trust Relationships` tab for the role, and select `Edit Trust Relationship`. The statement might look something like this:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    "... one or more statements"
  ]
}
```

Add an object to the beginning of the Statement array with the following contents:

```json
{
  "Effect": "Allow",
  "Principal": {
    "AWS": "$YOUR_REGISTRY_ROLE_ARN"
  },
  "Action": "sts:AssumeRole"
},
```

Note the comma after the object. Your trust relationship should now look something like this:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "$YOUR_REGISTRY_ROLE_ARN"
      },
      "Action": "sts:AssumeRole"
    },
    "... whatever was here before"
  ]
}
```

You can now configure a Quilt Role with this role (using the Catalog's admin panel, or `quilt3.admin.create_role`).

### S3 buckets with Service-Side Encryption using Key Management Service (SSE-KMS)

In order for Quilt to access and index buckets encrypted with SSE-KMS, you must do three things:

1. Add KMS Key Usage to Quilt Permission Boundary
2. Add Quilt Principals to KMS Key Policy
3. Add KMS Key Access to a Source=Quilt Role

NOTE: This will not work with the default Source=Custom Roles.

#### 1. Add KMS Key Usage to Quilt Permission Boundary

By default, AWS does not allow anything in your account to access KMS. If you haven't done so already, create an IAM policy that explicitly enables KMS access.

```json
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": [
      "kms:Decrypt",
      "kms:GenerateDataKey"
    ],
    "Resource": "arn:aws:kms:us-west-2:111122223333:key/*"
  }
}
```

Go to CloudFormation > Your Quilt Stack -> Update -> Parameters and add the ARN of that IAM policy to `ManagedUserRoleExtraPolicies` at the bottom of the page:

![](/files/UHAU0KvehEnaWzCbgInO)

If other policies are already in that field, you will need to add a comma before appending the ARN.

#### 2. Add Quilt Principals to KMS Key Policy

In order for Quilt to index buckets with SSE-KMS, you must add certain principals to the corresponding key policy. Go to CloudFormation > Your Quilt Stack > Resources and look for IAM roles with the following logical IDs:

* `AmazonECSTaskExecutionRole`
* `PkgEventsRole`
* `PkgSelectLambdaRole`
* `SearchHandlerRole`
* `T4BucketReadRole`
* `T4BucketWriteRole`

Note the ARN for each of the above logical IDs and add an Allow statement similar to the following to the KMS key policy:

```json
{
    "Effect": "Allow",
    "Principal": {
        "AWS": [
            "<RoleARN-1>",
            ...
            "<RoleARN-N>"
        ]
    },
    "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey"
    ],
    "Resource": "*"
}
```

#### 3. Add KMS Key Access to Quilt Role

Finally, you need create a restricted policy that gives a Quilt role access to the keys for specific buckets, e.g:

```json
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": [
      "kms:Decrypt",
      "kms:GenerateDataKey"
    ],
    "Resource": [
      "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
      "arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321"
    ]
  }
}
```

You can now create a Quilt Policy from this policy using the Catalog's admin panel. Afterwards, you can attach that Policy to a user-defined Quilt Role (which has Source=Quilt in the Roles panel, as opposed to system-defined Source=Custom Roles).

## Backup and Recovery

All data and metadata in Quilt is stored in S3. S3 data is automatically backed up (replicated across multiple available zones). To protect against accidental deletion or overwriting of data, we strongly recommend enabling object versioning for all S3 buckets connected to Quilt.

No data will be lost if a Quilt stack goes down. The Quilt search indexes will be automatically rebuilt when buckets are added to a new stack.

### Region Failure

To protect against data loss in the event of a region failure, enable [S3 Bucket Replication](https://aws.amazon.com/s3/features/replication/) on all S3 buckets.

The time to restore varies with storage needs, but a <2-hour recovery time objective (RTO) and <15 minute recovery point objective (RPO) are generally possible.

To restore Quilt in your backup region:

1. Create a new Quilt stack from the same CloudFormation template in the backup region.
2. Connect the replica buckets (in the backup region) to your Quilt stack. In the Quilt catalog, select "Users and Buckets"->"Buckets" and enter the bucket information.

## Emergency Maintenance

See [Troubleshooting](/quilt-python-sdk/more/troubleshooting.md)

## Support

Support is available to all Quilt customers by:

* online chat (in the Quilt catalog)
* email to <support@quilt.bio>
* [Slack](https://slack.quilt.bio)

Quilt guarantees response to support issues according to the following SLAs for Quilt Business and Quilt Enterprise customers.

### Quilt Business

|            | Initial Response | Temporary Resolution |
| ---------- | ---------------- | -------------------- |
| Priority 1 | 1 business day   | 3 business days      |
| Priority 2 | 2 business days  | 5 business days      |
| Priority 3 | 3 business days  | N/A                  |

### Quilt Enterprise

|            | Initial Response | Temporary Resolution |
| ---------- | ---------------- | -------------------- |
| Priority 1 | 4 business hours | 1 business day       |
| Priority 2 | 1 business day   | 2 business days      |
| Priority 3 | 1 business days  | N/A                  |

### Definitions

* *Business Day* means Monday through Friday (PST), excluding holidays observed by Quilt Data.
* *Business Hours* means 8:00 a.m. to 7:00 p.m. (PST) on Business Days.
* *Priority 1* means a critical problem with the Software in which the Software inoperable;
* *Priority 2* means a problem with the Software in which the Software is severely limited or degraded, major functions are not performing properly, and the situation is causing a significant impact to Customer's operations or productivity;
* *Priority 3* means a minor or cosmetic problem with the Software in which any of the following occur: the problem is an irritant, affects nonessential functions, or has minimal impact to business operations; the problem is localized or has isolated impact; the problem is an operational nuisance; the problem results in documentation errors; or the problem is any other problem that is not a Priority 1 or a Priority 2, but is otherwise a failure of the Software to conform to the Documentation or Specifications;
* *Temporary Resolution* means a temporary fix or patch that has been implemented and incorporated into the Software by Quilt Data to restore Software functionality.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.quilt.bio/quilt-platform-administrator/technical-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
