Skip to content

Commit

Permalink
OCM-8979 | test: Prepare shared VPC resources
Browse files Browse the repository at this point in the history
  • Loading branch information
jameszwang committed Jul 3, 2024
1 parent 9d3423c commit 7948203
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 36 deletions.
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ go 1.21

require (
github.com/apparentlymart/go-cidr v1.1.0
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2 v1.30.0
github.com/aws/aws-sdk-go-v2/config v1.27.9
github.com/aws/aws-sdk-go-v2/credentials v1.17.9
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.48.0
github.com/aws/aws-sdk-go-v2/service/ec2 v1.152.0
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.3
github.com/aws/aws-sdk-go-v2/service/iam v1.27.1
github.com/aws/aws-sdk-go-v2/service/kms v1.30.0
github.com/aws/aws-sdk-go-v2/service/ram v1.26.1
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.3
github.com/aws/aws-sdk-go-v2/service/sts v1.28.5
github.com/go-jose/go-jose/v4 v4.0.2
Expand All @@ -34,8 +35,8 @@ require (

require (
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.1
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
Expand Down
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU=
github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2 v1.30.0 h1:6qAwtzlfcTtcL8NHtbDQAqgM5s6NDipQTkPxyH/6kAA=
github.com/aws/aws-sdk-go-v2 v1.30.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
github.com/aws/aws-sdk-go-v2/config v1.27.9 h1:gRx/NwpNEFSk+yQlgmk1bmxxvQ5TyJ76CWXs9XScTqg=
Expand All @@ -10,10 +10,10 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMN
github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 h1:af5YzcLf80tv4Em4jWVD75lpnOHSBkPUZxZfGkrI3HI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 h1:SJ04WXGTwnHlWIODtC5kJzKbeuHt+OUNOgKg7nfnUGw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12/go.mod h1:FkpvXhA92gb3GE9LD6Og0pHHycTxW7xGpnEh5E7Opwo=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 h1:hb5KgeYfObi5MHkSSZMEudnIvX30iB+E21evI4r6BnQ=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12/go.mod h1:CroKe/eWJdyfy9Vx4rljP5wTUjNJfb+fPz1uMYUhEGM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.48.0 h1:uMlYsoHdd2Gr9sDGq2ieUR5jVu7F5AqPYz6UBJmdRhY=
Expand All @@ -32,6 +32,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHM
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU=
github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU=
github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g=
github.com/aws/aws-sdk-go-v2/service/ram v1.26.1 h1:1UcUsMsHB7ZnpcUYNwBTX90hFjIZrhf8Xu00R9Vo+Kg=
github.com/aws/aws-sdk-go-v2/service/ram v1.26.1/go.mod h1:e/3wE+afnOAeolpqyg8fKAQK/kKya+ycDW62/X4vjK8=
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.3 h1:wr5gulbwbb8PSRMWjCROoP0TIMccpF8x5A7hEk2SjpA=
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.3/go.mod h1:/Gyl9xjGcjIVe80ar75YlmA8m6oFh0A4XfLciBmdS8s=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 h1:mnbuWHOcM70/OFUlZZ5rcdfA8PflGXXiefU/O+1S3+8=
Expand Down
49 changes: 30 additions & 19 deletions pkg/aws/aws_client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package aws_client

import (
"context"
"os"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
Expand All @@ -12,7 +10,9 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/iam"
"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/aws/aws-sdk-go-v2/service/ram"
"github.com/aws/aws-sdk-go-v2/service/sts"
"os"

"github.com/openshift-online/ocm-common/pkg/log"

Expand All @@ -35,42 +35,52 @@ type AWSClient struct {
KmsClient *kms.Client
CloudWatchLogsClient *cloudwatchlogs.Client
AWSConfig *aws.Config
RamClient *ram.Client
}

type AccessKeyMod struct {
AccessKeyId string `ini:"aws_access_key_id,omitempty"`
SecretAccessKey string `ini:"aws_secret_access_key,omitempty"`
}

func CreateAWSClient(profileName string, region string) (*AWSClient, error) {
func CreateAWSClient(profileName string, region string, awsSharedCredentialFile ...string) (*AWSClient, error) {
var cfg aws.Config
var err error

if envCredential() {
log.LogInfo("Got AWS_ACCESS_KEY_ID env settings, going to build the config with the env")
if len(awsSharedCredentialFile) > 0 {
file := awsSharedCredentialFile[0]
log.LogInfo("Got aws shared credential file path: %s ", file)
cfg, err = config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithCredentialsProvider(
credentials.NewStaticCredentialsProvider(
os.Getenv("AWS_ACCESS_KEY_ID"),
os.Getenv("AWS_SECRET_ACCESS_KEY"),
"")),
config.WithSharedCredentialsFiles([]string{file}),
)
} else {
if envAwsProfile() {
file := os.Getenv("AWS_SHARED_CREDENTIALS_FILE")
log.LogInfo("Got file path: %s from env variable AWS_SHARED_CREDENTIALS_FILE\n", file)
if envCredential() {
log.LogInfo("Got AWS_ACCESS_KEY_ID env settings, going to build the config with the env")
cfg, err = config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithSharedCredentialsFiles([]string{file}),
config.WithCredentialsProvider(
credentials.NewStaticCredentialsProvider(
os.Getenv("AWS_ACCESS_KEY_ID"),
os.Getenv("AWS_SECRET_ACCESS_KEY"),
"")),
)
} else {
cfg, err = config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithSharedConfigProfile(profileName),
)
}
if envAwsProfile() {
file := os.Getenv("AWS_SHARED_CREDENTIALS_FILE")
log.LogInfo("Got file path: %s from env variable AWS_SHARED_CREDENTIALS_FILE\n", file)
cfg, err = config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithSharedCredentialsFiles([]string{file}),
)
} else {
cfg, err = config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithSharedConfigProfile(profileName),
)
}

}
}

if err != nil {
Expand All @@ -88,6 +98,7 @@ func CreateAWSClient(profileName string, region string) (*AWSClient, error) {
ClientContext: context.TODO(),
KmsClient: kms.NewFromConfig(cfg),
AWSConfig: &cfg,
RamClient: ram.NewFromConfig(cfg),
}
awsClient.AccountID = awsClient.GetAWSAccountID()
return awsClient, nil
Expand Down
32 changes: 32 additions & 0 deletions pkg/aws/aws_client/ram.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package aws_client

import (
"context"
"github.com/aws/aws-sdk-go-v2/service/ram"
"github.com/openshift-online/ocm-common/pkg/log"
)

func (awsClient AWSClient) CreateResourceShare(resourceShareName string, resourceArns []string, principles []string) (*ram.CreateResourceShareOutput, error) {
input := &ram.CreateResourceShareInput{
Name: &resourceShareName,
ResourceArns: resourceArns,
Principals: principles,
}

resp, err := awsClient.RamClient.CreateResourceShare(context.TODO(), input)
if err != nil {
log.LogError("Create resource share failed with name %s: %s", resourceShareName, err.Error())
} else {
log.LogInfo("Create resource share succeed with name %s", resourceShareName)
}
return resp, err
}

func (awsClient AWSClient) DeleteResourceShare(resourceShareArn string) error {
input := &ram.DeleteResourceShareInput{
ResourceShareArn: &resourceShareArn,
}

_, err := awsClient.RamClient.DeleteResourceShare(context.TODO(), input)
return err
}
43 changes: 43 additions & 0 deletions pkg/aws/aws_client/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/openshift-online/ocm-common/pkg/log"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -395,3 +396,45 @@ func (client *AWSClient) UntagRole(roleName string, tagKeys []string) error {
_, err := client.IamClient.UntagRole(context.TODO(), input)
return err
}

func (client *AWSClient) CreateRoleForSharedVPC(roleName, installerRoleArn string, ingressOperatorRoleArn string) (types.Role, error) {
statement := map[string]interface{}{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": map[string]interface{}{
"AWS": []string{installerRoleArn, ingressOperatorRoleArn},
},
"Action": "sts:AssumeRole",
}

assumeRolePolicyDocument, err := completeRolePolicyDocument(statement)
if err != nil {
log.LogError("Failed to convert Role Policy Document into JSON: ", err.Error())

Check failure on line 412 in pkg/aws/aws_client/role.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

github.com/openshift-online/ocm-common/pkg/log.LogError call has arguments but no formatting directives

Check failure on line 412 in pkg/aws/aws_client/role.go

View workflow job for this annotation

GitHub Actions / Lint

printf: github.com/openshift-online/ocm-common/pkg/log.LogError call has arguments but no formatting directives (govet)
return types.Role{}, err
}

return client.CreateRole(roleName, string(assumeRolePolicyDocument), "", make(map[string]string), "/")
}

func (client *AWSClient) CreatePolicyForSharedVPC(policyName string) (string, error) {
statement := map[string]interface{}{
"Sid": "Statement1",
"Effect": "Allow",
"Action": []string{
"route53:GetChange",
"route53:GetHostedZone",
"route53:ChangeResourceRecordSets",
"route53:ListHostedZones",
"route53:ListHostedZonesByName",
"route53:ListResourceRecordSets",
"route53:ChangeTagsForResource",
"route53:GetAccountLimit",
"route53:ListTagsForResource",
"route53:UpdateHostedZoneComment",
"tag:GetResources",
"tag:UntagResources",
},
"Resource": "*",
}
return client.CreatePolicy(policyName, statement)
}
23 changes: 19 additions & 4 deletions pkg/aws/aws_client/route53.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@ import (
"github.com/openshift-online/ocm-common/pkg/log"
)

func (awsClient AWSClient) CreateHostedZone(hostedZoneName string, vpcID string, private bool) (*route53.CreateHostedZoneOutput, error) {
func (awsClient AWSClient) CreateHostedZone(hostedZoneName string, callerReference string, vpcID string, region string, private bool) (*route53.CreateHostedZoneOutput, error) {
// CreateHostedZone is a function used for hosted zone creation on AWS
// callReference is a required field of CreateHostedZoneInput struct, which used to identifies the request as a unique string.
// Usually random string or date/time stamp can be used as callReference.
input := &route53.CreateHostedZoneInput{
Name: &hostedZoneName,
Name: &hostedZoneName,
CallerReference: &callerReference,
HostedZoneConfig: &types.HostedZoneConfig{
PrivateZone: private,
},
}
if vpcID != "" {
vpc := &types.VPC{
VPCId: &vpcID,
VPCId: &vpcID,
VPCRegion: types.VPCRegion(region),
}
input.VPC = vpc
}

resp, err := awsClient.Route53Client.CreateHostedZone(context.TODO(), input)
if err != nil {
log.LogError("Create hosted zone failed for vpc %s with name %s: %s", vpcID, hostedZoneName, err.Error())
} else {
log.LogError("Create hosted zone succeed for vpc %s with name %s", vpcID, hostedZoneName)
log.LogInfo("Create hosted zone succeed for vpc %s with name %s", vpcID, hostedZoneName)
}
return resp, err
}
Expand All @@ -47,3 +53,12 @@ func (awsClient AWSClient) ListHostedZoneByDNSName(hostedZoneName string) (*rout

return awsClient.Route53Client.ListHostedZonesByName(context.TODO(), input)
}

func (awsClient AWSClient) DeleteHostedZone(hostedZoneID string) error {
input := &route53.DeleteHostedZoneInput{
Id: &hostedZoneID,
}

_, err := awsClient.Route53Client.DeleteHostedZone(context.TODO(), input)
return err
}
17 changes: 13 additions & 4 deletions pkg/test/vpc_client/vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ func (vpc *VPC) DeleteVPCChain(totalClean ...bool) error {
// Just be careful once you use checkExisting, the vpc may have subnets not existing in your zones. And maybe multi subnets in the zones
// Try vpc.PreparePairSubnets by zone for further implementation to get a pair of
// Zones will be customized if you want. Otherwise, it will use the default zone "a"
func PrepareVPC(vpcName string, region string, vpcCIDR string, checkExisting bool, zones ...string) (*VPC, error) {
func PrepareVPC(vpcName string, region string, vpcCIDR string, checkExisting bool, awsSharedCredentialFile string, zones ...string) (*VPC, error) {
var awsclient *aws_client.AWSClient
var err error

if vpcCIDR == "" {
vpcCIDR = CON.DefaultVPCCIDR
}
Expand All @@ -160,7 +163,12 @@ func PrepareVPC(vpcName string, region string, vpcCIDR string, checkExisting boo
vpcName, region, vpcCIDR)
}
log.LogInfo(logMessage)
awsclient, err := aws_client.CreateAWSClient("", region)
if awsSharedCredentialFile == "" {
awsclient, err = aws_client.CreateAWSClient("", region)
} else {
awsclient, err = aws_client.CreateAWSClient("", region, awsSharedCredentialFile)
}

if err != nil {
log.LogError("Create AWS Client due to error: %s", err.Error())
return nil, err
Expand Down Expand Up @@ -217,8 +225,9 @@ func PrepareVPC(vpcName string, region string, vpcCIDR string, checkExisting boo

// GenerateVPCByID will return a VPC with CIDRpool and subnets
// If you know the vpc ID on AWS, then try to generate it
func GenerateVPCByID(vpcID string, region string) (*VPC, error) {
awsClient, err := aws_client.CreateAWSClient("", region)
func GenerateVPCByID(vpcID string, region string, awsSharedCredentialFile ...string) (*VPC, error) {
awsClient, err := aws_client.CreateAWSClient("", region, awsSharedCredentialFile...)

if err != nil {
return nil, err
}
Expand Down

0 comments on commit 7948203

Please sign in to comment.