身份验证与授权

本部分介绍了与 Fleet Engine 集成相关的身份验证和授权概念。

您可以通过 Google Cloud 控制台配置 Last Mile Fleet 解决方案提供的功能。Fleet Engine SDK 需要使用由相应服务帐号签名的 JSON Web 令牌 (JWT)。

概览

针对 Fleet Engine 进行身份验证和授权的客户后端应使用标准的应用默认凭据机制。

Fleet Engine 还可以接收来自低信任环境(例如智能手机和浏览器)的调用。为了保护仅适用于可信环境的服务帐号密钥,客户后端应生成带有特定于 Fleet Engine 的附加声明的已签名 JSON Web 令牌 (JWT),然后这些令牌会颁发给不受信任的环境(例如手机)。

身份验证设计原则

Fleet Engine 的身份验证流程融合了以下设计原则。

  • IAM 角色针对允许主帐号的资源定义一组权限。例如,Admin 角色可以使用应用默认凭据执行所有操作,而不受信任的 Driver* 角色则只能更新车辆位置,只能使用 JWT 进行身份验证和授权。

  • 对于不受信任的环境,JWT 声明会进一步限制调用者可以操作的实体。任务可以是特定任务,也可以是送货车辆。

  • 在低信任环境中运行的代码必须先调用在可信环境中运行的代码,以发出 JWT。

  • Fleet Engine 会对资源的 API 调用执行以下安全检查:

    1. 调用方主账号具有对资源执行的操作的相应权限(通过角色分配)。

    2. 对于非管理员角色,请求中传递的 JWT 声明会为资源提供必要的权限。

身份验证流程

以下序列图展示了这些身份验证流程的详细信息。

  1. 舰队管理员会创建服务帐号。

  2. 舰队管理员为服务账号分配特定的 IAM 角色。

  3. 舰队管理员使用服务帐号和应用默认凭据配置其后端。

  4. 客户端应用从客户后端请求 JWT。请求者可能是驾驶应用、消费者应用或监控应用。

  5. 客户后端为相应的服务帐号签名并颁发 JWT。客户端应用接收 JWT。

  6. 客户端应用使用 JWT 连接到 Fleet Engine 以读取或修改数据,具体取决于在设置阶段为其分配的 IAM 角色。

身份验证序列图

Cloud 项目设置

要设置您的云项目,请先创建项目,然后创建服务帐号。

如需创建 Google Cloud 项目,请执行以下操作:

  1. 使用 Google Cloud 控制台创建 Google Cloud 项目。
  2. 使用 API 和服务信息中心,启用 Local Rides and Deliveries API。

服务账号和 IAM 角色

服务帐号是一种由应用(而不是用户)使用的特殊帐号。通常,服务帐号用于创建 JWT,根据角色授予不同的权限集。为了降低滥用的可能性,您可以创建多个服务帐号,并为每个帐号分配一组所需的最少角色 ()。

最后一英里 Fleet 解决方案使用以下角色:

角色说明
Fleet Engine Delivery 可信驾驶员用户

roles/fleetengine.deliveryTrustedDriver
授予创建和更新送货车辆和任务的权限,包括更新送货车辆位置和任务状态或结果。由具有此角色的服务帐号创建的令牌通常从配送司机的移动设备或后端服务器使用。
Fleet Engine Delivery 不受信任的驾驶员用户

roles/fleetengine.deliveryUntrustedDriver
授予更新送货车辆位置的权限。由具有此角色的服务帐号创建的令牌通常在配送司机的移动设备上使用。
Fleet Engine Delivery 消费者用户

roles/fleetengine.deliveryConsumer
授予使用跟踪 ID 搜索任务的权限,以及读取但不更新任务信息的权限。由具有此角色的服务帐号创建的令牌通常通过交付使用方的网络浏览器使用。
Fleet Engine Delivery Admin

roles/fleetengine.deliveryAdmin
授予对传送资源的读写权限。具有此角色的主账号不需要使用 JWT,而应使用应用默认凭据。自定义 JWT 声明会被忽略。此角色应仅限受信任的环境(客户后端)使用。
Fleet Engine Delivery 超级用户 **(已弃用)**

