mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04: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 (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@ -16,8 +17,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
publicIPAddressRegexp = regexp.MustCompile(`/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft.Network/publicIPAddresses/(?P<IPname>[^/]+)`)
|
||||
keyPathRegexp = regexp.MustCompile(`^\/home\/([^\/]+)\/\.ssh\/authorized_keys$`)
|
||||
publicIPAddressRegexp = regexp.MustCompile(`/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft.Network/publicIPAddresses/(?P<IPname>[^/]+)`)
|
||||
keyPathRegexp = regexp.MustCompile(`^\/home\/([^\/]+)\/\.ssh\/authorized_keys$`)
|
||||
resourceGroupNameRegexp = regexp.MustCompile(`^(.*)-([^-]+)$`)
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (m *Metadata) getLoadBalancer(ctx context.Context) (*armnetwork.LoadBalancer, error) {
|
||||
providerID, err := m.providerID(ctx)
|
||||
@ -314,3 +335,11 @@ func extractSSHKeys(sshConfig armcomputev2.SSHConfiguration) map[string][]string
|
||||
}
|
||||
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) {
|
||||
testCases := map[string]struct {
|
||||
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.
|
||||
func (c *Client) RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error) {
|
||||
uid, err := c.uid()
|
||||
uid, err := c.UID()
|
||||
if err != nil {
|
||||
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.
|
||||
func (c *Client) RetrieveLoadBalancerIP(ctx context.Context, project, zone string) (string, error) {
|
||||
uid, err := c.uid()
|
||||
uid, err := c.UID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -284,8 +284,8 @@ func (c *Client) updateInstanceMetadata(ctx context.Context, project, zone, inst
|
||||
return nil
|
||||
}
|
||||
|
||||
// uid retrieves the current instances uid.
|
||||
func (c *Client) uid() (string, error) {
|
||||
// UID retrieves the current instances uid.
|
||||
func (c *Client) UID() (string, error) {
|
||||
// API endpoint: http://metadata.google.internal/computeMetadata/v1/instance/attributes/constellation-uid
|
||||
uid, err := c.RetrieveInstanceMetadata(constellationUIDMetadataKey)
|
||||
if err != nil {
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
|
||||
// API handles all GCP API requests.
|
||||
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(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error)
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (m *Metadata) Supported() bool {
|
||||
return true
|
||||
|
@ -231,6 +231,8 @@ func TestGetInstance(t *testing.T) {
|
||||
}
|
||||
|
||||
type stubGCPClient struct {
|
||||
retrieveUIDValue string
|
||||
retrieveUIDErr error
|
||||
retrieveInstanceValue metadata.InstanceMetadata
|
||||
retrieveInstanceErr error
|
||||
retrieveInstancesValues []metadata.InstanceMetadata
|
||||
@ -289,6 +291,10 @@ func (s *stubGCPClient) RetrieveLoadBalancerIP(ctx context.Context, project, zon
|
||||
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 {
|
||||
s.instanceMetadataProjects = append(s.instanceMetadataProjects, project)
|
||||
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")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (m Metadata) GetSubnetworkCIDR(ctx context.Context) (string, error) {
|
||||
return "10.244.0.0/16", nil
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
|
||||
// ProviderMetadata implementers read/write cloud provider metadata.
|
||||
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(ctx context.Context) ([]metadata.InstanceMetadata, error)
|
||||
// Self retrieves the current instance.
|
||||
@ -100,6 +102,9 @@ type stubProviderMetadata struct {
|
||||
|
||||
SupportedResp bool
|
||||
SupportsLoadBalancerResp bool
|
||||
|
||||
UIDErr error
|
||||
UIDResp string
|
||||
}
|
||||
|
||||
func (m *stubProviderMetadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
||||
@ -130,6 +135,10 @@ func (m *stubProviderMetadata) SupportsLoadBalancer() bool {
|
||||
return m.SupportsLoadBalancerResp
|
||||
}
|
||||
|
||||
func (m *stubProviderMetadata) UID(ctx context.Context) (string, error) {
|
||||
return m.UIDResp, m.UIDErr
|
||||
}
|
||||
|
||||
type stubCloudControllerManager struct {
|
||||
SupportedResp bool
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user