128 lines
6.0 KiB
Markdown
128 lines
6.0 KiB
Markdown
## 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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!`.
|
|
``` |