前言

零信任是不以「因為在內部網路中,所以就信任」為前提,而是在每次存取時都確認身分與權限的思維。
本文會聚焦在 AWS 上要建立哪些服務、哪些資源,才能把零信任落地。整體架構分成 5 個部分,依序列出各部分要建立的資源與 AWS CLI 指令。

  • 第 1 部分:用憑證確認 AWS 外部伺服器的身分
  • 第 2 部分:逐一授權服務之間的呼叫
  • 第 3 部分:收窄資料存取路徑
  • 第 4 部分:不經 VPN 判定使用者到應用程式的存取
  • 第 5 部分:記錄並偵測操作

先說明一下,本文中的 AWS CLI 指令,是依據官方文件與 AWS CLI 2.38.4 的說明確認語法,並非實際在帳戶中執行後的結果。
實際在本機動手驗證的只有第 1 部分中,使用 openssl 建立憑證的步驟。
各部分的「確認事項」是根據官方文件推導出的預期行為。

整體架構

這 5 個部分分別對應零信任中的「誰」「做什麼」「從哪裡來」「記錄」。

部分確認的對象使用的服務1AWS 外部的伺服器AWS IAM Roles Anywhere2服務間的呼叫Amazon VPC Lattice、Amazon Verified Permissions3資料的路徑VPC 端點、Amazon S3 的儲存貯體政策4人的存取AWS Verified Access、AWS IAM Identity Center5記錄與偵測AWS CloudTrail、Amazon GuardDuty、AWS Security Hub CSPM各部分彼此獨立,因此只做需要的部分即可。
所有資源名稱都以 zt- 開頭,方便後續清理時辨識。

architecture_overview_ja.jpg

前提條件

  • 可使用 AWS CLI v2、jq、openssl 的終端機
  • 東京區域(ap-northeast-1)的 VPC、私有子網路,以及在其中運作的 Amazon EC2 執行個體
  • 具有管理員等級權限的 IAM 角色

後續指令會使用以下變數。

export AWS_REGION=ap-northeast-1
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
VPC_ID=vpc-xxxxxxxx        # 請替換成你自己的 VPC ID

會產生費用的資源

以下包含按時間計費的資源。
單價是查詢美國東部的價格頁面得知,未確認東京區域的單價。

  • Amazon VPC Lattice:每個服務 0.025 美元/小時
  • AWS Verified Access:每個應用程式 0.27 美元/小時(未滿 1 小時以 1 小時計)
  • Amazon Verified Permissions:每次授權請求 0.000005 美元

AWS Verified Access 的單價較高,因此建議第 4 部分確認完成後立即刪除。

第 1 部分 用憑證確認 AWS 外部伺服器的身分

如果把存取金鑰放在內部機房或其他雲端的伺服器上,一旦外洩,就會在沒有期限的情況下被使用。
使用 AWS IAM Roles Anywhere,伺服器可以用 X.509 憑證證明身分,並取得有時效性的認證資訊。

要建立的資源如下:

  • 自建憑證授權單位(使用 openssl 建立)
  • 信任錨點 zt-anchor(註冊受信任的 CA)
  • IAM 角色 zt-workload-role
  • 設定檔 zt-profile(可承擔的角色定義)

architecture_part1_ja.jpg

建立憑證授權單位與伺服器憑證

雖然也可以使用 AWS Private Certificate Authority,但因為會產生月費,所以這裡改用 openssl 建立 CA。

# 憑證授權單位
openssl genrsa -out ca.key 4096
openssl req -new -key ca.key -subj "/CN=zt-root-ca" -out ca.csr
printf "basicConstraints=critical,CA:TRUE\nkeyUsage=critical,keyCertSign,cRLSign\n" > ca.ext
openssl x509 -req -in ca.csr -signkey ca.key -sha256 -days 365 -extfile ca.ext -out ca.pem

# 伺服器憑證(通用名稱 server01)
openssl genrsa -out server01.key 2048
openssl req -new -key server01.key -subj "/CN=server01" -out server01.csr
printf "basicConstraints=CA:FALSE\nkeyUsage=critical,digitalSignature\n" > server01.ext
openssl x509 -req -in server01.csr -CA ca.pem -CAkey ca.key -CAcreateserial \
  -sha256 -days 30 -extfile server01.ext -out server01.pem

