Skip to content

Commit

Permalink
azure.GetAuthInfo no longer returns credentials secret data
Browse files Browse the repository at this point in the history
- If we are using an authentication scheme other than client secret
  returning a map of credentials secret data is no longer possible.
  Thus, we need a change in the function signature.
- azure.GetAuthInfo now returns subscription ID, which is used
  by the downstream ARM resource SDK clients.

Signed-off-by: Alper Rifat Ulucinar <[email protected]>
  • Loading branch information
ulucinar committed Apr 19, 2022
1 parent 817e2c7 commit 08ba574
Show file tree
Hide file tree
Showing 20 changed files with 95 additions and 71 deletions.
11 changes: 10 additions & 1 deletion apis/v1beta1/providerconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ type ProviderConfigSpec struct {
// when Credentials.Source is `InjectedIdentity`. If unset and
// Credentials.Source is `InjectedIdentity`, then a system-assigned
// managed identity is used.
// +optional
// +kubebuilder:validation:Optional
ClientID *string `json:"clientID,omitempty"`
// ARMEndpoint is the Azure Resource Manager endpoint to use.
// Defaults to ARM public cloud endpoint.
// +kubebuilder:validation:Optional
ARMEndpoint *string `json:"armEndpoint,omitempty"`
// SubscriptionID is the Azure subscription ID to be used.
// If unset, subscription ID from Credentials will be used.
// Required if Credentials.Source is not Secret.
// +kubebuilder:validation:Optional
SubscriptionID *string `json:"subscriptionID,omitempty"`
}

// ProviderCredentials required to authenticate.
Expand Down
79 changes: 47 additions & 32 deletions pkg/clients/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ const (
errGetProvider = "cannot get referenced Provider"
errNeitherPCNorPGiven = "neither providerConfigRef nor providerRef was supplied"
errUnmarshalCredentialSecret = "cannot unmarshal the data in credentials secret"
errClientCredentials = "cannot get credentials"
errClientSecretAuth = "failed to initialize Azure identity client secret credential"
errDefaultAuth = "failed to initialize Azure identity default credential"
errFetchAccessToken = "failed to get Azure identity access token"
errSubscriptionIDNotSet = "subscription ID must be set in ProviderConfig when credential source is not Secret"
)

