I tried getting into a VPC using EventBridge Connection — Requesting an ALB inside a VPC from Step Functions without Lambda

I tried getting into a VPC using EventBridge Connection — Requesting an ALB inside a VPC from Step Functions without Lambda

EventBridge Connection (Private) and API Gateway REST API + VPC Link v2 — I validated two patterns for calling an Internal ALB inside a VPC from Step Functions without Lambda relay, and have organized the differences in routing path, IAM authentication, and constraints in a comparison table.
2026.06.14

This page has been translated by machine translation. View original

Introduction

This article was inspired by the slide deck "VPCの中、EventBridge Connectionで入れますよ?" (You can get inside a VPC with EventBridge Connection?) presented by Mr. Shimokawa from AWSJ at JAWS-UG Ibaraki #14 held on June 13, 2026, which motivated me to actually try reaching an Internal ALB inside a VPC from Step Functions.

https://speakerdeck.com/_kensh/eventbridge-connection

When you want to call an Internal ALB inside a VPC from Step Functions, the conventional approach was to use a VPC Lambda.

In December 2024, the Private connectivity feature for EventBridge Connection became GA (Generally Available), making it possible to reach private APIs inside a VPC via VPC Lattice without Lambda.

Additionally, in November 2025, API Gateway REST API's private integration became capable of directly specifying an ALB, enabling calls to an ALB inside a VPC via VPC Link v2 without Lambda as well.

Despite the GA release in December 2024, there are still few practical Japanese-language articles, and no comparison articles with API Gateway could be found, so I built and compared the following two patterns.

  • Pattern A: EventBridge Connection (Private) + via VPC Lattice
  • Pattern B: API Gateway REST API + via VPC Link v2

This article confirms that Step Functions can call an Internal ALB inside a VPC without Lambda relay, while organizing the differences in routing paths, IAM authentication, and constraints.

Test Environment

  • Region: ap-northeast-1
  • VPC: No public subnets (Isolated subnets × 3)
  • Common backend: Internal ALB (returns {"status":"ok","source":"internal-alb"} with Fixed Response)
  • IaC: CloudFormation (2-stack configuration)

Calling via EventBridge Connection (Private)

Architecture Diagram

Pattern A Architecture Diagram

Step Functions → HTTP Task → EventBridge Connection (Private)
  → VPC Lattice (Resource Configuration → Resource Gateway) → Internal ALB

How It Works

EventBridge Connection (Private) uses VPC Lattice's Resource Configuration / Resource Gateway, which enables reaching private resources inside a VPC.

  • Resource Gateway: Placed in a subnet inside the VPC, it serves as an entry point that accepts traffic from VPC Lattice
  • Resource Configuration: Defines "which domain and port to reach." It is associated with a Resource Gateway
  • EventBridge Connection (Private): Used by specifying a Resource Configuration. Requests via a Connection reach the destination in the order: VPC Lattice → Resource Gateway → destination

Data flow:

  1. Step Functions executes an HTTP Task and references the EventBridge Connection
  2. Authentication credentials associated with the Connection are used. Since credentials are held as a Secrets Manager secret managed by the Connection, the execution role requires events:RetrieveConnectionCredentials and reference permissions to Secrets Manager
  3. Step Functions sends the request. The Resource Configuration associated with the Connection delegates routing to VPC Lattice
  4. VPC Lattice reaches inside the VPC via the Resource Gateway, and the request is forwarded to the destination (Internal ALB) resolved by VPC internal DNS via the IN_VPC setting

Required IAM Permissions

The following permissions are required for the Step Functions execution role.

  • states:InvokeHTTPEndpoint — Permission to execute HTTP Tasks
  • events:RetrieveConnectionCredentials — Retrieve Connection credentials
  • secretsmanager:GetSecretValue / secretsmanager:DescribeSecret — Access to Secrets Manager used internally by the Connection
  • vpc-lattice-svcs:Invoke — Required when using ResourceConfigurationAuthType: AWS_IAM for Resource Configuration