之所以要指定這些擴充欄位,是有原因的。
AWS IAM Roles Anywhere 對憑證有以下要求:

  • CA 的憑證基本限制必須是 CA:TRUE,且金鑰用途需包含證書簽章
  • 伺服器憑證必須是 X.509v3,且金鑰用途需包含數位簽章
  • 簽章演算法必須是 SHA256 以上(MD5 與 SHA1 會被拒絕)

這個步驟是在 OpenSSL 4.0.3 上執行,並確認產生的憑證符合上述條件。

建立信任錨點

將 CA 的憑證註冊進去。若直接把 PEM 塞到引數中,換行處理會比較麻煩,因此用 jq 轉成 JSON 檔。

jq -n --rawfile cert ca.pem \
  '{sourceType:"CERTIFICATE_BUNDLE",sourceData:{x509CertificateData:$cert}}' > anchor-source.json

TA_ARN=$(aws rolesanywhere create-trust-anchor --name zt-anchor --enabled \
  --source file://anchor-source.json \
  --query trustAnchor.trustAnchorArn --output text)

建立角色

在信任政策中,同時把憑證的通用名稱與信任錨點寫成條件。

cat > trust-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "rolesanywhere.amazonaws.com"},
    "Action": ["sts:AssumeRole", "sts:TagSession", "sts:SetSourceIdentity"],
    "Condition": {
      "StringEquals": {"aws:PrincipalTag/x509Subject/CN": "server01"},
      "ArnEquals": {"aws:SourceArn": "$TA_ARN"}
    }
  }]
}
EOF

aws iam create-role --role-name zt-workload-role \
  --assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name zt-workload-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

通用名稱的條件不能省略。
因為 AWS IAM Roles Anywhere 的信任邊界是以帳戶為單位,如果不寫條件,帳戶內任何信任錨點簽發的憑證都可能承擔這個角色。

建立設定檔

PROFILE_ARN=$(aws rolesanywhere create-profile --name zt-profile --enabled \
  --role-arns arn:aws:iam::$ACCOUNT_ID:role/zt-workload-role \
  --query profile.profileArn --output text)

伺服器端設定

伺服器上放置 AWS 提供的認證資訊輔助工具(aws_signing_helper)。
下載位置可參考官方文件中的「Get temporary security credentials from IAM Roles Anywhere」。

在 AWS CLI 設定檔中,寫入呼叫此輔助工具的設定檔。

[profile zt-server01]
region = ap-northeast-1
credential_process = ./aws_signing_helper credential-process --certificate server01.pem --private-key server01.key --trust-anchor-arn <TA_ARN的值> --profile-arn <PROFILE_ARN的值> --role-arn arn:aws:iam::<帳戶ID>:role/zt-workload-role

確認事項

aws sts get-caller-identity --profile zt-server01
  • 會回傳承擔 zt-workload-role 的會話 ARN
  • 若使用通用名稱改成 server02 的憑證,會被拒絕承擔角色
  • 認證資訊有效期間可設定為 15 分鐘到 12 小時

若要讓憑證失效,則匯入撤銷清單。

aws rolesanywhere import-crl --name zt-crl --enabled \
  --crl-data fileb://crl.pem --trust-anchor-arn $TA_ARN

匯入的撤銷清單不會檢查有效期限,因此每次 CA 更新後都需要重新匯入。
另外也可以設定為自動從憑證中記載的發佈位置取得撤銷清單。

第 2 部分 逐一授權服務之間的呼叫

避免出現「因為在同一個 VPC 裡,所以就能呼叫」的狀況。
使用 Amazon VPC Lattice 判定「哪個角色可以呼叫這個服務」,並使用 Amazon Verified Permissions 在應用程式內判定「是否允許這項操作」。

