Skip to content

Commit

Permalink
Add support for GKE metadata concealment (hashicorp#1199)
Browse files Browse the repository at this point in the history
* add support for gke metadata concealment

* docs for metadata concealment
  • Loading branch information
danawillow authored and Ashish Amarnath committed Mar 20, 2018
1 parent 7a874b9 commit eaba29d
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 14 deletions.
57 changes: 46 additions & 11 deletions google/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,23 @@ var schemaNodeConfig = &schema.Schema{
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"workload_metadata_config": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"node_metadata": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED", "SECURE", "EXPOSE"}, false),
},
},
},
},
},
},
}
Expand Down Expand Up @@ -223,6 +240,13 @@ func expandNodeConfig(v interface{}) *containerBeta.NodeConfig {
nc.MinCpuPlatform = v.(string)
}

if v, ok := nodeConfig["workload_metadata_config"]; ok {
conf := v.([]interface{})[0].(map[string]interface{})
nc.WorkloadMetadataConfig = &containerBeta.WorkloadMetadataConfig{
NodeMetadata: conf["node_metadata"].(string),
}
}

return nc
}

Expand All @@ -234,17 +258,18 @@ func flattenNodeConfig(c *containerBeta.NodeConfig) []map[string]interface{} {
}

config = append(config, map[string]interface{}{
"machine_type": c.MachineType,
"disk_size_gb": c.DiskSizeGb,
"guest_accelerator": c.Accelerators,
"local_ssd_count": c.LocalSsdCount,
"service_account": c.ServiceAccount,
"metadata": c.Metadata,
"image_type": c.ImageType,
"labels": c.Labels,
"tags": c.Tags,
"preemptible": c.Preemptible,
"min_cpu_platform": c.MinCpuPlatform,
"machine_type": c.MachineType,
"disk_size_gb": c.DiskSizeGb,
"guest_accelerator": c.Accelerators,
"local_ssd_count": c.LocalSsdCount,
"service_account": c.ServiceAccount,
"metadata": c.Metadata,
"image_type": c.ImageType,
"labels": c.Labels,
"tags": c.Tags,
"preemptible": c.Preemptible,
"min_cpu_platform": c.MinCpuPlatform,
"workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig),
})

if len(c.OauthScopes) > 0 {
Expand All @@ -253,3 +278,13 @@ func flattenNodeConfig(c *containerBeta.NodeConfig) []map[string]interface{} {

return config
}

func flattenWorkloadMetadataConfig(c *containerBeta.WorkloadMetadataConfig) []map[string]interface{} {
result := []map[string]interface{}{}
if c != nil {
result = append(result, map[string]interface{}{
"node_metadata": c.NodeMetadata,
})
}
return result
}
9 changes: 7 additions & 2 deletions google/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import (
var (
instanceGroupManagerURL = regexp.MustCompile("^https://www.googleapis.com/compute/v1/projects/([a-z][a-z0-9-]{5}(?:[-a-z0-9]{0,23}[a-z0-9])?)/zones/([a-z0-9-]*)/instanceGroupManagers/([^/]*)")
ContainerClusterBaseApiVersion = v1
ContainerClusterVersionedFeatures = []Feature{Feature{Version: v1beta1, Item: "pod_security_policy_config"}}
ContainerClusterVersionedFeatures = []Feature{
{Version: v1beta1, Item: "pod_security_policy_config"},
{Version: v1beta1, Item: "node_config.*.workload_metadata_config"},
}

networkConfig = &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -738,7 +741,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
d.Set("monitoring_service", cluster.MonitoringService)
d.Set("network", cluster.Network)
d.Set("subnetwork", cluster.Subnetwork)
d.Set("node_config", flattenNodeConfig(cluster.NodeConfig))
if err := d.Set("node_config", flattenNodeConfig(cluster.NodeConfig)); err != nil {
return err
}
d.Set("zone", zoneName)
d.Set("project", project)
if cluster.AddonsConfig != nil {
Expand Down
48 changes: 48 additions & 0 deletions google/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,27 @@ func TestAccContainerCluster_withNodeConfigScopeAlias(t *testing.T) {
})
}

func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withWorkloadMetadataConfig(),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerCluster(
"google_container_cluster.with_workload_metadata_config"),
resource.TestCheckResourceAttr("google_container_cluster.with_workload_metadata_config",
"node_config.0.workload_metadata_config.0.node_metadata", "SECURE"),
),
},
},
})
}