Key Points of the CFn Template

Internal ALB (Minimal backend with Fixed Response)

ALB:
  Type: AWS::ElasticLoadBalancingV2::LoadBalancer
  Properties:
    Scheme: internal
    Subnets: !Ref SubnetIds
    SecurityGroups:
      - !Ref AlbSecurityGroup

HttpsListener:
  Type: AWS::ElasticLoadBalancingV2::Listener
  Properties:
    LoadBalancerArn: !Ref ALB
    Port: 443
    Protocol: HTTPS
    Certificates:
      - CertificateArn: !Ref CertificateArn
    DefaultActions:
      - Type: fixed-response
        FixedResponseConfig:
          StatusCode: "200"
          ContentType: application/json
          MessageBody: '{"status":"ok","source":"internal-alb"}'

The endpoint called from the Step Functions HTTP Task via EventBridge Connection (Private) requires HTTPS, and the destination certificate must be verifiable by a public CA (the Resource Configuration side is defined as TCP/443). Therefore, even an Internal ALB requires an ACM public certificate — self-signed certificates cannot be used.

Resource Gateway + Resource Configuration

ResourceGateway:
  Type: AWS::VpcLattice::ResourceGateway
  Properties:
    Name: eb-demo-resource-gw-v2
    IpAddressType: IPV4
    ResourceConfigDnsResolution: IN_VPC
    VpcIdentifier: !Ref VpcId
    SubnetIds: !Ref SubnetIds
    SecurityGroupIds:
      - !Ref ResourceGatewaySecurityGroup

ResourceConfiguration:
  Type: AWS::VpcLattice::ResourceConfiguration
  Properties:
    Name: eb-demo-resource-cfg-v3
    ResourceGatewayId: !GetAtt ResourceGateway.Id
    ResourceConfigurationType: SINGLE
    ResourceConfigurationAuthType: AWS_IAM
    ProtocolType: TCP
    PortRanges:
      - "443"
    AllowAssociationToSharableServiceNetwork: true
    ResourceConfigurationDefinition:
      DnsResource:
        DomainName: !Ref AlbDomainName
        IpAddressType: IPV4

Key points:

  • ResourceConfigDnsResolution: IN_VPC — The destination FQDN is resolved by the DNS resolver inside the VPC. This setting is required for configurations like this one, where a custom FQDN pointing to an Internal ALB is resolved by VPC internal DNS
  • ResourceConfigurationAuthType: AWS_IAM — Enables IAM authentication at the VPC Lattice layer. With this setting, granting vpc-lattice-svcs:Invoke to the Step Functions execution role is mandatory

Resource Gateway Security Group

ResourceGatewaySecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Security group for VPC Lattice Resource Gateway
    VpcId: !Ref VpcId
    SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 0
        ToPort: 65535
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 0
        ToPort: 65535
        CidrIpv6: "::/0"

During testing, allowing only 443/TCP from the VPC CIDR resulted in timeouts. The issue was resolved by aligning with the official documentation requirement of allowing all TCP ports from 0.0.0.0/0. The reason is explained in the "Pitfalls" section below.

EventBridge Connection Private Connectivity Settings

PrivateConnection:
  Type: AWS::Events::Connection
  Properties:
    Name: eb-demo-private-connection
    AuthorizationType: API_KEY
    AuthParameters:
      ApiKeyAuthParameters:
        ApiKeyName: x-dummy-key
        ApiKeyValue: dummy
    InvocationConnectivityParameters:
      ResourceParameters:
        ResourceConfigurationArn: !GetAtt ResourceConfiguration.Arn

Specifying the Resource Configuration in InvocationConnectivityParameters is the core of Private connectivity. API_KEY is specified for AuthorizationType, but this API key is not validated by the backend in this case. Access control is handled by ResourceConfigurationAuthType: AWS_IAM and vpc-lattice-svcs:Invoke.