// A FieldOption determines how common Go types are translated to the types
Expand Down Expand Up @@ -98,68 +100,84 @@ const (

// GetAuthInfo figures out how to connect to Azure API and returns the necessary
// information to be used for controllers to construct their specific clients.
func GetAuthInfo(ctx context.Context, c client.Client, mg resource.Managed) (content map[string]string, authorizer autorest.Authorizer, err error) {
func GetAuthInfo(ctx context.Context, c client.Client, mg resource.Managed) (string, autorest.Authorizer, error) {
switch {
case mg.GetProviderConfigReference() != nil:
return UseProviderConfig(ctx, c, mg)
case mg.GetProviderReference() != nil:
return UseProvider(ctx, c, mg)
default:
return nil, nil, errors.New(errNeitherPCNorPGiven)
return "", nil, errors.New(errNeitherPCNorPGiven)
}
}

// UseProvider to return the necessary information to construct an Azure client.
// Deprecated: Use UseProviderConfig
func UseProvider(ctx context.Context, c client.Client, mg resource.Managed) (map[string]string, autorest.Authorizer, error) {
func UseProvider(ctx context.Context, c client.Client, mg resource.Managed) (string, autorest.Authorizer, error) {
p := &v1alpha3.Provider{}
if err := c.Get(ctx, types.NamespacedName{Name: mg.GetProviderReference().Name}, p); err != nil {
return nil, nil, errors.Wrap(err, errGetProvider)
return "", nil, errors.Wrap(err, errGetProvider)
}

ref := p.Spec.CredentialsSecretRef
s := &corev1.Secret{}
if err := c.Get(ctx, types.NamespacedName{Name: ref.Name, Namespace: ref.Namespace}, s); err != nil {
return nil, nil, err
return "", nil, err
}
m := map[string]string{}
if err := json.Unmarshal(s.Data[ref.Key], &m); err != nil {
return nil, nil, errors.Wrap(err, errUnmarshalCredentialSecret)
return "", nil, errors.Wrap(err, errUnmarshalCredentialSecret)
}
a, err := clientSecretAuth(ctx, m)
return m, a, err
return m[CredentialsKeySubscriptionID], a, err
}

// UseProviderConfig to return the necessary information to construct an Azure
// client.
func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed) (map[string]string, autorest.Authorizer, error) {
func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed) (string, autorest.Authorizer, error) {
pc := &v1beta1.ProviderConfig{}
t := resource.NewProviderConfigUsageTracker(c, &v1beta1.ProviderConfigUsage{})
if err := t.Track(ctx, mg); err != nil {
return nil, nil, errors.Wrap(err, errTrackProviderConfigUsage)
return "", nil, errors.Wrap(err, errTrackProviderConfigUsage)
}
if err := c.Get(ctx, types.NamespacedName{Name: mg.GetProviderConfigReference().Name}, pc); err != nil {
return nil, nil, errors.Wrap(err, errGetProviderConfig)
return "", nil, errors.Wrap(err, errGetProviderConfig)
}

data, err := resource.CommonCredentialExtractor(ctx, pc.Spec.Credentials.Source, c, pc.Spec.Credentials.CommonCredentialSelectors)
if err != nil {
return nil, nil, errors.Wrap(err, "cannot get credentials")
}
m := map[string]string{}
if err := json.Unmarshal(data, &m); err != nil {
return nil, nil, errors.Wrap(err, errUnmarshalCredentialSecret)
}
var authorizer autorest.Authorizer
var err error
subscriptionID := ""
switch pc.Spec.Credentials.Source {
case xpv1.CredentialsSourceSecret:
m, err := getCredentialsMap(ctx, pc, c)
if err != nil {
return "", nil, err
}
subscriptionID = m[CredentialsKeySubscriptionID]
authorizer, err = clientSecretAuth(ctx, m)
case xpv1.CredentialsSourceInjectedIdentity:
authorizer, err = managedIdentityAuth(ctx, m, pc.Spec.ClientID)
if pc.Spec.SubscriptionID == nil || len(*pc.Spec.SubscriptionID) == 0 {
return "", nil, errors.New(errSubscriptionIDNotSet)
}
subscriptionID = *pc.Spec.SubscriptionID
authorizer, err = managedIdentityAuth(ctx, pc.Spec.ClientID, pc.Spec.ARMEndpoint)
default:
authorizer, err = defaultAuth(ctx, m)
if pc.Spec.SubscriptionID == nil || len(*pc.Spec.SubscriptionID) == 0 {
return "", nil, errors.New(errSubscriptionIDNotSet)
}
subscriptionID = *pc.Spec.SubscriptionID
authorizer, err = defaultAuth(ctx)
}
return m, authorizer, err
return subscriptionID, authorizer, err
}

func getCredentialsMap(ctx context.Context, pc *v1beta1.ProviderConfig, c client.Client) (map[string]string, error) {
data, err := resource.CommonCredentialExtractor(ctx, pc.Spec.Credentials.Source, c, pc.Spec.Credentials.CommonCredentialSelectors)
if err != nil {
return nil, errors.Wrap(err, errClientCredentials)
}
m := map[string]string{}
return m, errors.Wrap(json.Unmarshal(data, &m), errUnmarshalCredentialSecret)
}

func clientSecretAuth(ctx context.Context, m map[string]string) (autorest.Authorizer, error) {
Expand All @@ -170,10 +188,10 @@ func clientSecretAuth(ctx context.Context, m map[string]string) (autorest.Author
if err != nil {
return nil, errors.Wrap(err, errClientSecretAuth)
}
return fetchAccessToken(ctx, cred, m)
return fetchAccessToken(ctx, cred, m[CredentialsKeyResourceManagerEndpointURL])
}

func managedIdentityAuth(ctx context.Context, m map[string]string, clientID *string) (autorest.Authorizer, error) {
func managedIdentityAuth(ctx context.Context, clientID, armEndpoint *string) (autorest.Authorizer, error) {
var opts *azidentity.ManagedIdentityCredentialOptions
// if user-assigned managed identity
if clientID != nil && len(*clientID) != 0 {
Expand All @@ -185,23 +203,20 @@ func managedIdentityAuth(ctx context.Context, m map[string]string, clientID *str
if err != nil {
return nil, errors.Wrap(err, errClientSecretAuth)
}
return fetchAccessToken(ctx, cred, m)
return fetchAccessToken(ctx, cred, to.String(armEndpoint))
}

func defaultAuth(ctx context.Context, m map[string]string) (autorest.Authorizer, error) {
cred, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{
AuthorityHost: azidentity.AuthorityHost(m[CredentialsKeyActiveDirectoryEndpointURL]),
TenantID: m[CredentialsKeyTenantID],
})
func defaultAuth(ctx context.Context) (autorest.Authorizer, error) {
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
return nil, errors.Wrap(err, errDefaultAuth)
}
return fetchAccessToken(ctx, cred, m)
return fetchAccessToken(ctx, cred, "")
}

func fetchAccessToken(ctx context.Context, cred azcore.TokenCredential, m map[string]string) (autorest.Authorizer, error) {
func fetchAccessToken(ctx context.Context, cred azcore.TokenCredential, armEndpoint string) (autorest.Authorizer, error) {
token, err := cred.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string{endpointToScope(m[CredentialsKeyResourceManagerEndpointURL])},
Scopes: []string{endpointToScope(armEndpoint)},
})
if err != nil {
return nil, errors.Wrap(err, errFetchAccessToken)
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/cache/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ type connector struct {
}

func (c connector) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.kube, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.kube, mg)
if err != nil {
return nil, errors.Wrap(err, errConnectFailed)
}
cl := redis.NewClient(creds[azure.CredentialsKeySubscriptionID])
cl := redis.NewClient(subscriptionID)
cl.Authorizer = auth
return &external{kube: c.kube, client: cl}, nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/compute/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl, err := compute.NewAggregateClient(creds, auth)
cl, err := compute.NewAggregateClient(subscriptionID, auth)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/database/cosmosdb/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.kube, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.kube, mg)
if err != nil {
return nil, err
}
cl := documentdb.NewDatabaseAccountsClient(creds[azure.CredentialsKeySubscriptionID])
cl := documentdb.NewDatabaseAccountsClient(subscriptionID)
cl.Authorizer = auth
return &external{kube: c.kube, client: cl}, nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/database/mysqlserver/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := mysql.NewServersClient(creds[azure.CredentialsKeySubscriptionID])
cl := mysql.NewServersClient(subscriptionID)
cl.Authorizer = auth
return &external{kube: c.client, client: database.NewMySQLServerClient(cl), newPasswordFn: password.Generate}, nil
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/controller/database/mysqlserverconfiguration/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := mysql.NewConfigurationsClient(creds[azure.CredentialsKeySubscriptionID])
cl := mysql.NewConfigurationsClient(subscriptionID)
cl.Authorizer = auth
return &external{
kube: c.client,
client: configuration.NewMySQLConfigurationClient(cl),
subscriptionID: creds[azure.CredentialsKeySubscriptionID],
subscriptionID: subscriptionID,
}, nil
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/database/mysqlserverfirewallrule/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := mysql.NewFirewallRulesClient(creds[azure.CredentialsKeySubscriptionID])
cl := mysql.NewFirewallRulesClient(subscriptionID)
cl.Authorizer = auth
return &external{client: cl}, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}

cl := mysql.NewVirtualNetworkRulesClient(creds[azure.CredentialsKeySubscriptionID])
cl := mysql.NewVirtualNetworkRulesClient(subscriptionID)
cl.Authorizer = auth
return &external{client: cl}, nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/database/postgresqlserver/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := postgresql.NewServersClient(creds[azure.CredentialsKeySubscriptionID])
cl := postgresql.NewServersClient(subscriptionID)
cl.Authorizer = auth
return &external{kube: c.client, client: database.NewPostgreSQLServerClient(cl), newPasswordFn: password.Generate}, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := postgresql.NewConfigurationsClient(creds[azure.CredentialsKeySubscriptionID])
cl := postgresql.NewConfigurationsClient(subscriptionID)
cl.Authorizer = auth
return &external{
kube: c.client,
client: configuration.NewPostgreSQLConfigurationClient(cl),
subscriptionID: creds[azure.CredentialsKeySubscriptionID],
subscriptionID: subscriptionID,
}, nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := postgresql.NewFirewallRulesClient(creds[azure.CredentialsKeySubscriptionID])
cl := postgresql.NewFirewallRulesClient(subscriptionID)
cl.Authorizer = auth
return &external{client: cl}, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azure.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}

cl := postgresql.NewVirtualNetworkRulesClient(creds[azure.CredentialsKeySubscriptionID])
cl := postgresql.NewVirtualNetworkRulesClient(subscriptionID)
cl.Authorizer = auth
return &external{client: cl}, nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/dns/recordset/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := dns.NewRecordSetsClient(creds[azureclients.CredentialsKeySubscriptionID])
cl := dns.NewRecordSetsClient(subscriptionID)
cl.Authorizer = auth
return &external{
client: dnsclients.NewRecordSetClient(cl),
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/dns/zone/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := dnsapi.NewZonesClient(creds[azureclients.CredentialsKeySubscriptionID])
cl := dnsapi.NewZonesClient(subscriptionID)
cl.Authorizer = auth
return &external{
client: dns.NewZoneClient(cl),
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/network/publicipaddress/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ type connecter struct {
}

func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
creds, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg)
subscriptionID, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg)
if err != nil {
return nil, err
}
cl := azurenetwork.NewPublicIPAddressesClient(creds[azureclients.CredentialsKeySubscriptionID])
cl := azurenetwork.NewPublicIPAddressesClient(subscriptionID)
cl.Authorizer = auth
return &external{kube: c.client, client: cl}, nil
}
Expand Down
Loading

0 comments on commit 08ba574

Please sign in to comment.