kops/pkg/model/iam.go

139 lines
3.1 KiB
Go

package model
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/model/iam"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"text/template"
)
// IAMModelBuilder configures IAM objects
type IAMModelBuilder struct {
*KopsModelContext
}
var _ fi.ModelBuilder = &IAMModelBuilder{}
const RolePolicyTemplate = `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "{{ IAMServiceEC2 }}"},
"Action": "sts:AssumeRole"
}
]
}`
func (b *IAMModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Collect the roles in use
var roles []kops.InstanceGroupRole
for _, ig := range b.InstanceGroups {
found := false
for _, r := range roles {
if r == ig.Spec.Role {
found = true
}
}
if !found {
roles = append(roles, ig.Spec.Role)
}
}
// Generate IAM objects etc for each role
for _, role := range roles {
name := b.IAMName(role)
var iamRole *awstasks.IAMRole
{
rolePolicy, err := b.buildAWSIAMRolePolicy(role)
if err != nil {
return err
}
iamRole = &awstasks.IAMRole{
Name: s(name),
RolePolicyDocument: fi.WrapResource(rolePolicy),
}
c.AddTask(iamRole)
}
policy, err := b.buildAWSIAMPolicy(role)
if err != nil {
return err
}
{
t := &awstasks.IAMRolePolicy{
Name: s(name),
Role: iamRole,
PolicyDocument: fi.WrapResource(fi.NewStringResource(policy)),
}
c.AddTask(t)
}
var iamInstanceProfile *awstasks.IAMInstanceProfile
{
iamInstanceProfile = &awstasks.IAMInstanceProfile{
Name: s(name),
}
c.AddTask(iamInstanceProfile)
}
{
iamInstanceProfileRole := &awstasks.IAMInstanceProfileRole{
Name: s(name),
InstanceProfile: iamInstanceProfile,
Role: iamRole,
}
c.AddTask(iamInstanceProfileRole)
}
}
return nil
}
// buildAWSIAMPolicy produces the AWS IAM policy for the given role
func (b *IAMModelBuilder) buildAWSIAMPolicy(role kops.InstanceGroupRole) (string, error) {
pb := &iam.IAMPolicyBuilder{
Cluster: b.Cluster,
Role: role,
Region: b.Region,
}
policy, err := pb.BuildAWSIAMPolicy()
if err != nil {
return "", fmt.Errorf("error building IAM policy: %v", err)
}
json, err := policy.AsJSON()
if err != nil {
return "", fmt.Errorf("error building IAM policy: %v", err)
}
return json, nil
}
// buildAWSIAMRolePolicy produces the AWS IAM role policy for the given role
func (b *IAMModelBuilder) buildAWSIAMRolePolicy(role kops.InstanceGroupRole) (fi.Resource, error) {
functions := template.FuncMap{
"IAMServiceEC2": func() string {
// IAMServiceEC2 returns the name of the IAM service for EC2 in the current region
// it is ec2.amazonaws.com everywhere but in cn-north, where it is ec2.amazonaws.com.cn
switch b.Region {
case "cn-north-1":
return "ec2.amazonaws.com.cn"
default:
return "ec2.amazonaws.com"
}
},
}
templateResource, err := NewTemplateResource("AWSIAMRolePolicy", RolePolicyTemplate, functions, nil)
if err != nil {
return nil, err
}
return templateResource, nil
}