Dev.to Security 🔐 Cybersecurity 👁 0 📖 11 min read

Securing and Monitoring AI Workloads on AWS: A Hands-On Enterprise Security Guide

1. Introduction Deploying a generative AI application on AWS is relatively straightforward. Securing that application across its entire lifecycle is considerably more challenging. An enterprise AI application may acce

1. Introduction

Deploying a generative AI application on AWS is relatively straightforward. Securing that application across its entire lifecycle is considerably more challenging.

An enterprise AI application may access confidential documents, invoke foundation models, retrieve customer information and execute actions against business systems. Each integration creates a potential attack surface.

This tutorial demonstrates how to secure an Amazon Bedrock-based AI workload using AWS-native security controls.

Our security objectives are to:

  • Restrict AI model access to authorised workloads.
  • Protect communication between applications and AI services.
  • Prevent unnecessary exposure of sensitive information.
  • Apply AI-specific input and output safeguards.
  • Monitor model invocations, API activity and security findings.
  • Detect suspicious activity and generate operational alerts.

The tutorial assumes a dedicated AWS test environment. Production deployment requires additional controls, including centralised logging, infrastructure-as-code, backup policies and formal change management.

2. Prerequisites and Environment Preparation

Before starting, ensure you have an AWS account, AWS CLI v2, Python 3.11 or later, and the Boto3 SDK.

Use an AWS IAM Identity Center session or another approved temporary-credential mechanism. Avoid creating long-lived IAM access keys.

For this demonstration, we will use the AWS eu-west-2 Region (London), subject to service and model availability.

Verify the AWS identity:

aws sts get-caller-identity

Configure the environment:

export AWS_REGION=eu-west-2
export AWS_ACCOUNT_ID=$(aws sts \
  get-caller-identity \
  --query Account \
  --output text)

export APP_NAME=enterprise-ai

Verify the selected Region:

aws configure get region

If necessary, set the default Region for your CLI profile:

aws configure set region "$AWS_REGION"

Install the required Python library:

python3 -m pip install --upgrade boto3

Security consideration: The identity performing infrastructure setup needs separate administrative permissions from the identity used by the AI application. Never run the production AI workload using an administrator role.

3. Step One: Configure Least-Privilege IAM Access

The first security layer is controlling which AWS identities can invoke AI models.

For this example, create an IAM policy granting access to a specific foundation model. Replace the example model ID with an available model or inference profile supported in your selected Region.

Create a policy file named bedrock-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "InvokeApprovedModel",
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel"
      ],
      "Resource": [
        "arn:aws:bedrock:eu-west-2::foundation-model/REPLACE_WITH_MODEL_ID"
      ]
    }
  ]
}

Create the managed policy:

aws iam create-policy \
  --policy-name EnterpriseAIBedrockInvoke \
  --policy-document file://bedrock-policy.json

Attach this policy to the dedicated application execution role, not to a general-purpose user.

For example, after creating an application role with the appropriate Lambda, ECS or EC2 trust policy:

aws iam attach-role-policy \
  --role-name EnterpriseAIExecutionRole \
  --policy-arn \
  arn:aws:iam::$AWS_ACCOUNT_ID:policy/EnterpriseAIBedrockInvoke

The role EnterpriseAIExecutionRole must already exist and have an appropriate trust relationship.

Important: Some models require inference profile permissions and additional foundation-model resource ARNs. Adapt the policy to the selected model's documented resource requirements rather than granting unrestricted model access.

For stronger isolation, consider IAM conditions restricting inference to an approved VPC endpoint, and guardrail enforcement policies requiring an approved guardrail on supported inference operations.

Verification

Use IAM policy simulation or test from the actual workload role. Confirm that the application can invoke its approved model but cannot invoke an unauthorised model.

A successful test should demonstrate both an allowed operation and a denied operation.

4. Step Two: Secure Bedrock Network Connectivity

Although Amazon Bedrock is a managed AWS service, enterprise applications should minimise unnecessary exposure of inference traffic.

AWS PrivateLink allows applications running inside a VPC to connect privately to supported Bedrock service endpoints.

First, identify the VPC and private subnets used by the AI application.

aws ec2 describe-vpcs \
  --region "$AWS_REGION"

Create a dedicated security group for the VPC endpoint:

aws ec2 create-security-group \
  --group-name enterprise-ai-bedrock-vpce \
  --description "Bedrock private endpoint" \
  --vpc-id vpc-REPLACE

Configure an inbound TCP port 443 rule on that endpoint security group, restricted to the security group used by the AI application.

aws ec2 authorize-security-group-ingress \
  --group-id sg-ENDPOINT \
  --protocol tcp \
  --port 443 \
  --source-group sg-APPLICATION

Create the Bedrock Runtime interface endpoint:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-REPLACE \
  --vpc-endpoint-type Interface \
  --service-name \
  com.amazonaws.eu-west-2.bedrock-runtime \
  --subnet-ids subnet-PRIVATE_A subnet-PRIVATE_B \
  --security-group-ids sg-ENDPOINT \
  --private-dns-enabled

Replace the VPC, subnet and security group placeholders with real identifiers.

With private DNS enabled and correctly configured VPC DNS settings, applications can use the normal Bedrock Runtime endpoint name while traffic is routed through the interface endpoint.

Verification

Run the following from an EC2 instance or container inside the VPC:

nslookup bedrock-runtime.eu-west-2.amazonaws.com

Verify that DNS resolves to private addresses associated with the interface endpoint.

Then invoke an approved model from that workload and confirm successful connectivity.

DNS resolution alone is not sufficient proof of private routing. Use VPC Flow Logs and endpoint configuration to validate the network path.

Security consideration: A VPC endpoint does not automatically prevent public egress through other routes. Review NAT, proxy, security group and IAM restrictions to enforce the intended connectivity policy.

5. Step Three: Protect AI Data Using AWS KMS and Amazon S3

AI applications often process business documents, customer information and other confidential datasets.

A secure deployment must protect this data at rest and in transit while limiting access to authorised applications.

Create a dedicated KMS key for AI application data using the AWS KMS console or an approved infrastructure-as-code template.

For a CLI demonstration:

aws kms create-key \
  --description "Enterprise AI data encryption key"

Record the resulting key ARN. Before using the key in production, configure its key policy, administrators and authorised application roles.

Create a unique S3 bucket:

export DATA_BUCKET=enterprise-ai-data-$AWS_ACCOUNT_ID

aws s3api create-bucket \
  --bucket "$DATA_BUCKET" \
  --region "$AWS_REGION" \
  --create-bucket-configuration \
  LocationConstraint="$AWS_REGION"

Block public access:

aws s3api put-public-access-block \
  --bucket "$DATA_BUCKET" \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

Enable default SSE-KMS encryption:

aws s3api put-bucket-encryption \
  --bucket "$DATA_BUCKET" \
  --server-side-encryption-configuration \
  '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "REPLACE_WITH_KMS_KEY_ARN"
      },
      "BucketKeyEnabled": true
    }]
  }'

The IAM role accessing this bucket must have the required S3 and KMS permissions.

For production use, also enable S3 versioning where appropriate, apply lifecycle and retention policies, enforce TLS through a bucket policy, and consider Amazon Macie for sensitive data discovery.

6. Step Four: Configure Amazon Bedrock Guardrails

Traditional cloud security controls protect infrastructure and access. AI-specific safeguards help address unsafe model interactions and sensitive information handling.

Amazon Bedrock Guardrails supports content filters, denied topics, word filters and sensitive information filters.

To create a guardrail:

  1. Open the Amazon Bedrock console.
  2. Navigate to Guardrails.
  3. Select Create guardrail.
  4. Enter Enterprise-AI-Security-Guardrail.
  5. Configure content filters appropriate to the application's risk profile.
  6. Configure sensitive information filters, such as blocking or anonymising selected PII.
  7. Add denied topics relevant to the application's business requirements.
  8. Save the guardrail and create a numbered version for production use.

Record the guardrail ID and version.

A guardrail can be applied through guardrailConfig on a Converse request, by selectively marking content with guardContent, or through the separate ApplyGuardrail API.

Guardrails are not substitutes for authorisation, secure tool execution or prompt-injection testing.

7. Step Five: Implement a Secure Python AI Client

The following example invokes an approved Bedrock model while attaching the configured guardrail.

Create a file named secure_ai.py:

import os
import boto3
from botocore.exceptions import ClientError

region = os.environ["AWS_REGION"]
model_id = os.environ["BEDROCK_MODEL_ID"]
guardrail_id = os.environ["BEDROCK_GUARDRAIL_ID"]
guardrail_version = os.environ["BEDROCK_GUARDRAIL_VERSION"]

