diff --git a/api/restapi/server.go b/api/restapi/server.go index 5b9e1b162..ebfb66e97 100644 --- a/api/restapi/server.go +++ b/api/restapi/server.go @@ -8,6 +8,7 @@ import ( "crypto/x509" "errors" "fmt" + "github.com/loxilb-io/loxilb/options" "log" "net" "net/http" @@ -226,7 +227,7 @@ func (s *Server) Serve() (err error) { }(s.httpServerL) } - if s.hasScheme(schemeHTTPS) { + if s.hasScheme(schemeHTTPS) && options.Opts.TLS { httpsServer := new(http.Server) httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize) httpsServer.ReadTimeout = s.TLSReadTimeout diff --git a/options/options.go b/options/options.go index 5904a5ff2..8c80a9f51 100644 --- a/options/options.go +++ b/options/options.go @@ -12,6 +12,7 @@ var Opts struct { NoNlp bool `short:"n" long:"nonlp" description:"Do not register with nlp"` Host string `long:"host" description:"the IP to listen on" default:"0.0.0.0" env:"HOST"` Port int `long:"port" description:"the port to listen on for insecure connections" default:"11111" env:"PORT"` + TLS bool `long:"tls" description:"enable TLS " env:"TLS"` TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"` TLSPort int `long:"tls-port" description:"the port to listen on for secure connections" default:"8091" env:"TLS_PORT"` TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" default:"/opt/loxilb/cert/server.crt" env:"TLS_CERTIFICATE"` diff --git a/pkg/loxinet/rules.go b/pkg/loxinet/rules.go index 2b2aec0f6..c7b3535ce 100644 --- a/pkg/loxinet/rules.go +++ b/pkg/loxinet/rules.go @@ -1533,7 +1533,7 @@ func (R *RuleH) DeleteNatLbRule(serv cmn.LbServiceArg) (int, error) { if utils.IsIPHostAddr(sNetAddr.IP.String()) { loxinlp.DelAddrNoHook(sNetAddr.IP.String()+"/32", "lo") if mh.cloudLabel == "aws" { - err := AWSUpdatePrivateIp(sNetAddr.IP, false) + err := AWSUpdatePrivateIP(sNetAddr.IP, false) if err != nil { tk.LogIt(tk.LogError, "aws lb-rule vip %s delete failed. err: %v\n", sNetAddr.IP.String(), err) } @@ -2643,7 +2643,7 @@ func (R *RuleH) AdvRuleVIPIfL2(IP net.IP) error { if ev == 0 { if !utils.IsIPHostAddr(IP.String()) { if mh.cloudLabel == "aws" { - err := AWSUpdatePrivateIp(IP, true) + err := AWSUpdatePrivateIP(IP, true) if err != nil { tk.LogIt(tk.LogError, "aws lb-rule vip %s add failed. err: %v\n", IP.String(), err) return err diff --git a/pkg/loxinet/utils_aws.go b/pkg/loxinet/utils_aws.go index d65fca9aa..ccf66b34b 100644 --- a/pkg/loxinet/utils_aws.go +++ b/pkg/loxinet/utils_aws.go @@ -54,6 +54,154 @@ func AWSGetInstanceIDInfo() (string, error) { return string(instanceID), nil } +func AWSGetInstanceVPCInfo() (string, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*2)) + defer cancel() + resp, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{ + Path: "mac", + }) + if err != nil { + return "", err + } + + mac, err := io.ReadAll(resp.Content) + if err != nil { + return "", err + } + + vpcPath := fmt.Sprintf("network/interfaces/macs/%s/vpc-id", string(mac)) + resp2, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{ + Path: vpcPath, + }) + if err != nil { + return "", err + } + vpc, err := io.ReadAll(resp2.Content) + if err != nil { + return "", err + } + + return string(vpc), nil +} + +func AWSGetInstanceAvailabilityZone() (string, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*2)) + defer cancel() + resp, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{ + Path: "placement/availability-zone", + }) + if err != nil { + return "", err + } + + az, err := io.ReadAll(resp.Content) + if err != nil { + return "", err + } + + return string(az), nil +} + +func AWSPrepVIPNetwork() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*5)) + defer cancel() + + filterStr := "tag:loxiType" + output, err := ec2Client.DescribeNetworkInterfaces(ctx, &ec2.DescribeNetworkInterfacesInput{ + Filters: []types.Filter{ + {Name: &filterStr, Values: []string{"loxilb-eni"}}, + }, + }) + if err != nil { + fmt.Printf("no loxiType intf found \n") + return err + } + + subnets := []string{} + for _, intf := range output.NetworkInterfaces { + subnets = append(subnets, *intf.SubnetId) + _, err := ec2Client.DeleteNetworkInterface(ctx, &ec2.DeleteNetworkInterfaceInput{NetworkInterfaceId: intf.NetworkInterfaceId}) + if err != nil { + fmt.Printf("failed to delete intf (%s)\n", *intf.NetworkInterfaceId) + return err + } + } + + for _, subnet := range subnets { + _, err := ec2Client.DeleteSubnet(ctx, &ec2.DeleteSubnetInput{SubnetId: &subnet}) + if err != nil { + fmt.Printf("failed to delete subnet (%s)\n", subnet) + return err + } + } + + vpcID, err := AWSGetInstanceVPCInfo() + if err != nil { + fmt.Printf("failed to find vpcid for instance\n") + return nil + } + + fmt.Printf("vpcid for instance:%s\n", vpcID) + + azName, err := AWSGetInstanceAvailabilityZone() + if err != nil { + fmt.Printf("failed to find az for instance %v\n", vpcID) + return nil + } + fmt.Printf("AZ for instance:%s\n", azName) + + instanceID, err := AWSGetInstanceIDInfo() + if err != nil { + fmt.Printf("failed to find instanceID for instance %v\n", vpcID) + return nil + } + + cidrBlock := "123.123.123.0/28" + loxilbSubNetKey := "loxiType" + loxilbSubNetKeyVal := "loxilb-subnet" + subnetTag := types.Tag{Key: &loxilbSubNetKey, Value: &loxilbSubNetKeyVal} + subnetTags := []types.Tag{subnetTag} + subOutput, err := ec2Client.CreateSubnet(ctx, &ec2.CreateSubnetInput{ + VpcId: &vpcID, + AvailabilityZone: &azName, + CidrBlock: &cidrBlock, + TagSpecifications: []types.TagSpecification{{ResourceType: types.ResourceTypeSubnet, + Tags: subnetTags}, + }, + }) + if err != nil { + fmt.Printf("failed to create subnet for loxilb instance %v\n", vpcID) + return nil + } + + intfDesc := "loxilb-eni" + loxilbIntfKey := "loxiType" + loxilbIntfKeyVal := "loxilb-eni" + intfTag := types.Tag{Key: &loxilbIntfKey, Value: &loxilbIntfKeyVal} + intfTags := []types.Tag{intfTag} + intfOutput, err := ec2Client.CreateNetworkInterface(ctx, &ec2.CreateNetworkInterfaceInput{ + SubnetId: subOutput.Subnet.SubnetId, + Description: &intfDesc, + TagSpecifications: []types.TagSpecification{{ResourceType: types.ResourceTypeNetworkInterface, + Tags: intfTags}, + }, + }) + if err != nil { + fmt.Printf("failed to create interface for loxilb instance %v\n", vpcID) + return nil + } + + fmt.Printf("Create interface (%s) for loxilb instance %v\n", *intfOutput.NetworkInterface.NetworkInterfaceId, vpcID) + + devIdx := int32(1) + ec2Client.AttachNetworkInterface(ctx, &ec2.AttachNetworkInterfaceInput{DeviceIndex: &devIdx, + InstanceId: &instanceID, + NetworkInterfaceId: intfOutput.NetworkInterface.NetworkInterfaceId, + }) + + return nil +} + func AWSGetNetworkInterface(instanceID string, vIP net.IP) (string, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*5)) defer cancel() @@ -131,7 +279,7 @@ func AWSDeletePrivateIp(ni string, vIP net.IP) error { return nil } -func AWSUpdatePrivateIp(vIP net.IP, add bool) error { +func AWSUpdatePrivateIP(vIP net.IP, add bool) error { instanceID, err := AWSGetInstanceIDInfo() if err != nil { tk.LogIt(tk.LogError, "AWS get instance failed: %v\n", err)