Step Functions State Machine (Embedding Connection ARN)

StateMachineA:
  Type: AWS::StepFunctions::StateMachine
  Properties:
    StateMachineName: eb-demo-pattern-a-private
    RoleArn: !GetAtt PatternARole.Arn
    DefinitionString:
      Fn::Join:
        - ""
        - - '{"StartAt":"CallPrivateApi","States":{"CallPrivateApi":{"Type":"Task","Resource":"arn:aws:states:::http:invoke","TimeoutSeconds":60,"Parameters":{"ApiEndpoint":"https://eb-demo.example.com/","Method":"GET","Authentication":{"ConnectionArn":"'
          - Fn::GetStackOutput:
              StackName: !Ref InfraStackName
              OutputName: PrivateConnectionArn
          - '"}},"End":true}}}'

Fn::Join is used to embed the Connection ARN in the ASL definition. Cross-stack referencing is performed with Fn::GetStackOutput to retrieve the Connection ARN from Stack 1. Fn::GetStackOutput is a CloudFormation intrinsic function that allows referencing output values between stacks without using Fn::ImportValue + Export.

https://dev.classmethod.jp/articles/cloudformation-fn-getstackoutput-ga-known-limitations/

Test Results

The state machine was executed and a StatusCode 200 response with the Internal ALB's Fixed Response was confirmed.

{
  "StatusCode": 200,
  "StatusText": "OK",
  "ResponseBody": {"status": "ok", "source": "internal-alb"},
  "Headers": {
    "server": ["awselb/2.0"],
    "content-type": ["application/json; charset=utf-8"]
  }
}

Pitfalls

FQDN required, user-managed DNS registration needed

The destination for Resource Configuration is specified as an FQDN (IP addresses are not allowed, as stated in the official documentation). It was necessary to register a CNAME record for the ALB in a self-managed DNS. In this case, a CNAME from eb-demo.example.com → ALB DNS name was registered.

Restricting Resource Gateway Security Group Inbound rules causes timeouts

Initially, only 443/TCP from the VPC CIDR (192.168.0.0/18) was allowed, but traffic from VPC Lattice to the Resource Gateway timed out. The official documentation states that allowing all TCP ports from 0.0.0.0/0 is a Resource Gateway security group requirement, and aligning with this requirement resolved the issue. This is also mentioned in the slide deck.

HTTP Task has a 60-second timeout limit

Step Functions HTTP Tasks time out at a maximum of 60 seconds (as stated in the official documentation). This is not suitable for API calls that take a long time.

Architecture Diagram

Pattern B Architecture Diagram

Step Functions → apigateway:invoke (Optimized Integration, with IAM signature)
  → API Gateway REST API (AWS_IAM auth + resource policy)
    → VPC Link v2 → Internal ALB

How It Works

Using API Gateway REST API's VPC Link integration, the REST API receives HTTP requests and relays them to an Internal ALB inside the VPC. Step Functions calls it via Optimized Integration (apigateway:invoke). By specifying AuthType: IAM_ROLE, IAM signatures using the execution role's credentials are automatically attached.

This uses the November 2025 update that allows direct ALB specification in REST API private integrations. VPC Link v2 (AWS::ApiGatewayV2::VpcLink) is now supported with REST APIs, enabling direct ALB integration without an NLB.

https://dev.classmethod.jp/articles/api-gateway-rest-apis-integration-load-balancer/

Required IAM Permissions

The following permissions are required for the Step Functions execution role.

  • execute-api:Invoke — Permission to execute REST APIs

Compared to Pattern A, the number of required permissions is smaller and simpler.

Key Points of the CFn Template

VpcLink:
  Type: AWS::ApiGatewayV2::VpcLink
  Properties:
    Name: eb-demo-vpc-link
    SubnetIds: !Ref SubnetIds
    SecurityGroupIds:
      - !Ref VpcLinkSecurityGroup