client = boto3.client(
    "bedrock-runtime",
    region_name=region
)

def secure_inference(user_prompt):
    if not isinstance(user_prompt, str):
        raise ValueError("Prompt must be text")

    if not user_prompt.strip() or len(user_prompt) > 4000:
        raise ValueError("Invalid prompt length")

    try:
        response = client.converse(
            modelId=model_id,
            messages=[
                {
                    "role": "user",
                    "content": [{"text": user_prompt}]
                }
            ],
            inferenceConfig={
                "maxTokens": 500,
                "temperature": 0.2
            },
            guardrailConfig={
                "guardrailIdentifier": guardrail_id,
                "guardrailVersion": guardrail_version,
                "trace": "disabled"
            }
        )

        if response.get("stopReason") == "guardrail_intervened":
            return "Request blocked by AI security policy"

        return response["output"]["message"]["content"]

    except ClientError as error:
        code = error.response["Error"]["Code"]
        print(f"Bedrock request failed: {code}")
        raise

if __name__ == "__main__":
    result = secure_inference(
        "Explain the principle of least privilege."
    )
    print(result)

Set the required environment variables:

export BEDROCK_MODEL_ID="YOUR_APPROVED_MODEL_ID"
export BEDROCK_GUARDRAIL_ID="YOUR_GUARDRAIL_ID"
export BEDROCK_GUARDRAIL_VERSION="1"

Run the application:

python3 secure_ai.py

The expected result is a successful response for an authorised, benign request.

For a production application, additional controls are required: authenticated callers, request rate limits, user-level authorisation, output validation, secure error handling and explicit restrictions on any AI tools or actions.

8. Step Six: Enable AWS CloudTrail Auditing

AWS CloudTrail records supported AWS API activity and provides an audit trail for security investigations.

Create a dedicated audit trail using the AWS CloudTrail console:

  1. Navigate to CloudTrail → Trails.
  2. Select Create trail.
  3. Name the trail Enterprise-AI-Audit.
  4. Configure a dedicated encrypted S3 log destination.
  5. Enable log file validation.
  6. Select a multi-Region trail.
  7. Enable management events.
  8. Configure the relevant Bedrock data events separately where supported.

A CloudTrail trail must be started before it delivers ongoing event records.

For organisations using AWS Organizations, a centrally managed organisation trail is preferable.

To inspect supported recent management events:

aws cloudtrail lookup-events \
  --lookup-attributes \
  AttributeKey=EventSource,AttributeValue=bedrock.amazonaws.com \
  --max-results 20

This command does not replace querying configured CloudTrail data-event logs.

CloudTrail auditing and Bedrock model invocation logging are different capabilities. CloudTrail focuses on AWS API activity, whereas model invocation logging can capture inference metadata and, when configured, prompt and response content.

9. Step Seven: Configure Bedrock Invocation Monitoring

Amazon Bedrock supports model invocation logging to Amazon CloudWatch Logs and Amazon S3.

This capability is disabled by default.

In the Bedrock console:

  1. Open Amazon Bedrock → Settings.
  2. Locate Model invocation logging.
  3. Enable logging for the required modalities.
  4. Choose a CloudWatch Logs destination, an S3 destination or both.
  5. Configure the required delivery role and permissions.
  6. Apply the logging configuration.

For this example, use a log group named:

/aws/bedrock/enterprise-ai

Create the log group:

aws logs create-log-group \
  --log-group-name /aws/bedrock/enterprise-ai

Configure a retention period:

aws logs put-retention-policy \
  --log-group-name /aws/bedrock/enterprise-ai \
  --retention-in-days 30

The log group alone does not enable Bedrock invocation logging. The Bedrock logging configuration must also be associated with the destination and an authorised delivery role.

Analyse invocation activity

After logging has been enabled and requests have been processed, open CloudWatch Logs Insights and select the invocation log group.

Run:

fields @timestamp,
       identity.arn,
       modelId,
       input.inputTokenCount,
       output.outputTokenCount
| sort @timestamp desc
| limit 50

To identify high-volume callers:

fields identity.arn as principal,
       input.inputTokenCount as inputTokens,
       output.outputTokenCount as outputTokens
