Skip to content

Commit

Permalink
Feature: a new addon to support aks private cluster usecases (#458)
Browse files Browse the repository at this point in the history
* aks addon

* azurecaf version tag

* updated aks app v2

* - aks app v2 updates

* - read values from file

* name changed to uuid

* - keyvault provider

* kv object id reference

* module updates

* changes

* changes

* file name change

* added readme

* removed unused vars

* reverting aztf source ref

* reverting aztf source ref

* - namespace ref in role binding
- module dependency for role binding

* ns ref val change

* - examples

---------

Co-authored-by: Najeeb Vayal Valappil <najeeb.vayal-valappil@adesso.de>
Co-authored-by: Najeeb V V <najeebvv@outlook.com>
  • Loading branch information
3 people committed May 11, 2023
1 parent cfb12a8 commit 5b06fb9
Show file tree
Hide file tree
Showing 36 changed files with 732 additions and 0 deletions.
10 changes: 10 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/app/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
}
helm = {
source = "hashicorp/helm"
}
}
}
55 changes: 55 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/app/module.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
resource "kubernetes_namespace" "namespaces" {
for_each = var.namespaces
metadata {
annotations = try(each.value.annotations, null)
labels = try(each.value.labels, null)
name = each.value.name
}

}

resource "kubernetes_manifest" "cluster_manifest" {
for_each = var.manifests
manifest = try(yamldecode(each.value.contents), yamldecode(file("$(path.cwd)/each.value.file")), yamldecode(file("$(path.module)/each.value.file")), yamldecode(file(each.value.file)) )
}

# https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release
resource "helm_release" "charts" {
for_each = var.helm_charts

name = each.value.name
repository = each.value.repository
chart = each.value.chart

namespace = try(each.value.namespace, var.namespaces[each.value.namespace_key].name)
wait = try(each.value.wait, true)
timeout = try(each.value.timeout, 900)
skip_crds = try(each.value.skip_crds, false)
create_namespace = try(each.value.create_namespace, false)
values = try([ yamlencode(each.value.contents) ], [file("$(path.cwd)/each.value.file")], [file("$(path.module)/each.value.file")], [file(each.value.file)], [])
version = try(each.value.version, null)
atomic = try(each.value.atomic, false)
lint = try(each.value.lint, false)

dynamic "set" {
for_each = try(each.value.sets, {})
content {
name = set.key
value = set.value
}
}

dynamic "set_sensitive" {
for_each = try(each.value.sets_sensitive, {})
content {
name = set_sensitive.key
value = set_sensitive.value
}
}


# depends_on = [kubernetes_namespace.namespaces]
# values = [
# "${file("values.yaml")}"
# ]
}
Empty file.
11 changes: 11 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/app/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
variable "namespaces" {
default = {}
}

variable "helm_charts" {
default = {}
}