RestApi:
  Type: AWS::ApiGateway::RestApi
  Properties:
    Name: eb-demo-rest-api
    EndpointConfiguration:
      Types:
        - REGIONAL

RestApiMethod:
  Type: AWS::ApiGateway::Method
  Properties:
    RestApiId: !Ref RestApi
    ResourceId: !GetAtt RestApi.RootResourceId
    HttpMethod: GET
    AuthorizationType: AWS_IAM
    Integration:
      Type: HTTP_PROXY
      IntegrationHttpMethod: GET
      ConnectionType: VPC_LINK
      ConnectionId: !Ref VpcLink
      IntegrationTarget: !Ref HttpListener
      Uri: !Sub "http://${ALB.DNSName}/"

Since this relays to the Internal ALB's HTTP listener via VPC Link v2, no certificate is required on the ALB side. The ALB's HTTP listener is specified in IntegrationTarget (a 200 response was confirmed with Uri also specified). With AuthorizationType: AWS_IAM, requests without an IAM signature are rejected at the REST API layer.

Step Functions Optimized Integration

StateMachineB:
  Type: AWS::StepFunctions::StateMachine
  Properties:
    StateMachineName: eb-demo-pattern-b-apigw
    RoleArn: !GetAtt PatternBRole.Arn
    DefinitionString:
      Fn::Join:
        - ""
        - - '{"StartAt":"CallRestApi","States":{"CallRestApi":{"Type":"Task","Resource":"arn:aws:states:::apigateway:invoke","Parameters":{"ApiEndpoint":"'
          - Fn::GetStackOutput:
              StackName: !Ref InfraStackName
              OutputName: RestApiId
          - '.execute-api.ap-northeast-1.amazonaws.com","Method":"GET","Stage":"prod","AuthType":"IAM_ROLE"},"End":true}}}'

When AuthType: IAM_ROLE is specified, Step Functions automatically generates an IAM signature using the execution role's credentials.

Test Results

The state machine was executed and a StatusCode 200 response with the Internal ALB's Fixed Response was confirmed.

{
  "StatusCode": 200,
  "StatusText": "OK",
  "ResponseBody": {"status": "ok", "source": "internal-alb"},
  "Headers": {
    "server": ["awselb/2.0"],
    "apigw-requestid": ["e5Nw0iQQtjMEJUA="],
    "content-type": ["application/json; charset=utf-8"]
  }
}

Additional Control via Resource Policy

With only AWS_IAM authentication on the REST API, any IAM entity within the same account that has execute-api:Invoke permission can access it.

To forcibly deny access from entities other than a specific role on the REST API side, configure an explicit Deny with a StringNotEquals condition in the resource policy.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:ap-northeast-1:123456789012:<api-id>/prod/GET/",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalArn": "arn:aws:iam::123456789012:role/<PatternBRole>"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:ap-northeast-1:123456789012:<api-id>/prod/GET/"
    }
  ]
}

Why this is necessary: Within the same account, with an AWS_IAM authentication and Allow-only resource policy configuration, other IAM entities that have execute-api:Invoke via their identity-based policies can also access it. By adding an explicit Deny, access from entities other than the specified role can be reliably rejected.

After applying the resource policy, it was confirmed that Step Functions execution from PatternBRole still succeeded with a 200 response.

Comparison

Aspect EventBridge Connection (Private) API Gateway REST API + VPC Link v2
Routing path SFn → Connection → VPC Lattice → ALB SFn → API Gateway → VPC Link → ALB
ALB certificate Required (public CA) Not required for HTTP integration in this case
Protocol HTTPS only Both HTTP / HTTPS supported
Endpoint specification FQDN required ALB specified via VPC Link. No custom domain needed
Timeout HTTP Task 60-second limit API Gateway integration timeout default 29 seconds (can be extended via limit increase request)
User-managed DNS Required Not required
Required IAM permissions/control points states:InvokeHTTPEndpoint + events:RetrieveConnectionCredentials + secretsmanager:GetSecretValue/DescribeSecret + vpc-lattice-svcs:Invoke execute-api:Invoke + REST API AWS_IAM + resource policy
Step Functions integration method HTTP Task (http:invoke) Optimized Integration (apigateway:invoke)
EventBridge Rules integration A configuration where the same Private Connection can be reused with API Destination is expected (not verified in this article) API Gateway can be an EventBridge Rules target, but additional design is required for AWS_IAM auth configurations
VPC Lattice dependency Yes No
Resource Gateway SG All TCP / 0.0.0.0/0 allow required None (Resource Gateway not needed)

