Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions pkg/model/awsmodel/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ limitations under the License.
package awsmodel

import (
"context"
"fmt"
"sort"
"strings"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
awsiam "github.com/aws/aws-sdk-go-v2/service/iam"
"github.com/aws/aws-sdk-go/aws/endpoints"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
Expand Down Expand Up @@ -404,15 +406,21 @@ func (b *IAMModelBuilder) buildPolicy(policyString string) (*iam.Policy, error)

// IAMServiceEC2 returns the name of the IAM service for EC2 in the current region.
// It is ec2.amazonaws.com in the default aws partition, but different in other isolated/custom partitions
func IAMServiceEC2(region string) string {
partitions := endpoints.DefaultPartitions()
for _, p := range partitions {
if _, ok := p.Regions()[region]; ok {
ep := "ec2." + p.DNSSuffix()
return ep
}
func IAMServiceEC2(region string) (string, error) {
ctx := context.TODO()
resolver := ec2.NewDefaultEndpointResolverV2()
ep, err := resolver.ResolveEndpoint(ctx, ec2.EndpointParameters{Region: aws.String(region)})
if err != nil {
return "", fmt.Errorf("failed to resolve endpoint: %v", err)
}
if ep.URI.Host != "" {
// Remove the region from the hostname. Examples:
// ec2.us-east-1.amazonaws.com -> ec2.amazonaws.com
// ec2.cn-west-1.amazonaws.com.cn -> ec2.amazonaws.com.cn
// ec2.us-gov-west-1.amazonaws.com -> ec2.amazonaws.com
return strings.ReplaceAll(ep.URI.Host, fmt.Sprintf("%v.", region), ""), nil
}
return "ec2.amazonaws.com"
return "ec2.amazonaws.com", nil
}

func formatAWSIAMStatement(accountId, partition, oidcProvider, namespace, name string) (*iam.Statement, error) {
Expand Down Expand Up @@ -466,7 +474,11 @@ func (b *IAMModelBuilder) buildAWSIAMRolePolicy(role iam.Subject) (fi.Resource,
} else {
// We don't generate using json.Marshal here, it would create whitespace changes in the policy for existing clusters.

policy = strings.ReplaceAll(NodeRolePolicyTemplate, "{{ IAMServiceEC2 }}", IAMServiceEC2(b.Region))
ec2Service, err := IAMServiceEC2(b.Region)
if err != nil {
return nil, err
}
policy = strings.ReplaceAll(NodeRolePolicyTemplate, "{{ IAMServiceEC2 }}", ec2Service)
}

return fi.NewStringResource(policy), nil
Expand Down
5 changes: 4 additions & 1 deletion pkg/model/awsmodel/iam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ func TestIAMServiceEC2(t *testing.T) {
}

for region, expect := range expectations {
principal := IAMServiceEC2(region)
principal, err := IAMServiceEC2(region)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if principal != expect {
t.Errorf("expected %s for %s, but received %s", expect, region, principal)
}
Expand Down
153 changes: 111 additions & 42 deletions pkg/zones/wellknown.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,10 @@ limitations under the License.
package zones

import (
"context"
"sort"
"strings"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/scaleway/scaleway-sdk-go/scw"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
)

// These lists allow us to infer from certain well-known zones to a cloud
Expand Down Expand Up @@ -170,6 +164,116 @@ var hetznerZones = []string{
"hil",
}

var awsZones = []string{
"af-south-1a",
"af-south-1b",
"af-south-1c",
"ap-east-1a",
"ap-east-1b",
"ap-east-1c",
"ap-northeast-1a",
"ap-northeast-1b",
"ap-northeast-1c",
"ap-northeast-1d",
"ap-northeast-2a",
"ap-northeast-2b",
"ap-northeast-2c",
"ap-northeast-2d",
"ap-northeast-3a",
"ap-northeast-3b",
"ap-northeast-3c",
"ap-south-1a",
"ap-south-1b",
"ap-south-1c",
"ap-south-2a",
"ap-south-2b",
"ap-south-2c",
"ap-southeast-1a",
"ap-southeast-1b",
"ap-southeast-1c",
"ap-southeast-2a",
"ap-southeast-2b",
"ap-southeast-2c",
"ap-southeast-3a",
"ap-southeast-3b",
"ap-southeast-3c",
"ap-southeast-4a",
"ap-southeast-4b",
"ap-southeast-4c",
"ca-central-1a",
"ca-central-1b",
"ca-central-1c",
"ca-west-1a",
"ca-west-1b",
"ca-west-1c",
"eu-central-1a",
"eu-central-1b",
"eu-central-1c",
"eu-central-2a",
"eu-central-2b",
"eu-central-2c",
"eu-north-1a",
"eu-north-1b",
"eu-north-1c",
"eu-south-1a",
"eu-south-1b",
"eu-south-1c",
"eu-south-2a",
"eu-south-2b",
"eu-south-2c",
"eu-west-1a",
"eu-west-1b",
"eu-west-1c",
"eu-west-2a",
"eu-west-2b",
"eu-west-2c",
"eu-west-3a",
"eu-west-3b",
"eu-west-3c",
"il-central-1a",
"il-central-1b",
"il-central-1c",
"me-central-1a",
"me-central-1b",
"me-central-1c",
"me-south-1a",
"me-south-1b",
"me-south-1c",
"sa-east-1a",
"sa-east-1b",
"sa-east-1c",
"us-east-1a",
"us-east-1b",
"us-east-1c",
"us-east-1d",
"us-east-1e",
"us-east-1f",
"us-east-2a",
"us-east-2b",
"us-east-2c",
"us-west-1a",
"us-west-1b",
"us-west-1c",
"us-west-2a",
"us-west-2b",
"us-west-2c",
"us-west-2d",

"us-gov-east-1a",
"us-gov-east-1b",
"us-gov-east-1c",
"us-gov-west-1a",
"us-gov-west-1b",
"us-gov-west-1c",

"cn-north-1a",
"cn-north-1b",
"cn-north-1c",
"cn-northwest-1a",
"cn-northwest-1b",
"cn-northwest-1c",
}

var azureZones = []string{
"asia",
"asiapacific",
Expand Down Expand Up @@ -245,45 +349,10 @@ func scwZones() []string {
}

func WellKnownZonesForCloud(matchCloud kops.CloudProviderID, prefix string) []string {
ctx := context.Background()

var found []string
switch matchCloud {
case kops.CloudProviderAWS:
prefix = strings.ToLower(prefix)
for _, partition := range endpoints.DefaultResolver().(endpoints.EnumPartitions).Partitions() {
for _, region := range partition.Regions() {
regionName := strings.ToLower(region.ID())
if prefix == regionName || strings.HasPrefix(prefix, regionName+"-") {
// If the prefix is a region name or a Local Zone or a Wavelength Zone,
// return all its matching zones as the completion options.
awsCloud, err := awsup.NewAWSCloud(regionName, map[string]string{})
if err != nil {
continue
}
var zones *ec2.DescribeAvailabilityZonesOutput
zones, err = awsCloud.EC2().DescribeAvailabilityZones(ctx, &ec2.DescribeAvailabilityZonesInput{
AllAvailabilityZones: aws.Bool(true),
})
if err != nil {
continue
}
for _, zone := range zones.AvailabilityZones {
found = append(found, *zone.ZoneName)
}
} else if strings.HasPrefix(regionName, prefix) {
// Return the region name as the completion option. After the user completes
// that much, the code will then look up the specific zone options.
found = append(found, regionName)
} else {
// If the zone name is in the form of single-letter zones
// belonging to a region, that's good enough.
if len(prefix) == len(regionName)+1 && strings.HasPrefix(prefix, regionName) {
found = append(found, prefix)
}
}
}
}
found = awsZones
case kops.CloudProviderAzure:
found = azureZones
case kops.CloudProviderDO:
Expand Down
7 changes: 0 additions & 7 deletions upup/pkg/fi/cloudup/awsup/aws_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types"
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/smithy-go"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
Expand Down Expand Up @@ -156,9 +155,6 @@ func FindELBV2Tag(tags []elbv2types.Tag, key string) (string, bool) {

// AWSErrorCode returns the aws error code, if it is an awserr.Error or smithy.APIError, otherwise ""
func AWSErrorCode(err error) string {
if awsError, ok := err.(awserr.Error); ok {
return awsError.Code()
}
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return apiErr.ErrorCode()
Expand All @@ -168,9 +164,6 @@ func AWSErrorCode(err error) string {

// AWSErrorMessage returns the aws error message, if it is an awserr.Error or smithy.APIError, otherwise ""
func AWSErrorMessage(err error) string {
if awsError, ok := err.(awserr.Error); ok {
return awsError.Message()
}
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return apiErr.ErrorMessage()
Expand Down