要建立的資源如下:

  • 權限存放區(Cedar 的 schema 與 policy 存放位置)
  • AWS Lambda 函數 zt-orders-fn(被呼叫端)
  • 服務網路 zt-network 與服務 zt-orders
  • 呼叫端 IAM 角色 zt-client-role

architecture_part2_ja.jpg

建立權限存放區與 schema

Cedar 是用來撰寫授權規則的語言。
先把會出現的呼叫者、操作、資源型別定義為 schema。

STORE_ID=$(aws verifiedpermissions create-policy-store \
  --validation-settings mode=STRICT \
  --query policyStoreId --output text)

cat > schema.json <<'EOF'
{
  "ZeroTrust": {
    "entityTypes": {"Caller": {}, "Order": {}},
    "actions": {
      "ReadOrder":   {"appliesTo": {"principalTypes": ["Caller"], "resourceTypes": ["Order"]}},
      "UpdateOrder": {"appliesTo": {"principalTypes": ["Caller"], "resourceTypes": ["Order"]}}
    }
  }
}
EOF

jq -n --rawfile s schema.json '{cedarJson:$s}' > schema-def.json
aws verifiedpermissions put-schema --policy-store-id $STORE_ID \
  --definition file://schema-def.json

建立 Cedar policy

建立一則允許與一則禁止。

cat > permit.cedar <<'EOF'
permit(
  principal == ZeroTrust::Caller::"zt-client-role",
  action in [ZeroTrust::Action::"ReadOrder", ZeroTrust::Action::"UpdateOrder"],
  resource
);
EOF

cat > forbid.cedar <<'EOF'
forbid(
  principal,
  action == ZeroTrust::Action::"UpdateOrder",
  resource == ZeroTrust::Order::"1001"
);
EOF

for f in permit forbid; do
  jq -n --rawfile p $f.cedar '{static:{statement:$p}}' > $f-def.json
  aws verifiedpermissions create-policy --policy-store-id $STORE_ID \
    --definition file://$f-def.json
done

此時即可從 CLI 確認判定結果。

aws verifiedpermissions is-authorized --policy-store-id $STORE_ID \
  --principal entityType=ZeroTrust::Caller,entityId=zt-client-role \
  --action actionType=ZeroTrust::Action,actionId=UpdateOrder \
  --resource entityType=ZeroTrust::Order,entityId=1001
  • 訂單 1001 的更新會是 DENY(禁止優先於允許)
  • 訂單 1002 的更新會是 ALLOW
  • 沒有寫入政策的呼叫者會是 DENY(預設拒絕)

建立被呼叫端的 Lambda 函數

Amazon VPC Lattice 會把已通過驗證的呼叫端 ARN 放入事件中並傳給 Lambda 函數。
函數會取出該角色名稱,向權限存放區查詢判定。

# app.py
import json, os, boto3

avp = boto3.client("verifiedpermissions")
STORE_ID = os.environ["POLICY_STORE_ID"]

def handler(event, context):
    principal = event["requestContext"]["identity"].get("principal", "")
    # 例:arn:aws:iam::123456789012:assumed-role/zt-client-role/i-0123...
    caller = principal.split("/")[1] if "assumed-role/" in principal else "anonymous"
    action = "ReadOrder" if event["method"] == "GET" else "UpdateOrder"
    order_id = event["path"].split("?")[0].rstrip("/").split("/")[-1]

    decision = avp.is_authorized(
        policyStoreId=STORE_ID,
        principal={"entityType": "ZeroTrust::Caller", "entityId": caller},
        action={"actionType": "ZeroTrust::Action", "actionId": action},
        resource={"entityType": "ZeroTrust::Order", "entityId": order_id},
    )["decision"]

    return {
        "isBase64Encoded": False,
        "statusCode": 200 if decision == "ALLOW" else 403,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"caller": caller, "action": action, "decision": decision}),
    }

執行角色需要具備寫入日誌與查詢判定 API 的權限。