Selection Criteria

Cases where EventBridge Connection (Private) is suitable:

  • The caller is limited to Step Functions / EventBridge
  • You do not want to create an execute-api URL from API Gateway as an entry point
  • You want to use the same Connection with EventBridge API Destinations (use of Private Connection with API Destinations is not verified in this article)
  • You want VPC Lattice Resource Configuration / Resource Gateway to be the center of access control
  • API Gateway's API management features (throttling, usage plans, etc.) are not needed

Cases where API Gateway REST API + VPC Link v2 is suitable:

  • You simply want to call an Internal ALB from Step Functions and keep the configuration simple
  • You want to configure access control clearly with IAM authentication + resource policy
  • You want to avoid managing custom domain DNS and preparing public CA certificates

Summary

It was confirmed that both EventBridge Connection (Private) and API Gateway REST API + VPC Link v2 configurations allow Step Functions to call an Internal ALB inside a VPC without Lambda relay.

Both share the common point of being able to control access using IAM, but the authorization layer and routing path differ. Pattern A routes through VPC Lattice / Resource Configuration, while Pattern B uses API Gateway as the entry point. When restricting to a specific role in Pattern B, an explicit Deny via the REST API's resource policy is used in combination.

When you want to call a VPC internal API limited to Step Functions / EventBridge, EventBridge Connection (Private) is an option; when you want to have an entry point as an API Gateway REST API, API Gateway REST API + VPC Link v2 is the option.

If asynchronous processing is acceptable, SNS or SQS may be simpler in some cases, but when you need to synchronously call a VPC internal API and receive a return value, please try the two methods described in this article.

https://aws.amazon.com/jp/about-aws/whats-new/2024/12/amazon-eventbridge-step-functions-integration-private-apis/

https://aws.amazon.com/blogs/aws/securely-share-aws-resources-across-vpc-and-account-boundaries-with-privatelink-vpc-lattice-eventbridge-and-step-functions/

https://docs.aws.amazon.com/eventbridge/latest/userguide/connection-private-rc-provider.html

https://aws.amazon.com/blogs/compute/simplifying-private-api-integrations-with-amazon-eventbridge-and-aws-step-functions/

https://docs.aws.amazon.com/step-functions/latest/dg/connect-third-party-apis.html

https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-authorization-flow.html

https://dev.classmethod.jp/articles/api-gateway-rest-apis-integration-load-balancer/

https://dev.classmethod.jp/articles/cloudformation-fn-getstackoutput-ga-known-limitations/

Appendix: Complete CloudFormation Templates

Stack 1: 01-infra.yaml (ALB, VPC Lattice, Connection, API Gateway)
AWSTemplateFormatVersion: "2010-09-09"
Description: "Stack 1: Internal ALB + EventBridge Connection (Private) + API Gateway REST API"

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
    Default: vpc-0example1234567890
  SubnetIds:
    Type: CommaDelimitedList
    Default: "subnet-0example1a,subnet-0example1c,subnet-0example1d"
  CertificateArn:
    Type: String
    Default: arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  AlbDomainName:
    Type: String
    Default: eb-demo.example.com