roles/fleetengine.deliverySuperUser
授予对所有交付车辆和任务 API 的权限。由具有此角色的服务帐号创建的令牌通常从后端服务器使用。
Fleet Engine Delivery Fleet Reader

roles/fleetengine.deliveryFleetReader
授予读取送货车辆和任务以及使用跟踪 ID 搜索任务的权限。由具有此角色的服务帐号创建的令牌通常通过交付舰队运营商的网络浏览器使用。

使用由公司 IT 管理的设备为配送司机提供设备的组织可以利用 Fleet Engine Trusted Driver User 角色提供的灵活性,并选择在移动应用中集成部分或全部 Fleet Engine 互动。

支持自带设备政策的组织应选择 Fleet Engine Untrusted Driver User 角色安全,并且仅依赖移动应用向 Fleet Engine 发送车辆位置信息更新。所有其他互动都应来自客户后端服务器。

驱动程序 SDK 和使用方 SDK 是围绕这些标准角色构建的。不过,您可以创建自定义角色,以将任意一组权限捆绑在一起。如果缺少必需的权限,驱动程序 SDK 和使用方 SDK 将显示错误消息。因此,我们强烈建议使用上述一组标准角色,而不是自定义角色。

创建服务账号

您可以使用 Google Cloud Console 中的 IAM & Admin > Service Accounts 标签页创建服务帐号。从“角色”下拉列表中选择“Fleet Engine”,然后将其中一个角色分配给服务帐号。最好指明与每个角色关联的帐号。例如,为服务帐号指定一个含义明确的名称。

为方便起见,如果您需要为不受信任的客户端创建 JWT,只需将用户添加到 Service Account Token Creator 角色,即可让他们使用 gcloud 命令行工具创建令牌。

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

其中,my-user@example.com 是用于通过 gcloud (gcloud auth list --format='value(account)') 进行身份验证的电子邮件。

Fleet Engine 身份验证库

Fleet Engine 使用 JWT 限制在不受信任的环境中对 Fleet Engine API 的访问。Fleet Engine Auth 库(可在 GitHub 上获取)简化了 Fleet Engine JWT 的构建并安全地对其进行签名。

该库具有以下优势:

  • 简化了创建 Fleet Engine 令牌的流程。
  • 提供除使用凭据文件以外的令牌签名机制(例如模拟服务帐号)。

创建用于授权的 JSON Web 令牌 (JWT)

如果不使用 Fleet Engine Auth 库,则需要直接在代码库中创建 JWT。因此,您需要深入了解 JWT 及其与 Fleet Engine 之间的关系。因此,我们强烈建议您充分利用 Fleet Engine Auth 库。

在 Fleet Engine 中,JWT 提供短期身份验证,并确保设备只能修改其获得授权的车辆或任务。JWT 包含标头和声明部分。标头部分包含要使用的私钥(从服务帐号获取)和加密算法等信息。声明部分包含令牌的创建时间、令牌的存留时间、令牌声明访问权限的服务,以及用于确定访问权限范围的其他授权信息;例如货运车辆 ID。

JWT 标头部分包含以下字段:

字段说明
alg 要使用的算法。`RS256`。
typ 令牌的类型。“JWT”。
儿童 您的服务帐号的私钥 ID。您可以在服务帐号 JSON 文件的“private_key_id”字段中找到此值。 请务必使用具有正确权限级别的服务账号中的密钥。

JWT 声明部分包含以下字段:

字段说明
iss 您的服务帐号的电子邮件地址。
sub 您的服务帐号的电子邮件地址。
aud 您的服务帐号的 SERVICE_NAME,在本示例中为 https://fleetengine.googleapis.com/
iat 令牌创建的时间戳,自世界协调时间 (UTC) 1970 年 1 月 1 日 00:00:00 起经过的秒数指定。等待 10 分钟,使数据出现偏差。如果时间戳离现在太远或将来的时间,服务器可能会报告错误。
exp 令牌到期的时间戳,自世界协调时间 (UTC) 1970 年 1 月 1 日 00:00:00 起经过的秒数指定。如果时间戳超过未来一小时,则请求失败。
授权 可能包含“deliveryvehicleid”“trackingid”“taskid”或“taskids”,具体取决于用例。