cat > lambda-trust.json <<'EOF'
{"Version":"2012-10-17","Statement":[{"Effect":"Allow",
 "Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}
EOF
aws iam create-role --role-name zt-orders-fn-role \
  --assume-role-policy-document file://lambda-trust.json
aws iam attach-role-policy --role-name zt-orders-fn-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

cat > avp-policy.json <<EOF
{"Version":"2012-10-17","Statement":[{"Effect":"Allow",
 "Action":"verifiedpermissions:IsAuthorized",
 "Resource":"arn:aws:verifiedpermissions::$ACCOUNT_ID:policy-store/$STORE_ID"}]}
EOF
aws iam put-role-policy --role-name zt-orders-fn-role \
  --policy-name zt-avp --policy-document file://avp-policy.json

zip fn.zip app.py
FN_ARN=$(aws lambda create-function --function-name zt-orders-fn \
  --runtime python3.13 --handler app.handler \
  --role arn:aws:iam::$ACCOUNT_ID:role/zt-orders-fn-role \
  --zip-file fileb://fn.zip \
  --environment "Variables={POLICY_STORE_ID=$STORE_ID}" \
  --query FunctionArn --output text)

建立服務與服務網路

將 Lambda 函數註冊到目標群組,並由服務的接聽程式轉送。
事件格式指定為 V2,以便包含呼叫端資訊。

TG_ID=$(aws vpc-lattice create-target-group --name zt-orders-tg --type LAMBDA \
  --config lambdaEventStructureVersion=V2 --query id --output text)
aws vpc-lattice register-targets --target-group-identifier $TG_ID \
  --targets id=$FN_ARN

SVC_ID=$(aws vpc-lattice create-service --name zt-orders --auth-type AWS_IAM \
  --query id --output text)

cat > listener-config.json <<EOF
{"forward":{"targetGroups":[{"targetGroupIdentifier":"$TG_ID","weight":100}]}}
EOF
aws vpc-lattice create-listener --service-identifier $SVC_ID --name https-443 \
  --protocol HTTPS --port 443 --default-action file://listener-config.json

SN_ID=$(aws vpc-lattice create-service-network --name zt-network --auth-type AWS_IAM \
  --query id --output text)
aws vpc-lattice create-service-network-service-association \
  --service-identifier $SVC_ID --service-network-identifier $SN_ID
aws vpc-lattice create-service-network-vpc-association \
  --service-network-identifier $SN_ID --vpc-identifier $VPC_ID

依據官方文件,透過 CLI 註冊 Lambda 函數時,Amazon VPC Lattice 用來呼叫該函數的權限會自動加入。

設定驗證政策

驗證政策要分別套用在服務網路與服務本身兩個地方。
在服務網路端,先一次排除未簽章的請求。

cat > sn-auth.json <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "vpc-lattice-svcs:Invoke",
    "Resource": "*",
    "Condition": {"StringNotEquals": {"aws:PrincipalType": "Anonymous"}}
  }]
}
EOF
aws vpc-lattice put-auth-policy --resource-identifier $SN_ID \
  --policy "$(jq -c . sn-auth.json)"

在服務端,將可呼叫的角色限制為 zt-client-role。

SVC_ARN=$(aws vpc-lattice get-service --service-identifier $SVC_ID --query arn --output text)
cat > svc-auth.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::$ACCOUNT_ID:role/zt-client-role"},
    "Action": "vpc-lattice-svcs:Invoke",
    "Resource": "$SVC_ARN/*"
  }]
}
EOF
aws vpc-lattice put-auth-policy --resource-identifier $SVC_ID \
  --policy "$(jq -c . svc-auth.json)"

有三個注意事項:

  • 只把認證類型設成 AWS_IAM 還不夠,如果沒有寫排除匿名的條件,依政策不同,未簽章請求也可能通過
  • 認證政策 JSON 不能包含換行,因此要先用 jq -c 壓成一行再傳入
  • 呼叫端角色也需要允許 vpc-lattice-svcs:Invoke 的 IAM 政策

呼叫端 EC2 執行個體所使用的角色 zt-client-role,需套用以下政策。

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "vpc-lattice-svcs:Invoke",
    "Resource": "*"
  }]
}

確認事項

取得服務網域名稱。

aws vpc-lattice get-service --service-identifier $SVC_ID \
  --query dnsEntry.domainName --output text

