Files
kodekloud-engineer/aws-48.md

6.0 KiB

Task 48

The Nautilus DevOps team needs to implement a Lambda function using a CloudFormation stack. Create a CloudFormation template named /root/devops-lambda.yml on the AWS client host and configure it to create the following components. The stack name must be devops-lambda-app.

Create a Lambda function named devops-lambda. Use the Runtime Python. The function should print the body Welcome to KKE AWS Labs!. Ensure the status code is 200. Create and use the IAM role named lambda_execution_role.

Solution

Lambda via CloudFormation Task (devops-lambda-app) — KodeKloud-Constrained

A simple single-Lambda CloudFormation stack. The only real substance is the two-resource template (role + function) with inline code, plus the KodeKloud limits baked in from the start.

KodeKloud limits applied to this task

Limit Where Why
Lambda timeout ≤ 10s Timeout: 10 > 10s auto-reset to 3s; > 30s suspends session
Lambda memory ≤ 256 MB MemorySize: 256 > 256 auto-reset to 128
Config set at CREATE time all in the template post-hoc Lambda config updates are blocked
IAM: managed policies only role uses ManagedPolicyArns inline/custom policy creation is denied
IAM within login scope AWSLambdaBasicExecutionRole (AWS-managed) can't exceed the kk_labs_user scope
Region us-east-1 deploy --region us-east-1 only allowed region
CFN named-IAM capability CAPABILITY_NAMED_IAM stack creates a named IAM role

Step 1 — Write the template

cat > /root/devops-lambda.yml << 'YAML'
AWSTemplateFormatVersion: '2010-09-09'
Description: devops-lambda function with execution role

Resources:

  # IAM role — MANAGED policy only (KodeKloud-safe), named as the task requires
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: lambda_execution_role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  # Lambda function — inline code, KodeKloud timeout/memory caps
  DevopsLambda:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: devops-lambda
      Handler: index.lambda_handler
      Runtime: python3.13
      Role: !GetAtt LambdaExecutionRole.Arn
      Timeout: 10
      MemorySize: 256
      Code:
        ZipFile: |
          def lambda_handler(event, context):
              return {
                  'statusCode': 200,
                  'body': 'Welcome to KKE AWS Labs!'
              }

Outputs:
  FunctionName:
    Value: !Ref DevopsLambda
  RoleArn:
    Value: !GetAtt LambdaExecutionRole.Arn
YAML

Every requirement mapped:

  • FunctionName: devops-lambda — req 1.
  • Runtime: python3.13 — req 2 ("Python"). 3.13 is current/supported; 3.14 is the newest if the grader wants absolute latest, but 3.13 is the safe pick. (Avoid 3.10/3.11 — AL2 deprecation track.)
  • The inline handler returns statusCode: 200 + body: 'Welcome to KKE AWS Labs!' — reqs 3 & 4. "Print the body" maps to the returned body field (the invocation response payload), exactly matching the earlier console-Lambda task.
  • LambdaExecutionRole named lambda_execution_role with AWSLambdaBasicExecutionRole attached — req 5. That managed policy grants CloudWatch Logs write (all a bare Lambda needs), and being AWS-managed it complies with the KodeKloud "no inline/custom, stay within login scope" rule.
  • Handler: index.lambda_handler — CloudFormation's inline ZipFile is written to a file named index.py internally, so the handler is index.<function>. The function is lambda_handler, hence index.lambda_handler. (No hyphen problem here — inline code, not an uploaded lambda-function.py.)
  • Timeout: 10 / MemorySize: 256 — KodeKloud caps, set at create.

Step 2 — Deploy

REGION=us-east-1

aws cloudformation deploy \
  --template-file /root/devops-lambda.yml \
  --stack-name devops-lambda-app \
  --capabilities CAPABILITY_NAMED_IAM \
  --region $REGION

⚠️ --capabilities CAPABILITY_NAMED_IAM is mandatory — the stack creates an IAM role with an explicit name (lambda_execution_role). Without it, deploy fails InsufficientCapabilities.

Step 3 — Verify

# Stack created cleanly
aws cloudformation describe-stacks --stack-name devops-lambda-app \
  --region $REGION --query 'Stacks[0].StackStatus'

# Function exists with correct config
aws lambda get-function-configuration --function-name devops-lambda \
  --region $REGION \
  --query '{Name:FunctionName,Runtime:Runtime,Timeout:Timeout,Memory:MemorySize,Role:Role}'

# Invoke and confirm the response body + status code
aws lambda invoke --function-name devops-lambda --region $REGION /tmp/out.json
cat /tmp/out.json

Want: stack CREATE_COMPLETE; the function showing python3.13, Timeout: 10, Memory: 256, role ending lambda_execution_role; and the invoke returning {"statusCode": 200, "body": "Welcome to KKE AWS Labs!"}. That payload is the task's proof.

Debug order

  1. Deploy InsufficientCapabilities → add --capabilities CAPABILITY_NAMED_IAM.
  2. Stack ROLLBACK_COMPLETE on the role → the lab may pre-create lambda_execution_role, causing a name collision (already exists). Check aws iam get-role --role-name lambda_execution_role; if it exists, remove the LambdaExecutionRole resource from the template and set the function's Role to that role's ARN directly. Then — since ROLLBACK_COMPLETE is terminal — aws cloudformation delete-stack --stack-name devops-lambda-app && aws cloudformation wait stack-delete-complete ... before redeploying.
  3. Timeout became 3s / memory 128 → you exceeded the caps somewhere; confirm Timeout: 10 and MemorySize: 256.
  4. Invoke returns wrong body → typo in the inline string; must be exactly Welcome to KKE AWS Labs!.