LLM Classification Configuration
Astralis' Data Discovery module includes an LLM-powered data classifier that leverages large language models to automatically identify and categorize sensitive data in your systems. This guide explains how to configure AWS Bedrock as the LLM backend for Astralis' data classification capabilities.
Overview
The LLM classifier in Astralis can use a variety of LLM providers to support intelligent, context-aware data categorization.
If you are running Astralis on AWS, you may want to use AWS Bedrock as the LLM provider for Astralis' data classifier.
AWS Bedrock provides access to foundation models from leading AI companies, enabling sophisticated natural language processing for data classification tasks.
Prerequisites
Before configuring AWS Bedrock for Astralis, ensure you have:
- An Astralis deployment running on AWS EKS or AWS ECS (Astralis 2.94.0 or later if you plan to use the optional Gemma 4 31B model through Bedrock Mantle)
- AWS Bedrock enabled in your AWS account with appropriate model access
- Permissions to create and manage IAM roles and policies
- Access to update Astralis configuration settings
- Astralis OAuth access token with
config:updatescope
Note: AWS Bedrock must be enabled in your AWS account and you must have access to the foundation models you wish to use. Visit the AWS Bedrock console (opens in a new tab) to enable model access.
Authentication Methods
Astralis supports multiple authentication methods for connecting to AWS Bedrock.
Recommended: IAM Role-Based Authentication
For production deployments, Ethyca recommends using IAM role-based authentication to eliminate the need for long-term credentials:
Note: The steps below serve as an illustrative example of how to set up appropriate AWS resources. They should be adapted to meet your organization’s AWS best practices.
Note: Many of the examples below use CLI tools like aws iam and eksctl, as a reference. You may prefer to use terraform to define and manage these resources.
EKS Deployments: IRSA (IAM Roles for Service Accounts)
If Astralis is deployed on Amazon EKS, use IRSA (see AWS user guide (opens in a new tab)) to enable secure, credential-less authentication.
Step 1: Create an IAM Policy for Bedrock Access
Create an IAM policy that grants the minimum required permissions to invoke Bedrock models:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeBedrockFoundationModels",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "arn:aws:bedrock:*:*:foundation-model/*"
},
{
"Sid": "InvokeBedrockInferenceProfiles",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "arn:aws:bedrock:*:*:inference-profile/*"
},
{
"Sid": "InvokeMantleDefaultProject",
"Effect": "Allow",
"Action": [
"bedrock-mantle:CreateInference"
],
"Resource": "arn:aws:bedrock-mantle:*:ACCOUNT_ID:project/default"
}
]
}Bedrock Mantle: The InvokeMantleDefaultProject statement is only needed if you use Google Gemma 4 31B, which is served through the Bedrock Mantle endpoint, a separate IAM service namespace that the bedrock:InvokeModel* statements do not cover. Replace ACCOUNT_ID with your AWS account ID. If you use Claude Haiku 4.5, the recommended model, you can omit the statement. See Supported Bedrock Models.
Using the AWS CLI:
aws iam create-policy \
--policy-name bedrock-invoke-policy \
--policy-document file://bedrock-policy.jsonStep 2: Set Up OIDC Provider and Service Account
Associate an OIDC provider with your EKS cluster (one-time setup):
# Set your cluster details
CLUSTER_NAME="your-cluster-name"
AWS_REGION="us-east-1"
NAMESPACE="fides"
SERVICE_ACCOUNT="fides-bedrock-sa"
# Associate OIDC provider with the cluster
eksctl utils associate-iam-oidc-provider \
--region=$AWS_REGION \
--cluster=$CLUSTER_NAME \
--approveStep 3: Create the IAM Service Account
Create a Kubernetes ServiceAccount linked to an IAM role:
# Replace with your policy ARN from Step 1
POLICY_ARN="arn:aws:iam::ACCOUNT_ID:policy/bedrock-invoke-policy"
# Create the service account and IAM role
eksctl create iamserviceaccount \
--name=$SERVICE_ACCOUNT \
--namespace=$NAMESPACE \
--cluster=$CLUSTER_NAME \
--region=$AWS_REGION \
--attach-policy-arn=$POLICY_ARN \
--approve \
--override-existing-serviceaccountsStep 4: Update Your Astralis Deployment
Configure your Astralis deployment to use the service account:
apiVersion: apps/v1
kind: Deployment
metadata:
name: fides
namespace: fides
spec:
template:
spec:
serviceAccountName: fides-bedrock-sa # Reference the service account
containers:
- name: fides
env:
- name: AWS_REGION
value: "us-east-1" # Set to your AWS regionNote: The AWS SDK used by Astralis automatically detects and uses the IRSA credentials without requiring additional environment variables or configuration within the application. The service account token is automatically mounted and refreshed by EKS.
ECS Deployments: Task IAM Roles
If Astralis is deployed on Amazon ECS, use ECS Task IAM Roles for authentication:
Step 1: Create an IAM Policy
Use the same IAM policy JSON from the EKS section above to create a policy with Bedrock permissions.
Step 2: Create an ECS Task Role
Create an IAM role with a trust policy that allows ECS tasks to assume it:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}Attach the Bedrock policy to the task role:
aws iam attach-role-policy \
--role-name fides-ecs-task-role \
--policy-arn arn:aws:iam::ACCOUNT_ID:policy/bedrock-invoke-policyStep 3: Update Your ECS Task Definition
Configure your ECS task definition to use the task role:
{
"family": "fides-task",
"taskRoleArn": "arn:aws:iam::ACCOUNT_ID:role/fides-ecs-task-role",
"containerDefinitions": [
{
"name": "fides",
"environment": [
{
"name": "AWS_REGION",
"value": "us-east-1"
}
]
}
]
}Note: ECS automatically provides temporary credentials to containers via the task role. No additional configuration is needed in your application code.
Optional: Assuming a Separate IAM Role
The IRSA and ECS Task Role setups above give the Astralis worker an AWS identity, and by default Astralis calls Bedrock directly as that identity. You can instead configure Astralis to assume a separate IAM role for every Bedrock call. This is the simplest way to reach Bedrock in a different AWS account from your Astralis deployment, without registering your cluster's OIDC provider in that account. It also lets you keep Bedrock permissions on a dedicated role rather than on the worker's own role.
The worker's own identity (the IRSA role or ECS task role) is still required: it is the identity that calls sts:AssumeRole.
Configuration Variables
Set the following environment variables on your Astralis worker containers:
| Name | Type | Default | Description |
|---|---|---|---|
FIDESPLUS__BEDROCK__ASSUME_ROLE_ARN | string | None | ARN of the IAM role Bedrock calls should assume, e.g. arn:aws:iam::222222222222:role/fides-bedrock-invoke. Unset means the worker's own credentials are used. |
FIDESPLUS__BEDROCK__ROLE_SESSION_NAME | string | FidesAssumeRoleSession | STS session name for the assumed role (2-64 characters of letters, digits, or _+=,.@-). Appears in CloudTrail. |
FIDESPLUS__BEDROCK__EXTERNAL_ID | string | None | STS external ID to present when assuming the role. Only needed if the target role's trust policy requires one. |
Note: These are deployment settings, read when the Astralis process starts. They cannot be set through the Astralis configuration API; changing them requires restarting the containers.
Which Credentials Are Used
- No role configured: Bedrock calls use the worker's ambient credentials (IRSA, ECS task role, or instance profile) exactly as before. If you already set the
AWS_ROLE_NAMEenvironment variable for the underlying LLM library, it continues to apply. - Role configured: every Bedrock call assumes
FIDESPLUS__BEDROCK__ASSUME_ROLE_ARN, starting from the worker's ambient credentials. AWS_BEARER_TOKEN_BEDROCKis set: the bearer token overrides the role entirely and Bedrock calls are signed with the token, not the assumed role. Astralis logs a warning when both are present. Remove the variable for the role to take effect.
Note: Configuring the role the worker already runs as is harmless: Astralis detects that it is already that role and skips the extra AssumeRole call.
Example: Cross-Account Role Assumption
This example assumes Astralis runs in account 111111111111 as the role fides-worker (its IRSA or ECS task role), and Bedrock is used in account 222222222222 through the role fides-bedrock-invoke.
Step 1: Create the Target Role in the Bedrock Account
In account 222222222222, create fides-bedrock-invoke with a trust policy that delegates to the worker's account, narrowed to the worker's role.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowFidesWorker",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"ArnEquals": {
"aws:PrincipalArn": "arn:aws:iam::111111111111:role/fides-worker"
}
}
}
]
}If you set FIDESPLUS__BEDROCK__EXTERNAL_ID, also add an sts:ExternalId condition with the same value to the statement's Condition block. Leave it out otherwise: with the condition present and no external ID configured, the assumption fails with AccessDenied.
"StringEquals": {
"sts:ExternalId": "your-external-id"
}Attach the Bedrock invoke policy from Step 1 of the EKS section to fides-bedrock-invoke. The Bedrock permissions belong on the target role, since that is the identity that calls Bedrock.
Step 2: Allow the Worker to Assume the Target Role
In account 111111111111, add the following to the worker role's (fides-worker) permissions. Without this grant, the assumption fails with AccessDenied even when the trust policy is correct.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeBedrockRole",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/fides-bedrock-invoke"
}
]
}Note: No sts:GetCallerIdentity permission is needed. AWS allows that call for every authenticated identity and it cannot be denied by policy.
Step 3: Configure Astralis
Set the role variables on the Astralis containers. On EKS, alongside the service account from the IRSA section:
spec:
template:
spec:
serviceAccountName: fides-bedrock-sa
containers:
- name: fides
env:
- name: AWS_REGION
value: "us-east-1"
- name: FIDESPLUS__BEDROCK__ASSUME_ROLE_ARN
value: "arn:aws:iam::222222222222:role/fides-bedrock-invoke"
- name: FIDESPLUS__BEDROCK__EXTERNAL_ID # only if the trust policy requires it
value: "your-external-id"On ECS, add the same variables to the container's environment in the task definition. Then restart the containers and verify the setup with the connection test.
Alternative: Long-Term API Token (Not Recommended for Production)
For development or testing environments, you can use long-term Bedrock API tokens. However, this approach is not recommended for production due to security concerns around credential management and rotation.
To use long-term API tokens, create a long-term Bedrock API token, and then set the following environment variable on your deployed Astralis containers:
| Name | Type | Default | Description |
|---|---|---|---|
AWS_BEARER_TOKEN_BEDROCK | string | None | One way to authenticate with AWS Bedrock for the LLM classifier. Not required if using IAM role-based authentication (IRSA or Task IAM Roles), which is the recommended approach for production. |
AWS_BEARER_TOKEN_BEDROCK="your-bedrock-api-token"This variable is also referenced in the Fidesplus configuration variable reference.
Security Warning: Long-term API token require manual rotation and are more susceptible to credential leakage. Always use IAM role-based authentication (IRSA or Task IAM Roles) for production deployments.
If AWS_BEARER_TOKEN_BEDROCK is set, it takes precedence over IAM credentials, including a role configured with FIDESPLUS__BEDROCK__ASSUME_ROLE_ARN. Remove it when moving to role-based authentication.
Testing the Bedrock Connection
Once you've configured authentication, verify that Astralis can successfully connect to AWS Bedrock.
Using the Astralis API
Test the connection by making a POST request to the Bedrock test endpoint:
curl -X POST '{{FIDES_URL}}/api/v1/plus/connection/aws-bedrock/test' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {{FIDES_ACCESS_TOKEN}}' \
-d '{
"model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0",
"aws_region": "us-east-1"
}'In the above example:
{{FIDES_URL}}is the URL to your Astralis server{{FIDES_ACCESS_TOKEN}}is your Astralis OAuth access tokenmodelspecifies the Bedrock model to test (use any model you have access to; for examplebedrock_mantle/google.gemma-4-31bto test the Mantle setup for Gemma 4 31B)aws_regionis the AWS region where Bedrock is enabled. For Bedrock Mantle models this must be one of the Mantle regions
Successful Response
If the connection is configured correctly, you'll receive a success response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"message": "AWS Bedrock connection test completed successfully",
"response_content": "...",
"model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0",
"usage": { "...": "..." },
"error_type": null,
"credential_source": "default_chain",
"warnings": [],
"resolved_role_arn": null,
"worker_identity_arn": "arn:aws:sts::111111111111:assumed-role/fides-worker/...",
"sts_error_code": null
}The credential_source field reports which credentials the test actually used. For the requests shown in this guide, it is default_chain for IRSA, ECS task roles, and other ambient credentials, assumed_role when a separate role was assumed, or env_bearer_token when AWS_BEARER_TOKEN_BEDROCK was used. The values explicit_bearer_token and web_identity apply when credentials are supplied in the request itself. The field is null if the test fails before a credential source is resolved.
Verifying Role Assumption
If you configured FIDESPLUS__BEDROCK__ASSUME_ROLE_ARN, the connection test assumes that role by default. You can make this explicit with credential_source:
curl -X POST '{{FIDES_URL}}/api/v1/plus/connection/aws-bedrock/test' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {{FIDES_ACCESS_TOKEN}}' \
-d '{
"model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0",
"aws_region": "us-east-1",
"credential_source": "assumed_role"
}'To try a role before configuring it, add "aws_role_arn": "arn:aws:iam::222222222222:role/fides-bedrock-invoke" to the request. A role other than the configured one is assumed without the configured external ID, so this works only for roles whose trust policy does not require one.
The response includes the following diagnostic fields, on success and on failure:
| Field | Description |
|---|---|
credential_source | assumed_role when the role was used. Any other value means Bedrock was called with different credentials. |
resolved_role_arn | The role that was assumed, or that Astralis attempted to assume when the assumption was denied. |
worker_identity_arn | The worker's own AWS identity, before assuming the role. This is an STS session ARN of the form arn:aws:sts::<account>:assumed-role/<role>/<session>. The target role's trust policy must allow the corresponding IAM role, arn:aws:iam::<account>:role/<role>, not the session ARN, whose session name changes with each pod or task. |
sts_error_code | The AWS STS error code when the role assumption failed, e.g. AccessDenied. |
error_type | The kind of failure, when success is false. See the table below. |
warnings | Notes about the test, for example that AWS_BEARER_TOKEN_BEDROCK is set and will override the role for classification, or that the test did not exercise the configured role. |
A denied assumption looks like this:
{
"success": false,
"message": "AWS denied assuming the configured Bedrock role. Check that the role exists, that its trust policy allows this deployment's identity, that the deployment's policy grants sts:AssumeRole on it, and that any external ID matches",
"response_content": null,
"model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0",
"usage": null,
"error_type": "RoleAssumptionDeniedError",
"credential_source": "assumed_role",
"warnings": [],
"resolved_role_arn": "arn:aws:iam::222222222222:role/fides-bedrock-invoke",
"worker_identity_arn": "arn:aws:sts::111111111111:assumed-role/fides-worker/...",
"sts_error_code": "AccessDenied"
}Use error_type to tell which side of the setup to fix:
error_type | Meaning | What to check |
|---|---|---|
RoleAssumptionDeniedError | AWS refused to let the worker assume the role. AWS does not say which of the possible causes applies. | The target role exists; its trust policy allows the IAM role behind worker_identity_arn (as Principal or via aws:PrincipalArn); the worker's policy grants sts:AssumeRole on resolved_role_arn; FIDESPLUS__BEDROCK__EXTERNAL_ID matches the trust policy's sts:ExternalId. |
BedrockAccessDeniedError | The role was assumed, but Bedrock refused the model call for it. | The target role's permissions: bedrock:InvokeModel on the model or inference profile, and model access enabled in that account and region. |
InvalidRoleArnError | AWS rejected the role ARN or session name as malformed. | The format of FIDESPLUS__BEDROCK__ASSUME_ROLE_ARN and FIDESPLUS__BEDROCK__ROLE_SESSION_NAME. |
WorkerCredentialsError | The worker has no valid AWS credentials to call STS with. | The worker's own IRSA or ECS task role setup, from the sections above. |
Troubleshooting Connection Issues
If the connection test fails, check the following:
Authentication Issues
- Verify that the IAM policy is correctly attached to the role
- Ensure the trust policy allows the service account or ECS task to assume the role
- Check that the service account annotation (EKS) or task role ARN (ECS) is correctly configured
- If you configured a separate role to assume, see Verifying Role Assumption for how to read the diagnostic fields
Permission Issues
- Confirm that Bedrock is enabled in your AWS account
- Verify you have requested access to the specific foundation models you're trying to use
- Review AWS CloudTrail logs for
AssumeRoleWithWebIdentity(EKS) or IAM role assumption events (ECS)
Network Issues
- Ensure your Astralis deployment has outbound internet access or VPC endpoints for Bedrock
- Verify security groups allow HTTPS (port 443) outbound traffic
- For private deployments, configure VPC endpoints for Bedrock and STS services
Check Astralis Logs
View the Astralis pod or container logs for detailed error messages. When a role is configured, Astralis logs Bedrock calls will assume role with the role ARN before its first Bedrock call, and a warning if AWS_BEARER_TOKEN_BEDROCK will override it.
Supported Bedrock Models
Astralis supports any AWS Bedrock foundation model or inference profile that provides text generation capabilities. A Bedrock deployment must set the "Model override" field on every monitor that uses the LLM classifier; a monitor with no override does not use your AWS account's Bedrock models.
Ethyca recommends two models for the LLM classifier on Bedrock. Both are benchmarked by Ethyca at equivalent overall accuracy with batched classification, and both complete a full classification run in a similar amount of time. Claude Haiku 4.5 is the simplest choice and is available in every Bedrock region. If your deployment can use Bedrock Mantle, Gemma 4 31B is worth considering: it costs roughly a tenth as much per token for the same accuracy. Bedrock Mantle is a newer AWS endpoint serving fewer regions, and AWS ramps its throughput gradually for an account that has not used it before, so move one monitor across first and confirm its classification runs before switching others.
Batched classification: Starting with Astralis 2.94.0, datastore discovery monitors classify the fields of each table together in a small number of LLM calls, instead of one call per field. This is substantially faster and cheaper than earlier releases, with the largest gains on monitors covering many tables, and it is supported with both models below. Monitors already pinned to Claude Haiku 4.5 need no change when upgrading; switching a monitor to Gemma 4 31B is optional and is done by editing its model override. This is unrelated to AWS Bedrock batch inference — see Batched classification vs. batch inference.
Anthropic Claude Haiku 4.5 (recommended)
- Model override:
bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0 - Requires: model access requested in the Bedrock console. The standard IAM policy above is sufficient.
- Why: the simplest setup, and available in every Bedrock region.
Model Access: Anthropic models require you to request access in the AWS Bedrock console before use. Model availability varies by region. Refer to the AWS Bedrock documentation (opens in a new tab) for details.
Claude Haiku 4.5 lifecycle: Claude Haiku 4.5 is an Active model on Amazon Bedrock with no retirement announced. AWS commits to at least six months' notice before an Anthropic model reaches end of life, so it will remain available for at least six months after any such announcement. Ethyca will update this guide when a successor is recommended. You can check the current status on the Claude Haiku 4.5 model card (opens in a new tab).
Google Gemma 4 31B (lower cost)
- Model override:
bedrock_mantle/google.gemma-4-31b - Requires: Astralis 2.94.0 or later, the
InvokeMantleDefaultProjectIAM statement, and a Mantle region. See Using Gemma 4 31B through Bedrock Mantle. - Why: roughly a tenth of Claude Haiku 4.5's per-token price at equivalent classification accuracy. Gemma 4 is not served through classic Bedrock, so Bedrock Mantle is the only way to use it.
If neither model is available for use in your organization, please contact Ethyca support to determine a viable alternative.
Using Gemma 4 31B through Bedrock Mantle
Gemma 4 models are served only through the Bedrock Mantle endpoint (https://bedrock-mantle.<region>.api.aws/openai/v1), which is a separate IAM service namespace from classic Bedrock. To use Gemma 4 31B:
- Run Astralis 2.94.0 or later.
- Include the
InvokeMantleDefaultProjectstatement from the IAM policy above in the role Astralis uses. - Deploy in a Mantle region (see below) and set the model override to
bedrock_mantle/google.gemma-4-31b.
Bedrock Mantle regions
Mantle serves Gemma 4 in-region only, with no cross-region inference profiles. At the time of writing it is available in us-east-1, us-east-2, us-west-2 and eu-central-1; check the Gemma 4 31B model card (opens in a new tab) for the current list. Astralis selects the region from the AWS_REGION environment variable on its containers (set automatically by IRSA on EKS), so make sure it names a Mantle region.
Throughput ramp-up: AWS scales on-demand Mantle throughput for an account gradually, and does not guarantee every request within quota during periods of high demand. Batched classification runs up to 64 LLM calls concurrently by default. If a new account sees throttling errors during its first classification runs, lower the monitor's num_workers classification parameter (for example to 16) and raise it as throughput becomes available. Astralis retries throttled calls automatically.
Batched classification vs. batch inference
"Batch" means two different things in this area, and only one of them is an Astralis feature.
Batched classification is how Astralis composes its prompts. It asks about many of a table's fields in a single request, instead of sending one request per field. Those requests are ordinary real-time inference calls, several of them running at once, and the answers come back while the monitor is still running.
Batch inference is a delivery mode that model providers offer, including AWS Bedrock batch inference (opens in a new tab). You hand the provider a file of independent requests, the provider works through them offline, and you collect the results later — Bedrock reads and writes those files in Amazon S3, with a turnaround measured in hours. Other model providers offer equivalent asynchronous batch APIs.
| Batched classification (Astralis) | Batch inference (model provider) | |
|---|---|---|
| What is batched | many fields of one table in one prompt | many unrelated requests in one job |
| How it is sent | normal real-time inference calls | a separate asynchronous job API |
| When results arrive | during the monitor run, typically minutes | hours later, up to a 24-hour window |
| Extra setup | none beyond the model override | job submission, result storage, and their permissions |
| Why it saves money | fewer, larger calls means fewer tokens overall | a provider discount on batch jobs |
Astralis does not use provider batch inference APIs for classification, so there is no batch job to configure, no S3 bucket to provision, and no bedrock:CreateModelInvocationJob permission to grant. Enabling batch inference in your AWS account changes nothing about how classification runs, and the provider's batch discount does not apply to it. The savings from batched classification come from sending far fewer, larger requests.