9.6.5 访问控制策略与最小权限实践

访问控制策略需围绕“最小权限”落地到命名空间、角色、配置与服务操作。推荐采用 RBAC,将管理员、运维、开发、只读审计等角色权限边界清晰化,并将权限绑定到业务域与命名空间,避免直接授权到个人或单个配置项。对高敏感配置与高风险操作(删除配置、清空实例、修改健康阈值)实施专用命名空间与审批流程。

原理草图(权限校验路径):

文章图片

一、启用认证与最小权限的基础配置#

示例:在 Nacos 启用鉴权并限定 token 过期时间(/nacos/conf/application.properties)

# 启用认证
nacos.core.auth.enabled=true
# token 过期时间(秒)
nacos.core.auth.default.token.expire.seconds=1800
# 允许使用 NACOS_AUTH_SYSTEM_TYPE=internal
nacos.core.auth.system.type=internal

命令解释
- nacos.core.auth.enabled=true:开启认证鉴权;
- token.expire.seconds:缩短 token 生命周期,降低泄露风险;
- system.type=internal:使用内置用户体系,便于最小权限控制。

重启 Nacos:

/opt/nacos/bin/shutdown.sh
/opt/nacos/bin/startup.sh -m standalone

预期效果:访问控制台或 API 时需携带登录凭证/Token。

二、基于 RBAC 的角色与权限最小化配置(示例)#

1. 获取管理员 Token#

# 登录并获取 Token(默认 admin/nacos)
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/login" \
  -d "username=admin&password=nacos"

预期输出(示例):

{"accessToken":"9c1b...","tokenTtl":1800}

2. 创建专用用户与角色(运维、开发、只读)#

# 创建用户(以 admin token 认证)
TOKEN="9c1b..."
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/users" \
  -H "Authorization: Bearer $TOKEN" \
  -d "username=dev_user&password=Dev@123"

curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/users" \
  -H "Authorization: Bearer $TOKEN" \
  -d "username=ops_user&password=Ops@123"

curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/users" \
  -H "Authorization: Bearer $TOKEN" \
  -d "username=auditor&password=Aud@123"

命令解释
- Authorization: Bearer $TOKEN:使用管理员 Token 进行管理操作;
- username/password:创建独立账户,禁止共享通用账号。

3. 绑定最小权限(命名空间 + 分组 + 操作)#

示例:只允许 dev_userdev-namespace 命名空间读取配置与发现服务,禁止写入。

# 创建角色
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/roles" \
  -H "Authorization: Bearer $TOKEN" \
  -d "role=dev_readonly"

# 绑定权限:命名空间 dev-namespace,配置只读
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/permissions" \
  -H "Authorization: Bearer $TOKEN" \
  -d "role=dev_readonly&resource=namespace:dev-namespace&action=READ"

# 绑定用户与角色
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/users/roles" \
  -H "Authorization: Bearer $TOKEN" \
  -d "username=dev_user&role=dev_readonly"

命令解释
- resource=namespace:dev-namespace:将权限收敛到命名空间;
- action=READ:仅允许读取;
- users/roles:用户与角色绑定。

4. 配置敏感命名空间与专用角色#

# 创建高敏感命名空间角色
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/roles" \
  -H "Authorization: Bearer $TOKEN" \
  -d "role=secret_reader"

# 只允许读取 secret-namespace
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/permissions" \
  -H "Authorization: Bearer $TOKEN" \
  -d "role=secret_reader&resource=namespace:secret-namespace&action=READ"

三、最小权限访问示例(配置与服务)#

1. 读取配置(只读角色)#

# 使用 dev_user 登录获取 token
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/login" \
  -d "username=dev_user&password=Dev@123"
# 读取配置(应成功)
DEV_TOKEN="devtoken"
curl -s -G \
  "http://127.0.0.1:8848/nacos/v1/cs/configs" \
  -H "Authorization: Bearer $DEV_TOKEN" \
  --data-urlencode "dataId=app.yml" \
  --data-urlencode "group=DEFAULT_GROUP" \
  --data-urlencode "tenant=dev-namespace"

预期效果:返回配置内容;写入操作应被拒绝(HTTP 403)。

2. 服务发现(只读)#

curl -s -G \
  "http://127.0.0.1:8848/nacos/v1/ns/instance/list" \
  -H "Authorization: Bearer $DEV_TOKEN" \
  --data-urlencode "serviceName=order-service" \
  --data-urlencode "namespaceId=dev-namespace"

预期效果:返回实例列表;注册实例应被拒绝。

四、CI/CD 服务账号示例#

创建专用 ci_user,仅允许写入配置(部署场景),禁止删除:

curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/users" \
  -H "Authorization: Bearer $TOKEN" \
  -d "username=ci_user&password=CI@123"

curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/roles" \
  -H "Authorization: Bearer $TOKEN" \
  -d "role=ci_writer"

# 允许写入配置但不允许删除(实际控制需结合审批流程与审计)
curl -s -X POST \
  "http://127.0.0.1:8848/nacos/v1/auth/permissions" \
  -H "Authorization: Bearer $TOKEN" \
  -d "role=ci_writer&resource=namespace:prod-namespace&action=WRITE"

五、常见排错#

  1. 403 Forbidden
    - 原因:权限未绑定到命名空间或动作。
    - 排查:
    bash # 查看用户角色 curl -s -G "http://127.0.0.1:8848/nacos/v1/auth/users/roles" \ -H "Authorization: Bearer $TOKEN" \ --data-urlencode "username=dev_user"
  2. Token 失效
    - 原因:tokenTtl 过期或时间漂移。
    - 处理:重新登录获取 token,校验服务器时间同步(NTP)。
  3. 读取到不应访问的配置
    - 原因:命名空间未隔离或权限过宽。
    - 处理:重新绑定 resource=namespace:xxx 并收敛 action 范围。

六、练习#

  1. 创建 test_user 仅允许读取 test-namespacegroup=payment 的配置。
  2. ops_user 添加服务注册权限,但禁止配置写入。
  3. 模拟 dev_user 尝试删除配置并验证返回 403。
  4. 设置 token.expire.seconds=600 并验证 token 过期行为。