從 VPC 內的 EC2 執行個體,以 SigV4(與 AWS API 相同的簽章方式)簽章後進行呼叫。Amazon VPC Lattice 不支援對本文做簽章,因此要在標頭中指定 UNSIGNED-PAYLOAD。

# call.py (pip install botocore awscrt requests)
import sys, requests, botocore.session
from botocore import crt
from botocore.awsrequest import AWSRequest

url, method = sys.argv[1], sys.argv[2]
session = botocore.session.Session()
signer = crt.auth.CrtSigV4Auth(session.get_credentials(), "vpc-lattice-svcs", "ap-northeast-1")
headers = {"x-amz-content-sha256": "UNSIGNED-PAYLOAD"}
request = AWSRequest(method=method, url=url, headers=headers)
request.context["payload_signing_enabled"] = False
signer.add_auth(request)
prepped = request.prepare()
response = requests.request(method, prepped.url, headers=prepped.headers)
print(response.status_code, response.text)
python3 call.py https://<服務網域名稱>/orders/1001 GET
python3 call.py https://<服務網域名稱>/orders/1001 PUT
curl https://<服務網域名稱>/orders/1001
  • 帶簽章的 GET 會回傳 ALLOW 的判定
  • 帶簽章的 PUT 會先通過 Amazon VPC Lattice,再因 Cedar 中的禁止規則而回傳 DENY
  • 不帶簽章的 curl 會在到達 Lambda 函數前就被拒絕

這三個結果可驗證:在通訊入口與應用程式內部,確實進行了兩層判定。

第 3 部分 收窄資料存取路徑

即使身分正確,也希望避免資料能從非預期路徑被存取。
將 VPC 端點與儲存貯體政策搭配,讓 Amazon S3 只接受「經過這個 VPC 的這個端點」送出的請求。

要建立的資源如下:

  • Amazon S3 儲存貯體 zt-data-<帳戶ID>
  • Gateway 型 VPC 端點(附端點政策)
  • 儲存貯體政策

architecture_part3_ja.jpg

建立 VPC 端點

透過端點政策,將這個端點可到達的目標限制為指定的儲存貯體。

BUCKET=zt-data-$ACCOUNT_ID
aws s3api create-bucket --bucket $BUCKET \
  --create-bucket-configuration LocationConstraint=ap-northeast-1

cat > endpoint-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
    "Resource": ["arn:aws:s3:::$BUCKET", "arn:aws:s3:::$BUCKET/*"]
  }]
}
EOF

VPCE_ID=$(aws ec2 create-vpc-endpoint --vpc-endpoint-type Gateway \
  --vpc-id $VPC_ID --service-name com.amazonaws.ap-northeast-1.s3 \
  --route-table-ids rtb-xxxxxxxx \
  --policy-document file://endpoint-policy.json \
  --query VpcEndpoint.VpcEndpointId --output text)

若不套用端點政策,預設政策會允許所有操作。

設定儲存貯體政策

拒絕非經由端點送來的請求。若條件寫錯,自己也會無法操作,因此先把管理用角色列為例外。

cat > bucket-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyUnlessFromVpce",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": ["arn:aws:s3:::$BUCKET", "arn:aws:s3:::$BUCKET/*"],
    "Condition": {
      "StringNotEquals": {"aws:SourceVpce": "$VPCE_ID"},
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::$ACCOUNT_ID:role/<管理用的角色名稱>"}
    }
  }]
}
EOF
aws s3api put-bucket-policy --bucket $BUCKET --policy file://bucket-policy.json

確認事項

  • 從 VPC 內的 EC2 執行個體,可以列出儲存貯體並進行讀寫
  • 在 VPC 外(例如自己的本機端)使用相同認證資訊時,會被拒絕存取
  • 從 VPC 內的 EC2 執行個體嘗試存取其他儲存貯體時,會因端點政策而無法到達

即使第 1 部分建立的角色對這個儲存貯體有權限,只要不是經由端點,就會被拒絕。
這代表身分確認與路徑確認,是在不同層次上疊加進行的。

第 4 部分 不經 VPN 判定使用者到應用程式的存取

