Skip to content

Commit

Permalink
fix: Enhance WI module usability with existing KSA (#557)
Browse files Browse the repository at this point in the history
  • Loading branch information
bharathkkb committed Jun 23, 2020
1 parent 0bcf3ca commit cf3273d
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 10 deletions.
23 changes: 23 additions & 0 deletions examples/workload_identity/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module "gke" {
]
}

# example without existing KSA
module "workload_identity" {
source = "../../modules/workload-identity"
project_id = var.project_id
Expand All @@ -61,5 +62,27 @@ module "workload_identity" {
use_existing_k8s_sa = false
}


# example with existing KSA
resource "kubernetes_service_account" "test" {
metadata {
name = "foo-ksa"
}
secret {
name = "bar"
}
}

module "workload_identity_existing_ksa" {
source = "../../modules/workload-identity"
project_id = var.project_id
name = "existing-${module.gke.name}"
cluster_name = module.gke.name
location = module.gke.location
namespace = "default"
use_existing_k8s_sa = true
k8s_sa_name = kubernetes_service_account.test.metadata.0.name
}

data "google_client_config" "default" {
}
5 changes: 2 additions & 3 deletions modules/workload-identity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ resource "kubernetes_service_account" "preexisting" {
metadata {
name = "preexisting-sa"
namespace = "prod"
annotations = {
"iam.gke.io/gcp-service-account" = "preexisting-sa@${var.project_id}.iam.gserviceaccount.com"
}
}
}
Expand All @@ -71,7 +68,9 @@ module "my-app-workload-identity" {

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| cluster\_name | Cluster name. Required if using existing KSA. | string | `""` | no |
| k8s\_sa\_name | Name for the existing Kubernetes service account | string | `"null"` | no |
| location | Cluster location (region if regional cluster, zone if zonal cluster). Required if using existing KSA. | string | `""` | no |
| name | Name for both service accounts | string | n/a | yes |
| namespace | Namespace for k8s service account | string | `"default"` | no |
| project\_id | GCP project ID | string | n/a | yes |
Expand Down
28 changes: 21 additions & 7 deletions modules/workload-identity/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,23 @@ locals {
gcp_sa_email = google_service_account.cluster_service_account.email

# This will cause terraform to block returning outputs until the service account is created
k8s_given_name = var.k8s_sa_name != null ? var.k8s_sa_name : var.name
output_k8s_name = var.use_existing_k8s_sa ? local.k8s_given_name : kubernetes_service_account.main[0].metadata[0].name
output_k8s_namespace = var.use_existing_k8s_sa ? var.namespace : kubernetes_service_account.main[0].metadata[0].namespace
k8s_given_name = var.k8s_sa_name != null ? var.k8s_sa_name : var.name
output_k8s_name = var.use_existing_k8s_sa ? local.k8s_given_name : kubernetes_service_account.main[0].metadata[0].name
output_k8s_namespace = var.use_existing_k8s_sa ? var.namespace : kubernetes_service_account.main[0].metadata[0].namespace
token = var.use_existing_k8s_sa ? data.google_client_config.default.0.access_token : ""
cluster_ca_certificate = var.use_existing_k8s_sa ? data.google_container_cluster.primary.0.master_auth.0.cluster_ca_certificate : ""
cluster_endpoint = var.use_existing_k8s_sa ? "https://${data.google_container_cluster.primary.0.endpoint}" : ""
}

data "google_container_cluster" "primary" {
count = var.use_existing_k8s_sa ? 1 : 0
name = var.cluster_name
project = var.project_id
location = var.location
}

data "google_client_config" "default" {
count = var.use_existing_k8s_sa ? 1 : 0
}

resource "google_service_account" "cluster_service_account" {
Expand Down Expand Up @@ -51,11 +65,11 @@ module "annotate-sa" {
enabled = var.use_existing_k8s_sa
skip_download = true

create_cmd_entrypoint = "kubectl"
create_cmd_body = "annotate sa -n ${local.output_k8s_namespace} ${local.k8s_given_name} iam.gke.io/gcp-service-account=${local.gcp_sa_email}"
create_cmd_entrypoint = "${path.module}/scripts/kubectl_wrapper.sh"
create_cmd_body = "${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl annotate --overwrite sa -n ${local.output_k8s_namespace} ${local.k8s_given_name} iam.gke.io/gcp-service-account=${local.gcp_sa_email}"

destroy_cmd_entrypoint = "kubectl"
destroy_cmd_body = "annotate sa -n ${local.output_k8s_namespace} ${local.k8s_given_name} iam.gke.io/gcp-service-account-"
destroy_cmd_entrypoint = "${path.module}/scripts/kubectl_wrapper.sh"
destroy_cmd_body = "${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl annotate sa -n ${local.output_k8s_namespace} ${local.k8s_given_name} iam.gke.io/gcp-service-account-"
}

resource "google_service_account_iam_member" "main" {
Expand Down
53 changes: 53 additions & 0 deletions modules/workload-identity/scripts/kubectl_wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash
# Copyright 2018 Google LLC
#
# 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.


set -e

if [ "$#" -lt 3 ]; then
>&2 echo "Not all expected arguments set."
exit 1
fi

HOST=$1
TOKEN=$2
CA_CERTIFICATE=$3

shift 3

RANDOM_ID="${RANDOM}_${RANDOM}"
export TMPDIR="/tmp/kubectl_wrapper_${RANDOM_ID}"

function cleanup {
rm -rf "${TMPDIR}"
}
trap cleanup EXIT

mkdir "${TMPDIR}"

export KUBECONFIG="${TMPDIR}/config"

# shellcheck disable=SC1117
base64 --help | grep "\--decode" && B64_ARG="--decode" || B64_ARG="-d"
echo "${CA_CERTIFICATE}" | base64 ${B64_ARG} > "${TMPDIR}/ca_certificate"

kubectl config set-cluster kubectl-wrapper --server="${HOST}" --certificate-authority="${TMPDIR}/ca_certificate" --embed-certs=true 1>/dev/null
rm -f "${TMPDIR}/ca_certificate"
kubectl config set-context kubectl-wrapper --cluster=kubectl-wrapper --user=kubectl-wrapper --namespace=default 1>/dev/null
kubectl config set-credentials kubectl-wrapper --token="${TOKEN}" 1>/dev/null
kubectl config use-context kubectl-wrapper 1>/dev/null
kubectl version 1>/dev/null

"$@"
12 changes: 12 additions & 0 deletions modules/workload-identity/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ variable "name" {
type = string
}

variable "cluster_name" {
description = "Cluster name. Required if using existing KSA."
type = string
default = ""
}

variable "location" {
description = "Cluster location (region if regional cluster, zone if zonal cluster). Required if using existing KSA."
type = string
default = ""
}

variable "k8s_sa_name" {
description = "Name for the existing Kubernetes service account"
type = string
Expand Down

0 comments on commit cf3273d

Please sign in to comment.