Skip to content

Commit

Permalink
adding cluster principal and credentails prvider
Browse files Browse the repository at this point in the history
  • Loading branch information
nader-ziada committed Oct 7, 2020
1 parent 27f33d5 commit 045fad3
Show file tree
Hide file tree
Showing 27 changed files with 1,082 additions and 18 deletions.
1 change: 1 addition & 0 deletions api/v1alpha2/azurecluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (src *AzureCluster) ConvertTo(dstRaw conversion.Hub) error { // nolint

dst.Status.FailureDomains = restored.Status.FailureDomains
dst.Spec.NetworkSpec.Vnet.CIDRBlocks = restored.Spec.NetworkSpec.Vnet.CIDRBlocks
dst.Spec.PrincipalRef = restored.Spec.PrincipalRef

for _, restoredSubnet := range restored.Spec.NetworkSpec.Subnets {
if restoredSubnet != nil {
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions api/v1alpha3/azurecluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ const (
ClusterFinalizer = "azurecluster.infrastructure.cluster.x-k8s.io"
)

// AzurePrincipalKind defines allowed Azure cluster principal types
// +kubebuilder:validation:Enum=AzureSystemAssigned;AzureUserAssigned;AzureServicePrincipal
type AzurePrincipalKind string

// AzurePrincipalRef is a reference to a principal
type AzurePrincipalRef struct {
Kind AzurePrincipalKind `json:"kind"`
Name string `json:"name"`
Namespace string `json:"namespace"`
}

// AzureClusterSpec defines the desired state of AzureCluster
type AzureClusterSpec struct {
// NetworkSpec encapsulates all things related to Azure network.
Expand All @@ -48,6 +59,10 @@ type AzureClusterSpec struct {
// ones added by default.
// +optional
AdditionalTags Tags `json:"additionalTags,omitempty"`

// PrincipalRef is a reference to a principal to be used when reconciling this cluster
// +optional
PrincipalRef *AzurePrincipalRef `json:"principalRef,omitempty"`
}

// AzureClusterStatus defines the observed state of AzureCluster
Expand Down
72 changes: 72 additions & 0 deletions api/v1alpha3/azureserviceprincipal_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha3

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=azureclusterprincipals,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion

// AzureClusterPrincipal represents a reference to an Azure access key ID and
// secret access key, stored in a secret.
type AzureClusterPrincipal struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// Spec for this AzureClusterPrincipalSpec.
Spec AzureClusterPrincipalSpec `json:"spec,omitempty"`
}

// +kubebuilder:object:root=true

// AzureClusterPrincipalList contains a list of AzureClusterPrincipal
type AzureClusterPrincipalList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AzureClusterPrincipal `json:"items"`
}

// AzureClusterPrincipalSpec defines the fileds of the Azure cluster principal
type AzureClusterPrincipalSpec struct {
Name string `json:"name"`
// Reference to a secret containing the credentials. The secret should
// contain the following data keys:
// tenantID
// clientID
// clientSecret
SecretRef corev1.SecretReference `json:"secretRef"`
// AllowedNamespaces is a selector of namespaces that AzureClusters can
// use this ClusterPrincipal from. This is a standard Kubernetes LabelSelector,
// a label query over a set of resources. The result of matchLabels and
// matchExpressions are ANDed. Controllers must not support AzureClusters in
// namespaces outside this selector.
//
// An empty selector (default) indicates that AzureClusters can use this
// AzureClusterPrincipal from any namespace. This field is intentionally not a
// pointer because the nil behavior (no namespaces) is undesirable here.
//
// +optional
AllowedNamespaces metav1.LabelSelector `json:"allowedNamespaces"`
}

func init() {
SchemeBuilder.Register(&AzureClusterPrincipal{}, &AzureClusterPrincipalList{})
}
95 changes: 95 additions & 0 deletions api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions cloud/scope/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package scope

import (
"context"
"fmt"
"strings"

Expand Down Expand Up @@ -82,3 +83,32 @@ func (c *AzureClients) setCredentials(subscriptionID string) error {
c.Authorizer, err = c.GetAuthorizer()
return err
}

func (c *AzureClients) setCredentialsWithProvider(ctx context.Context, subscriptionID string, credentialsProvider *AzureCredentialsProvider) error {
if credentialsProvider == nil {
return fmt.Errorf("Credentials provider cannot have an empty value")
}

settings, err := auth.GetSettingsFromEnvironment()
if err != nil {
return err
}

if subscriptionID == "" {
subscriptionID = settings.GetSubscriptionID()
if subscriptionID == "" {
return fmt.Errorf("error creating azure services. subscriptionID is not set in cluster or AZURE_SUBSCRIPTION_ID env var")
}
}

c.EnvironmentSettings = settings
c.ResourceManagerEndpoint = settings.Environment.ResourceManagerEndpoint
c.ResourceManagerVMDNSSuffix = settings.Environment.ResourceManagerVMDNSSuffix
c.Values[auth.ClientID] = strings.TrimSuffix(c.Values[auth.ClientID], "\n")
c.Values[auth.ClientSecret] = strings.TrimSuffix(c.Values[auth.ClientSecret], "\n")
c.Values[auth.SubscriptionID] = strings.TrimSuffix(subscriptionID, "\n")
c.Values[auth.TenantID] = strings.TrimSuffix(c.Values[auth.TenantID], "\n")

c.Authorizer, err = credentialsProvider.GetAuthorizer(ctx)
return err
}
23 changes: 17 additions & 6 deletions cloud/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ package scope
import (
"context"
"fmt"
"k8s.io/utils/net"
"strconv"

"github.com/Azure/go-autorest/autorest/to"
"k8s.io/utils/net"

"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
"github.com/go-logr/logr"
"github.com/pkg/errors"
"k8s.io/klog/klogr"
Expand All @@ -46,7 +46,7 @@ type ClusterScopeParams struct {

// NewClusterScope creates a new Scope from the supplied parameters.
// This is meant to be called for each reconcile iteration.
func NewClusterScope(params ClusterScopeParams) (*ClusterScope, error) {
func NewClusterScope(ctx context.Context, params ClusterScopeParams) (*ClusterScope, error) {
if params.Cluster == nil {
return nil, errors.New("failed to generate new scope from nil Cluster")
}
Expand All @@ -58,9 +58,20 @@ func NewClusterScope(params ClusterScopeParams) (*ClusterScope, error) {
params.Logger = klogr.New()
}

err := params.AzureClients.setCredentials(params.AzureCluster.Spec.SubscriptionID)
if err != nil {
return nil, errors.Wrap(err, "failed to configure azure settings and credentials from environment")
if params.AzureCluster.Spec.PrincipalRef == nil {
err := params.AzureClients.setCredentials(params.AzureCluster.Spec.SubscriptionID)
if err != nil {
return nil, errors.Wrap(err, "failed to configure azure settings and credentials from environment")
}
} else {
credentailsProvider, err := NewAzureCredentialsProvider(ctx, params.Client, params.ResourceManagerEndpoint, params.AzureCluster.Spec.PrincipalRef)
if err != nil {
return nil, errors.Wrap(err, "failed to init credentials provider")
}
err = params.AzureClients.setCredentialsWithProvider(ctx, params.AzureCluster.Spec.SubscriptionID, credentailsProvider)
if err != nil {
return nil, errors.Wrap(err, "failed to configure azure settings and credentials from environment")
}
}

helper, err := patch.NewHelper(params.AzureCluster, params.Client)
Expand Down
Loading

0 comments on commit 045fad3

Please sign in to comment.