Skip to content

Commit

Permalink
Adding support for AzureAD auth to AKS via RBAC (#1820)
Browse files Browse the repository at this point in the history
* Adding support for AzureAD auth to AKS via RBAC

* formatting

* formatting

* Adding documentation updates

* Fixing issues with aadProfile server_app_secret always causing a new cluster

* Refactoring code to avoid repetition in some areas. Documentation updates.

* minor updates to testing section of main documentation index

* docs: client_id -> client_app_id

* fixing one more misnamed var in the docs

* AKS: switching RBAC to be an independent block

* Rewriting the documentation to be clearer (ala VM's)

* AKS: refactoring

* AKS: adding additional context to the errors

* updating a todo

* Data Source: refactoring

* Data Source: continued re-ordering/removing the existing structure

* d/AKS: adding the `role_based_access_control` block

* AKS: support for up to 100 agents

* Updating the versions of kubernetes being used

* Documentation: moving the AKS Examples into their own folder

* removing the older aks examples

* Updating to include the changes from #2286

* re-ordering/updating the errors

* removing the unused env variables

* fixing the linting

* fixing broken tests

* fixes from code review
  • Loading branch information
timcurless authored and tombuildsstuff committed Nov 15, 2018
1 parent 7c1fab7 commit 89a15ed
Show file tree
Hide file tree
Showing 26 changed files with 1,618 additions and 1,146 deletions.
471 changes: 283 additions & 188 deletions azurerm/data_source_kubernetes_cluster.go

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions azurerm/data_source_kubernetes_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func TestAccDataSourceAzureRMKubernetesCluster_basic(t *testing.T) {
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKubernetesClusterExists(dataSourceName),
resource.TestCheckResourceAttr(dataSourceName, "role_based_access_control.#", "0"),
resource.TestCheckResourceAttrSet(dataSourceName, "kube_config.0.client_key"),
resource.TestCheckResourceAttrSet(dataSourceName, "kube_config.0.client_certificate"),
resource.TestCheckResourceAttrSet(dataSourceName, "kube_config.0.cluster_ca_certificate"),
Expand All @@ -38,6 +39,34 @@ func TestAccDataSourceAzureRMKubernetesCluster_basic(t *testing.T) {
})
}

func TestAccDataSourceAzureRMKubernetesCluster_roleBasedAccessControl(t *testing.T) {
dataSourceName := "data.azurerm_kubernetes_cluster.test"
ri := acctest.RandInt()
clientId := os.Getenv("ARM_CLIENT_ID")
clientSecret := os.Getenv("ARM_CLIENT_SECRET")
tenantId := os.Getenv("ARM_TENANT_ID")
location := testLocation()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMKubernetesClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAzureRMKubernetesCluster_roleBasedAccessControl(ri, location, clientId, clientSecret, tenantId),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKubernetesClusterExists(dataSourceName),
resource.TestCheckResourceAttr(dataSourceName, "role_based_access_control.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "role_based_access_control.0.azure_active_directory.#", "1"),
resource.TestCheckResourceAttrSet(dataSourceName, "role_based_access_control.0.azure_active_directory.0.client_app_id"),
resource.TestCheckResourceAttrSet(dataSourceName, "role_based_access_control.0.azure_active_directory.0.server_app_id"),
resource.TestCheckResourceAttrSet(dataSourceName, "role_based_access_control.0.azure_active_directory.0.tenant_id"),
),
},
},
})
}

