测试Policy

Amazon Verified Permissions 页面上,点击左侧菜单中的 Test bench

image-20260316112605037

它允许我们通过定义主体、操作、资源、请求上下文和实体列表来测试我们的策略。

Cedar 中的实体是一个存储对象,用于表示应用程序中的主体、操作和资源。Cedar 中的实体包含以下组件:

  • 实体类型 – 类型决定了该类型实体所需或支持的属性。示例包括 UserPhotoAlbumGroupAccount 等。将实体类型定义为应用程序 schema 的一部分。
  • 实体标识符 (EID) – EID 允许我们在策略中引用特定实体。实体类型和 EID 的组合唯一标识 Cedar 中的一个对象。
  • 属性 – 零个或多个属性,可以是 Cedar 支持的任何数据类型

让我们在页面顶部定义 Request details。让我们测试 alice 是否可以读取她自己的列表。为此,我们应该使用以下值:

字段 entity type Entity ID
Principal taking action User alice
Resource List LIST#000001
Action Action ReadList

将上述值复制到相应字段中。

对于 ContextEntities 文本框,点击 AVP Format 按钮。我们目前不需要 Context 字段。

image-20260316112908697

AVP Format 是一种面向开发者的格式,适用于希望使用构建器模式来实例化实体的用户。点击此处 查看 AVP 和 Cedar 格式之间的差异。

以下是我们可以用来测试策略的示例实体列表:

[
    {
        "identifier": {
            "entityType": "User",
            "entityId": "alice"
        },
        "parents": [],
        "attributes": {}
    },
    {
        "identifier": {
            "entityType": "User",
            "entityId": "bob"
        },
        "parents": [],
        "attributes": {}
    },
    {
        "identifier": {
            "entityType": "User",
            "entityId": "charlie"
        },
        "parents": [],
        "attributes": {}
    },
    {
        "identifier": {
            "entityType": "List",
            "entityId": "LIST#000001"
        },
        "parents": [],
        "attributes": {
            "listId": {
                "long": 1
            },
            "description": {
                "string": "Alice's daily tasks"
            },
            "name": {
                "string": "Alice's list"
            },
            "nextTaskId": {
                "long": 3
            },
            "owner": {
                "entityIdentifier": {
                    "entityType": "User",
                    "entityId": "alice"
                }
            }
        }
    },
    {
        "identifier": {
            "entityType": "List",
            "entityId": "LIST#000002"
        },
        "parents": [],
        "attributes": {
            "listId": {
                "long": 2
            },
            "description": {
                "string": "Bob's most important tasks"
            },
            "name": {
                "string": "Bob's tasks"
            },
            "nextTaskId": {
                "long": 3
            },
            "owner": {
                "entityIdentifier": {
                    "entityType": "User",
                    "entityId": "bob"
                }
            }
        }
    },
    {
        "identifier": {
            "entityType": "List",
            "entityId": "LIST#000003"
        },
        "parents": [],
        "attributes": {
            "listId": {
                "long": 3
            },
            "description": {
                "string": "Charlie's daily tasks"
            },
            "name": {
                "string": "Charlie's tasks"
            },
            "nextTaskId": {
                "long": 3
            },
            "owner": {
                "entityIdentifier": {
                    "entityType": "User",
                    "entityId": "charlie"
                }
            }
        }
    },
    {
        "identifier": {
            "entityType": "Task",
            "entityId": "TASK#000001"
        },
        "parents": [
            {
                "entityType": "List",
                "entityId": "LIST#000001"
            }
        ],
        "attributes": {
            "listId": {
                "long": 1
            },
            "description": {
                "string": "Read emails in the morning"
            },
            "name": {
                "string": "Read emails"
            },
            "taskId": {
                "long": 1
            }
        }
    },
    {
        "identifier": {
            "entityType": "Task",
            "entityId": "TASK#000002"
        },
        "parents": [
            {
                "entityType": "List",
                "entityId": "LIST#000001"
            }
        ],
        "attributes": {
            "listId": {
                "long": 1
            },
            "description": {
                "string": "Send a daily report to the team at 5pm"
            },
            "name": {
                "string": "Send a daily report to the team"
            },
            "taskId": {
                "long": 2
            }
        }
    },
    {
        "identifier": {
            "entityType": "Task",
            "entityId": "TASK#000001"
        },
        "parents": [
            {
                "entityType": "List",
                "entityId": "LIST#000002"
            }
        ],
        "attributes": {
            "listId": {
                "long": 2
            },
            "description": {
                "string": "Attend the daily standup meeting at 9am"
            },
            "name": {
                "string": "Attend the daily standup meeting"
            },
            "taskId": {
                "long": 1
            }
        }
    },
    {
        "identifier": {
            "entityType": "Task",
            "entityId": "TASK#000002"
        },
        "parents": [
            {
                "entityType": "List",
                "entityId": "LIST#000002"
            }
        ],
        "attributes": {
            "listId": {
                "long": 2
            },
            "description": {
                "string": "Complete the time journal at 5pm"
            },
            "name": {
                "string": "Complete the time journal"
            },
            "taskId": {
                "long": 2
            }
        }
    },
    {
        "identifier": {
            "entityType": "Task",
            "entityId": "TASK#000001"
        },
        "parents": [
            {
                "entityType": "List",
                "entityId": "LIST#000003"
            }
        ],
        "attributes": {
            "listId": {
                "long": 3
            },
            "description": {
                "string": "Review new pull requests at 10am"
            },
            "name": {
                "string": "Review new pull requests"
            },
            "taskId": {
                "long": 1
            }
        }
    },
    {
        "identifier": {
            "entityType": "Task",
            "entityId": "TASK#000002"
        },
        "parents": [
            {
                "entityType": "List",
                "entityId": "LIST#000003"
            }
        ],
        "attributes": {
            "listId": {
                "long": 3
            },
            "description": {
                "string": "Check the team's KPIs at 5pm"
            },
            "name": {
                "string": "Check the team's KPIs"
            },
            "taskId": {
                "long": 2
            }
        }
    }
]