func TestAccContainerCluster_network(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1325,6 +1346,33 @@ resource "google_container_cluster" "with_node_config_scope_alias" {
}`, acctest.RandString(10))
}

func testAccContainerCluster_withWorkloadMetadataConfig() string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
zone = "us-central1-a"
}
resource "google_container_cluster" "with_workload_metadata_config" {
name = "cluster-test-%s"
zone = "us-central1-a"
initial_node_count = 1
min_master_version = "${data.google_container_engine_versions.central1a.latest_master_version}"
node_version = "${data.google_container_engine_versions.central1a.latest_node_version}"
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
workload_metadata_config {
node_metadata = "SECURE"
}
}
}
`, acctest.RandString(10))
}

func testAccContainerCluster_networkRef() string {
return fmt.Sprintf(`
resource "google_compute_network" "container_network" {
Expand Down
4 changes: 3 additions & 1 deletion google/resource_container_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import (

var (
ContainerNodePoolBaseApiVersion = v1
ContainerNodePoolVersionedFeatures = []Feature{}
ContainerNodePoolVersionedFeatures = []Feature{
{Version: v1beta1, Item: "node_config.*.workload_metadata_config"},
}
)

func resourceContainerNodePool() *schema.Resource {
Expand Down
52 changes: 52 additions & 0 deletions google/resource_container_node_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,26 @@ func TestAccContainerNodePool_withNodeConfig(t *testing.T) {
})
}

func TestAccContainerNodePool_withWorkloadMetadataConfig(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerNodePool_withWorkloadMetadataConfig(),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerNodePoolMatches("google_container_node_pool.with_workload_metadata_config"),
resource.TestCheckResourceAttr("google_container_node_pool.with_workload_metadata_config",
"node_config.0.workload_metadata_config.0.node_metadata", "SECURE"),
),
},
},
})
}

func TestAccContainerNodePool_withGPU(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -617,6 +637,38 @@ resource "google_container_node_pool" "np_with_node_config" {
}`, acctest.RandString(10), acctest.RandString(10))
}

func testAccContainerNodePool_withWorkloadMetadataConfig() string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
zone = "us-central1-a"
}
resource "google_container_cluster" "cluster" {
name = "tf-cluster-nodepool-test-%s"
zone = "us-central1-a"
initial_node_count = 1
min_master_version = "${data.google_container_engine_versions.central1a.latest_master_version}"
}
resource "google_container_node_pool" "with_workload_metadata_config" {
name = "tf-nodepool-test-%s"
zone = "us-central1-a"
cluster = "${google_container_cluster.cluster.name}"
initial_node_count = 1
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
workload_metadata_config {
node_metadata = "SECURE"
}
}
}
`, acctest.RandString(10), acctest.RandString(10))
}

func testAccContainerNodePool_withGPU() string {
return fmt.Sprintf(`
resource "google_container_cluster" "cluster" {
Expand Down
11 changes: 11 additions & 0 deletions website/docs/r/container_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ The `node_config` block supports:
* `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify
valid sources or targets for network firewalls.

* `workload_metadata_config` - (Optional) Metadata configuration to expose to workloads on the node pool.
Structure is documented below.

The `guest_accelerator` block supports:

* `type` (Required) - The accelerator type resource to expose to this instance. E.g. `nvidia-tesla-k80`.
Expand All @@ -301,6 +304,14 @@ The `pod_security_policy_config` block supports:
* `enabled` (Required) - Enable the PodSecurityPolicy controller for this cluster.
If enabled, pods must be valid under a PodSecurityPolicy to be created.

The `workload_metadata_config` block supports:

* `node_metadata` (Required) How to expose the node metadata to the workload running on the node.
Accepted values are:
* UNSPECIFIED: Not Set
* SECURE: Prevent workloads not in hostNetwork from accessing certain VM metadata, specifically kube-env, which contains Kubelet credentials, and the instance identity token. See [Metadata Concealment](https://cloud.google.com/kubernetes-engine/docs/how-to/metadata-proxy) documentation.
* EXPOSE: Expose all VM metadata to pods.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are
Expand Down

0 comments on commit eaba29d

Please sign in to comment.