func TestAccDataSourceAzureRMKubernetesCluster_internalNetwork(t *testing.T) {
dataSourceName := "data.azurerm_kubernetes_cluster.test"
ri := acctest.RandInt()
Expand Down Expand Up @@ -244,6 +273,18 @@ data "azurerm_kubernetes_cluster" "test" {
`, r)
}

func testAccDataSourceAzureRMKubernetesCluster_roleBasedAccessControl(rInt int, location, clientId, clientSecret, tenantId string) string {
resource := testAccAzureRMKubernetesCluster_roleBasedAccessControl(rInt, location, clientId, clientSecret, tenantId)
return fmt.Sprintf(`
%s
data "azurerm_kubernetes_cluster" "test" {
name = "${azurerm_kubernetes_cluster.test.name}"
resource_group_name = "${azurerm_kubernetes_cluster.test.resource_group_name}"
}
`, resource)
}

func testAccDataSourceAzureRMKubernetesCluster_internalNetwork(rInt int, clientId string, clientSecret string, location string) string {
r := testAccAzureRMKubernetesCluster_internalNetwork(rInt, clientId, clientSecret, location)
return fmt.Sprintf(`
Expand Down
54 changes: 52 additions & 2 deletions azurerm/helpers/kubernetes/kube_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ type user struct {
ClientKeyData string `yaml:"client-key-data"`
}

type userItemAAD struct {
Name string `yaml:"name"`
User userAAD `yaml:"user"`
}

type userAAD struct {
AuthProvider authProvider `yaml:"auth-provider"`
}

type authProvider struct {
Name string `yaml:"name"`
Config configAzureAD `yaml:"config"`
}

type configAzureAD struct {
APIServerID string `yaml:"apiserver-id,omitempty"`
ClientID string `yaml:"client-id,omitempty"`
TenantID string `yaml:"tenant-id,omitempty"`
}

type contextItem struct {
Name string `yaml:"name"`
Context context `yaml:"context"`
Expand All @@ -38,16 +58,25 @@ type context struct {
Namespace string `yaml:"namespace,omitempty"`
}

type KubeConfig struct {
type KubeConfigBase struct {
APIVersion string `yaml:"apiVersion"`
Clusters []clusterItem `yaml:"clusters"`
Users []userItem `yaml:"users"`
Contexts []contextItem `yaml:"contexts,omitempty"`
CurrentContext string `yaml:"current-context,omitempty"`
Kind string `yaml:"kind,omitempty"`
Preferences map[string]interface{} `yaml:"preferences,omitempty"`
}

type KubeConfig struct {
KubeConfigBase `yaml:",inline"`
Users []userItem `yaml:"users"`
}

type KubeConfigAAD struct {
KubeConfigBase `yaml:",inline"`
Users []userItemAAD `yaml:"users"`
}

func ParseKubeConfig(config string) (*KubeConfig, error) {
if config == "" {
return nil, fmt.Errorf("Cannot parse empty config")
Expand All @@ -72,3 +101,24 @@ func ParseKubeConfig(config string) (*KubeConfig, error) {

return &kubeConfig, nil
}

func ParseKubeConfigAAD(config string) (*KubeConfigAAD, error) {
if config == "" {
return nil, fmt.Errorf("Cannot parse empty config")
}

var kubeConfig KubeConfigAAD
if err := yaml.Unmarshal([]byte(config), &kubeConfig); err != nil {
return nil, fmt.Errorf("Failed to unmarshal YAML config with error %+v", err)
}
if len(kubeConfig.Clusters) <= 0 || len(kubeConfig.Users) <= 0 {
return nil, fmt.Errorf("Config %+v contains no valid clusters or users", kubeConfig)
}

c := kubeConfig.Clusters[0].Cluster
if c.Server == "" {
return nil, fmt.Errorf("Config has invalid or non existent server for cluster %+v", c)
}

return &kubeConfig, nil
}
104 changes: 55 additions & 49 deletions azurerm/helpers/kubernetes/kube_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ func TestParseKubeConfig(t *testing.T) {
{
"user_with_token.yml",
KubeConfig{
APIVersion: "v1",
Clusters: []clusterItem{
{
Name: "test-cluster",
Cluster: cluster{
Server: "https://testcluster.net:8080",
KubeConfigBase: KubeConfigBase{
APIVersion: "v1",
Clusters: []clusterItem{
{
Name: "test-cluster",
Cluster: cluster{
Server: "https://testcluster.net:8080",
},
},
},
Kind: "Config",
},
Users: []userItem{
{
Expand All @@ -34,22 +37,36 @@ func TestParseKubeConfig(t *testing.T) {
},
},
},
Kind: "Config",
},
isValidConfig,
},
{
"user_with_cert.yml",
KubeConfig{
APIVersion: "v1",
Clusters: []clusterItem{
{
Name: "test-cluster",
Cluster: cluster{
ClusterAuthorityData: "test-cluster-authority-data",
Server: "https://testcluster.org:443",
KubeConfigBase: KubeConfigBase{
APIVersion: "v1",
Clusters: []clusterItem{
{
Name: "test-cluster",
Cluster: cluster{
ClusterAuthorityData: "test-cluster-authority-data",
Server: "https://testcluster.org:443",
},
},
},
Contexts: []contextItem{
{
Name: "test-cluster",
Context: context{
Cluster: "test-cluster",
User: "test-user",
Namespace: "test-namespace",
},
},
},
CurrentContext: "test-cluster",
Kind: "Config",
Preferences: nil,
},
Users: []userItem{
{
Expand All @@ -60,34 +77,38 @@ func TestParseKubeConfig(t *testing.T) {
},
},
},
Contexts: []contextItem{
{
Name: "test-cluster",
Context: context{
Cluster: "test-cluster",
User: "test-user",
Namespace: "test-namespace",
},
},
},
CurrentContext: "test-cluster",
Kind: "Config",
Preferences: nil,
},
isValidConfig,
},
{
"user_with_cert_token.yml",
KubeConfig{
APIVersion: "v1",
Clusters: []clusterItem{
{
Name: "test-cluster",
Cluster: cluster{
ClusterAuthorityData: "test-cluster-authority-data",
Server: "https://testcluster.org:443",
KubeConfigBase: KubeConfigBase{
APIVersion: "v1",
Clusters: []clusterItem{
{
Name: "test-cluster",
Cluster: cluster{
ClusterAuthorityData: "test-cluster-authority-data",
Server: "https://testcluster.org:443",
},
},
},
Contexts: []contextItem{
{
Name: "test-cluster",
Context: context{
Cluster: "test-cluster",
User: "test-user",
Namespace: "test-namespace",
},
},
},
CurrentContext: "test-cluster",
Kind: "Config",
Preferences: map[string]interface{}{
"colors": true,
},
},
Users: []userItem{
{
Expand All @@ -99,21 +120,6 @@ func TestParseKubeConfig(t *testing.T) {
},
},
},
Contexts: []contextItem{
{
Name: "test-cluster",
Context: context{
Cluster: "test-cluster",
User: "test-user",
Namespace: "test-namespace",
},
},
},
CurrentContext: "test-cluster",
Kind: "Config",
Preferences: map[string]interface{}{
"colors": true,
},
},
isValidConfig,
},
Expand Down
Loading

0 comments on commit 89a15ed

Please sign in to comment.