aws-cloudformation / aws-cloudformation-resource-providers-awsutilities-commandrunner

Apache License 2.0
81 stars 21 forks source link

Failing when CommandRunner is run in a private subnet #31

Closed maslick closed 2 years ago

maslick commented 3 years ago

I am trying to run CommandRunner in a private subnet with the following definition:

AWSTemplateFormatVersion: 2010-09-09
Description: AWS CLI version

Resources:
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/command-runner/${AWS::StackName}/"
      RetentionInDays: 14

  Role:
    Type: AWS::IAM::Role
    Properties:
      Description: "Role assumed by Command Runnner"
      MaxSessionDuration: 14400
      Path: "/"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref Role

  CommandRunner:
    Type: AWSUtility::CloudFormation::CommandRunner
    Properties:
      LogGroup: !Ref LogGroup
      Role: !Ref InstanceProfile
      SubnetId: subnet-029045502cbb1957b
      Command: |
        aws --version 2>&1 \
          | tail -1 \
          | head -n 1 \
          > /command-output.txt

Outputs:
  AwsCliVersion:
    Description: AWS CLI version
    Value: !GetAtt CommandRunner.Output

The Cloudformation stack fails with the following error (for the CommandRunner local resource name):

Resource handler returned message: "ParameterValue for ParameterKey SecurityGroupId is 
required (Service: AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; 
Request ID: 40883ed7-9c82-4c7a-9680-a725d511af23; Proxy: null) 400 ValidationError 
Client 40883ed7-9c82-4c7a-9680-a725d511af23" (RequestToken: 
1e4386ca-6b22-bbf0-3fb8-db6c14321538, HandlerErrorCode: InternalFailure)

According to BaseTemplate.json:

  "Resources": {
    "SecurityGroup": {
      "Condition": "CreateSecurityGroup",
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": {
          "Fn::Sub": "aws-cloudformation-commandrunner-temp-sg-${AWS::StackName}}"
        },
        "GroupDescription": "A temporary security group for AWS::CloudFormation::Command",
        "SecurityGroupEgress": [
          {
            "CidrIp": "0.0.0.0/0",
            "FromPort": -1,
            "IpProtocol": -1,
            "ToPort": -1
          }
        ],
        "VpcId": {
          "Ref": "VpcId"
        }
      }
    },

a security group will be created if the CreateSecurityGroup condition is met:

  "Conditions": {
    "CreateSecurityGroup": {
      "Fn::Equals": [
        {
          "Ref": "SecurityGroupId"
        },
        "empty"
      ]
    },

So, that means that the error raised when deploying my CommandRunner example template (SecurityGroupId is required) doesn't make any sense. The stack should be deployed normally without any error.

I am reporting this as a bug.

maslick commented 3 years ago

The evil comes from these checks:

Screenshot 2021-10-12 at 14 15 35

Even if either subnetId or securityGroupId were null (like in my case), it will still run the Both are provided block, it will set SecurityGroupId to null, and go on creating the stack which will fail since security group value cannot be null.

maslick commented 3 years ago

Here is the cure: #32

maslick commented 2 years ago

Hi @shantgup , what do you think?

shantgup commented 2 years ago

Thank you for this @maslick, I will include this fix in the next version.

shantgup commented 2 years ago

Fixed in version 2.0.