variable "manifests" {
default = {}
}
6 changes: 6 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/applications.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module "app" {
source = "./app"
namespaces = var.namespaces
helm_charts = var.helm_charts
manifests = var.manifests
}
4 changes: 4 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/backend.azurerm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
terraform {
backend "azurerm" {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# naming convention
resource "azurecaf_name" "cluster_role" {
name = var.settings.name
resource_type = "azurerm_role_definition"
prefixes = var.global_settings.prefixes
random_length = var.global_settings.random_length
clean_input = true
passthrough = var.global_settings.passthrough
use_slug = var.global_settings.use_slug
}

resource "kubernetes_cluster_role_v1" "cluster_role" {
metadata {
annotations = try(var.settings.annotations, null)
labels = try(var.settings.labels, null)
name = azurecaf_name.cluster_role.result
}
dynamic "rule" {
for_each = try(var.settings.rule, {})
content {
api_groups = try(rule.value.api_groups, null)
non_resource_urls = try(rule.value.non_resource_urls, null)
resource_names = try(rule.value.resource_names, null)
resources = try(rule.value.resources, null)
verbs = try(rule.value.verbs, null)
}
}

dynamic "aggregation_rule" {
for_each = try(var.settings.aggregation_rule, {})
content {
cluster_role_selectors {
dynamic "match_expressions" {
for_each = try(aggregation_rule.value.match_expressions, {})
content {
key = try(match_expressions.value.key, null)
operator = try(match_expressions.value.operator, null)
values = try(match_expressions.value.values, [])
}
}
match_labels = try(aggregation_rule.match_labels, {})
}
}
}
}
10 changes: 10 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/cluster_role/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
}
azurecaf = {
source = "aztfmod/azurecaf"
}
}
}
Empty file.
16 changes: 16 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/cluster_role/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
variable "global_settings" {
default = {}
}
variable "role" {
default = {}
}
variable "settings" {}
variable "azuread_service_principals" {
default = {}
}
variable "azuread_groups" {
default = {}
}
variable "managed_identities" {
default = {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
resource "azurecaf_name" "cluster_role_binding" {
name = var.settings.name
resource_type = "azurerm_role_assignment"
prefixes = var.global_settings.prefixes
random_length = var.global_settings.random_length
clean_input = true
passthrough = var.global_settings.passthrough
use_slug = var.global_settings.use_slug
}

resource "kubernetes_cluster_role_binding_v1" "cluster_role_binding" {
metadata {
annotations = try(var.settings.annotations, null)
labels = try(var.settings.labels, null)
name = azurecaf_name.cluster_role_binding.result
}
role_ref {
name = try(var.cluster_role[var.settings.role_key].name, var.settings.role_name)
kind = "ClusterRole"
api_group = "rbac.authorization.k8s.io"
}
dynamic "subject" {
for_each = try(var.settings.subjects, {})
content {
name = coalesce(try(subject.value.name, null), try(var.managed_identities[subject.value.lz_key][subject.value.object_key].rbac_id, null), try(var.azuread_service_principals[subject.value.lz_key][subject.value.object_key].rbac_id, null), try(var.azuread_groups[subject.value.lz_key][subject.value.object_key].rbac_id, null))
kind = can(subject.value.kind) ? subject.value.kind : can(try(var.managed_identities[subject.value.lz_key][subject.value.object_key].rbac_id, null)) ? "User" : can(try(var.azuread_service_principals[subject.value.lz_key][subject.value.object_key].rbac_id, null)) ? "User" : can(try(var.azuread_groups[subject.value.lz_key][subject.value.object_key].rbac_id, null)) ? "Group" : null
api_group = "rbac.authorization.k8s.io"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
}
azurecaf = {
source = "aztfmod/azurecaf"
}
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
variable "global_settings" {
default = {}
}
variable "cluster_role" {
default = {}
}
variable "cluster_role_binding" {
default = {}
}
variable "azuread_service_principals" {
default = {}
}
variable "azuread_groups" {
default = {}
}
variable "managed_identities" {
default = {}
}
variable "settings" {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Helm chart definition
helm_charts = {
falco = {
name = "falco"
create_namespace = false
namespace = "falco-system"
repository = "https://falcosecurity.github.io/charts"
chart = "falco"
version = "3.1.3"
}
}

# namespace creation
namespaces = {
falco = {
name = "falco-system"
}
}

# Keyvault integration for csi driver
kv_csi_driver = {
workload_kv_reader = {
aks_clusters = {
lz_key = "aks"
key = "aks_cluster1"
}
keyvault = {
key = "aks_kv"
lz_key = "aks"
}
role_definition_name = "Key Vault Reader"
}
}

# kubernetes manifest. More than one in a single file is not supported. separate it with multiple files
manifests = {
agentconfig = {
file = "add-ons/aks_applications_v2/examples/files/denyall.yml"
}
}

# Cluster to authenticate
aks_clusters = {
lz_key = "aks"
key = "cluster_re1"
}

# Keyvault to fetch secrets from in order to authenticate with kubernetes provider. a SP credentials must exists
# and shall have cluster admin role to perform necessary operations
keyvaults = {
key = "aks_kv"
lz_key = "aks"
secret_prefix = "aks"
}

# Kubernetes rbac
cluster_role_binding = {
cluster_admin = {
name = "aks-admin-sp"
role_name = "cluster-admin"
subjects = {
aks_admin_sp = {
# lz key where service principal is created
lz_key = "aks"
# SP key
object_key = "aks_admin_sp"
}
}
}
}
role_binding = {
ns_admin = {
name = "aks-ns-admin-sp"
namespace_key = "default"
role_name = "admin"
subjects = {
demouser = {
# user object id
name = "e74a2ee6-433c-46b3-b10f-9abac25b1ba8"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: default
labels:
app.kubernetes.io/managed-by: caf-manifest
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.99"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "azurerm_role_assignment" "for" {
principal_id = var.secret_identity_id
role_definition_name = var.settings.role_definition_name
scope = try(var.settings.keyvault.keyvault_id, var.keyvaults[var.settings.keyvault.lz_key][var.settings.keyvault.key].id)
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
variable "global_settings" {
default = {}
}
variable "keyvaults" {
default = {}
}
variable "aks_clusters" {
default = {}
}
variable "settings" {}
variable "secret_identity_id" {}
8 changes: 8 additions & 0 deletions caf_solution/add-ons/aks_applications_v2/keyvault-csi.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module "keyvault-csi-driver" {
for_each = var.kv_csi_driver
source = "./keyvault-csi-driver"
global_settings = local.global_settings
settings = each.value
secret_identity_id = local.secret_identity_id
keyvaults = local.remote.keyvaults
}
Loading

0 comments on commit 5b06fb9

Please sign in to comment.