VPN 會讓已連線的裝置取得整個網路的可達性。
AWS Verified Access 則是以應用程式為單位,逐次針對每個請求將使用者資訊與政策比對。

要建立的資源如下:

  • Verified Access 執行個體(執行判定的核心)
  • 信任提供者(提供使用者資訊的來源)
  • 群組(將相同需求的應用程式集合在一起的單位,並持有政策)
  • 端點(應用程式入口)

architecture_part4_ja.jpg

本部分前提

  • 內部用的 Application Load Balancer,以及其後方運作的應用程式
  • 對外公開的網域名稱,以及 AWS Certificate Manager 的憑證
  • AWS IAM Identity Center 的組織執行個體(需在相同區域啟用)

AWS IAM Identity Center 的帳戶執行個體不能作為信任提供者使用。若沒有組織執行個體,則改用支援 OIDC 的 IdP 作為信任提供者。

建立執行個體與信任提供者

VA_ID=$(aws ec2 create-verified-access-instance --description zt-va \
  --query VerifiedAccessInstance.VerifiedAccessInstanceId --output text)

TP_ID=$(aws ec2 create-verified-access-trust-provider \
  --trust-provider-type user \
  --user-trust-provider-type iam-identity-center \
  --policy-reference-name idc \
  --query VerifiedAccessTrustProvider.VerifiedAccessTrustProviderId --output text)

aws ec2 attach-verified-access-trust-provider \
  --verified-access-instance-id $VA_ID \
  --verified-access-trust-provider-id $TP_ID

在 policy-reference-name 中指定的 idc,會在下方政策中用來參照使用者資訊。

建立群組與政策

只允許屬於 AWS IAM Identity Center 特定群組,且電子郵件地址已驗證的使用者。群組不是用名稱,而是用 ID 指定。

cat > va-policy.cedar <<'EOF'
permit(principal,action,resource)
when {
    context.idc.groups has "<AWS IAM Identity Center的群組ID>"
    && context.idc.user.email.verified == true
};
EOF

VAG_ID=$(aws ec2 create-verified-access-group \
  --verified-access-instance-id $VA_ID \
  --policy-document file://va-policy.cedar \
  --query VerifiedAccessGroup.VerifiedAccessGroupId --output text)

在定義政策之前,所有請求預設都會被拒絕。

建立端點

aws ec2 create-verified-access-endpoint \
  --verified-access-group-id $VAG_ID \
  --endpoint-type load-balancer --attachment-type vpc \
  --domain-certificate-arn <憑證ARN> \
  --application-domain app.example.com \
  --endpoint-domain-prefix zt-app \
  --security-group-ids sg-xxxxxxxx \
  --load-balancer-options Protocol=https,Port=443,LoadBalancerArn=<ALB的ARN>,SubnetIds=subnet-aaaa,subnet-bbbb

建立後,將公開網域名稱(app.example.com)的 CNAME 記錄指向端點的網域名稱。
ALB 的安全群組只允許來自端點安全群組的流量。

確認事項

  • 用瀏覽器開啟公開網域時,會跳轉到 AWS IAM Identity Center 的登入畫面
  • 指定群組的使用者可以看到應用程式畫面
  • 不屬於該群組的使用者即使登入成功,也無法到達應用程式

如果也想把裝置狀態(例如 OS 更新狀況或風險評分)納入條件,可加入 CrowdStrike、Jamf、JumpCloud 其中之一作為裝置信任提供者。
一個執行個體可以掛一個使用者信任提供者,以及多個裝置信任提供者。

第 5 部分 記錄並偵測操作

前面 4 個部分都是在存取當下進行判定的機制。
在零信任中,不只要在允許當下確認,之後也要持續確認。
這些材料就是 API 操作記錄,以及對可疑使用方式的偵測。

要建立的資源如下:

  • 證跡 zt-trail(將 API 操作記錄儲存到 Amazon S3)
  • Amazon GuardDuty 偵測器
  • AWS Security Hub CSPM(集中彙整偵測結果與檢查設定)

architecture_part5_ja.jpg

建立證跡

