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 }