继上篇:“如何理解Google Cloud的ServiceAccount、Role和Policy等概念”,本篇继续聊聊Google Cloud如何给ServiceAccount授予资源细粒度的权限控制。举例:如何给一个ServiceAccount授权Cloud SQL Admin角色,并且只允许操作某个Mysql实例。
首先介绍如何在控制台上配置,然后介绍如何通过API写代码配置。与前一篇相比,本篇介绍的是另一个通用的API,也是笔者踩的坑。
我们打开Google Cloud控制台,转到IAM和管理->IAM下,如下图:
点击授予访问权限,我们会看到下面的侧边弹窗。
在“新的主账号”输入需要被授权的ServiceAccount账号,然后点击添加其它角色,然后选择Cloud SQL Admin角色,这样就可以给ServiceAccount授权了Cloud SQL Admin角色,这个ServiceAccount就有了Cloud SQL Admin角色拥有的权限。
然而,这样粒度太粗了,这个ServiceAccount将能操作所有的Mysql实例。
那么怎么限制只能操作某个实例呢?点击角色右边的IAM条件编辑图标,给这个授权添加一个条件。
首先给条件取个名称,然后在条件编辑器输入条件表达式,如图中:resource.name=="资源name"
,这里我们填mysql实例的资源名称。
以上所有步骤都保存后,这个授权就生效了。
那么对应的代码怎么写呢?
上一篇文章我们也介绍了如何给资源实例授权,并用Cloud Storage的Buckets实例来举例。根据Google Cloud的文档介绍,要管理对资源的访问权限,我们应该使用资源的GetIamPolicy、SetIamPolicy接口,例如:
// Cloud Storage 伪代码
var svc2 *storage.Service
svc2.Buckets.GetIamPolicy()
svc2.Buckets.SetIamPolicy()
除了Cloud Storage支持,Pub/Sub也支持,例如:
// Pub/Sub 伪代码
var svc *pubsub.Service
svc.Projects.Topics.GetIamPolicy()
svc.Projects.Topics.SetIamPolicy()
但,Mysql、Redis等资源并不提供这样的API。
那Mysql、Redis等资源怎么授权呢?
根据在Google Cloud控制台的操作,通过浏览器控制台debug,我们找到添加条件调用的接口传的body是:
{"fullResourceName":"//cloudresourcemanager.googleapis.com/projects/infrastructure-xxxx","condition":{"title":"tets","description":null,"expression":"resource.name == \"ddd\""}}
然后顺藤摸瓜找到了cloud resource manager,然后根据官方文档”Resource Manager“我们找到了对应的接口。
crmSvc,err := cloudresourcemanager.NewService(ctx,option.WithTokenSource(tokenSource))
// .....
resource := "projects/xxxxxxxx/instances/gcni-mysql-test"
role := "roles/cloudsql.admin"
serviceAccountEmail:=""
projectId := "xxxxxxxx"
// GetIamPolicy
policy, err := crmSvc.Projects.GetIamPolicy(projectId, &cloudresourcemanager.GetIamPolicyRequest{
}).Context(ctx).Do()
if err != nil {
return err
}
// 绑定角色
policy.Bindings = append(policy.Bindings, &cloudresourcemanager.Binding{
Condition: &cloudresourcemanager.Expr{
Expression: fmt.Sprintf("resource.name == \"%s\"", resource),
Title: "auto-add-" + util.MD5String(resource),
},
Members: []string{
fmt.Sprintf("serviceAccount:%s", serviceAccountEmail),
},
Role: role,
})
// SetIamPolicy
_, err = crmSvc.Projects.SetIamPolicy(projectId, &cloudresourcemanager.SetIamPolicyRequest{
Policy: policy,
}).Context(ctx).Do()
其它编程语言同理,找到cloud resource manager相关的API即可。
这个方法适合给所有资源授权。
参考文档:
- Resource Manager
- [IAM/指南/控制对资源的访问权限/授权访问权限/管理对其它资源的访问权限](