mirror of https://github.com/kubernetes/kops.git
139 lines
3.1 KiB
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
|
|
}
|