mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-11 15:39:33 -05:00
Separate shared azure code
This commit is contained in:
parent
6cd93e4179
commit
180d7872dd
@ -6,7 +6,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/url"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/authorization/mgmt/authorization"
|
"github.com/Azure/azure-sdk-for-go/profiles/latest/authorization/mgmt/authorization"
|
||||||
@ -15,6 +14,7 @@ import (
|
|||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
"github.com/Azure/go-autorest/autorest/date"
|
"github.com/Azure/go-autorest/autorest/date"
|
||||||
"github.com/Azure/go-autorest/autorest/to"
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
|
"github.com/edgelesssys/constellation/internal/azureshared"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,12 +47,12 @@ func (c *Client) CreateServicePrincipal(ctx context.Context) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApplicationCredentials{
|
return azureshared.ApplicationCredentials{
|
||||||
TenantID: c.tenantID,
|
TenantID: c.tenantID,
|
||||||
ClientID: createAppRes.AppID,
|
ClientID: createAppRes.AppID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
Location: c.location,
|
Location: c.location,
|
||||||
}.ConvertToCloudServiceAccountURI(), nil
|
}.ToCloudServiceAccountURI(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TerminateServicePrincipal terminates an Azure AD app together with the service principal.
|
// TerminateServicePrincipal terminates an Azure AD app together with the service principal.
|
||||||
@ -164,30 +164,6 @@ func (c *Client) assignResourceGroupRole(ctx context.Context, principalID, roleD
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplicationCredentials is a set of Azure AD application credentials.
|
|
||||||
// It is the equivalent of a service account key in other cloud providers.
|
|
||||||
type ApplicationCredentials struct {
|
|
||||||
TenantID string
|
|
||||||
ClientID string
|
|
||||||
ClientSecret string
|
|
||||||
Location string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConvertToCloudServiceAccountURI converts the ApplicationCredentials into a cloud service account URI.
|
|
||||||
func (c ApplicationCredentials) ConvertToCloudServiceAccountURI() string {
|
|
||||||
query := url.Values{}
|
|
||||||
query.Add("tenant_id", c.TenantID)
|
|
||||||
query.Add("client_id", c.ClientID)
|
|
||||||
query.Add("client_secret", c.ClientSecret)
|
|
||||||
query.Add("location", c.Location)
|
|
||||||
uri := url.URL{
|
|
||||||
Scheme: "serviceaccount",
|
|
||||||
Host: "azure",
|
|
||||||
RawQuery: query.Encode(),
|
|
||||||
}
|
|
||||||
return uri.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
type createADApplicationOutput struct {
|
type createADApplicationOutput struct {
|
||||||
AppID string
|
AppID string
|
||||||
ObjectID string
|
ObjectID string
|
||||||
|
@ -3,7 +3,6 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net/url"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||||
@ -12,7 +11,6 @@ import (
|
|||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -358,27 +356,3 @@ func TestAssignOwnerOfResourceGroup(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertToCloudServiceAccountURI(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
require := require.New(t)
|
|
||||||
key := ApplicationCredentials{
|
|
||||||
TenantID: "tenant-id",
|
|
||||||
ClientID: "client-id",
|
|
||||||
ClientSecret: "client-secret",
|
|
||||||
Location: "location",
|
|
||||||
}
|
|
||||||
|
|
||||||
cloudServiceAccountURI := key.ConvertToCloudServiceAccountURI()
|
|
||||||
uri, err := url.Parse(cloudServiceAccountURI)
|
|
||||||
require.NoError(err)
|
|
||||||
query := uri.Query()
|
|
||||||
assert.Equal("serviceaccount", uri.Scheme)
|
|
||||||
assert.Equal("azure", uri.Host)
|
|
||||||
assert.Equal(url.Values{
|
|
||||||
"tenant_id": []string{"tenant-id"},
|
|
||||||
"client_id": []string{"client-id"},
|
|
||||||
"client_secret": []string{"client-secret"},
|
|
||||||
"location": []string{"location"},
|
|
||||||
}, query)
|
|
||||||
}
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
azurecl "github.com/edgelesssys/constellation/cli/azure/client"
|
azurecl "github.com/edgelesssys/constellation/cli/azure/client"
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
|
||||||
gcpcl "github.com/edgelesssys/constellation/cli/internal/gcp/client"
|
gcpcl "github.com/edgelesssys/constellation/cli/internal/gcp/client"
|
||||||
|
"github.com/edgelesssys/constellation/internal/azureshared"
|
||||||
"github.com/edgelesssys/constellation/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/internal/cloud/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/internal/gcpshared"
|
"github.com/edgelesssys/constellation/internal/gcpshared"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
@ -121,10 +122,10 @@ func (c *fakeAzureClient) CreateInstancesVMs(ctx context.Context, input azurecl.
|
|||||||
|
|
||||||
func (c *fakeAzureClient) CreateServicePrincipal(ctx context.Context) (string, error) {
|
func (c *fakeAzureClient) CreateServicePrincipal(ctx context.Context) (string, error) {
|
||||||
c.adAppObjectID = "00000000-0000-0000-0000-000000000001"
|
c.adAppObjectID = "00000000-0000-0000-0000-000000000001"
|
||||||
return azurecl.ApplicationCredentials{
|
return azureshared.ApplicationCredentials{
|
||||||
ClientID: "client-id",
|
ClientID: "client-id",
|
||||||
ClientSecret: "client-secret",
|
ClientSecret: "client-secret",
|
||||||
}.ConvertToCloudServiceAccountURI(), nil
|
}.ToCloudServiceAccountURI(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeAzureClient) TerminateResourceGroup(ctx context.Context) error {
|
func (c *fakeAzureClient) TerminateResourceGroup(ctx context.Context) error {
|
||||||
@ -199,10 +200,10 @@ func (c *stubAzureClient) CreateInstancesVMs(ctx context.Context, input azurecl.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *stubAzureClient) CreateServicePrincipal(ctx context.Context) (string, error) {
|
func (c *stubAzureClient) CreateServicePrincipal(ctx context.Context) (string, error) {
|
||||||
return azurecl.ApplicationCredentials{
|
return azureshared.ApplicationCredentials{
|
||||||
ClientID: "00000000-0000-0000-0000-000000000000",
|
ClientID: "00000000-0000-0000-0000-000000000000",
|
||||||
ClientSecret: "secret",
|
ClientSecret: "secret",
|
||||||
}.ConvertToCloudServiceAccountURI(), c.createServicePrincipalErr
|
}.ToCloudServiceAccountURI(), c.createServicePrincipalErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *stubAzureClient) TerminateResourceGroup(ctx context.Context) error {
|
func (c *stubAzureClient) TerminateResourceGroup(ctx context.Context) error {
|
||||||
|
@ -3,6 +3,7 @@ package azure
|
|||||||
import (
|
import (
|
||||||
"github.com/edgelesssys/constellation/coordinator/cloudprovider/cloudtypes"
|
"github.com/edgelesssys/constellation/coordinator/cloudprovider/cloudtypes"
|
||||||
"github.com/edgelesssys/constellation/coordinator/kubernetes/k8sapi/resources"
|
"github.com/edgelesssys/constellation/coordinator/kubernetes/k8sapi/resources"
|
||||||
|
"github.com/edgelesssys/constellation/internal/azureshared"
|
||||||
k8s "k8s.io/api/core/v1"
|
k8s "k8s.io/api/core/v1"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
@ -21,7 +22,7 @@ func (a *Autoscaler) Secrets(instance cloudtypes.Instance, cloudServiceAccountUR
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return resources.Secrets{}, err
|
return resources.Secrets{}, err
|
||||||
}
|
}
|
||||||
creds, err := getApplicationCredentials(cloudServiceAccountURI)
|
creds, err := azureshared.ApplicationCredentialsFromURI(cloudServiceAccountURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resources.Secrets{}, err
|
return resources.Secrets{}, err
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/cloudprovider"
|
"github.com/edgelesssys/constellation/coordinator/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/coordinator/cloudprovider/cloudtypes"
|
"github.com/edgelesssys/constellation/coordinator/cloudprovider/cloudtypes"
|
||||||
"github.com/edgelesssys/constellation/coordinator/kubernetes/k8sapi/resources"
|
"github.com/edgelesssys/constellation/coordinator/kubernetes/k8sapi/resources"
|
||||||
|
"github.com/edgelesssys/constellation/internal/azureshared"
|
||||||
k8s "k8s.io/api/core/v1"
|
k8s "k8s.io/api/core/v1"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
@ -68,7 +69,7 @@ func (c *CloudControllerManager) Secrets(ctx context.Context, instance cloudtype
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return resources.Secrets{}, err
|
return resources.Secrets{}, err
|
||||||
}
|
}
|
||||||
creds, err := getApplicationCredentials(cloudServiceAccountURI)
|
creds, err := azureshared.ApplicationCredentialsFromURI(cloudServiceAccountURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resources.Secrets{}, err
|
return resources.Secrets{}, err
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
package azure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/azure/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// getApplicationCredentials converts a cloudServiceAccountURI into Azure ApplicationCredentials.
|
|
||||||
func getApplicationCredentials(cloudServiceAccountURI string) (client.ApplicationCredentials, error) {
|
|
||||||
uri, err := url.Parse(cloudServiceAccountURI)
|
|
||||||
if err != nil {
|
|
||||||
return client.ApplicationCredentials{}, err
|
|
||||||
}
|
|
||||||
if uri.Scheme != "serviceaccount" {
|
|
||||||
return client.ApplicationCredentials{}, fmt.Errorf("invalid service account URI: invalid scheme: %s", uri.Scheme)
|
|
||||||
}
|
|
||||||
if uri.Host != "azure" {
|
|
||||||
return client.ApplicationCredentials{}, fmt.Errorf("invalid service account URI: invalid host: %s", uri.Host)
|
|
||||||
}
|
|
||||||
query := uri.Query()
|
|
||||||
return client.ApplicationCredentials{
|
|
||||||
TenantID: query.Get("tenant_id"),
|
|
||||||
ClientID: query.Get("client_id"),
|
|
||||||
ClientSecret: query.Get("client_secret"),
|
|
||||||
Location: query.Get("location"),
|
|
||||||
}, nil
|
|
||||||
}
|
|
51
internal/azureshared/appcredentials.go
Normal file
51
internal/azureshared/appcredentials.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package azureshared
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApplicationCredentials is a set of Azure AD application credentials.
|
||||||
|
// It is the equivalent of a service account key in other cloud providers.
|
||||||
|
type ApplicationCredentials struct {
|
||||||
|
TenantID string
|
||||||
|
ClientID string
|
||||||
|
ClientSecret string
|
||||||
|
Location string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplicationCredentialsFromURI converts a cloudServiceAccountURI into Azure ApplicationCredentials.
|
||||||
|
func ApplicationCredentialsFromURI(cloudServiceAccountURI string) (ApplicationCredentials, error) {
|
||||||
|
uri, err := url.Parse(cloudServiceAccountURI)
|
||||||
|
if err != nil {
|
||||||
|
return ApplicationCredentials{}, err
|
||||||
|
}
|
||||||
|
if uri.Scheme != "serviceaccount" {
|
||||||
|
return ApplicationCredentials{}, fmt.Errorf("invalid service account URI: invalid scheme: %s", uri.Scheme)
|
||||||
|
}
|
||||||
|
if uri.Host != "azure" {
|
||||||
|
return ApplicationCredentials{}, fmt.Errorf("invalid service account URI: invalid host: %s", uri.Host)
|
||||||
|
}
|
||||||
|
query := uri.Query()
|
||||||
|
return ApplicationCredentials{
|
||||||
|
TenantID: query.Get("tenant_id"),
|
||||||
|
ClientID: query.Get("client_id"),
|
||||||
|
ClientSecret: query.Get("client_secret"),
|
||||||
|
Location: query.Get("location"),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCloudServiceAccountURI converts the ApplicationCredentials into a cloud service account URI.
|
||||||
|
func (c ApplicationCredentials) ToCloudServiceAccountURI() string {
|
||||||
|
query := url.Values{}
|
||||||
|
query.Add("tenant_id", c.TenantID)
|
||||||
|
query.Add("client_id", c.ClientID)
|
||||||
|
query.Add("client_secret", c.ClientSecret)
|
||||||
|
query.Add("location", c.Location)
|
||||||
|
uri := url.URL{
|
||||||
|
Scheme: "serviceaccount",
|
||||||
|
Host: "azure",
|
||||||
|
RawQuery: query.Encode(),
|
||||||
|
}
|
||||||
|
return uri.String()
|
||||||
|
}
|
@ -1,15 +1,15 @@
|
|||||||
package azure
|
package azureshared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/azure/client"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetApplicationCredentials(t *testing.T) {
|
func TestApplicationCredentialsFromURI(t *testing.T) {
|
||||||
creds := client.ApplicationCredentials{
|
creds := ApplicationCredentials{
|
||||||
TenantID: "tenant-id",
|
TenantID: "tenant-id",
|
||||||
ClientID: "client-id",
|
ClientID: "client-id",
|
||||||
ClientSecret: "client-secret",
|
ClientSecret: "client-secret",
|
||||||
@ -17,7 +17,7 @@ func TestGetApplicationCredentials(t *testing.T) {
|
|||||||
}
|
}
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
cloudServiceAccountURI string
|
cloudServiceAccountURI string
|
||||||
wantCreds client.ApplicationCredentials
|
wantCreds ApplicationCredentials
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"getApplicationCredentials works": {
|
"getApplicationCredentials works": {
|
||||||
@ -43,7 +43,7 @@ func TestGetApplicationCredentials(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
creds, err := getApplicationCredentials(tc.cloudServiceAccountURI)
|
creds, err := ApplicationCredentialsFromURI(tc.cloudServiceAccountURI)
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
return
|
return
|
||||||
@ -53,3 +53,27 @@ func TestGetApplicationCredentials(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToCloudServiceAccountURI(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
require := require.New(t)
|
||||||
|
key := ApplicationCredentials{
|
||||||
|
TenantID: "tenant-id",
|
||||||
|
ClientID: "client-id",
|
||||||
|
ClientSecret: "client-secret",
|
||||||
|
Location: "location",
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudServiceAccountURI := key.ToCloudServiceAccountURI()
|
||||||
|
uri, err := url.Parse(cloudServiceAccountURI)
|
||||||
|
require.NoError(err)
|
||||||
|
query := uri.Query()
|
||||||
|
assert.Equal("serviceaccount", uri.Scheme)
|
||||||
|
assert.Equal("azure", uri.Host)
|
||||||
|
assert.Equal(url.Values{
|
||||||
|
"tenant_id": []string{"tenant-id"},
|
||||||
|
"client_id": []string{"client-id"},
|
||||||
|
"client_secret": []string{"client-secret"},
|
||||||
|
"location": []string{"location"},
|
||||||
|
}, query)
|
||||||
|
}
|
10
internal/azureshared/doc.go
Normal file
10
internal/azureshared/doc.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package azureshared
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package azureshared contains code that is related to Microsoft Azure
|
||||||
|
and is used by multiple microservices.
|
||||||
|
|
||||||
|
This package is intended to have a minimal size and surface. If you
|
||||||
|
have Azure related code that is not shared by multiple microservices,
|
||||||
|
please keep the code in the microservice's internal package.
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user