mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-11 15:39:33 -05:00
Add constellation UID retrieval to cloudprovider metadata APIs
Signed-off-by: Malte Poll <mp@edgeless.systems>
This commit is contained in:
parent
2f925b5955
commit
18a89d2881
@ -2,6 +2,7 @@ package azure
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -18,6 +19,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
publicIPAddressRegexp = regexp.MustCompile(`/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft.Network/publicIPAddresses/(?P<IPname>[^/]+)`)
|
publicIPAddressRegexp = regexp.MustCompile(`/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft.Network/publicIPAddresses/(?P<IPname>[^/]+)`)
|
||||||
keyPathRegexp = regexp.MustCompile(`^\/home\/([^\/]+)\/\.ssh\/authorized_keys$`)
|
keyPathRegexp = regexp.MustCompile(`^\/home\/([^\/]+)\/\.ssh\/authorized_keys$`)
|
||||||
|
resourceGroupNameRegexp = regexp.MustCompile(`^(.*)-([^-]+)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Metadata implements azure metadata APIs.
|
// Metadata implements azure metadata APIs.
|
||||||
@ -183,6 +185,25 @@ func (m *Metadata) GetSubnetworkCIDR(ctx context.Context) (string, error) {
|
|||||||
return *virtualNetwork.Properties.Subnets[0].Properties.AddressPrefix, nil
|
return *virtualNetwork.Properties.Subnets[0].Properties.AddressPrefix, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UID retrieves the UID of the constellation.
|
||||||
|
func (m *Metadata) UID(ctx context.Context) (string, error) {
|
||||||
|
providerID, err := m.providerID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
_, resourceGroup, err := azureshared.BasicsFromProviderID(providerID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, err := getUIDFromResourceGroup(resourceGroup)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return uid, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getLoadBalancer retrieves the load balancer from cloud provider metadata.
|
// getLoadBalancer retrieves the load balancer from cloud provider metadata.
|
||||||
func (m *Metadata) getLoadBalancer(ctx context.Context) (*armnetwork.LoadBalancer, error) {
|
func (m *Metadata) getLoadBalancer(ctx context.Context) (*armnetwork.LoadBalancer, error) {
|
||||||
providerID, err := m.providerID(ctx)
|
providerID, err := m.providerID(ctx)
|
||||||
@ -314,3 +335,11 @@ func extractSSHKeys(sshConfig armcomputev2.SSHConfiguration) map[string][]string
|
|||||||
}
|
}
|
||||||
return sshKeys
|
return sshKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getUIDFromResourceGroup(resourceGroup string) (string, error) {
|
||||||
|
matches := resourceGroupNameRegexp.FindStringSubmatch(resourceGroup)
|
||||||
|
if len(matches) != 3 {
|
||||||
|
return "", errors.New("error splitting resource group name")
|
||||||
|
}
|
||||||
|
return matches[2], nil
|
||||||
|
}
|
||||||
|
@ -499,6 +499,58 @@ func TestProviderID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUID(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
imdsAPI imdsAPI
|
||||||
|
wantErr bool
|
||||||
|
wantUID string
|
||||||
|
}{
|
||||||
|
"uid extraction from providerID works": {
|
||||||
|
imdsAPI: &stubIMDSAPI{
|
||||||
|
res: metadataResponse{Compute: struct {
|
||||||
|
ResourceID string `json:"resourceId,omitempty"`
|
||||||
|
}{"/subscriptions/subscription-id/resourceGroups/basename-uid/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id"}},
|
||||||
|
},
|
||||||
|
wantUID: "uid",
|
||||||
|
},
|
||||||
|
"providerID does not contain uid": {
|
||||||
|
imdsAPI: &stubIMDSAPI{
|
||||||
|
res: metadataResponse{Compute: struct {
|
||||||
|
ResourceID string `json:"resourceId,omitempty"`
|
||||||
|
}{"/subscriptions/subscription-id/resourceGroups/invalid/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id"}},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"providerID is invalid": {
|
||||||
|
imdsAPI: newInvalidIMDSStub(),
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"imds retrieval fails": {
|
||||||
|
imdsAPI: &stubIMDSAPI{retrieveErr: errors.New("imds err")},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
metadata := Metadata{
|
||||||
|
imdsAPI: tc.imdsAPI,
|
||||||
|
}
|
||||||
|
uid, err := metadata.UID(context.Background())
|
||||||
|
|
||||||
|
if tc.wantErr {
|
||||||
|
assert.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(err)
|
||||||
|
assert.Equal(tc.wantUID, uid)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExtractInstanceTags(t *testing.T) {
|
func TestExtractInstanceTags(t *testing.T) {
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
in map[string]*string
|
in map[string]*string
|
||||||
|
@ -53,7 +53,7 @@ func NewClient(ctx context.Context) (*Client, error) {
|
|||||||
|
|
||||||
// RetrieveInstances returns list of instances including their ips and metadata.
|
// RetrieveInstances returns list of instances including their ips and metadata.
|
||||||
func (c *Client) RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error) {
|
func (c *Client) RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error) {
|
||||||
uid, err := c.uid()
|
uid, err := c.UID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ func (c *Client) RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone,
|
|||||||
|
|
||||||
// RetrieveLoadBalancerIP returns the IP address of the load balancer specified by project, zone and loadBalancerName.
|
// RetrieveLoadBalancerIP returns the IP address of the load balancer specified by project, zone and loadBalancerName.
|
||||||
func (c *Client) RetrieveLoadBalancerIP(ctx context.Context, project, zone string) (string, error) {
|
func (c *Client) RetrieveLoadBalancerIP(ctx context.Context, project, zone string) (string, error) {
|
||||||
uid, err := c.uid()
|
uid, err := c.UID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -284,8 +284,8 @@ func (c *Client) updateInstanceMetadata(ctx context.Context, project, zone, inst
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// uid retrieves the current instances uid.
|
// UID retrieves the current instances uid.
|
||||||
func (c *Client) uid() (string, error) {
|
func (c *Client) UID() (string, error) {
|
||||||
// API endpoint: http://metadata.google.internal/computeMetadata/v1/instance/attributes/constellation-uid
|
// API endpoint: http://metadata.google.internal/computeMetadata/v1/instance/attributes/constellation-uid
|
||||||
uid, err := c.RetrieveInstanceMetadata(constellationUIDMetadataKey)
|
uid, err := c.RetrieveInstanceMetadata(constellationUIDMetadataKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
// API handles all GCP API requests.
|
// API handles all GCP API requests.
|
||||||
type API interface {
|
type API interface {
|
||||||
|
// UID retrieves the current instances uid.
|
||||||
|
UID() (string, error)
|
||||||
// RetrieveInstances retrieves a list of all accessible GCP instances with their metadata.
|
// RetrieveInstances retrieves a list of all accessible GCP instances with their metadata.
|
||||||
RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error)
|
RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error)
|
||||||
// RetrieveInstances retrieves a single GCP instances with its metadata.
|
// RetrieveInstances retrieves a single GCP instances with its metadata.
|
||||||
@ -122,6 +124,11 @@ func (m *Metadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
|||||||
return m.api.RetrieveLoadBalancerIP(ctx, project, zone)
|
return m.api.RetrieveLoadBalancerIP(ctx, project, zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UID retrieves the UID of the constellation.
|
||||||
|
func (m *Metadata) UID(ctx context.Context) (string, error) {
|
||||||
|
return m.api.UID()
|
||||||
|
}
|
||||||
|
|
||||||
// Supported is used to determine if metadata API is implemented for this cloud provider.
|
// Supported is used to determine if metadata API is implemented for this cloud provider.
|
||||||
func (m *Metadata) Supported() bool {
|
func (m *Metadata) Supported() bool {
|
||||||
return true
|
return true
|
||||||
|
@ -231,6 +231,8 @@ func TestGetInstance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type stubGCPClient struct {
|
type stubGCPClient struct {
|
||||||
|
retrieveUIDValue string
|
||||||
|
retrieveUIDErr error
|
||||||
retrieveInstanceValue metadata.InstanceMetadata
|
retrieveInstanceValue metadata.InstanceMetadata
|
||||||
retrieveInstanceErr error
|
retrieveInstanceErr error
|
||||||
retrieveInstancesValues []metadata.InstanceMetadata
|
retrieveInstancesValues []metadata.InstanceMetadata
|
||||||
@ -289,6 +291,10 @@ func (s *stubGCPClient) RetrieveLoadBalancerIP(ctx context.Context, project, zon
|
|||||||
return s.loadBalancerIP, s.retrieveLoadBalancerErr
|
return s.loadBalancerIP, s.retrieveLoadBalancerErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stubGCPClient) UID() (string, error) {
|
||||||
|
return s.retrieveUIDValue, s.retrieveUIDErr
|
||||||
|
}
|
||||||
|
|
||||||
func (s *stubGCPClient) SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error {
|
func (s *stubGCPClient) SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error {
|
||||||
s.instanceMetadataProjects = append(s.instanceMetadataProjects, project)
|
s.instanceMetadataProjects = append(s.instanceMetadataProjects, project)
|
||||||
s.instanceMetadataZones = append(s.instanceMetadataZones, zone)
|
s.instanceMetadataZones = append(s.instanceMetadataZones, zone)
|
||||||
|
@ -70,6 +70,13 @@ func (m Metadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
|||||||
panic("function *Metadata.GetLoadBalancerIP not implemented")
|
panic("function *Metadata.GetLoadBalancerIP not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UID returns the UID of the constellation.
|
||||||
|
func (m Metadata) UID(ctx context.Context) (string, error) {
|
||||||
|
// We expect only one constellation to be deployed in the same QEMU / libvirt environment.
|
||||||
|
// the UID can be an empty string.
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetSubnetworkCIDR retrieves the subnetwork CIDR from cloud provider metadata.
|
// GetSubnetworkCIDR retrieves the subnetwork CIDR from cloud provider metadata.
|
||||||
func (m Metadata) GetSubnetworkCIDR(ctx context.Context) (string, error) {
|
func (m Metadata) GetSubnetworkCIDR(ctx context.Context) (string, error) {
|
||||||
return "10.244.0.0/16", nil
|
return "10.244.0.0/16", nil
|
||||||
|
@ -11,6 +11,8 @@ import (
|
|||||||
|
|
||||||
// ProviderMetadata implementers read/write cloud provider metadata.
|
// ProviderMetadata implementers read/write cloud provider metadata.
|
||||||
type ProviderMetadata interface {
|
type ProviderMetadata interface {
|
||||||
|
// UID returns the unique identifier for the constellation.
|
||||||
|
UID(ctx context.Context) (string, error)
|
||||||
// List retrieves all instances belonging to the current Constellation.
|
// List retrieves all instances belonging to the current Constellation.
|
||||||
List(ctx context.Context) ([]metadata.InstanceMetadata, error)
|
List(ctx context.Context) ([]metadata.InstanceMetadata, error)
|
||||||
// Self retrieves the current instance.
|
// Self retrieves the current instance.
|
||||||
@ -100,6 +102,9 @@ type stubProviderMetadata struct {
|
|||||||
|
|
||||||
SupportedResp bool
|
SupportedResp bool
|
||||||
SupportsLoadBalancerResp bool
|
SupportsLoadBalancerResp bool
|
||||||
|
|
||||||
|
UIDErr error
|
||||||
|
UIDResp string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *stubProviderMetadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
func (m *stubProviderMetadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
||||||
@ -130,6 +135,10 @@ func (m *stubProviderMetadata) SupportsLoadBalancer() bool {
|
|||||||
return m.SupportsLoadBalancerResp
|
return m.SupportsLoadBalancerResp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *stubProviderMetadata) UID(ctx context.Context) (string, error) {
|
||||||
|
return m.UIDResp, m.UIDErr
|
||||||
|
}
|
||||||
|
|
||||||
type stubCloudControllerManager struct {
|
type stubCloudControllerManager struct {
|
||||||
SupportedResp bool
|
SupportedResp bool
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user