AWS Machine Learning Blog 08月30日
使用CloudFront为Bedrock AgentCore Runtime配置自定义域名
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何利用Amazon CloudFront、Route 53和AWS Certificate Manager (ACM) 为Amazon Bedrock AgentCore Runtime创建自定义域名。通过将默认的AWS端点(如https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{EncodedAgentARN}/invocations)转换为用户友好的URL(如https://agent.yourcompany.com),可以提升专业性和用户体验。该方案还能简化代理管理、增强品牌形象,并提供更佳的开发体验。文章详细阐述了解决方案架构、先决条件、创建带入站身份验证的代理、设置自定义域名(包括CORS配置)以及使用AWS CDK部署和测试的步骤。

🌟 **提升用户体验与品牌形象**:通过使用自定义域名(如https://agent.yourcompany.com)替代默认的AWS端点,可以为客户提供更专业、更易记的访问方式,增强品牌一致性。

🚀 **利用CloudFront实现反向代理**:Amazon CloudFront作为反向代理,能够将来自自定义域名的请求转发至Amazon Bedrock AgentCore Runtime的API端点,实现URL的转换和统一管理。

🔒 **安全与可扩展性**:结合AWS Certificate Manager (ACM) 提供SSL证书,Route 53进行DNS解析,可构建一个安全、可扩展的自定义域名解决方案,同时支持CORS策略以解决跨域问题。

🛠️ **AWS CDK自动化部署**:文章提供了使用AWS CDK(Cloud Development Kit)部署此解决方案的代码示例,包括创建CloudFront分发、配置行为选项、处理SSL证书和DNS记录,简化了基础设施的配置和管理过程。

💡 **AgentCore Runtime的优势**:Amazon Bedrock AgentCore Runtime本身提供了框架无关性、长执行时间(最长8小时)、独立的微虚拟机安全隔离、按消耗付费以及内置的身份验证和可观察性等优势,结合自定义域名能进一步发挥其价值。

When deploying AI agents to Amazon Bedrock AgentCore Runtime (currently in preview), customers often want to use custom domain names to create a professional and seamless experience.

By default, AgentCore Runtime agents use endpoints like https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{EncodedAgentARN}/invocations.

In this post, we discuss how to transform these endpoints into user-friendly custom domains (like https://agent.yourcompany.com) using Amazon CloudFront as a reverse proxy. The solution combines CloudFront, Amazon Route 53, and AWS Certificate Manager (ACM) to create a secure, scalable custom domain setup that works seamlessly with your existing agents.

Benefits of Amazon Bedrock AgentCore Runtime

If you’re building AI agents, you have probably wrestled with hosting challenges: managing infrastructure, handling authentication, scaling, and maintaining security. Amazon Bedrock AgentCore Runtime helps address these problems.

Amazon Bedrock AgentCore Runtime is framework agnostic; you can use it with LangGraph, CrewAI, Strands Agents, or custom agents you have built from scratch. It supports extended execution times up to 8 hours, perfect for complex reasoning tasks that traditional serverless functions can’t handle. Each user session runs in its own isolated microVM, providing security that’s crucial for enterprise applications.

The consumption-based pricing model means you only pay for what you use, not what you provision. And unlike other hosting solutions, Amazon Bedrock AgentCore Runtime includes built-in authentication and specialized observability for AI agents out of the box.

Benefits of custom domains

When using Amazon Bedrock AgentCore Runtime with Open Authorization (OAuth) authentication, your applications make direct HTTPS requests to the service endpoint. Although this works, custom domains offer several benefits:

Solution overview

In this solution, we use CloudFront as a reverse proxy to transform requests from your custom domain into Amazon Bedrock AgentCore Runtime API calls. Instead of using the default endpoint, your applications can make requests to a user-friendly URL like https://agent.yourcompany.com/.

The following diagram illustrates the solution architecture.

The workflow consists of the following steps:

    A client application authenticates with Amazon Cognito and receives a bearer token. The client makes an HTTPS request to your custom domain. Route 53 resolves the DNS request to CloudFront. CloudFront forwards the authenticated request to the Amazon Bedrock Runtime agent. The agent processes the request and returns the response through the same path.

You can use the same CloudFront distribution to serve both your frontend application and backend agent endpoints, avoiding cross-origin resource sharing (CORS) issues because everything originates from the same domain.

Prerequisites

To follow this walkthrough, you must have the following in place:

Although Amazon Bedrock AgentCore Runtime can be in other supported AWS Regions, CloudFront requires SSL certificates to be in the us-east-1 Region.

You can choose from the following domain options:

Choose the third option if you want to test the solution quickly before setting up a custom domain.

Create an agent with inbound authentication

If you already have an agent deployed with OAuth authentication, you can skip to the next section to set up the custom domain. Otherwise, follow these steps to create a new agent using Amazon Cognito as your OAuth provider:

    Create a new directory for your agent with the following structure:
your_project_directory/├── agent_example.py # Your main agent code├── requirements.txt # Dependencies for your agent└── __init__.py # Makes the directory a Python package
    Create the main agent code in agent_example.py:
# agent_example.pyfrom strands import Agentfrom bedrock_agentcore.runtime import BedrockAgentCoreAppagent = Agent()app = BedrockAgentCoreApp()@app.entrypointdef invoke(payload):    """Process user input and return a response"""    user_message = payload.get("prompt", "Hello")    response = agent(user_message)    return str(response) # response should be json serializableif __name__ == "__main__":    app.run()
    Add dependencies to requirements.txt:
# requirements.txtstrands-agentsbedrock-agentcore
    Run the following commands to create an Amazon Cognito user pool and test user:
# Create User Pool and capture Pool IDexport POOL_ID=$(aws cognito-idp create-user-pool \  --pool-name "MyUserPool" \  --policies '{"PasswordPolicy":{"MinimumLength":8}}' \  --region us-east-1 | jq -r '.UserPool.Id')# Create App Client and capture Client IDexport CLIENT_ID=$(aws cognito-idp create-user-pool-client \  --user-pool-id $POOL_ID \  --client-name "MyClient" \  --no-generate-secret \  --explicit-auth-flows "ALLOW_USER_PASSWORD_AUTH" "ALLOW_REFRESH_TOKEN_AUTH" \  --region us-east-1 | jq -r '.UserPoolClient.ClientId')# Create and configure a test useraws cognito-idp admin-create-user \  --user-pool-id $POOL_ID \  --username "testuser" \  --temporary-password "Temp1234" \  --region us-east-1 \  --message-action SUPPRESSaws cognito-idp admin-set-user-password \  --user-pool-id $POOL_ID \  --username "testuser" \  --password "MyPassword123" \  --region us-east-1 \  --permanentecho "Pool ID: $POOL_ID"echo "Discovery URL: https://cognito-idp.us-east-1.amazonaws.com/$POOL_ID/.well-known/openid-configuration"echo "Client ID: $CLIENT_ID"
    Deploy the agent using the Amazon Bedrock AgentCore command line interface (CLI) provided by the starter toolkit:
pip install bedrock-agentcore-starter-toolkit #install the starter toolkitagentcore configure --entrypoint agent_example.py \--name my_agent \--execution-role your-execution-role-arn \--requirements-file requirements.txt \--authorizer-config "{\"customJWTAuthorizer\":{\"discoveryUrl\":\"https://cognito-idp.us-east-1.amazonaws.com/$POOL_ID/.well-known/openid-configuration\",\"allowedClients\":[\"$CLIENT_ID\"]}}"agentcore launch

Make note of your agent runtime Amazon Resource Name (ARN) after deployment. You will need this for the custom domain configuration.

For additional examples and details, see Authenticate and authorize with Inbound Auth and Outbound Auth.

Set up the custom domain solution

Now let’s implement the custom domain solution using the AWS CDK. This section shows you how to create the CloudFront distribution that proxies your custom domain requests to Amazon Bedrock AgentCore Runtime endpoints.

    Create a new directory and initialize an AWS CDK project:
mkdir agentcore-custom-domaincd agentcore-custom-domaincdk init app --language pythonsource .venv/bin/activatepip install aws-cdk-lib constructs
    Encode the agent ARN and prepare the CloudFront origin configuration:
# agentcore_custom_domain_stack.py import urllib.parseagent_runtime_arn = "arn:aws:bedrock-agentcore:us-east-1:accountId:runtime/my_agent-xbcDkz4FR9"encoded_arn = urllib.parse.quote(agent_runtime_arn, safe='') # URL-encode the ARNregion = agent_runtime_arn.split(':')[3]  # Extract region from ARN

If your frontend application runs on a different domain than your agent endpoint, you must configure CORS headers. This is common if your frontend is hosted on a different domain (for example, https://app.yourcompany.com calling https://agent.yourcompany.com), or if you’re developing locally (for example, http://localhost:3000 calling your production agent endpoint).

    To handle CORS requirements, create a CloudFront response headers policy:
# agentcore_custom_domain_stack.py from aws_cdk.aws_cloudfront import ResponseHeadersPolicy, ResponseHeadersCorsBehavior# Create CORS response headers policycors_policy = ResponseHeadersPolicy(self, 'CorsPolicy',    cors_behavior=ResponseHeadersCorsBehavior(        access_control_allow_origins=['*'], # Or specify your frontend domains        access_control_allow_headers=[            'Authorization',            'Content-Type',             'X-Amzn-*',            'X-Requested-With'        ],        access_control_allow_methods=['GET', 'POST', 'OPTIONS'],        access_control_allow_credentials=False,        access_control_expose_headers=['*'],        origin_override=True # Overrides CORS headers from origin    ))
    Create a CloudFront distribution to act as a reverse proxy for your agent endpoints:
# agentcore_custom_domain_stack.py from aws_cdk.aws_cloudfront import (    Distribution, BehaviorOptions, CachePolicy,     AllowedMethods, ViewerProtocolPolicy,    OriginProtocolPolicy, OriginRequestPolicy)from aws_cdk.aws_cloudfront_origins import HttpOriginbedrock_agentcore_hostname = f"bedrock-agentcore.{region}.amazonaws.com"origin_path = f"/runtimes/{encoded_arn}/invocations"distribution = Distribution(self, 'Distribution',    default_behavior=BehaviorOptions(        origin=HttpOrigin(            bedrock_agentcore_hostname,            origin_path=origin_path,             protocol_policy=OriginProtocolPolicy.HTTPS_ONLY,            read_timeout=Duration.seconds(120) # Optional: for responses >30s, adjust as needed        ),        viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,        cache_policy=CachePolicy.CACHING_DISABLED,  # Critical for dynamic APIs        allowed_methods=AllowedMethods.ALLOW_ALL,        response_headers_policy=cors_policy,  # Add CORS policy if created        origin_request_policy=OriginRequestPolicy.ALL_VIEWER,  # Forward headers for MCP    ),    # Add domain configuration if using custom domains    domain_names=[domain_name] if domain_name else None,    certificate=certificate if domain_name else None,)

Set cache_policy=CachePolicy.CACHING_DISABLED to make sure your agent responses remain dynamic and aren’t cached by CloudFront.

    If you’re using a custom domain, add an SSL certificate and DNS configuration to your stack:
# agentcore_custom_domain_stack.py from aws_cdk.aws_certificatemanager import Certificate, CertificateValidationfrom aws_cdk.aws_route53 import HostedZone, ARecord, RecordTargetfrom aws_cdk.aws_route53_targets import CloudFrontTarget# For existing domainshosted_zone = HostedZone.from_lookup(self, 'HostedZone',    domain_name='yourcompany.com')# SSL certificate with automatic DNS validationcertificate = Certificate(self, 'Certificate',    domain_name='my-agent.yourcompany.com',    validation=CertificateValidation.from_dns(hosted_zone),)# DNS record pointing to CloudFrontARecord(self, 'AliasRecord',    zone=hosted_zone,    record_name='my-agent.yourcompany.com',    target=RecordTarget.from_alias(CloudFrontTarget(distribution)),)

The following code is the complete AWS CDK stack that combines all the components:

# agentcore_custom_domain_stack.pyimport urllib.parsefrom aws_cdk import Stack, CfnOutput, Durationfrom aws_cdk.aws_cloudfront import (    Distribution, BehaviorOptions,    CachePolicy, AllowedMethods,    ViewerProtocolPolicy, OriginProtocolPolicy,    ResponseHeadersPolicy, ResponseHeadersCorsBehavior,    OriginRequestPolicy)from aws_cdk.aws_cloudfront_origins import HttpOriginfrom aws_cdk.aws_certificatemanager import Certificate, CertificateValidationfrom aws_cdk.aws_route53 import HostedZone, ARecord, RecordTargetfrom aws_cdk.aws_route53_targets import CloudFrontTargetfrom constructs import Constructclass AgentcoreCustomDomainStack(Stack):    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:        super().__init__(scope, construct_id, **kwargs)        # Configuration - Update these for your setup        agent_runtime_arn = "arn:aws:bedrock-agentcore:us-east-1:accountId:runtime/my_agent-xbcDkz4FR9"        region = agent_runtime_arn.split(':')[3]  # Extract region from ARN        domain_name = "agent.yourcompany.com"  # Using your hosted zone        hosted_zone_id = "Z1234567890ABC"  # Your hosted zone ID        enable_cors = True  # Set to False if serving frontend and backend from same domain        # Encode the agent ARN for the origin path        encoded_arn = urllib.parse.quote(agent_runtime_arn, safe='')        bedrock_agentcore_hostname = f"bedrock-agentcore.{region}.amazonaws.com"        origin_path = f"/runtimes/{encoded_arn}/invocations"        # Create CORS response headers policy if needed        cors_policy = None        if enable_cors:            cors_policy = ResponseHeadersPolicy(self, 'CorsPolicy',                cors_behavior=ResponseHeadersCorsBehavior(                    access_control_allow_origins=['*'],  # Or specify your frontend domains                    access_control_allow_headers=[                        'Authorization',                        'Content-Type',                         'X-Amzn-*',                        'X-Requested-With'                    ],                    access_control_allow_methods=['GET', 'POST', 'OPTIONS'],                    access_control_expose_headers=['*'],                    access_control_allow_credentials=False,                    origin_override=True  # Overrides CORS headers from origin                )            )        # Base distribution configuration        distribution_props = {            "default_behavior": BehaviorOptions(                origin=HttpOrigin(                    bedrock_agentcore_hostname,                    origin_path=origin_path,  # Direct path to agent endpoint                    protocol_policy=OriginProtocolPolicy.HTTPS_ONLY,                    read_timeout=Duration.seconds(120) # Optional: for responses >30s, adjust as needed                ),                viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,                cache_policy=CachePolicy.CACHING_DISABLED,                allowed_methods=AllowedMethods.ALLOW_ALL,                response_headers_policy=cors_policy,  # Add CORS policy if enabled                origin_request_policy=OriginRequestPolicy.ALL_VIEWER,  # Forward headers for MCP            )        }        # Optional: Add custom domain        if domain_name:            # Use from_hosted_zone_attributes for specific zone            hosted_zone = HostedZone.from_hosted_zone_attributes(self, 'HostedZone',                                                                 zone_name='yourcompany.com',  # Your root domain                                                                 hosted_zone_id=hosted_zone_id                                                                 )            certificate = Certificate(self, 'Certificate',                                      domain_name=domain_name,                                      validation=CertificateValidation.from_dns(                                          hosted_zone),                                      )            # Add custom domain to distribution            distribution_props["domain_names"] = [domain_name]            distribution_props["certificate"] = certificate        distribution = Distribution(self, 'Distribution', **distribution_props)        # Create DNS record if using custom domain        if domain_name:            ARecord(self, 'AliasRecord',                    zone=hosted_zone,                    record_name=domain_name,                    target=RecordTarget.from_alias(                        CloudFrontTarget(distribution)),                    )        # Outputs        if domain_name:            domain_url = f"https://{domain_name}/"            CfnOutput(self, "AgentEndpoint",                      value=domain_url,                      description="Your custom domain endpoint"                      )        CfnOutput(self, "CloudFrontDistribution",                  value=f"https://{distribution.distribution_domain_name}/",                  description="CloudFront default domain (works without custom domain)"                  )
    Configure the AWS CDK app entry point:
# app.py#!/usr/bin/env python3import aws_cdk as cdkfrom agentcore_custom_domain.agentcore_custom_domain_stack import AgentCoreCustomDomainStackapp = cdk.App()AgentcoreCustomDomainStack(app, "AgentCoreCustomDomainStack",    # CloudFront requires certificates in us-east-1    env=cdk.Environment(region='us-east-1'),)app.synth()

Deploy your custom domain

Now you can deploy the solution and verify it works with both custom and default domains. Complete the following steps:

    Update the following values in agentcore_custom_domain_stack.py:
      Your Amazon Bedrock AgentCore Runtime ARN Your domain name (if using a custom domain) Your hosted zone ID (if using a custom domain)
    Deploy using the AWS CDK:
cdk deploy

Test your endpoint

After you deploy the custom domain, you can test your endpoints using either the custom domain or the CloudFront default domain.First, get a JWT token from Amazon Cognito:

export TOKEN=$(aws cognito-idp initiate-auth \  --client-id "your-client-id" \  --auth-flow USER_PASSWORD_AUTH \  --auth-parameters USERNAME='testuser',PASSWORD='MyPassword123' \  --region us-east-1 | jq -r '.AuthenticationResult.AccessToken')

Use the following code to test with your custom domain:

curl -X POST "https://my-agent.yourcompany.com/" \  -H "Authorization: Bearer $TOKEN" \  -H "Content-Type: application/json" \  -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: session-12345678901234567890123456789012345" \  -d '{"prompt": "Hello, how can you help me today?"}'

Alternatively, use the following code to test with the CloudFront default domain:

curl -X POST "https://d1234567890123.cloudfront.net/" \  -H "Authorization: Bearer $TOKEN" \  -H "Content-Type: application/json" \  -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: session-12345678901234567890123456789012345" \  -d '{"prompt": "Hello, how can you help me today?"}'

If everything works correctly, you will receive a response from your agent through either endpoint. You’ve successfully created a custom domain for your Amazon Bedrock AgentCore Runtime agent!

Considerations

As you implement this solution in production, the following are some important considerations:

Clean up

To avoid ongoing costs, delete the resources when you no longer need them:

cdk destroy

You might need to manually delete the Route 53 hosted zones and ACM certificates from their respective service consoles.

Conclusion

In this post, we showed you how to create custom domain names for your Amazon Bedrock AgentCore Runtime agent endpoints using CloudFront as a reverse proxy. This solution provides several key benefits: simplified integration for development teams, custom domains that align with your organization, cleaner infrastructure abstraction, and straightforward maintenance when endpoints need updates. By using CloudFront as a reverse proxy, you can also serve both your frontend application and backend agent endpoints from the same domain, avoiding common CORS challenges.

We encourage you to explore this solution further by adapting it to your specific needs. You might want to enhance it with additional security features, set up monitoring, or integrate it with your existing infrastructure.

To learn more about building and deploying AI agents, see the Amazon Bedrock AgentCore Developer Guide. For advanced configurations and best practices with CloudFront, refer to the Amazon CloudFront documentation. You can find detailed information about SSL certificates in the AWS Certificate Manager documentation, and domain management in the Amazon Route 53 documentation.

Amazon Bedrock AgentCore is currently in preview and subject to change. Standard AWS pricing applies to additional services used, such as CloudFront, Route 53, and Certificate Manager.


About the authors

Rahmat Fedayizada is a Senior Solutions Architect with the AWS Energy and Utilities team. He works with energy companies to design and implement scalable, secure, and highly available architectures. Rahmat is passionate about translating complex technical requirements into practical solutions that drive business value.

Paras Bhuva is a Senior Manager of Solutions Architecture at AWS, where he leads a team of solution architects helping energy customers innovate and accelerate their transformation. Having started as a Solution Architect in 2012, Paras is passionate about architecting scalable solutions and building organizations focused on application modernization and AI initiatives.

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Amazon Bedrock AgentCore Runtime CloudFront 自定义域名 AWS CDK 反向代理 Route 53 ACM AI Agents Custom Domain Reverse Proxy Cloud Computing
相关文章