AB#2286 Return only primary IPs for instance metadata operations (#335)

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2022-08-04 11:08:20 +02:00 committed by GitHub
parent 5c00dafe9b
commit 4151d365fb
21 changed files with 180 additions and 185 deletions

View File

@ -18,7 +18,7 @@ func TestList(t *testing.T) {
{
Name: "scale-set-name-instance-id",
ProviderID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"user": {"key-data"}},
},
}
@ -85,7 +85,7 @@ func TestSelf(t *testing.T) {
wantScaleSetInstance := metadata.InstanceMetadata{
Name: "scale-set-name-instance-id",
ProviderID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"user": {"key-data"}},
}
testCases := map[string]struct {
@ -634,6 +634,7 @@ func newNetworkInterfacesStub() *stubNetworkInterfacesAPI {
{
Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{
PrivateIPAddress: to.StringPtr("192.0.2.0"),
Primary: to.BoolPtr(true),
},
},
},

View File

@ -44,17 +44,17 @@ func (m *Metadata) getScaleSetVMInterfaces(ctx context.Context, vm armcompute.Vi
return networkInterfaces, nil
}
// getScaleSetVMPublicIPAddresses retrieves all public IP addresses from a network interface which is referenced by a scale set virtual machine.
func (m *Metadata) getScaleSetVMPublicIPAddresses(ctx context.Context, resourceGroup, scaleSet, instanceID string,
// getScaleSetVMPublicIPAddress retrieves the primary public IP address from a network interface which is referenced by a scale set virtual machine.
func (m *Metadata) getScaleSetVMPublicIPAddress(ctx context.Context, resourceGroup, scaleSet, instanceID string,
networkInterfaces []armnetwork.Interface,
) ([]string, error) {
var publicIPAddresses []string
) (string, error) {
for _, networkInterface := range networkInterfaces {
if networkInterface.Properties == nil || networkInterface.Name == nil {
continue
}
for _, config := range networkInterface.Properties.IPConfigurations {
if config == nil || config.Properties == nil || config.Properties.PublicIPAddress == nil || config.Name == nil {
if config == nil || config.Name == nil || config.Properties == nil || config.Properties.PublicIPAddress == nil ||
config.Properties.Primary == nil || !*config.Properties.Primary {
continue
}
publicIPAddressName := *config.Properties.PublicIPAddress.ID
@ -62,32 +62,37 @@ func (m *Metadata) getScaleSetVMPublicIPAddresses(ctx context.Context, resourceG
publicIPAddressName = publicIPAddressNameParts[len(publicIPAddressNameParts)-1]
publicIPAddress, err := m.publicIPAddressesAPI.GetVirtualMachineScaleSetPublicIPAddress(ctx, resourceGroup, scaleSet, instanceID, *networkInterface.Name, *config.Name, publicIPAddressName, nil)
if err != nil {
return nil, fmt.Errorf("failed to retrieve public ip address %v: %w", publicIPAddressName, err)
return "", fmt.Errorf("failed to retrieve public ip address %v: %w", publicIPAddressName, err)
}
if publicIPAddress.Properties == nil || publicIPAddress.Properties.IPAddress == nil {
return nil, errors.New("retrieved public ip address has invalid ip address")
return "", errors.New("retrieved public ip address has invalid ip address")
}
publicIPAddresses = append(publicIPAddresses, *publicIPAddress.Properties.IPAddress)
return *publicIPAddress.Properties.IPAddress, nil
}
}
return publicIPAddresses, nil
// instances may have no public IP, in that case we don't return an error.
return "", nil
}
// extractPrivateIPs extracts private IPs from a list of network interface IP configurations.
func extractPrivateIPs(networkInterfaces []armnetwork.Interface) []string {
addresses := []string{}
// extractVPCIP extracts the primary VPC IP from a list of network interface IP configurations.
func extractVPCIP(networkInterfaces []armnetwork.Interface) string {
for _, networkInterface := range networkInterfaces {
if networkInterface.Properties == nil || len(networkInterface.Properties.IPConfigurations) == 0 {
continue
}
for _, config := range networkInterface.Properties.IPConfigurations {
if config == nil || config.Properties == nil || config.Properties.PrivateIPAddress == nil {
if config == nil || config.Properties == nil || config.Properties.PrivateIPAddress == nil || config.Properties.Primary == nil {
continue
}
addresses = append(addresses, *config.Properties.PrivateIPAddress)
if *config.Properties.Primary {
return *config.Properties.PrivateIPAddress
}
}
}
return addresses
return ""
}
// extractInterfaceNamesFromInterfaceReferences extracts the name of a network interface from a reference id.

View File

@ -216,6 +216,7 @@ func TestGetScaleSetVMPublicIPAddresses(t *testing.T) {
{
Name: to.StringPtr("ip-config-name"),
Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{
Primary: to.BoolPtr(true),
PublicIPAddress: &armnetwork.PublicIPAddress{
ID: to.StringPtr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Network/publicIPAddresses/public-ip-name"),
},
@ -244,7 +245,7 @@ func TestGetScaleSetVMPublicIPAddresses(t *testing.T) {
networkInterfacesMutator func(*[]armnetwork.Interface)
networkInterfaces []armnetwork.Interface
publicIPAddressesAPI publicIPAddressesAPI
wantIPs []string
wantIP string
wantErr bool
}{
"retrieval works": {
@ -258,7 +259,7 @@ func TestGetScaleSetVMPublicIPAddresses(t *testing.T) {
},
}},
networkInterfaces: newNetworkInterfaces(),
wantIPs: []string{"192.0.2.1", "192.0.2.1"},
wantIP: "192.0.2.1",
},
"retrieval works for no valid interfaces": {
publicIPAddressesAPI: &stubPublicIPAddressesAPI{getVirtualMachineScaleSetPublicIPAddressResponse: armnetwork.PublicIPAddressesClientGetVirtualMachineScaleSetPublicIPAddressResponse{
@ -304,14 +305,14 @@ func TestGetScaleSetVMPublicIPAddresses(t *testing.T) {
publicIPAddressesAPI: tc.publicIPAddressesAPI,
}
ips, err := metadata.getScaleSetVMPublicIPAddresses(context.Background(), "resource-group", "scale-set-name", "instance-id", tc.networkInterfaces)
ips, err := metadata.getScaleSetVMPublicIPAddress(context.Background(), "resource-group", "scale-set-name", "instance-id", tc.networkInterfaces)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.Equal(tc.wantIPs, ips)
assert.Equal(tc.wantIP, ips)
})
}
}
@ -319,7 +320,7 @@ func TestGetScaleSetVMPublicIPAddresses(t *testing.T) {
func TestExtractPrivateIPs(t *testing.T) {
testCases := map[string]struct {
networkInterfaces []armnetwork.Interface
wantIPs []string
wantIP string
}{
"extraction works": {
networkInterfaces: []armnetwork.Interface{
@ -328,14 +329,20 @@ func TestExtractPrivateIPs(t *testing.T) {
IPConfigurations: []*armnetwork.InterfaceIPConfiguration{
{
Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{
Primary: to.BoolPtr(true),
PrivateIPAddress: to.StringPtr("192.0.2.0"),
},
},
{
Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{
PrivateIPAddress: to.StringPtr("192.0.2.1"),
},
},
},
},
},
},
wantIPs: []string{"192.0.2.0"},
wantIP: "192.0.2.0",
},
"can be empty": {
networkInterfaces: []armnetwork.Interface{},
@ -349,9 +356,8 @@ func TestExtractPrivateIPs(t *testing.T) {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
ips := extractPrivateIPs(tc.networkInterfaces)
assert.ElementsMatch(tc.wantIPs, ips)
ip := extractVPCIP(tc.networkInterfaces)
assert.Equal(tc.wantIP, ip)
})
}
}

View File

@ -31,12 +31,12 @@ func (m *Metadata) getScaleSetVM(ctx context.Context, providerID string) (metada
if err != nil {
return metadata.InstanceMetadata{}, err
}
publicIPAddresses, err := m.getScaleSetVMPublicIPAddresses(ctx, resourceGroup, scaleSet, instanceID, networkInterfaces)
publicIPAddress, err := m.getScaleSetVMPublicIPAddress(ctx, resourceGroup, scaleSet, instanceID, networkInterfaces)
if err != nil {
return metadata.InstanceMetadata{}, err
}
return convertScaleSetVMToCoreInstance(scaleSet, vmResp.VirtualMachineScaleSetVM, networkInterfaces, publicIPAddresses)
return convertScaleSetVMToCoreInstance(scaleSet, vmResp.VirtualMachineScaleSetVM, networkInterfaces, publicIPAddress)
}
// listScaleSetVMs lists all scale set VMs in the current resource group.
@ -58,7 +58,7 @@ func (m *Metadata) listScaleSetVMs(ctx context.Context, resourceGroup string) ([
if err != nil {
return nil, err
}
instance, err := convertScaleSetVMToCoreInstance(*scaleSet.Name, *vm, interfaces, nil)
instance, err := convertScaleSetVMToCoreInstance(*scaleSet.Name, *vm, interfaces, "")
if err != nil {
return nil, err
}
@ -71,7 +71,7 @@ func (m *Metadata) listScaleSetVMs(ctx context.Context, resourceGroup string) ([
}
// convertScaleSetVMToCoreInstance converts an azure scale set virtual machine with interface configurations into a core.Instance.
func convertScaleSetVMToCoreInstance(scaleSet string, vm armcompute.VirtualMachineScaleSetVM, networkInterfaces []armnetwork.Interface, publicIPAddresses []string) (metadata.InstanceMetadata, error) {
func convertScaleSetVMToCoreInstance(scaleSet string, vm armcompute.VirtualMachineScaleSetVM, networkInterfaces []armnetwork.Interface, publicIPAddress string) (metadata.InstanceMetadata, error) {
if vm.ID == nil {
return metadata.InstanceMetadata{}, errors.New("retrieving instance from armcompute API client returned no instance ID")
}
@ -88,8 +88,8 @@ func convertScaleSetVMToCoreInstance(scaleSet string, vm armcompute.VirtualMachi
Name: *vm.Properties.OSProfile.ComputerName,
ProviderID: "azure://" + *vm.ID,
Role: extractScaleSetVMRole(scaleSet),
PrivateIPs: extractPrivateIPs(networkInterfaces),
PublicIPs: publicIPAddresses,
VPCIP: extractVPCIP(networkInterfaces),
PublicIP: publicIPAddress,
SSHKeys: sshKeys,
}, nil
}

View File

@ -18,7 +18,7 @@ func TestGetScaleSetVM(t *testing.T) {
wantInstance := metadata.InstanceMetadata{
Name: "scale-set-name-instance-id",
ProviderID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"user": {"key-data"}},
}
testCases := map[string]struct {
@ -77,7 +77,7 @@ func TestListScaleSetVMs(t *testing.T) {
{
Name: "scale-set-name-instance-id",
ProviderID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"user": {"key-data"}},
},
}
@ -153,7 +153,7 @@ func TestConvertScaleSetVMToCoreInstance(t *testing.T) {
testCases := map[string]struct {
inVM armcompute.VirtualMachineScaleSetVM
inInterface []armnetwork.Interface
inPublicIPs []string
inPublicIP string
wantErr bool
wantInstance metadata.InstanceMetadata
}{
@ -176,6 +176,7 @@ func TestConvertScaleSetVMToCoreInstance(t *testing.T) {
IPConfigurations: []*armnetwork.InterfaceIPConfiguration{
{
Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{
Primary: to.BoolPtr(true),
PrivateIPAddress: to.StringPtr("192.0.2.0"),
},
},
@ -183,12 +184,12 @@ func TestConvertScaleSetVMToCoreInstance(t *testing.T) {
},
},
},
inPublicIPs: []string{"192.0.2.100", "192.0.2.101"},
inPublicIP: "192.0.2.100",
wantInstance: metadata.InstanceMetadata{
Name: "scale-set-name-instance-id",
ProviderID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id",
PrivateIPs: []string{"192.0.2.0"},
PublicIPs: []string{"192.0.2.100", "192.0.2.101"},
VPCIP: "192.0.2.0",
PublicIP: "192.0.2.100",
SSHKeys: map[string][]string{},
},
},
@ -203,7 +204,7 @@ func TestConvertScaleSetVMToCoreInstance(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
instance, err := convertScaleSetVMToCoreInstance("scale-set", tc.inVM, tc.inInterface, tc.inPublicIPs)
instance, err := convertScaleSetVMToCoreInstance("scale-set", tc.inVM, tc.inInterface, tc.inPublicIP)
if tc.wantErr {
assert.Error(err)

View File

@ -294,33 +294,35 @@ func (c *Client) uid() (string, error) {
return uid, nil
}
// extractPrivateIPs extracts private interface IPs from a list of interfaces.
func extractPrivateIPs(interfaces []*computepb.NetworkInterface) []string {
ips := []string{}
// extractVPCIP extracts the primary private IP from a list of interfaces.
func extractVPCIP(interfaces []*computepb.NetworkInterface) string {
for _, interf := range interfaces {
if interf == nil || interf.NetworkIP == nil {
if interf == nil || interf.NetworkIP == nil || interf.Name == nil || *interf.Name != "nic0" {
continue
}
ips = append(ips, *interf.NetworkIP)
// return private IP from the default interface
return *interf.NetworkIP
}
return ips
return ""
}
// extractPublicIPs extracts public interface IPs from a list of interfaces.
func extractPublicIPs(interfaces []*computepb.NetworkInterface) []string {
ips := []string{}
// extractPublicIP extracts a public IP from a list of interfaces.
func extractPublicIP(interfaces []*computepb.NetworkInterface) string {
for _, interf := range interfaces {
if interf == nil || interf.AccessConfigs == nil {
if interf == nil || interf.AccessConfigs == nil || interf.Name == nil || *interf.Name != "nic0" {
continue
}
// return public IP from the default interface
// GCP only supports one type of access config, so returning the first IP should result in a valid public IP
for _, accessConfig := range interf.AccessConfigs {
if accessConfig == nil || accessConfig.NatIP == nil {
continue
}
ips = append(ips, *accessConfig.NatIP)
return *accessConfig.NatIP
}
}
return ips
return ""
}
// extractAliasIPRanges extracts alias interface IPs from a list of interfaces.
@ -377,8 +379,8 @@ func convertToCoreInstance(in *computepb.Instance, project string, zone string)
Name: *in.Name,
ProviderID: gcpshared.JoinProviderID(project, zone, *in.Name),
Role: extractRole(mdata),
PrivateIPs: extractPrivateIPs(in.NetworkInterfaces),
PublicIPs: extractPublicIPs(in.NetworkInterfaces),
VPCIP: extractVPCIP(in.NetworkInterfaces),
PublicIP: extractPublicIP(in.NetworkInterfaces),
AliasIPRanges: extractAliasIPRanges(in.NetworkInterfaces),
SSHKeys: extractSSHKeys(mdata),
}, nil

View File

@ -54,6 +54,7 @@ func TestRetrieveInstances(t *testing.T) {
},
NetworkInterfaces: []*computepb.NetworkInterface{
{
Name: proto.String("nic0"),
NetworkIP: proto.String("192.0.2.0"),
AliasIpRanges: []*computepb.AliasIpRange{{IpCidrRange: proto.String("192.0.2.0/16")}},
AccessConfigs: []*computepb.AccessConfig{{NatIP: proto.String("192.0.2.1")}},
@ -82,8 +83,8 @@ func TestRetrieveInstances(t *testing.T) {
ProviderID: "gce://someProject/someZone/someInstance",
Role: role.ControlPlane,
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
},
},
@ -106,8 +107,8 @@ func TestRetrieveInstances(t *testing.T) {
ProviderID: "gce://someProject/someZone/someInstance",
Role: role.ControlPlane,
AliasIPRanges: []string{},
PublicIPs: []string{},
PrivateIPs: []string{},
PublicIP: "",
VPCIP: "",
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
},
},
@ -123,8 +124,8 @@ func TestRetrieveInstances(t *testing.T) {
ProviderID: "gce://someProject/someZone/someInstance",
Role: role.ControlPlane,
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{},
PublicIP: "192.0.2.1",
VPCIP: "",
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
},
},
@ -153,8 +154,8 @@ func TestRetrieveInstances(t *testing.T) {
ProviderID: "gce://someProject/someZone/someInstance",
Role: role.Unknown,
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
},
},
@ -211,6 +212,7 @@ func TestRetrieveInstance(t *testing.T) {
},
NetworkInterfaces: []*computepb.NetworkInterface{
{
Name: proto.String("nic0"),
NetworkIP: proto.String("192.0.2.0"),
AliasIpRanges: []*computepb.AliasIpRange{{IpCidrRange: proto.String("192.0.2.0/16")}},
AccessConfigs: []*computepb.AccessConfig{{NatIP: proto.String("192.0.2.1")}},
@ -233,8 +235,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},
@ -249,8 +251,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
},
},
@ -265,9 +267,9 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PublicIP: "192.0.2.1",
Role: role.ControlPlane,
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},
@ -286,8 +288,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},
@ -299,8 +301,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},
@ -312,8 +314,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},
@ -325,8 +327,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{},
PublicIPs: []string{},
PrivateIPs: []string{},
PublicIP: "",
VPCIP: "",
SSHKeys: map[string][]string{},
},
},
@ -338,8 +340,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{},
PublicIP: "192.0.2.1",
VPCIP: "",
SSHKeys: map[string][]string{},
},
},
@ -351,8 +353,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{},
PublicIPs: []string{"192.0.2.1"},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "192.0.2.1",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},
@ -364,8 +366,8 @@ func TestRetrieveInstance(t *testing.T) {
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
AliasIPRanges: []string{"192.0.2.0/16"},
PublicIPs: []string{},
PrivateIPs: []string{"192.0.2.0"},
PublicIP: "",
VPCIP: "192.0.2.0",
SSHKeys: map[string][]string{},
},
},

View File

@ -18,7 +18,7 @@ func TestList(t *testing.T) {
{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
}
}
@ -43,7 +43,7 @@ func TestList(t *testing.T) {
{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
},
},
@ -113,13 +113,13 @@ func TestSelf(t *testing.T) {
retrieveInstanceValue: metadata.InstanceMetadata{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
},
wantInstance: metadata.InstanceMetadata{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
},
"retrieve error is detected": {
@ -186,13 +186,13 @@ func TestGetInstance(t *testing.T) {
retrieveInstanceValue: metadata.InstanceMetadata{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
},
wantInstance: metadata.InstanceMetadata{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
},
"retrieve error is detected": {

View File

@ -41,7 +41,7 @@ func (f *providerMetadataFake) Self(ctx context.Context) (metadata.InstanceMetad
Name: "instanceName",
ProviderID: "fake://instance-id",
Role: role.Unknown,
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
}, nil
}

View File

@ -253,7 +253,7 @@ func (c *JoinClient) startNodeAndJoin(ticket *joinproto.IssueJoinTicketResponse,
}
if c.role == role.ControlPlane {
if err := c.writeControlePlaneFiles(ticket.ControlPlaneFiles); err != nil {
if err := c.writeControlPlaneFiles(ticket.ControlPlaneFiles); err != nil {
return fmt.Errorf("writing control plane files: %w", err)
}
}
@ -304,11 +304,12 @@ func (c *JoinClient) getNodeMetadata() error {
}
var ips []net.IP
for _, ip := range inst.PrivateIPs {
ips = append(ips, net.ParseIP(ip))
if inst.VPCIP != "" {
ips = append(ips, net.ParseIP(inst.VPCIP))
}
for _, ip := range inst.PublicIPs {
ips = append(ips, net.ParseIP(ip))
if inst.PublicIP != "" {
ips = append(ips, net.ParseIP(inst.PublicIP))
}
c.nodeName = inst.Name
@ -346,8 +347,8 @@ func (c *JoinClient) getControlPlaneIPs() ([]string, error) {
ips := []string{}
for _, instance := range instances {
if instance.Role == role.ControlPlane {
ips = append(ips, instance.PrivateIPs...)
if instance.Role == role.ControlPlane && instance.VPCIP != "" {
ips = append(ips, instance.VPCIP)
}
}
@ -355,7 +356,7 @@ func (c *JoinClient) getControlPlaneIPs() ([]string, error) {
return ips, nil
}
func (c *JoinClient) writeControlePlaneFiles(files []*joinproto.ControlPlaneCertOrKey) error {
func (c *JoinClient) writeControlPlaneFiles(files []*joinproto.ControlPlaneCertOrKey) error {
for _, cert := range files {
if err := c.fileHandler.Write(
filepath.Join(kubeconstants.KubernetesDir, kubeconstants.DefaultCertificateDir, cert.Name),

View File

@ -40,9 +40,10 @@ func TestClient(t *testing.T) {
workerSelf := metadata.InstanceMetadata{Role: role.Worker, Name: "node-1"}
controlSelf := metadata.InstanceMetadata{Role: role.ControlPlane, Name: "node-5"}
peers := []metadata.InstanceMetadata{
{Role: role.Worker, Name: "node-2", PrivateIPs: []string{"192.0.2.8"}},
{Role: role.ControlPlane, Name: "node-3", PrivateIPs: []string{"192.0.2.1"}},
{Role: role.ControlPlane, Name: "node-4", PrivateIPs: []string{"192.0.2.2", "192.0.2.3"}},
{Role: role.Worker, Name: "node-2", VPCIP: "192.0.2.8"},
{Role: role.ControlPlane, Name: "node-3", VPCIP: "192.0.2.1"},
{Role: role.ControlPlane, Name: "node-4", VPCIP: "192.0.2.2"},
{Role: role.ControlPlane, Name: "node-5", VPCIP: "192.0.2.3"},
}
testCases := map[string]struct {

View File

@ -103,20 +103,17 @@ func (k *KubeWrapper) InitCluster(
if err != nil {
return nil, fmt.Errorf("retrieving own instance metadata failed: %w", err)
}
for _, ip := range instance.PrivateIPs {
validIPs = append(validIPs, net.ParseIP(ip))
if instance.VPCIP != "" {
validIPs = append(validIPs, net.ParseIP(instance.VPCIP))
}
for _, ip := range instance.PublicIPs {
validIPs = append(validIPs, net.ParseIP(ip))
if instance.PublicIP != "" {
validIPs = append(validIPs, net.ParseIP(instance.PublicIP))
}
nodeName = k8sCompliantHostname(instance.Name)
providerID = instance.ProviderID
if len(instance.PrivateIPs) > 0 {
nodeIP = instance.PrivateIPs[0]
}
if len(instance.PublicIPs) > 0 {
publicIP = instance.PublicIPs[0]
}
nodeIP = instance.VPCIP
publicIP = instance.PublicIP
if len(instance.AliasIPRanges) > 0 {
nodePodCIDR = instance.AliasIPRanges[0]
}
@ -253,9 +250,7 @@ func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTo
}
providerID = instance.ProviderID
nodeName = instance.Name
if len(instance.PrivateIPs) > 0 {
nodeInternalIP = instance.PrivateIPs[0]
}
nodeInternalIP = instance.VPCIP
}
nodeName = k8sCompliantHostname(nodeName)

View File

@ -82,8 +82,8 @@ func TestInitCluster(t *testing.T) {
SelfResp: metadata.InstanceMetadata{
Name: nodeName,
ProviderID: providerID,
PrivateIPs: []string{privateIP},
PublicIPs: []string{publicIP},
VPCIP: privateIP,
PublicIP: publicIP,
AliasIPRanges: []string{aliasIPRange},
},
GetLoadBalancerIPResp: loadbalancerIP,
@ -353,7 +353,7 @@ func TestJoinCluster(t *testing.T) {
SelfResp: metadata.InstanceMetadata{
ProviderID: "provider-id",
Name: "metadata-name",
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
},
},
CloudControllerManager: &stubCloudControllerManager{},
@ -375,7 +375,7 @@ func TestJoinCluster(t *testing.T) {
SelfResp: metadata.InstanceMetadata{
ProviderID: "provider-id",
Name: "metadata-name",
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
},
},
CloudControllerManager: &stubCloudControllerManager{
@ -399,7 +399,7 @@ func TestJoinCluster(t *testing.T) {
SelfResp: metadata.InstanceMetadata{
ProviderID: "provider-id",
Name: "metadata-name",
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
},
},
CloudControllerManager: &stubCloudControllerManager{},

View File

@ -73,7 +73,9 @@ func (f *Fetcher) DiscoverDebugdIPs(ctx context.Context) ([]string, error) {
}
var ips []string
for _, instance := range instances {
ips = append(ips, instance.PrivateIPs...)
if instance.VPCIP != "" {
ips = append(ips, instance.VPCIP)
}
}
return ips, nil
}

View File

@ -31,13 +31,13 @@ func TestDiscoverDebugIPs(t *testing.T) {
meta: stubMetadata{
listRes: []metadata.InstanceMetadata{
{
PrivateIPs: []string{"192.0.2.0"},
VPCIP: "192.0.2.0",
},
{
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
},
{
PrivateIPs: []string{"192.0.2.2"},
VPCIP: "192.0.2.2",
},
},
},

View File

@ -73,16 +73,14 @@ func (s *Server) listSelf(w http.ResponseWriter, r *http.Request) {
}
for _, peer := range peers {
for _, ip := range peer.PublicIPs {
if ip == remoteIP {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(peer); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Infof("Request successful")
if peer.PublicIP == remoteIP {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(peer); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Infof("Request successful")
return
}
}
@ -178,7 +176,7 @@ func (s *Server) exportPCRs(w http.ResponseWriter, r *http.Request) {
return
}
for _, peer := range peers {
if peer.PublicIPs[0] == remoteIP {
if peer.PublicIP == remoteIP {
nodeName = peer.Name
}
}
@ -225,8 +223,8 @@ func (s *Server) listAll() ([]metadata.InstanceMetadata, error) {
peers = append(peers, metadata.InstanceMetadata{
Name: lease.Hostname,
Role: instanceRole,
PrivateIPs: []string{lease.IPaddr},
PublicIPs: []string{lease.IPaddr},
VPCIP: lease.IPaddr,
PublicIP: lease.IPaddr,
ProviderID: "qemu:///hostname/" + lease.Hostname,
})
}

View File

@ -1,6 +1,7 @@
package server
import (
"context"
"encoding/json"
"errors"
"io"
@ -145,7 +146,7 @@ func TestListSelf(t *testing.T) {
server := New(logger.NewTest(t), tc.connect, file.Handler{})
req, err := http.NewRequest(http.MethodGet, "http://192.0.0.1/self", nil)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://192.0.0.1/self", nil)
require.NoError(err)
req.RemoteAddr = tc.remoteAddr
@ -163,7 +164,7 @@ func TestListSelf(t *testing.T) {
var metadata metadata.InstanceMetadata
require.NoError(json.Unmarshal(metadataRaw, &metadata))
assert.Equal(tc.connect.network.leases[0].Hostname, metadata.Name)
assert.Equal(tc.connect.network.leases[0].IPaddr, metadata.PublicIPs[0])
assert.Equal(tc.connect.network.leases[0].IPaddr, metadata.PublicIP)
})
}
}
@ -207,7 +208,7 @@ func TestListPeers(t *testing.T) {
server := New(logger.NewTest(t), tc.connect, file.Handler{})
req, err := http.NewRequest(http.MethodGet, "http://192.0.0.1/peers", nil)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://192.0.0.1/peers", nil)
require.NoError(err)
req.RemoteAddr = tc.remoteAddr
@ -262,7 +263,7 @@ func TestPostLog(t *testing.T) {
server := New(logger.NewTest(t), &stubConnect{}, file.NewHandler(afero.NewMemMapFs()))
req, err := http.NewRequest(tc.method, "http://192.0.0.1/logs", tc.message)
req, err := http.NewRequestWithContext(context.Background(), tc.method, "http://192.0.0.1/logs", tc.message)
require.NoError(err)
req.RemoteAddr = tc.remoteAddr
@ -343,7 +344,7 @@ func TestExportPCRs(t *testing.T) {
file := file.NewHandler(afero.NewMemMapFs())
server := New(logger.NewTest(t), tc.connect, file)
req, err := http.NewRequest(tc.method, "http://192.0.0.1/pcrs", strings.NewReader(tc.message))
req, err := http.NewRequestWithContext(context.Background(), tc.method, "http://192.0.0.1/pcrs", strings.NewReader(tc.message))
require.NoError(err)
req.RemoteAddr = tc.remoteAddr

View File

@ -12,11 +12,13 @@ import (
// InstanceMetadata describes metadata of a peer.
type InstanceMetadata struct {
Name string
ProviderID string
Role role.Role
PrivateIPs []string
PublicIPs []string
Name string
ProviderID string
Role role.Role
// VPCIP is the primary IP address of the instance in the VPC.
VPCIP string
// PublicIP is the primary public IP of the instance, if available, empty string otherwise.
PublicIP string
AliasIPRanges []string
// SSHKeys maps usernames to ssh public keys.
SSHKeys map[string][]string
@ -32,24 +34,6 @@ type InstanceLister interface {
List(ctx context.Context) ([]InstanceMetadata, error)
}
// InitServerEndpoints returns the list of endpoints for the init server, which are running on the control plane nodes.
func InitServerEndpoints(ctx context.Context, lister InstanceLister) ([]string, error) {
instances, err := lister.List(ctx)
if err != nil {
return nil, fmt.Errorf("retrieving instances list from cloud provider: %w", err)
}
initServerEndpoints := []string{}
for _, instance := range instances {
if instance.Role == role.ControlPlane {
for _, ip := range instance.PrivateIPs {
initServerEndpoints = append(initServerEndpoints, net.JoinHostPort(ip, strconv.Itoa(constants.BootstrapperPort)))
}
}
}
return initServerEndpoints, nil
}
// JoinServiceEndpoints returns the list of endpoints for the join service, which are running on the control plane nodes.
func JoinServiceEndpoints(ctx context.Context, lister InstanceLister) ([]string, error) {
instances, err := lister.List(ctx)
@ -59,8 +43,8 @@ func JoinServiceEndpoints(ctx context.Context, lister InstanceLister) ([]string,
joinEndpoints := []string{}
for _, instance := range instances {
if instance.Role == role.ControlPlane {
for _, ip := range instance.PrivateIPs {
joinEndpoints = append(joinEndpoints, net.JoinHostPort(ip, strconv.Itoa(constants.JoinServiceNodePort)))
if instance.VPCIP != "" {
joinEndpoints = append(joinEndpoints, net.JoinHostPort(instance.VPCIP, strconv.Itoa(constants.JoinServiceNodePort)))
}
}
}

View File

@ -14,6 +14,7 @@ import (
qemucloud "github.com/edgelesssys/constellation/bootstrapper/cloudprovider/qemu"
"github.com/edgelesssys/constellation/internal/atls"
"github.com/edgelesssys/constellation/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/internal/cloud/metadata"
"github.com/edgelesssys/constellation/internal/constants"
"github.com/edgelesssys/constellation/internal/file"
"github.com/edgelesssys/constellation/internal/grpc/atlscredentials"
@ -96,39 +97,34 @@ func main() {
}
func getVPCIP(ctx context.Context, provider string) (string, error) {
var metadata metadataAPI
var err error
switch cloudprovider.FromString(provider) {
case cloudprovider.Azure:
metadata, err := azurecloud.NewMetadata(ctx)
metadata, err = azurecloud.NewMetadata(ctx)
if err != nil {
return "", err
}
self, err := metadata.Self(ctx)
if err != nil {
return "", err
}
return self.PrivateIPs[0], nil
case cloudprovider.GCP:
gcpClient, err := gcpcloud.NewClient(ctx)
if err != nil {
return "", err
}
metadata := gcpcloud.New(gcpClient)
if err != nil {
return "", err
}
self, err := metadata.Self(ctx)
if err != nil {
return "", err
}
return self.PrivateIPs[0], nil
metadata = gcpcloud.New(gcpClient)
case cloudprovider.QEMU:
metadata := &qemucloud.Metadata{}
self, err := metadata.Self(ctx)
if err != nil {
return "", err
}
return self.PrivateIPs[0], nil
metadata = &qemucloud.Metadata{}
default:
return "", errors.New("unsupported cloud provider")
}
self, err := metadata.Self(ctx)
if err != nil {
return "", err
}
return self.VPCIP, nil
}
type metadataAPI interface {
Self(ctx context.Context) (metadata.InstanceMetadata, error)
}

View File

@ -33,7 +33,7 @@ func TestRequestKeyLoop(t *testing.T) {
Name: "test-instance",
ProviderID: "/test/provider",
Role: role.ControlPlane,
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
}
testCases := map[string]struct {

View File

@ -142,7 +142,7 @@ func (f *fakeMetadataAPI) List(ctx context.Context) ([]metadata.InstanceMetadata
Name: "instanceName",
ProviderID: "fake://instance-id",
Role: role.Unknown,
PrivateIPs: []string{"192.0.2.1"},
VPCIP: "192.0.2.1",
},
}, nil
}