# 怎麼確認真的是唯讀？

{% embed url="<https://youtu.be/EBCDzgTQp2Y>" %}

我們把授權內容用**透明**的方式呈現：您可以在加入前的「唯讀角色」頁面直接看到 CloudFormation 建立的角色權限內容。

### 1. 身份驗證 - 這個角色「只允許被誰使用」？

請檢查 JSON 中的 CrossAccountRole 區段：

* `Principal: {"AWS": {"Ref": "EliteIamRole"}}`\
  \&#xNAN;**→ 含義：**&#x4EE3;表「只有勤英科技指定的 IAM Role（EliteIamRole）可以來扮演（Assume）這個角色」。其他人（就算知道 Role ARN）都不能直接使用。
* `Action: "sts:AssumeRole"`\
  \&#xNAN;**→ 含義：**&#x4EE3;表「只允許透過 AssumeRole 取得暫時性憑證」，不會建立/發放永久金鑰（Access Key）。
* `Condition: sts:ExternalId == EliteExternalID`\
  \&#xNAN;**→ 含義：**&#x9019;是 External ID 防護。防止第三方冒用、或混淆代理人問題（Confused Deputy Problem）。\
  即使有人知道 Role ARN，也不能隨便 Assume，必須帶正確 External ID 才能通過。

<mark style="color:$primary;">**這個 Role 不是誰都能使用，且有 External ID 保護。**</mark>

***

### 2. 權限驗證 - 這個角色「能做什麼？不能做什麼？」

我們的權限設定分為兩層，您可以逐一審查：

#### 第一層：AWS Managed Policy：`ReadOnlyAccess`, `SecurityAudit`

* `ManagedPolicyArns": ["arn:aws:iam::aws:policy/ReadOnlyAccess","arn:aws:iam::aws:policy/SecurityAudit"]`

我們使用「 AWS 官方的 ReadOnlyAccess 與 SecurityAudit」，這代表角色權限以「讀取/列出/描述」為主，此權限可以檢查您的設定與資源狀態，用於成本優化/資安/合規快篩，且不包含 「Start/Stop/Modify/Delete」 這類寫入變更行為。

#### 第二層：**Inline Policy：**`ExplicitDenySensitiveAccess`

雖然我們已經使用 ReadOnlyAccess 與 SecurityAudit，但為確保您的資料安全，我們加了第二層防護：「<mark style="color:red;">**禁止**</mark> Role 取得以下重要服務的權限」。

* `"Effect": "Deny"`：<mark style="color:red;">**代表禁止以下功能**</mark>
* `"lambda:GetFunction"`：取得 Lambda 函數的設定與程式碼位置
* `"lambda:GetFunctionCodeSigningConfig"`：取得 Lambda 程式碼簽章設定資訊
* `"s3:GetObject"`：下載 S3 物件內容
* `"s3:GetObjectVersion"`：下載指定版本的 S3 物件
* `"s3:GetObjectTorrent"`：以 BitTorrent 方式下載 S3 物件
* `"secretsmanager:GetSecretValue"`：讀取 Secrets Manager 中的內容
* `"secretsmanager:BatchGetSecretValue"`：批次讀取多個Secrets Manager中的內容
* `"ssm:GetParameter"`：讀取單一 Parameter Store 參數
* `"ssm:GetParameters"`：讀取多個 Parameter Store 參數
* `"ssm:GetParametersByPath"`：依路徑批次讀取參數
* `"ssm:StartSession"`：透過 Session Manager 建立遠端連線
* `"ssm:ResumeSession"`：恢復既有的 Session Manager 連線
* `"ssm:SendCommand"`：透過 SSM 對主機下遠端指令
* `"ssm:GetCommandInvocation"`：查看指令執行結果
* `"ssm:ListCommandInvocations"`：列出指令執行紀錄
* `"ssm:TerminateSession"：`終止 Session Manager 連線
* `"kms:Decrypt"`：使用 KMS 金鑰解密資料
* `"logs:GetLogEvents"`：讀取 CloudWatch Logs 日誌內容
* `"logs:FilterLogEvents"`：依條件搜尋日誌內容
* `"logs:StartQuery"`：啟動 Logs Insights 查詢
* `"logs:GetQueryResults"`：取得查詢結果
* `"logs:StopQuery"`：停止日誌查詢
* `"ecr:GetDownloadUrlForLayer"`：取得 ECR 映像層下載網址
* `"ecr:BatchGetImage"`：批次取得容器映像
* `"sqs:ReceiveMessage"`：從 SQS 佇列接收訊息
* `"sqs:DeleteMessage"`：刪除佇列中的訊息
* `"sqs:ChangeMessageVisibility"`：修改訊息隱藏時間
* `"codecommit:GitPull"`：從 CodeCommit 下載程式碼（git pull）
* `"codecommit:GetBlob"`：取得儲存庫中的 blob 內容
* `"codecommit:GetFile"`：取得單一檔案內容
* `"codecommit:GetFolder"`：取得資料夾內容
* `"codecommit:GetDifferences"`：取得程式碼差異
* `"cloudformation:GetTemplate"`：下載 CloudFormation 範本
* `"rds:DownloadDBLogFilePortion"`：下載部分 RDS 資料庫日誌
* `"rds:DownloadCompleteDBLogFile"`：下載完整 RDS 資料庫日誌&#x20;

<mark style="color:$primary;">**限制這些較容易暴露敏感資訊的權限**</mark><mark style="color:$primary;">**。**</mark>

```
 "Policies": [
          {
            "PolicyName": "ExplicitDenySensitiveAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Deny",
                  "Action": [
                    "lambda:GetFunction",
                    "lambda:GetFunctionCodeSigningConfig",
                    "s3:GetObject",
                    "s3:GetObjectVersion",
                    "s3:GetObjectTorrent",
                    "secretsmanager:GetSecretValue",
                    "secretsmanager:BatchGetSecretValue",
                    "ssm:GetParameter",
                    "ssm:GetParameters",
                    "ssm:GetParametersByPath",
                    "ssm:StartSession",
                    "ssm:ResumeSession",
                    "ssm:SendCommand",
                    "ssm:GetCommandInvocation",
                    "ssm:ListCommandInvocations",
                    "ssm:TerminateSession",
                    "kms:Decrypt",
                    "logs:GetLogEvents",
                    "logs:FilterLogEvents",
                    "logs:StartQuery",
                    "logs:GetQueryResults",
                    "logs:StopQuery",
                    "ecr:GetDownloadUrlForLayer",
                    "ecr:BatchGetImage",
                    "sqs:ReceiveMessage",
                    "sqs:DeleteMessage",
                    "sqs:ChangeMessageVisibility", 
                    "codecommit:GitPull",
                    "codecommit:GetBlob",
                    "codecommit:GetFile",
                    "codecommit:GetFolder",
                    "codecommit:GetDifferences",
                    "cloudformation:GetTemplate",
                    "rds:DownloadDBLogFilePortion",
                    "rds:DownloadCompleteDBLogFile"
                  ],
                  "Resource": "*"
                }
              ]
            }
          }
        ]
```

***

### 3. 為什麼一定要用 CloudFormation 建 Stack？

CloudFormation 的優點是「可稽核、可追溯、可撤銷」：

* 結構固定： 權限結構固定，不靠人工手動點來點去，大幅降低配置錯誤風險。
* 變更記錄： 任何修改都有 AWS 官方的變更記錄 (Log)。
* 一鍵撤銷： 若未來要停止服務，只需直接刪除該 Stack，就能把授權整包移除。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.elite.cloud/security-and-permissions/verify-read-only.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