AWS CloudTrail 的事件歷史最多只會顯示最近 90 天的管理事件。
因此若要長期保存,就需要建立證跡。
另外,儲存目的地的儲存貯體也需要允許 AWS CloudTrail 寫入的儲存貯體政策。

aws cloudtrail create-trail --name zt-trail \
  --s3-bucket-name <記錄保存用的儲存貯體名稱> \
  --is-multi-region-trail --enable-log-file-validation
aws cloudtrail start-logging --name zt-trail

像 Amazon S3 物件操作這類資料事件,預設不會被記錄。
若要記錄第 3 部分中儲存貯體的讀寫,需手動加入。

cat > selectors.json <<EOF
[{
  "Name": "zt-data-bucket",
  "FieldSelectors": [
    {"Field": "eventCategory", "Equals": ["Data"]},
    {"Field": "resources.type", "Equals": ["AWS::S3::Object"]},
    {"Field": "resources.ARN", "StartsWith": ["arn:aws:s3:::$BUCKET/"]}
  ]
}]
EOF
aws cloudtrail put-event-selectors --trail-name zt-trail \
  --advanced-event-selectors file://selectors.json

啟用 Amazon GuardDuty 與 AWS Security Hub CSPM

aws guardduty create-detector --enable
aws securityhub enable-security-hub --enable-default-standards

只要啟用,Amazon GuardDuty 就會開始分析以下三種資料來源:

  • AWS CloudTrail 管理事件
  • VPC 流量記錄
  • Amazon Route 53 Resolver 的 DNS 查詢記錄

即使沒有自行設定證跡或流量記錄,Amazon GuardDuty 也會透過獨立途徑取得這些資料。

確認事項

  • 第 1 到第 4 部分所做的操作,會連同呼叫者資訊一起保留在 AWS CloudTrail 的事件歷史中
  • Amazon GuardDuty 的偵測結果會彙整到 AWS Security Hub CSPM
  • AWS Security Hub CSPM 的安全標準會列出設定上的缺失

Amazon GuardDuty 具有一種偵測結果:當發給 EC2 執行個體的暫時認證資訊被拿到 AWS 外部使用時,會標記為 InstanceCredentialExfiltration.OutsideAWS。
即使憑證本身是合法的,只要使用方式不自然,就會被視為異常,這正是零信任的思維直接反映在偵測上的例子。

清理

為了停止計費,先刪除按時間計費的資源。

  • 第 4 部分:先解除並刪除端點、群組、信任提供者,最後刪除執行個體
  • 第 2 部分:依序刪除服務網路關聯、接聽程式、服務、目標群組、服務網路
  • 第 5 部分:Amazon GuardDuty 與 AWS Security Hub CSPM 在 30 天免費試用後才會開始計費

其餘資源(IAM 角色、信任錨點、設定檔、權限存放區、Lambda 函數、VPC 端點、儲存貯體、證跡)請依名稱前綴 zt- 逐一刪除。

5 個部分總結建立了什麼

一開始提到,本文聚焦於「要建立哪個服務的哪個資源,才能形成整體」。
整理後可分成以下 4 層,以及第 5 部分的記錄機制。

  • 身分:憑證與 IAM 角色(第 1 部分)、AWS IAM Identity Center 的使用者與群組(第 4 部分)
  • 通訊入口:Amazon VPC Lattice 的驗證政策(第 2 部分)、AWS Verified Access 的政策(第 4 部分)
  • 應用程式內部:Amazon Verified Permissions 的 Cedar 政策(第 2 部分)
  • 資料路徑:端點政策與儲存貯體政策(第 3 部分)

每一層的設計都相同:預設拒絕,只放行明確允許的項目。
把這種設計一層一層疊起來,就是 AWS 上的零信任架構。

感謝閱讀到最後。

參考資料


原文出處:https://qiita.com/yama3133/items/11a360fc97ed3ec09742


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
boluoji
📝37   💬3   ❤️7
892
🥈
我愛JS
📝3   💬1   ❤️5
93
🥉
站長阿川
📝1   💬3   ❤️2
44
#4
mike
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登