此 JSON 定义了一个实体列表及其层次结构和属性。对于每个实体,我们需要描述以下字段:

  1. identifier:该字段用于唯一标识实体。例如,对于表示用户的实体,此字段将包含 userID
  2. entityType 字段用于定义实体的类型。例如,对于表示用户的实体,此字段将包含 MyNamespace::User
  3. parents 字段用于定义父实体。例如,对于表示用户的实体,此字段将包含该用户所属的组。
  4. attributes 字段用于定义实体的属性。例如,对于表示用户的实体,此字段将包含 location

在我们的示例中,我们有以下实体:

  • User - 用户 alicebobcharlie 定义在第 2-25 行。
  • List - 三个列表(每个用户一个)定义在第 26-106 行。每个列表具有以下属性:listIddescriptionnamenextTaskIdowner
  • Task - 任务定义在第 107-262 行。每个任务具有以下属性:listIddescriptionnametaskId

将上述 JSON 复制到 Entities 字段中。

填写完字段后,点击页面右上角的 Run authorization request 按钮。结果应如下所示:

image-20260316113318392

现在让我们测试 alice 是否可以读取 bob 的列表。为此,我们应该使用以下值:

字段 实体类型 实体 ID
Principal taking action User alice
Resource List LIST#000002
Action Action ReadList

请将上述值复制到相应字段中。

填写完字段后,点击 Run authorization request 按钮。结果应如下所示:

image-20260316113412404

请注意,结果为 Decision: Deny。正如我们在第 53-79 行所看到的,列表 LIST#000002 属于 bob,因此考虑到我们的策略仅允许列表所有者访问 when { principal == resource.owner }Deny 是预期结果。