bootstrapper: add fallback endpoint and custom endpoint to SAN field (#2108)

terraform: collect apiserver cert SANs and support custom endpoint

constants: add new constants for cluster configuration and custom endpoint

cloud: support apiserver cert sans and prepare for endpoint migration on AWS

config: add customEndpoint field

bootstrapper: use per-CSP apiserver cert SANs

cli: route customEndpoint to terraform and add migration for apiserver cert SANs

bootstrapper: change interface of GetLoadBalancerEndpoint to return host and port separately
This commit is contained in:
Malte Poll 2023-07-21 16:43:51 +02:00 committed by GitHub
parent 3324a4eba2
commit 8da6a23aa5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 724 additions and 301 deletions

View file

@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"path"
"strconv"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4"
@ -28,6 +29,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/cloud"
"github.com/edgelesssys/constellation/v2/internal/cloud/azureshared"
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/role"
)
@ -156,41 +158,12 @@ func (c *Cloud) GetCCMConfig(ctx context.Context, providerID string, cloudServic
//
// The returned string is an IP address without a port, but the method name needs to satisfy the
// metadata interface.
func (c *Cloud) GetLoadBalancerEndpoint(ctx context.Context) (string, error) {
resourceGroup, err := c.imds.resourceGroup(ctx)
func (c *Cloud) GetLoadBalancerEndpoint(ctx context.Context) (host, port string, err error) {
hostname, err := c.getLoadBalancerPublicIP(ctx)
if err != nil {
return "", fmt.Errorf("retrieving resource group: %w", err)
return "", "", fmt.Errorf("retrieving load balancer public IP: %w", err)
}
uid, err := c.imds.uid(ctx)
if err != nil {
return "", fmt.Errorf("retrieving instance UID: %w", err)
}
lb, err := c.getLoadBalancer(ctx, resourceGroup, uid)
if err != nil {
return "", fmt.Errorf("retrieving load balancer: %w", err)
}
if lb == nil || lb.Properties == nil {
return "", errors.New("could not dereference load balancer IP configuration")
}
var pubIP string
for _, fipConf := range lb.Properties.FrontendIPConfigurations {
if fipConf == nil || fipConf.Properties == nil || fipConf.Properties.PublicIPAddress == nil || fipConf.Properties.PublicIPAddress.ID == nil {
continue
}
pubIP = path.Base(*fipConf.Properties.PublicIPAddress.ID)
break
}
resp, err := c.pubIPAPI.Get(ctx, resourceGroup, pubIP, nil)
if err != nil {
return "", fmt.Errorf("retrieving load balancer public IP address: %w", err)
}
if resp.Properties == nil || resp.Properties.IPAddress == nil {
return "", fmt.Errorf("could not resolve public IP address reference for load balancer")
}
return *resp.Properties.IPAddress, nil
return hostname, strconv.FormatInt(constants.KubernetesPort, 10), nil
}
// List retrieves all instances belonging to the current constellation.
@ -409,6 +382,86 @@ func (c *Cloud) getVMInterfaces(ctx context.Context, vm armcompute.VirtualMachin
return networkInterfaces, nil
}
// getLoadBalancerPublicIP retrieves the first load balancer IP from cloud provider metadata.
func (c *Cloud) getLoadBalancerPublicIP(ctx context.Context) (string, error) {
resourceGroup, err := c.imds.resourceGroup(ctx)
if err != nil {
return "", fmt.Errorf("retrieving resource group: %w", err)
}
uid, err := c.imds.uid(ctx)
if err != nil {
return "", fmt.Errorf("retrieving instance UID: %w", err)
}
lb, err := c.getLoadBalancer(ctx, resourceGroup, uid)
if err != nil {
return "", fmt.Errorf("retrieving load balancer: %w", err)
}
if lb == nil || lb.Properties == nil {
return "", errors.New("could not dereference load balancer IP configuration")
}
var pubIP string
for _, fipConf := range lb.Properties.FrontendIPConfigurations {
if fipConf == nil || fipConf.Properties == nil || fipConf.Properties.PublicIPAddress == nil || fipConf.Properties.PublicIPAddress.ID == nil {
continue
}
pubIP = path.Base(*fipConf.Properties.PublicIPAddress.ID)
break
}
resp, err := c.pubIPAPI.Get(ctx, resourceGroup, pubIP, nil)
if err != nil {
return "", fmt.Errorf("retrieving load balancer public IP address: %w", err)
}
if resp.Properties == nil || resp.Properties.IPAddress == nil {
return "", fmt.Errorf("could not resolve public IP address reference for load balancer")
}
return *resp.Properties.IPAddress, nil
}
/*
// TODO(malt3): uncomment and use as soon as we switch the primary endpoint to DNS.
// getLoadBalancerDNSName retrieves the dns name of the load balancer.
// On Azure, the DNS name is the DNS name of the public IP address of the load balancer.
func (c *Cloud) getLoadBalancerDNSName(ctx context.Context) (string, error) {
resourceGroup, err := c.imds.resourceGroup(ctx)
if err != nil {
return "", fmt.Errorf("retrieving resource group: %w", err)
}
uid, err := c.imds.uid(ctx)
if err != nil {
return "", fmt.Errorf("retrieving instance UID: %w", err)
}
lb, err := c.getLoadBalancer(ctx, resourceGroup, uid)
if err != nil {
return "", fmt.Errorf("retrieving load balancer: %w", err)
}
if lb == nil || lb.Properties == nil {
return "", errors.New("could not dereference load balancer IP configuration")
}
var pubIP string
for _, fipConf := range lb.Properties.FrontendIPConfigurations {
if fipConf == nil || fipConf.Properties == nil || fipConf.Properties.PublicIPAddress == nil || fipConf.Properties.PublicIPAddress.ID == nil {
continue
}
pubIP = path.Base(*fipConf.Properties.PublicIPAddress.ID)
break
}
resp, err := c.pubIPAPI.Get(ctx, resourceGroup, pubIP, nil)
if err != nil {
return "", fmt.Errorf("retrieving load balancer public IP address: %w", err)
}
if resp.Properties == nil || resp.Properties.DNSSettings == nil || resp.Properties.DNSSettings.Fqdn == nil {
return "", fmt.Errorf("could not resolve public IP address fqdn for load balancer")
}
return *resp.Properties.DNSSettings.Fqdn, nil
}
*/
type cloudConfig struct {
Cloud string `json:"cloud,omitempty"`
TenantID string `json:"tenantId,omitempty"`