| stats count(*) as calls,
        sum(inputTokens) as totalInputTokens,
        sum(outputTokens) as totalOutputTokens
  by principal
| sort calls desc

These queries can help identify unexpected usage patterns, excessive token consumption and unusual workload activity.

Privacy warning: Model invocation logging can capture prompt and response content. For sensitive workloads, assess whether full-content logging is necessary, restrict access to log destinations and configure retention and masking appropriately.

10. Step Eight: Enable Threat Detection and Security Findings

AWS GuardDuty analyses supported AWS telemetry to identify suspicious activity, including certain credential, network and workload threats.

Enable GuardDuty in the selected Region:

aws guardduty create-detector \
  --enable \
  --finding-publishing-frequency FIFTEEN_MINUTES

Retrieve the detector ID:

aws guardduty list-detectors

GuardDuty does not automatically detect all prompt-injection attacks, model poisoning attempts or malicious AI responses. These require additional application-level detection and testing.

Next, enable AWS Security Hub through the console and select appropriate security standards and controls.

Security Hub provides centralised visibility into supported security findings and compliance controls.

For enterprise environments, integrate GuardDuty, Security Hub, AWS Config and other approved detection sources into a central security operations workflow.

11. Step Nine: Configure Security Alerts

Monitoring becomes operationally useful when suspicious activity triggers timely alerts.

For example, create an Amazon SNS topic:

aws sns create-topic \
  --name enterprise-ai-security-alerts

Create a CloudWatch alarm for abnormal Bedrock invocation errors or throttling using the relevant published metrics.

For GuardDuty and Security Hub findings, configure Amazon EventBridge rules to route selected findings to an approved notification or incident-response target.

A typical EventBridge rule can filter GuardDuty findings with high severity and forward them to SNS or an incident management system.

Ensure that the EventBridge target has the required permissions and that alerts are tested using approved sample findings.

Avoid sending confidential prompts, responses or customer data directly into notification messages.

12. Step Ten: Validate the Security Controls

A deployment should not be considered secure simply because its configuration commands completed successfully.

Perform controlled tests in an authorised environment.

Test Expected result
Invoke an approved model Successful inference
Invoke an unauthorised model Access denied
Access a private S3 object anonymously Access denied
Submit a prohibited test input Guardrail intervenes according to policy
Invoke Bedrock through the VPC endpoint Private network path verified
Inspect CloudTrail Supported API activity recorded
Inspect Bedrock invocation logs Expected inference records visible
Generate a GuardDuty sample finding Finding appears and notification path works
Simulate excessive application requests Rate limiting or monitoring responds

Document the results and retain evidence for security reviews.

13. Production Security Recommendations

The demonstration provides a foundation, but production deployments require additional hardening.

Recommended improvements include AWS Organizations guardrails, IAM permission boundaries, automated configuration checks, infrastructure-as-code scanning, secret rotation, centralised audit logging, tested incident response procedures and regular AI red-team exercises.

For applications using retrieval-augmented generation, enforce document-level authorisation before information reaches the model.

For agentic AI applications, treat every model-generated tool call as an untrusted request requiring independent permission checks.

Finally, ensure monitoring covers both traditional cloud security and AI-specific behaviour. A healthy EC2 instance or successful API response does not necessarily mean that the AI application is operating securely.

Conclusion

Securing AI workloads on AWS requires more than enabling encryption and restricting network access.

Enterprise AI security must combine identity protection, private connectivity, data governance, model safeguards, audit logging, behavioural monitoring and continuous validation.

Amazon Bedrock provides managed AI capabilities, while services such as IAM, KMS, CloudTrail, CloudWatch, GuardDuty and Security Hub provide complementary security controls.

The objective is to create an environment where AI applications are not only scalable and useful, but also observable, auditable and resilient against misuse.

As enterprise adoption accelerates, security must become an integral part of AI engineering rather than a final deployment checklist.

Technical References

  • AWS: Amazon Bedrock security and private connectivity documentation.
  • AWS: Amazon Bedrock Guardrails developer documentation.
  • AWS: Model invocation logging using CloudWatch Logs and Amazon S3.
  • AWS: IAM and the AWS Shared Responsibility Model.
  • AWS: CloudTrail, GuardDuty and Security Hub documentation.
  • OWASP: Top 10 for Large Language Model Applications.
  • NIST: AI Risk Management Framework.
📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.