2024 第2课题 全国技能竞赛 评分标准
1. 评分注意事项
工种名称
云计算
※ 评分时请注意以下事项。
1) AWS 的区域使用各课题指定的 Region。
2) 网页访问使用 Chrome 或 Firefox。
3) 网页中根据语言不同,文字可能显示不同。
4) shell 中命令的输出可能因版本不同而略有差异。
5) 试题和评分表中的 <> 是变量。请更改该部分后输入。
6) 评分必须按题目顺序进行。
7) 已删除的评分资料无法恢复,请务必注意;在申诉完成之后,删除选手创建的云资源。
8) 有部分分数的题目,评分项中写有部分分数。
9) 没有单独部分分数的题目,必须全部正确才计分。
10) 读取资源信息的评分项,原则上通过脚本结果进行评分;如果选手有异议,可以直接输入命令进行确认。
11) [ ] 符号不影响评分。
12) 命令输入框中的命令行是一行命令。如果没有单独指示,请原样复制框内全部内容并粘贴到 shell 中执行命令。
13) (预期输出)表示紧接其前的(命令输入)的预期输出。
2. 评分标准表
1) 按主要项配分
| 课题 | 序号 | 编号 | 评分方法 主要项 | 配分 | 独立 | 协议 | 评分时间 比赛中 | 评分时间 比赛结束后 | 备注 |
|---|---|---|---|---|---|---|---|---|---|
| 庆北2课题3号 | 1 | | Elastic_stack | 3.0 | ○ | ○ | | | |
| 光州2课题3号 | 2 | | Collect application logs using Fluent-bit and Fluentd | 3.0 | ○ | ○ | | | |
| 大田2课题3号 | 3 | | EKS Observability with FluentBit | 3.0 | ○ | ○ | | | |
| 釜山2课题2号 | 4 | | Governance | 3.0 | ○ | ○ | | | |
| 首尔2课题1号 | 5 | | Image resizing on Edge location | 3.0 | ○ | ○ | | | |
| 首尔2课题3号 | 6 | | IAM security maintenance system | 3.0 | ○ | ○ | | | |
| 济州2课题3号 | 7 | | Secure networking | 3.0 | ○ | ○ | | | |
| 忠南2课题1号 | 8 | | Dynamic IAM Role Authorization Enforcement | 3.0 | ○ | ○ | | | |
| | 9 | | ClientVPN | 3.0 | ○ | ○ | | | |
| | 10 | | Keycloack | 3.0 | ○ | ○ | | | |
| 合计 | | | | 30 | | | | | |
2) 评分方法及标准
| 课题 | 序号 | 编号 | 主要项 | 子项序号 | 子项(评分方法) | 配分 |
|---|---|---|---|---|---|---|
| 庆北2课题3号 | 1 | | Elastic_stack | 1 | Bastion EC2 – 实例类型确认 | 0.2 |
| 庆北2课题3号 | 1 | | Elastic_stack | 2 | App EC2 – 实例类型确认 | 0.2 |
| 庆北2课题3号 | 1 | | Elastic_stack | 3 | Web 应用程序 - API 请求确认 | 0.4 |
| 庆北2课题3号 | 1 | | Elastic_stack | 4 | OpenSearch – 域确认 | 0.4 |
| 庆北2课题3号 | 1 | | Elastic_stack | 5 | OpenSearch – 详细设置确认 | 0.8 |
| 庆北2课题3号 | 1 | | Elastic_stack | 6 | OpenSearch – 日志确认 | 1 |
| 光州2课题3号 | 2 | | 使用 Fluent-bit 和 Fluentd 收集应用程序日志 | 1 | 基本部署配置确认 | 0.6 |
| 光州2课题3号 | 2 | | 使用 Fluent-bit 和 Fluentd 收集应用程序日志 | 2 | 集中式日志记录确认 | 1.2 |
| 光州2课题3号 | 2 | | 使用 Fluent-bit 和 Fluentd 收集应用程序日志 | 3 | 应用程序日志记录 | 1.2 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 1 | EKS – EKS Cluster 创建确认 | 0.24 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 2 | EKS – Namespace 确认 | 0.24 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 3 | CloudWatch Log Group 创建确认 | 0.24 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 4 | EKS Setting – Deployment 确认 | 0.24 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 5 | EKS Setting – Sidecar Pattern 确认 | 0.64 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 6 | Application – Application 确认 | 0.4 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 7 | Application – CloudWatch Log Stream 创建确认 | 0.44 |
| 大田2课题3号 | 3 | | 使用 FluentBit 的 EKS 可观测性 | 8 | Application – 日志格式确认 | 0.56 |
| 釜山2课题2号 | 4 | | 治理 | 1 | EC2 服务器配置 | 0.4 |
| 釜山2课题2号 | 4 | | 治理 | 2 | IAM User | 0.4 |
| 釜山2课题2号 | 4 | | 治理 | 3 | Trailing | 0.4 |
| 釜山2课题2号 | 4 | | 治理 | 4 | CloudWatch - User Login | 0.4 |
| 釜山2课题2号 | 4 | | 治理 | 5 | CloudWatch - 登录日志 | 0.4 |
| 釜山2课题2号 | 4 | | 治理 | 6 | Lambda 配置 | 0.4 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 1 | S3 Bucket | 0.2 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 2 | CloudFront - Resizing | 0.8 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 3 | CloudFront - Redirection | 0.6 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 4 | CloudFront - Caching | 0.4 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 5 | CloudFront - Ignore caching | 0.4 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 6 | CloudFront - CloudFront function | 0.4 |
| 首尔2课题1号 | 5 | | 边缘位置上的图像缩放 | 7 | Lambda - Runtime | 0.2 |
| 首尔2课题3号 | 6 | | IAM 安全维护系统 | 1 | tester | 0.2 |
| 首尔2课题3号 | 6 | | IAM 安全维护系统 | 2 | tester admin role | 0.2 |
| 首尔2课题3号 | 6 | | IAM 安全维护系统 | 3 | mfaBucketDeleteControl | 1.2 |
| 首尔2课题3号 | 6 | | IAM 安全维护系统 | 4 | user_group_kr | 0.2 |
| 首尔2课题3号 | 6 | | IAM 安全维护系统 | 5 | Only Seoul region | 1.2 |
| 济州2课题3号 | 7 | | 安全网络 | 1 | S3 - S3 名称 | 0.12 |
| 济州2课题3号 | 7 | | 安全网络 | 2 | S3 - S3 访问确认 | 0.64 |
| 济州2课题3号 | 7 | | 安全网络 | 3 | S3 - 备份桶文件复制确认 | 0.64 |
| 济州2课题3号 | 7 | | 安全网络 | 4 | SQS - S3 事件发生确认 | 0.64 |
| 济州2课题3号 | 7 | | 安全网络 | 5 | SQS - EC2 事件发生确认 | 0.28 |
| 济州2课题3号 | 7 | | 安全网络 | 6 | NAT G/W & Internet G/W 创建与否确认 | 0.4 |
| 济州2课题3号 | 7 | | 安全网络 | 7 | endpoint - 实例访问子网确认 | 0.28 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 1 | IAM - User Name | 0.16 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 2 | IAM - User policy | 0.2 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 3 | IAM - instance role Name | 0.16 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 4 | IAM - instance role policy | 0.2 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 5 | Monitoring Service Name - CloudTrail Name | 0.16 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 6 | CloudWatch Alarm Name | 0.2 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 7 | CloudWtach Log Group Name | 0.16 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 8 | Lambda - Lambda name | 0.16 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 9 | Employee - Alarm | 0.4 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 10 | Employee - instance role policy test | 0.4 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 11 | Admin - Alarm | 0.4 |
| 忠南2课题1号 | 8 | | 动态 IAM 角色授权强制执行 | 12 | Admin - instance role policy test | 0.4 |
| | 9 | | ClientVPN | 1 | 域查询 | 1.5 |
| | 9 | | ClientVPN | 2 | DB 连接 | 1.5 |
| | 10 | | Keycloak | 1 | admin 登录 | 1.5 |
| | 10 | | Keycloak | 2 | dev 登录 | 1.5 |
总分 30
3) 评分内容
| 序号 | 评分项 | 命令输入 | 预期输出 |
|---|---|---|---|
| 1-1 | 1-1-A | `aws ec2 describe-instances --filter Name=tag:Name,Values=wsi-bastion \`
`--query "Reservations[].Instances[].InstanceType"` | `[`
`"t3.small"`
`]` |
| 1-2 | 1-2-A | `aws ec2 describe-instances --filter Name=tag:Name,Values=wsi-app \`
`--query "Reservations[].Instances[].InstanceType"` | `[`
`"t3.small"`
`]` |
| 1-3 | 1-3-A | `APP_PRIVATE_IP=$(aws ec2 describe-instances --filters`
`"Name=tag:Name,Values=wsi-app" --query`
`"Reservations[*].Instances[*].PrivateIpAddress" --output text)`
`curl $APP_PRIVATE_IP:5000/log`
`echo ""`
`curl $APP_PRIVATE_IP:5000/healthcheck` | `Log entry created`
`status: ok` |
| 1-4 | 1-4-A | `aws opensearch list-domain-names \| grep wsi-opensearch` | `"DomainName": "wsi-opensearch"` |
| 1-5 | 1-5-A | `aws opensearch describe-domain --domain-name wsi-opensearch --query`
`"DomainStatus.ClusterConfig.[InstanceCount, DedicatedMasterCount]"` | `[`
`2,`
`3`
`]` |
| 1-5 | 1-5-B | `aws opensearch describe-domain --domain-name wsi-opensearch --query`
`"DomainStatus.EngineVersion"` | `"OpenSearch_2.13"` |
| 1-5 | 1-5-C | `OPENSEARCH_ENDPOINT=$(aws opensearch describe-domain --domain-name`
`wsi-opensearch \| jq -r '.DomainStatus.Endpoint')`
`curl -s -u admin:Password01!`
`"https://$OPENSEARCH_ENDPOINT/_cat/indices?index=app-log"` | `green open app-log dWxHtcnyQcGsMwhGB0FMYw 5 1 2 0 34kb 17kb`
确认是否存在如上包含 app-log 的输出 |
| 1-5 | 1-5-D | `OPENSEARCH_ENDPOINT=$(aws opensearch describe-domain --domain-name`
`wsi-opensearch \| jq -r '.DomainStatus.Endpoint')`
`curl -s -u admin:Password01! https://$OPENSEARCH_ENDPOINT/app-log \|`
`jq '.["app-log"].mappings.properties \| keys[]'` | `"clientip"`
`"method"`
`"path"`
`"protocol"`
`"responsecode"`
`"time"`
`"useragent“"`
不必完全一致 |
确认是否如上所述输出 clientip、method、path、protocol、responsecode、time、
useragent
1-6-A
(输入命令)
aws opensearch describe-domain --domain-name wsi-opensearch --output json |
jq -r '.DomainStatus.Endpoint + "/_dashboards"'
1-6-A
输出仪表板 URL。
(预期输出)
1-6
在浏览器中访问输出的 URL。
1-6-B
(访问仪表板)
使用 ID admin、密码 Password01! 登录。
访问仪表板的 discover 标签页。
将 index 指定为 app-log。
序号
评分项
1-6-B
(预期输出)
确认是否输出日志。
1-6
1-6-C
在 search 中输入 /healthcheck。
(仪表板确认)
1-6-C
(预期输出)
确认没有日志输出。
序号
评分项
kubectl get deployment service-a -n app -o=json | jq
'.spec.template.spec.containers' | grep '"image"' \
2-1-A
(输入命令)
; kubectl get deployment service-b -n app -o=json | jq
'.spec.template.spec.containers' | grep '"image"' \
; kubectl get deployment service-c -n app -o=json | jq
'.spec.template.spec.containers' | grep '"image"'
"image": "250832144271.dkr.ecr.ap-northeast-2.amazonaws.com/service:a",
"image": "fluent/fluent-bit:latest",
"image": "250832144271.dkr.ecr.ap-northeast-2.amazonaws.com/service:b",
2-1-A
(预期输出)
2-1
"image": "fluent/fluent-bit:latest",
"image": "250832144271.dkr.ecr.ap-northeast-2.amazonaws.com/service:c",
"image": "fluent/fluent-bit:latest",
* 除下划线部分外,其余必须全部相同
NODE_COUNT=$(kubectl get nodes | grep Ready | wc -l) \
; DAEMONSET_COUNT=$(kubectl get daemonsets -n fluentd | tail -n 1 | awk
2-1-B
{'print $4'}) \
(输入命令)
; echo $(expr $NODE_COUNT - $DAEMONSET_COUNT) \
; kubectl describe -n fluentd daemonset fluentd | grep Image | grep fluent
2-1-B
0
(预期输出)
Image: fluent/fluentd-kubernetes-daemonset:v1.10.3-debian-cloudwatch-1.0
完全一致
序号
评分项
cd /tmp
kubectl get daemonset fluentd -n fluentd -o yaml > fluentd.yaml
kubectl delete daemonset fluentd -n fluentd
date
kubectl exec -it -n app deployment.apps/service-a -- curl localhost:8080 > /dev/null 2>&1
kubectl exec -it -n app deployment.apps/service-b -- curl localhost:8080 > /dev/null 2>&1
2-2-A
kubectl exec -it -n app deployment.apps/service-c -- curl localhost:8080 > /dev/null 2>&1
sleep 30;
(输入命令)
aws logs get-log-events --log-group-name /gwangju/eks/application/logs --log-stream-name
service-a-logs --limit 1 --query 'events[*].message' --output json \
; aws logs get-log-events --log-group-name /gwangju/eks/application/logs --log-stream-name
service-b-logs --limit 1 --query 'events[*].message' --output json \
; aws logs get-log-events --log-group-name /gwangju/eks/application/logs --log-stream-name
service-c-logs --limit 1 --query 'events[*].message' --output json
kubectl apply -f fluentd.yaml
daemonset.apps "fluentd" deleted
Fri May 31 02:00:30 UTC 2024
2-2
[
"{\"log\":\"[2024-05-31 01:55:07,660] Service A 127.0.0.1 \\\"GET
/\\\" 0.93ms 200\"}"
]
[
"{\"log\":\"[2024-05-31 01:55:08,682] Service B 127.0.0.1 \\\"GET
2-2-A
(预期输出)
/\\\" 0.45ms 200\"}"
]
[
"{\"log\":\"[2024-05-31 01:57:06,019] Service C 127.0.0.1 \\\"GET
/\\\" 0.78ms 200\"}"
]
daemonset.apps/fluentd created
* 如果出现 date 时间之后的日志,则判为错误
序号
评分项
date
kubectl exec -it -n app deployment.apps/service-a -- curl localhost:8080 > /dev/null 2>&1
kubectl exec -it -n app deployment.apps/service-b -- curl localhost:8080 > /dev/null 2>&1
kubectl exec -it -n app deployment.apps/service-c -- curl localhost:8080 > /dev/null 2>&1
2-3-A
sleep 30;
aws logs get-log-events --log-group-name /gwangju/eks/application/logs --log-stream-name
(输入命令)
service-a-logs --limit 1 --query 'events[*].message' --output json \
; aws logs get-log-events --log-group-name /gwangju/eks/application/logs --log-stream-name
service-b-logs --limit 1 --query 'events[*].message' --output json \
; aws logs get-log-events --log-group-name /gwangju/eks/application/logs --log-stream-name
service-c-logs --limit 1 --query 'events[*].message' --output json
Fri May 31 01:49:42 UTC 2024
[
"{\"log\":\"[2024-05-31 01:49:43,591] Service A 127.0.0.1 \\\"GET
2-3
/\\\" 0.59ms 200\"}"
]
[
"{\"log\":\"[2024-05-31 01:49:44,473] Service B 127.0.0.1 \\\"GET
2-3-A
(预期输出)
/\\\" 0.95ms 200\"}"
]
[
"{\"log\":\"[2024-05-31 01:49:45,463] Service C 127.0.0.1 \\\"GET
/\\\" 0.82ms 200\"}"
]
* Service A、B、C 必须各输出一次,并确认 date 命令输出时间之后的日志是否在 30 秒内记录
序号
评分项
1) 通过 SSH 访问 EC2。
2) 输入以下命令后,确认是否输出 “wsi-eks-cluster”。
3-1
aws eks describe-cluster --name wsi-eks-cluster —query "cluster.name“
3) 输入以下命令后,确认是否输出 “1.29”。
aws eks describe-cluster --name wsi-eks-cluster --query "cluster.version"
3-2
1) 通过 SSH 访问 EC2。
3-2
2) 输入以下命令后,确认是否输出 “wsi-ns”。
kubectl get ns -o json | jq '.items[] | select(.metadata.name == "wsi-ns") |
.metadata.name'
3-3
1) 通过 SSH 访问 EC2。
3-3
2) 输入以下命令后,确认是否输出 “/wsi/eks/log/”。
aws logs describe-log-groups --query "logGroups[?contains(logGroupName,
'/wsi/eks/log/')].logGroupName“
3-4
1) 通过 SSH 访问 EC2。
3-4
2) 输入以下命令后,确认是否输出 “wsi-dpm”。
kubectl get deploy -n wsi-ns -o json | jq '.items[].metadata.name’
3-5
1) 通过 SSH 访问 EC2。
3-5
2) 输入以下命令后,确认是否输出 “wsi-cnt”和“fluent-bit-cnt”。
(必须存在 wsi-cnt 2 个、fluent-bit-cnt 2 个,共 4 个。)
kubectl get po -n wsi-ns -o json | jq '.items[].spec.containers[].name'
1) 通过 SSH 访问 EC2。
2) 输入以下命令。
POD_NAME=$(kubectl get po -n wsi-ns -o jsonpath='{.items[0].metadata.name}')
3) 输入以下命令后,确认是否输出 “{'status': '200'}”。
kubectl exec -it $POD_NAME -n wsi-ns -- curl localhost:8080/2xx
3) 输入以下命令后,确认是否输出 “{'status': '300'}”。
3-6
kubectl exec -it $POD_NAME -n wsi-ns -- curl localhost:8080/3xx
3) 输入以下命令后,确认是否输出 “{'status': '400'}“。
kubectl exec -it $POD_NAME -n wsi-ns -- curl localhost:8080/4xx
3) 输入以下命令后,确认是否输出 “{'status': '500'}“。
kubectl exec -it $POD_NAME -n wsi-ns -- curl localhost:8080/5xx
3) 输入以下命令后,确认是否输出 “{'status': 'ok'}“。
kubectl exec -it $POD_NAME -n wsi-ns -- curl localhost:8080/healthz
序号
评分项
1) 通过 SSH 访问 EC2。
2) 输入以下命令。
CW_LOG_STREAM_NAME=$(aws logs describe-log-streams --log-group-name /wsi/eks/log/ \
--query "logStreams[].logStreamName" --output text)
3-7
POD_ID=$(kubectl get po -n wsi-ns -o jsonpath='{.items[0].metadata.name}')
MATCHING_LOG_STREAM_NAME="log-$POD_ID"
3) 输入以下命令后,确认是否输出 “log-{Pod ID}”。
{Pod ID} 表示对应 Pod 的名称,每位选手的值可能不同。
[ "$CW_LOG_STREAM_NAME" == "$MATCHING_LOG_STREAM_NAME" ] && aws logs describe-log-streams \
--log-group-name /wsi/eks/log/ —query "logStreams[].logStreamName“
1) 通过 SSH 访问 EC2。
2) 输入以下命令。
aws logs tail /wsi/eks/log/ | tail -n 1 | awk '{print substr($0,index($0,"{"))}' | jq .
3) 确认如下图中所示是否存在 day、hour、ip、method、minute、month、path、port、second、statuscode、year。(只要有一个不存在,即视为错误。)
(Key 的位置可以不同,Value 也可能存在差异。)
3-8
序号
评分项
aws ec2 describe-instances --filters
"Name=tag:Name,Values=wsi-bastion-ec2" --query
"Reservations[*].Instances[*].[InstanceId, InstanceType,
IamInstanceProfile.Arn]" --output text | awk '{print $1,$2,$3}' | xargs -I
{} bash -c 'INSTANCE_PROFILE_NAME=$(echo {} | awk -F"/" "{print
4-1-A
(命令输入)
\$NF}"); ROLE_NAME=$(aws iam get-instance-profile
--instance-profile-name $INSTANCE_PROFILE_NAME --query
"InstanceProfile.Roles[*].RoleName" --output text); echo "Instance ID:
4-1
$(echo {} | awk "{print \$1}")"; echo "Instance Type: $(echo {} | awk
"{print \$2}")"; aws iam list-attached-role-policies --role-name
$ROLE_NAME --query "AttachedPolicies[*].[PolicyName, PolicyArn]"
--output text'
4-1-A
Instance ID: i-xxxxxxxxxxxxxxxxxxxxxxxx
(预期输出)
Instance Type: t3.small
完全匹配
AdministratorAccess
arn:aws:iam::aws:policy/AdministratorAccess
顺序重要
aws iam get-user --user-name wsi-project-user --query
"User.UserName" --output text \
; aws iam list-attached-user-policies --user-name wsi-project-user
4-2-A
(命令输入)
--query 'AttachedPolicies[*].PolicyName' --output text && aws iam
list-user-policies --user-name wsi-project-user --query 'PolicyNames'
--output text
4-2
4-2-A
(预期输出)
wsi-project-user
完全匹配
AdministratorAccess
顺序重要
序号
评分项
4-3-A
(命令输入)
4-3
aws cloudtrail describe-trails --query
'trailList[?Name==`wsi-project-trail`].Name' --output json
4-3-A
[
(预期输出)
"wsi-project-trail"
完全匹配
]
顺序重要
4-4-A
4-4
4-4-A
从账户注销后,使用此前创建的 IAM 用户登录。
序号
评分项
登录后
需 4 分钟
date -d "+9 hours" "+%Y-%m-%d.%H.%M.%S“
echo "4분 소요"
sleep 240
LOG_GROUP_NAME="wsi-project-login"
aws logs describe-log-groups --log-group-name-prefix $LOG_GROUP_NAME
--query 'logGroups[?logGroupName==`wsi-project-login`].logGroupName' --output
4-5-A
json
LATEST_LOG_STREAM=$(aws logs describe-log-streams --log-group-name
(命令输入)
$LOG_GROUP_NAME --order-by LastEventTime --descending --limit 1 --query
'logStreams[0].logStreamName' --output text)
aws logs get-log-events --log-group-name $LOG_GROUP_NAME
--log-stream-name $LATEST_LOG_STREAM --limit 1 --query
'events[-1].{timestamp:timestamp, message:message}' --output json | jq -r
'"\(.timestamp)\t\(.message)"' | while IFS=$'\t' read -r timestamp message; do
echo -e "$(date -d @$((timestamp / 1000 + 9 * 3600))
'+%Y-%m-%d-%H:%M:%S')\t$message"; done
4-5-A
(预期输出)
2024-07-21.20.23.52
[
确认 timestamp,检查是否包含在 4 分钟内
4-6-A
(命令输入)
4-6
"wsi-project-login"
]
2024-07-21.20.24.51
{ USER : "wsi-project-user has logged in!" }
(截止 UTC 时间也允许计分)
aws lambda get-function --function-name wsi-project-log-function
--query 'Configuration.FunctionName' --output json
4-6-A
(预期输出)
"wsi-project-log-function"
完全匹配
顺序重要
序号
评分项
5-1-A
aws s3 ls s3://${STATIC_BUCKET}/ --recursive | awk '{print $4}'
(命令输入)
5-1
5-1-A
(预期输出)
dev/
images/glass.jpg
images/hamster.jpg
完全匹配
顺序重要
5-2-A
(命令输入)
5-2
images/library.jpg
index.html
curl -s "https://${CF_DOMAIN}/images/library.jpg?width=400&height=400" | file -b
- | grep -oE '[0-9]+x[0-9]+' | tail -n 1
5-2-A
(预期输出)
400x400
完全匹配
顺序重要
5-3-A
(命令输入)
curl -sIL -o /dev/null -w '%{url_effective}\n' https://${CF_DOMAIN}/dev/
curl -sIL -o /dev/null -w '%{url_effective}\n' https://${CF_DOMAIN}/
5-3-A
5-3
(预期输出)
完全匹配
https:///index.html
可能因选手而异
https:///index.html
curl -sI "https://${CF_DOMAIN}/images/library.jpg?width=123&height=32" | grep -i
"x-cache"
5-4-A
(命令输入)
curl -sI "https://${CF_DOMAIN}/images/library.jpg?width=123&height=32" | grep -i
"x-cache"
curl -sI "https://${CF_DOMAIN}/images/library.jpg?width=123&height=40" | grep -i
5-4
"x-cache"
5-4-A
(预期输出)
x-cache: Miss from cloudfront
x-cache: Hit from cloudfront
完全匹配
顺序重要
x-cache: Miss from cloudfront
序号
5-5
评分项
5-5-A
curl -sI "https://${CF_DOMAIN}/index.html" | grep -i "x-cache"
(命令输入)
curl -sI "https://${CF_DOMAIN}/index.html" | grep -i "x-cache"
5-5-A
(预期输出)
x-cache: Miss from cloudfront
完全匹配
x-cache: Miss from cloudfront
顺序重要
aws cloudfront get-distribution-config --id ${DISTRIBUTION_ID} --query
5-6-A
"DistributionConfig.DefaultCacheBehavior.FunctionAssociations.Quantity > \`0\` ||
(命令输入)
DistributionConfig.CacheBehaviors.Items[].FunctionAssociations.Quantity > \`0\`"
--output text
5-6
5-6-A
(预期输出)
True
完全匹配
顺序重要
5-7-A
(命令输入)
5-7
aws lambda get-function-configuration --function-name ${LAMBDA_NAME}
--region us-east-1 --query "Runtime" --output text
5-7-A
(预期输出)
nodejs20.x
仅二者之一
python3.9
匹配
序号
评分项
6-1-A
(命令输入)
6-1
aws iam list-users --query "Users[?UserName=='tester']" | grep -i
username
6-1-A
(预期输出)
"UserName": "tester",
完全匹配
顺序重要
6-2-A
(命令输入)
6-2
aws iam list-attached-user-policies --user-name tester | grep
AdministratorAccess
6-2-A
(预期输出)
"PolicyName": "AdministratorAccess",
完全匹配
"PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
顺序重要
aws iam get-policy-version --policy-arn arn:aws:iam::$(aws sts
6-3-A
(命令输入)
get-caller-identity --query "Account" --output
text):policy/mfaBucketDeleteControl --version-id v1 --query
'PolicyVersion.Document.Statement[].Condition' | jq
[
6-3
{
6-3-A
"Bool": {
(预期输出)
"aws:MultiFactorAuthPresent": "false"
完全匹配
}
顺序重要
}
]
6-4-A
(命令输入)
6-4
aws iam list-groups --query "Groups[?GroupName=='user_group_kr']" |
grep GroupName
6-4-A
(预期输出)
"GroupName": "user_group_kr",
完全匹配
顺序重要
序号
评分项
aws iam simulate-principal-policy \
6-5-A
(命令输入)
--policy-source-arn arn:aws:iam::$ACCOUNT_ID:user/tester \
--action-names ec2:DescribeInstances \
--region ap-northeast-2 | jq '.EvaluationResults[0].EvalDecision'
6-5
6-5-A
(预期输出)
"explicitDeny"
高亮色匹配
buckets=$(aws s3 ls | awk '{print $3}' | grep -E
'j-s3-bucket-[a-zA-Z0-9]{7}-(original|backup)')
bucket1=$(echo "$buckets" | grep 'original' | head -n 1)
7-1-A
(命令输入)
bucket2=$(echo "$buckets" | grep 'backup' | head -n 1)
buckets=$(aws s3 ls | awk '{print $3}' | grep -E
7-1
'^j-s3-bucket-[a-zA-Z0-9]{7}-(original|backup)$')
echo "$buckets"
7-1-A
j-s3-bucket-<任意7个字符>-backup
完全匹配
j-s3-bucket-<任意7个字符>-original
echo “test” > test.txt
7-2-A
(命令输入)
aws s3 cp test.txt s3://j-s3-bucket-<任意7个字符>-original/
aws s3 cp test.txt s3://j-s3-bucket-<任意7个字符>-original/2024/
aws s3 cp test.txt s3://j-s3-bucket-<任意7个字符>-backup/
sleep 80
upload: ./test.txt to s3://j-s3-bucket-<任意7个字符>-original/test.txt
7-2-A
7-2
完全匹配
upload: ./test.txt to s3://j-s3-bucket-<任意7个字符>-original/2024/test.txt
upload: ./test.txt to s3://j-s3-bucket-<任意7个字符>-backup/test.txt
7-2-B
(命令输入)
7-2-B
完全匹配
aws s3 cp test.txt s3://j-s3-bucket-<任意7个字符>-backup/2024/
upload failed: ./test.txt to s3://j-s3-bucket-<任意7个字符>-backup/2024/test.txt An error
occurred (AccessDenied) when calling the PutObject operation: Access Denied
序号
评分项
echo “copy” > copy.txt
7-3-A
(命令输入)
aws s3 cp copy.txt s3://j-s3-bucket-<任意7个字符>-original/2024/
sleep 80
7-3-A
完全匹配
upload: ./copy.txt to s3://j-s3-bucket-<任意7个字符>-original/2024/copy.txt
移动到 https://ap-northeast-2.console.aws.amazon.com/s3。
移动到 j-s3-bucket-<任意7个字符>-backup。进入 2024/ 文件夹后,
确认是否存在 copy.txt 文件。如果存在,则进入 j-s3-bucket-<任意7个
字符>-original 桶和 j-s3-bucket-<任意7个字符>-backup 的 2024/ 文件夹,
点击 show versions,确认 copy.txt 的 Version ID 是否相同。必须在 4 分钟内
完成复制。
7-3
7-3-B
确认文件是否
上传到备份桶
echo “check” > check.txt
7-4-A
(命令输入)
aws s3 cp check.txt s3://j-s3-bucket-<任意7个字符>-original/2024/
sleep 80
7-4
7-4-A
完全匹配
upload: ./check.txt to s3://j-s3-bucket-<任意7个字符>-original/2024/check.txt
序号
评分项
移动到 https://ap-northeast-2.console.aws.amazon.com/s3/。
确认 j-s3-bucket-example-backup 的 2024/ 文件夹中名为 check.txt 的文件是否为 1 个,
并检查 Last Modified。
7-4-B
手动
7-4
移动到 https://ap-northeast-2.console.aws.amazon.com/sqs/v3/home?region=ap-northea
st-2#/queues。移动到创建的 Queues。移动后,点击右上方的 Send and receive messages。
如果文件上传到 j-s3-bucket-example-backup 的 2024 文件夹,则点击 Poll for messages。
7-4-C
确认是否发生
Event
Sent 时间必须与 j-s3-bucket-example-backup 的 2024/ 文件夹中
check.txt 的 Last Modified 相同。(可能会有约 1 分钟的误差范围。)
ex ) Last modified 07:22 -> SQS Send 07:23 O 07:21 X
aws sqs send-message --queue-url \
https://sqs.ap-northeast-2.amazonaws.com// \
7-5-A
手动
--message-body "Hello from EC2!“
必须将 和 替换为选手指定的内容。
7-5
{
7-5-A
完全匹配
"MD5OfMessageBody": "d6d829edde2cd621a6f20ef7e8c15c61",
"MessageId": "37c567b2-175f-4b23-9532-bc6c3d117e47"
}
MD5OfMessageBody 和 MessageId 可能不同。
序号
评分项
https://ap-northeast-2.console.aws.amazon.com/vpcconsole/home?region
=ap-northeast-2#NatGateways:
1) 通过上述 URL 进入,确认 Bastion 所属 VPC 中未创建 Nat G/W。
7-6
7-6-A
手动
https://ap-northeast-2.console.aws.amazon.com/vpcconsole/home?region
=ap-northeast-2#igws:
2) 通过上述 URL 进入,确认 Bastion 所属 VPC 中未创建 IGW。
3) 如果创建了其中任何一个,则该项按 0 分处理。
https://ap-northeast-2.console.aws.amazon.com/vpcconsole/home?region
=ap-northeast-2#Endpoints:
通过上述 URL 进入。进入后,单击 VPC endpoint ID 以 eice- 开头的
endpoint,然后点击 Subnet,确认其是否为 J-company-priv-sub-b。
7-7
7-7-A
手动
序号
评分项
8-1-A
aws iam list-users --query "Users[?UserName=='myadmin'].UserName“
(命令输入)
aws iam list-users --query "Users[?UserName=='Employee'].UserName“
[
“myadmin”
8-1
8-1-A
],
(预期输出)
[
完全匹配
“ Employee”
]
8-2-A
aws iam list-attached-user-policies --user-name mydmin
(命令输入)
aws iam list-attached-user-policies --user-name Employee
{
"AttachedPolicies": [
{
"PolicyName": "AdministratorAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
}
8-2
]
8-2-A
},
(预期输出)
{
完全匹配
"AttachedPolicies": [
{
"PolicyName": "IAMFullAccess",
"PolicyArn": "arn:aws:iam::aws:policy/IAMFullAccess"
}
]
}
序号
评分项
8-3-A
序号 评分项
## 8-3
**8-3-A**
(输入命令)
```bash
aws iam get-role --role-name wsc2024-instance-role --query 'Role.RoleName'
```
(预期输出)
```
"wsc2024-instance-role"
```
完全匹配
## 8-4
**8-4-A**
(输入命令)
```bash
aws iam list-attached-role-policies --role-name wsc2024-instance-role --query "AttachedPolicies[].PolicyArn"
```
(预期输出)
```
[
"arn:aws:iam:aws:policy/AmazonSSMManagedInstanceCore"
]
```
完全匹配
## 8-5
**8-5-A**
(输入命令)
```bash
aws cloudtrail describe-trails --trail-name-list wsc2024-CT --query "trailList[].Name"
```
(预期输出)
```
[
"wsc2024-CT"
]
```
完全匹配
## 8-6
**8-6-A**
(输入命令)
```bash
aws cloudwatch describe-alarms --alarm-name-prefix wsc2024-gvn-alarm --query 'MetricAlarms[*].AlarmName'
```
(预期输出)
```
[
"wsc2024-gvn-alarm"
]
```
完全匹配
## 8-7
**8-7-A**
(输入命令)
```bash
aws logs describe-log-groups --log-group-name-prefix wsc2024-gvn-LG --query 'logGroups[].logGroupName' --output text
```
(预期输出)
```
wsc2024-gvn-LG
```
完全匹配
## 8-8
**8-8-A**
(输入命令)
```bash
aws lambda list-functions --query "Functions[?FunctionName=='wsc2024-gvn-Lambda'].FunctionName"
```
(预期输出)
```
[
"wsc2024-gvn-Lambda"
]
```
完全匹配
## 8-9
**8-9-A**
(输入命令)
```bash
USERNAME="Employee"
CREATED_KEYS=$(aws iam create-access-key --user-name "$USERNAME")
ACCESS_KEY_ID=$(echo "$CREATED_KEYS" | jq -r '.AccessKey.AccessKeyId')
SECRET_ACCESS_KEY=$(echo "$CREATED_KEYS" | jq -r '.AccessKey.SecretAccessKey')
aws configure set aws_access_key_id "$ACCESS_KEY_ID"
aws configure set aws_secret_access_key "$SECRET_ACCESS_KEY"
sleep 10
aws iam attach-role-policy --role-name wsc2024-instance-role --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
rm -rf ~/.aws/*
timeout 180 bash -c 'while [ "$(aws cloudwatch describe-alarms
--alarm-names "wsc2024-gvn-alarm" --query "MetricAlarms[0].StateValue"
--output text)" != "ALARM" ]; do echo "Waiting for alarm to enter ALARM
state..."; sleep 30; done; echo "Alarm is now in ALARM state."'
```
(预期输出)
```
Wating for alarm to enter ALARM state...
Wating for alarm to enter ALARM state...
Wating for alarm to enter ALARM state...
Alarm is now in ALARM state.
```
下划线部分匹配
## 8-10
**8-10-A**
(输入命令)
```bash
aws iam list-attached-role-policies --role-name wsc2024-instance-role
```
(预期输出)
```json
{
"AttachedPolicies": [
{
"PolicyName": "AmazonSSMManagedInstanceCore",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
]
}
```
完全匹配
## 8-11
**8-11-A**
(输入命令)
```bash
USERNAME="Admin"
CREATED_KEYS=$(aws iam create-access-key --user-name "$USERNAME")
ACCESS_KEY_ID=$(echo "$CREATED_KEYS" | jq -r '.AccessKey.AccessKeyId')
SECRET_ACCESS_KEY=$(echo "$CREATED_KEYS" | jq -r '.AccessKey.SecretAccessKey')
aws configure set aws_access_key_id "$ACCESS_KEY_ID"
aws configure set aws_secret_access_key "$SECRET_ACCESS_KEY"
sleep 10
aws iam attach-role-policy --role-name wsc2024-instance-role --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
sleep 180 && aws cloudwatch describe-alarms --alarm-names "wsc2024-gvn-alarm" --query "MetricAlarms[0].StateValue" --output text
```
(预期输出)
```
仅确认不是 ALARM 状态
INSUFFICIENT_DATA
OK
```
## 8-12
**8-12-A**
(输入命令)
```bash
aws iam list-attached-role-policies --role-name wsc2024-instance-role
```
(预期输出)
```json
{
"AttachedPolicies": [
{
"PolicyName": "AmazonSSMManagedInstanceCore",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
},
{
"PolicyName": "AdministratorAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
}
]
}
```
完全匹配
序号 评分项
如果符合以下任一要素,即视为使用非正常方法作答,Client VPN 项全部不予评分。其他事项也会核查,若判定使用了不正当方法,则不予评分。
1) 确认 Client VPN 连接是否已断开。
2) 在选手 Windows PC 上输入以下命令,确认查询是否失败。
> nslookup db.day2.local
3) 在选手 Windows PC 上输入以下命令,确认是否因无法找到主机错误而导致连接失败。
> ping db.day2.local
4) 在选手 Windows PC 上输入以下命令,确认没有处于 listen 状态的端口。
> netstat -an | findstr 5432
## 9-1
1) 在 Windows PC 上连接 Client VPN。务必确认使用 ws-day2 配置文件。
2) 连接 VPN 后,在 Windows 中输入以下命令,确认是否返回正确的 canonical name 和 IP。
>nslookup db.day2.local
输出包含 canonical name:rds.amazonaws.com.
IP address:172.26.10.1 ~ 172.26.10.254 或 172.26.20.1 ~ 172.26.20.254 之间的地址
## 9-2
1) 在 Windows PC 上确认 Client VPN 是否已连接。(使用 ws-day2 配置文件)
2) 连接 VPN 后,在 Windows 中输入以下命令,确认是否可以访问 DB。
> psql -U day2_root -d day2 -h db.day2.local -p 5432
3) 输入以下命令,确认 day2 Database 是否已创建。(小写 L)
PSQL> \l
序号 评分项
如果符合以下任一要素,即视为使用非正常方法作答,Keycloak 项全部不予评分。其他事项也会核查,若判定使用了不正当方法,则不予评分。
1) 检查选手提交的 URL,确认 Keycloak 服务器是否位于选手的账户中。
## 10-1
1) 新建浏览器窗口,访问任务书上写的 Keycloak 地址,确认是否显示与下方类似的页面。
2) 在账号名称中输入 admin<编号>,确认能否正常登录。
3) 确认是否跳转到 AWS 页面并显示与下方类似的页面。UI 可能略有不同,但选手账号编号与 admin-access role 必须一致。
4) 使用 admin-access Role 确认能否正常登录 AWS 账号。登录后查看右上角的账号信息,确认账号编号和 Role 名称。
序号 评分项
如果符合以下任一要素,即视为使用非正常方法作答,Keycloak 项全部不予评分。其他事项也会核查,若判定使用了不正当方法,则不予评分。
1) 检查选手提交的 URL,确认 Keycloak 服务器是否位于选手的账户中。
## 10-2
1) 新建浏览器窗口,访问任务书上写的 Keycloak 地址,确认是否显示与下方类似的页面。
2) 在账号名称中输入 dev<编号>,确认能否正常登录。
3) 确认是否跳转到 AWS 页面并显示与下方类似的页面。UI 可能略有不同,但选手账号编号与 poweruser-access role 必须一致。
4) 使用 poweruser-access Role 确认能否正常登录 AWS 账号。登录后查看右上角的账号信息,确认账号编号和 Role 名称。