创建 JWT 令牌意味着对其进行签名。如需查看创建和 JWT 签名的说明和代码示例,请参阅不使用 OAuth 的服务帐号授权。然后,您可以将创建的令牌附加到 gRPC 调用或用于访问 Fleet Engine 的其他方法。

JWT 声明

最后一英里舰队解决方案使用私密声明。使用私有声明可确保只有获得授权的客户端才能访问自己的数据。例如,当您的后端为配送员的移动设备签发 JSON Web 令牌时,该令牌应包含 deliveryvehicleid 声明以及该司机的配送车辆 ID 的值。然后,根据驾驶员角色,令牌仅会启用对特定交付的车辆 ID 的访问权限,而不对任何其他任意车辆 ID 启用访问权限。

最后一英里舰队解决方案使用以下私有声明:

  • deliveryvehicleid - 调用按交付车辆的 API 时使用。
  • taskid - 调用按任务划分的 API 时使用。
  • taskids - 调用 BatchCreateTasksAPI 时使用。此声明必须采用数组形式,并且数组应包含完成请求所需的所有任务 ID。请勿包含 delivervehicleidtrackingidtaskid 声明。
  • trackingid - 调用 GetTaskTrackingInfoAPI 时使用。该声明必须与请求中的跟踪 ID 匹配。请勿包含 delivervehicleidtaskidtaskids 声明。

从后端服务器调用 API 时,令牌还必须包含相应的声明,但您可以针对 deliveryvehicleidtaskidtrackingid 声明使用星号(“*”)的特殊值。taskids 声明中也可以使用星号(“*”),但它必须是数组中的唯一元素。

如果要作为令牌不记名对象直接创建 JSON 并为其签名,而不是使用 OAuth 2.0 访问令牌,请阅读 Identity 开发者文档中不使用 OAuth 的服务帐号授权说明。

将令牌附加到 gRPC 调用的机制取决于进行调用所用的语言和框架。为 HTTP 调用指定令牌的机制是,在 Authorization 标头中加入一个包含令牌的不记名令牌,如各个运送跟踪舰队性能用例的授权说明中所述。

以下示例展示了来自后端服务器的针对每项任务操作的令牌:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_provider_service_account"
    }
    .
    {
      "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
      "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "taskid": "*"
       }
    }

以下示例展示了来自后端服务器用于批量创建任务操作的令牌:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_provider_service_account"
    }
    .
    {
      "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
      "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "taskids": ["*"]
       }
    }

以下示例展示了来自后端服务器,用于按配送车辆执行的操作的令牌:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_provider_service_account"
    }
    .
    {
      "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
      "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "deliveryvehicleid": "*"
       }
    }

以下示例展示了最终用户客户的令牌:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_delivery_consumer_service_account"
    }
    .
    {
      "iss": "consumer@yourgcpproject.iam.gserviceaccount.com",
      "sub": "consumer@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "trackingid": "shipment_12345"
       }
    }

以下示例展示了您的驱动程序应用的令牌:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_delivery_driver_service_account"
    }
    .
    {
      "iss": "driver@yourgcpproject.iam.gserviceaccount.com",
      "sub": "driver@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "deliveryvehicleid": "driver_12345"
       }
    }
  • 对于标头中的 kid 字段,请指定您服务帐号的私钥 ID。您可以在服务帐号 JSON 文件的 private_key_id 字段中找到此值。
  • 对于 isssub 字段,请指定您的服务帐号的电子邮件地址。您可以在服务帐号 JSON 文件的 client_email 字段中找到此值。
  • 对于 aud 字段,请指定 https://SERVICE_NAME/
  • 对于 iat 字段,指定创建令牌时的时间戳,以自世界协调时间 (UTC) 1970 年 1 月 1 日 00:00:00 起经过的秒数表示。出现偏差需要 10 分钟。如果时间戳过于久远或将来,服务器可能会报告错误。
  • 对于 exp 字段,请指定令牌到期时的时间戳,以自世界协调时间 (UTC) 1970 年 1 月 1 日 00:00:00 起的秒数表示。建议值为 iat + 3600。

在对要传递给移动设备或最终用户的令牌进行签名时,请务必使用“交付司机”或“消费者”角色的凭据文件。否则,移动设备或最终用户将能够更改或查看他们无权访问的信息。