Resources:
  # ============================================================
  # Common: Internal ALB
  # ============================================================
  AlbSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP/HTTPS from VPC CIDR
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 192.168.0.0/18
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 192.168.0.0/18

  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internal
      Subnets: !Ref SubnetIds
      SecurityGroups:
        - !Ref AlbSecurityGroup

  HttpListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref ALB
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - Type: fixed-response
          FixedResponseConfig:
            StatusCode: "200"
            ContentType: application/json
            MessageBody: '{"status":"ok","source":"internal-alb"}'

  HttpsListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref ALB
      Port: 443
      Protocol: HTTPS
      Certificates:
        - CertificateArn: !Ref CertificateArn
      DefaultActions:
        - Type: fixed-response
          FixedResponseConfig:
            StatusCode: "200"
            ContentType: application/json
            MessageBody: '{"status":"ok","source":"internal-alb"}'

  # ============================================================
  # Pattern A: EventBridge Connection (Private) via VPC Lattice
  # ============================================================
  ResourceGatewaySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for VPC Lattice Resource Gateway
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
          CidrIpv6: "::/0"

  ResourceGateway:
    Type: AWS::VpcLattice::ResourceGateway
    Properties:
      Name: eb-demo-resource-gw-v2
      IpAddressType: IPV4
      ResourceConfigDnsResolution: IN_VPC
      VpcIdentifier: !Ref VpcId
      SubnetIds: !Ref SubnetIds
      SecurityGroupIds:
        - !Ref ResourceGatewaySecurityGroup

  ResourceConfiguration:
    Type: AWS::VpcLattice::ResourceConfiguration
    Properties:
      Name: eb-demo-resource-cfg-v3
      ResourceGatewayId: !GetAtt ResourceGateway.Id
      ResourceConfigurationType: SINGLE
      ResourceConfigurationAuthType: AWS_IAM
      ProtocolType: TCP
      PortRanges:
        - "443"
      AllowAssociationToSharableServiceNetwork: true
      ResourceConfigurationDefinition:
        DnsResource:
          DomainName: !Ref AlbDomainName
          IpAddressType: IPV4

  PrivateConnection:
    Type: AWS::Events::Connection
    Properties:
      Name: eb-demo-private-connection
      AuthorizationType: API_KEY
      AuthParameters:
        ApiKeyAuthParameters:
          ApiKeyName: x-dummy-key
          ApiKeyValue: dummy
      InvocationConnectivityParameters:
        ResourceParameters:
          ResourceConfigurationArn: !GetAtt ResourceConfiguration.Arn

  # ============================================================
  # Pattern B: API Gateway REST API + VPC Link v2
  # ============================================================
  VpcLinkSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for API Gateway VPC Link
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 192.168.0.0/18

  VpcLink:
    Type: AWS::ApiGatewayV2::VpcLink
    Properties:
      Name: eb-demo-vpc-link
      SubnetIds: !Ref SubnetIds
      SecurityGroupIds:
        - !Ref VpcLinkSecurityGroup

  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: eb-demo-rest-api
      EndpointConfiguration:
        Types:
          - REGIONAL

  RestApiMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      RestApiId: !Ref RestApi
      ResourceId: !GetAtt RestApi.RootResourceId
      HttpMethod: GET
      AuthorizationType: AWS_IAM
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        ConnectionType: VPC_LINK
        ConnectionId: !Ref VpcLink
        IntegrationTarget: !Ref HttpListener
        Uri: !Sub "http://${ALB.DNSName}/"

  RestApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: RestApiMethod
    Properties:
      RestApiId: !Ref RestApi

  RestApiStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      RestApiId: !Ref RestApi
      DeploymentId: !Ref RestApiDeployment
      StageName: prod

  PublicConnection:
    Type: AWS::Events::Connection
    Properties:
      Name: eb-demo-public-connection
      AuthorizationType: API_KEY
      AuthParameters:
        ApiKeyAuthParameters:
          ApiKeyName: x-dummy-key
          ApiKeyValue: dummy

Outputs:
  AlbDnsName:
    Value: !GetAtt ALB.DNSName
  AlbHttpsListenerArn:
    Value: !Ref HttpsListener
  PrivateConnectionArn:
    Value: !GetAtt PrivateConnection.Arn
  PublicConnectionArn:
    Value: !GetAtt PublicConnection.Arn
  RestApiEndpoint:
    Value: !Sub "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"
  RestApiId:
    Value: !Ref RestApi
Stack 2: 02-stepfunctions.yaml (IAM Role × 2, State Machine × 2)
AWSTemplateFormatVersion: "2010-09-09"
Description: "Stack 2: Step Functions state machines (Pattern A: Private Connection, Pattern B: REST API)"

Parameters:
  InfraStackName:
    Type: String
    Default: eb-connection-infra

Resources:
  # ============================================================
  # IAM Role - Pattern A (Private Connection)
  # ============================================================
  PatternARole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: states.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: HttpInvokePrivate
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: states:InvokeHTTPEndpoint
                Resource: "*"
              - Effect: Allow
                Action: events:RetrieveConnectionCredentials
                Resource:
                  Fn::GetStackOutput:
                    StackName: !Ref InfraStackName
                    OutputName: PrivateConnectionArn
              - Effect: Allow
                Action:
                  - secretsmanager:GetSecretValue
                  - secretsmanager:DescribeSecret
                Resource:
                  Fn::Join:
                    - ""
                    - - "arn:aws:secretsmanager:"
                      - !Ref AWS::Region
                      - ":"
                      - !Ref AWS::AccountId
                      - ":secret:events!connection/eb-demo-private-connection/*"
              - Effect: Allow
                Action: vpc-lattice-svcs:Invoke
                Resource: "*"

  # ============================================================
  # IAM Role - Pattern B (REST API direct integration)
  # ============================================================
  PatternBRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: states.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: HttpInvokeRestApi
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: execute-api:Invoke
                Resource:
                  Fn::Join:
                    - ""
                    - - "arn:aws:execute-api:"
                      - !Ref AWS::Region
                      - ":"
                      - !Ref AWS::AccountId
                      - ":"
                      - Fn::GetStackOutput:
                          StackName: !Ref InfraStackName
                          OutputName: RestApiId
                      - "/prod/GET/"

  # ============================================================
  # State Machine A: Via EventBridge Connection (Private)
  # ============================================================
  StateMachineA:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      StateMachineName: eb-demo-pattern-a-private
      RoleArn: !GetAtt PatternARole.Arn
      DefinitionString:
        Fn::Join:
          - ""
          - - '{"StartAt":"CallPrivateApi","States":{"CallPrivateApi":{"Type":"Task","Resource":"arn:aws:states:::http:invoke","TimeoutSeconds":60,"Parameters":{"ApiEndpoint":"https://eb-demo.example.com/","Method":"GET","Authentication":{"ConnectionArn":"'
            - Fn::GetStackOutput:
                StackName: !Ref InfraStackName
                OutputName: PrivateConnectionArn
            - '"}},"End":true}}}'

  # ============================================================
  # State Machine B: Via API Gateway REST API (Optimized Integration)
  # ============================================================
  StateMachineB:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      StateMachineName: eb-demo-pattern-b-apigw
      RoleArn: !GetAtt PatternBRole.Arn
      DefinitionString:
        Fn::Join:
          - ""
          - - '{"StartAt":"CallRestApi","States":{"CallRestApi":{"Type":"Task","Resource":"arn:aws:states:::apigateway:invoke","Parameters":{"ApiEndpoint":"'
            - Fn::GetStackOutput:
                StackName: !Ref InfraStackName
                OutputName: RestApiId
            - '.execute-api.ap-northeast-1.amazonaws.com","Method":"GET","Stage":"prod","AuthType":"IAM_ROLE"},"End":true}}}'

Outputs:
  StateMachineArnPatternA:
    Value: !GetAtt StateMachineA.Arn
  StateMachineArnPatternB:
    Value: !GetAtt StateMachineB.Arn

Share this article

AWSのお困り事はクラスメソッドへ