Skip to content

Commit 82da85d

Browse files
feat: use operator
1 parent 727d51a commit 82da85d

18 files changed

+382
-39
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,10 @@ Once you are finished with the reference architecture, you can remove all provis
221221
| github | ~> 5.38 |
222222
| helm | ~> 2.12 |
223223
| humanitec | ~> 1.0 |
224+
| kubectl | ~> 2.0 |
224225
| kubernetes | ~> 2.25 |
225226
| random | ~> 3.5 |
227+
| tls | ~> 4.0 |
226228

227229
### Providers
228230

@@ -254,7 +256,7 @@ Once you are finished with the reference architecture, you can remove all provis
254256
| aws\_region | AWS region | `string` | n/a | yes |
255257
| disk\_size | Disk size in GB to use for EKS nodes | `number` | `20` | no |
256258
| github\_org\_id | GitHub org id (required for Backstage) | `string` | `null` | no |
257-
| humanitec\_org\_id | Humanitec Organization ID (required for Backstage) | `string` | `null` | no |
259+
| humanitec\_org\_id | Humanitec Organization ID | `string` | `null` | no |
258260
| instance\_types | List of EC2 instances types to use for EKS nodes | `list(string)` | <pre>[<br> "t3.large"<br>]</pre> | no |
259261
| with\_backstage | Deploy Backstage | `bool` | `false` | no |
260262
<!-- END_TF_DOCS -->

main.tf

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
module "base" {
44
source = "./modules/base"
55

6-
region = var.aws_region
7-
instance_types = var.instance_types
8-
disk_size = var.disk_size
6+
humanitec_org_id = var.humanitec_org_id
7+
aws_account_id = var.aws_account_id
8+
aws_region = var.aws_region
9+
instance_types = var.instance_types
10+
disk_size = var.disk_size
911
}
1012

1113
# User used for scaffolding and deploying apps
@@ -62,6 +64,7 @@ module "portal_backstage" {
6264

6365
humanitec_org_id = var.humanitec_org_id
6466
humanitec_ci_service_user_token = humanitec_service_user_token.deployer[0].token
67+
humanitec_secret_store_id = module.base.humanitec_secret_store_id
6568

6669
github_org_id = var.github_org_id
6770
github_app_client_id = module.github_app[0].client_id

modules/base/README.md

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,25 @@ Module that provides the reference architecture.
1010
| Name | Version |
1111
|------|---------|
1212
| terraform | >= 1.3.0 |
13-
| aws | >= 4.50 |
13+
| aws | ~> 5.17 |
1414
| helm | ~> 2.12 |
1515
| humanitec | ~> 1.0 |
16-
| kubernetes | >= 2.0.3 |
16+
| kubectl | ~> 2.0 |
17+
| kubernetes | ~> 2.0 |
1718
| random | ~> 3.5 |
19+
| tls | ~> 4.0 |
1820

1921
### Providers
2022

2123
| Name | Version |
2224
|------|---------|
23-
| aws | >= 4.50 |
25+
| aws | ~> 5.17 |
2426
| helm | ~> 2.12 |
2527
| humanitec | ~> 1.0 |
26-
| kubernetes | >= 2.0.3 |
28+
| kubectl | ~> 2.0 |
29+
| kubernetes | ~> 2.0 |
2730
| random | ~> 3.5 |
31+
| tls | ~> 4.0 |
2832

2933
### Modules
3034

@@ -40,18 +44,37 @@ Module that provides the reference architecture.
4044

4145
| Name | Type |
4246
|------|------|
47+
| [aws_eks_pod_identity_association.humanitec_operator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
48+
| [aws_iam_policy.humanitec_operator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
49+
| [aws_iam_role.humanitec_operator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
4350
| [aws_iam_role.humanitec_svc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
51+
| [aws_iam_role_policy_attachment.humanitec_operator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
4452
| [aws_iam_role_policy_attachment.humanitec_svc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
53+
| [helm_release.humanitec_agent](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
54+
| [helm_release.humanitec_operator](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
4555
| [helm_release.ingress_nginx](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
56+
| [humanitec_agent.agent](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/agent) | resource |
57+
| [humanitec_key.operator_public_key](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/key) | resource |
4658
| [humanitec_resource_account.cluster_account](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_account) | resource |
59+
| [humanitec_resource_definition.agent](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource |
4760
| [humanitec_resource_definition.k8s_cluster_driver](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource |
4861
| [humanitec_resource_definition.k8s_namespace](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource |
62+
| [humanitec_resource_definition_criteria.agent](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
4963
| [humanitec_resource_definition_criteria.default_mysql](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
5064
| [humanitec_resource_definition_criteria.default_postgres](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
5165
| [humanitec_resource_definition_criteria.k8s_cluster_driver](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
5266
| [humanitec_resource_definition_criteria.k8s_namespace](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
67+
| [humanitec_secretstore.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/secretstore) | resource |
68+
| [kubectl_manifest.humanitec_operator_secret_store](https://registry.terraform.io/providers/alekc/kubectl/latest/docs/resources/manifest) | resource |
69+
| [kubernetes_namespace.agent-namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
70+
| [kubernetes_namespace.humanitec_operator](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
71+
| [kubernetes_secret.humanitec_operator](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
5372
| [random_password.external_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
73+
| [tls_private_key.agent_private_key](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource |
74+
| [tls_private_key.operator_private_key](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource |
5475
| [aws_elb_hosted_zone_id.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/elb_hosted_zone_id) | data source |
76+
| [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
77+
| [aws_iam_policy_document.humanitec_operator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
5578
| [aws_iam_policy_document.instance_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
5679
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
5780
| [kubernetes_service.ingress_nginx_controller](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/data-sources/service) | data source |
@@ -60,7 +83,10 @@ Module that provides the reference architecture.
6083

6184
| Name | Description | Type | Default | Required |
6285
|------|-------------|------|---------|:--------:|
86+
| aws\_account\_id | AWS Account (ID) to use | `string` | n/a | yes |
87+
| humanitec\_org\_id | Humanitec Organization ID | `string` | n/a | yes |
6388
| additional\_k8s\_access\_entries | Additional access entries add to the k8s aws-auth configmap | <pre>list(object({<br> id = string<br> principal_arn = string<br> groups = list(string)<br> }))</pre> | `[]` | no |
89+
| aws\_region | AWS Region to deploy into | `string` | `"us-east-1"` | no |
6490
| capacity\_type | Defines whether to use ON\_DEMAND or SPOT EC2 instances for EKS nodes | `string` | `"ON_DEMAND"` | no |
6591
| cluster\_name | Name for the EKS cluster | `string` | `"ref-arch"` | no |
6692
| cluster\_version | Version of the EKS cluster to deploy | `string` | `null` | no |
@@ -74,7 +100,6 @@ Module that provides the reference architecture.
74100
| node\_group\_desired\_size | Desired number of nodes for the EKS node group | `number` | `3` | no |
75101
| node\_group\_max\_size | Maximum number of nodes for the EKS node group | `number` | `3` | no |
76102
| node\_group\_min\_size | Minimum number of nodes for the EKS node group | `number` | `2` | no |
77-
| region | AWS Region to deploy into | `string` | `"us-east-1"` | no |
78103
| vpc\_name | AWS VPC name | `string` | `"ref-arch"` | no |
79104

80105
### Outputs
@@ -88,6 +113,7 @@ Module that provides the reference architecture.
88113
| eks\_oidc\_provider\_arn | The ARN of the OIDC Provider |
89114
| environment | Name of the environment to be deployed into |
90115
| humanitec\_resource\_account\_id | Humanitec resource account id for the cluster |
116+
| humanitec\_secret\_store\_id | Humanitec secret store id |
91117
| ingress\_nginx\_external\_dns | External DNS entry for the Nginx ingress controller |
92118
| vpc\_id | VPC id |
93119
<!-- END_TF_DOCS -->

modules/base/humanitec-agent.tf

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Installs the humanitec-agent into the cluster
2+
3+
# More details https://developer.humanitec.com/integration-and-extensions/humanitec-agent/overview/
4+
5+
resource "kubernetes_namespace" "agent-namespace" {
6+
metadata {
7+
labels = {
8+
"app.kubernetes.io/name" = "humanitec-operator"
9+
"app.kubernetes.io/instance" = "humanitec-operator"
10+
}
11+
12+
name = "humanitec-agent"
13+
}
14+
}
15+
16+
resource "tls_private_key" "agent_private_key" {
17+
algorithm = "RSA"
18+
rsa_bits = 4096
19+
}
20+
21+
locals {
22+
agent_id = "${local.res_def_prefix}agent"
23+
}
24+
25+
resource "humanitec_agent" "agent" {
26+
id = local.agent_id
27+
description = "reference-architecture-aws"
28+
public_keys = [{
29+
key = tls_private_key.agent_private_key.public_key_pem
30+
}]
31+
}
32+
33+
resource "helm_release" "humanitec_agent" {
34+
name = "humanitec-agent"
35+
namespace = kubernetes_namespace.agent-namespace.id
36+
37+
repository = "oci://ghcr.io/humanitec/charts"
38+
chart = "humanitec-agent"
39+
version = "1.1.0"
40+
wait = true
41+
timeout = 300
42+
43+
set {
44+
name = "humanitec.org"
45+
value = var.humanitec_org_id
46+
}
47+
48+
set {
49+
name = "humanitec.privateKey"
50+
value = tls_private_key.agent_private_key.private_key_pem
51+
}
52+
53+
depends_on = [
54+
humanitec_agent.agent
55+
]
56+
}
57+
58+
resource "humanitec_resource_definition" "agent" {
59+
id = local.agent_id
60+
name = local.agent_id
61+
type = "agent"
62+
63+
driver_type = "humanitec/agent"
64+
driver_inputs = {
65+
values_string = jsonencode({
66+
id = local.agent_id
67+
})
68+
}
69+
70+
depends_on = [
71+
helm_release.humanitec_agent
72+
]
73+
}
74+
75+
resource "humanitec_resource_definition_criteria" "agent" {
76+
resource_definition_id = humanitec_resource_definition.agent.id
77+
res_id = "agent"
78+
env_type = var.environment
79+
80+
force_delete = true
81+
}

modules/base/humanitec-operator.tf

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Installs the humanitec-operator into the cluster
2+
3+
# More details https://developer.humanitec.com/integration-and-extensions/humanitec-operator/overview/
4+
5+
resource "kubernetes_namespace" "humanitec_operator" {
6+
metadata {
7+
labels = {
8+
"app.kubernetes.io/name" = "humanitec-operator"
9+
"app.kubernetes.io/instance" = "humanitec-operator"
10+
}
11+
12+
name = "humanitec-operator"
13+
}
14+
}
15+
16+
17+
resource "tls_private_key" "operator_private_key" {
18+
algorithm = "RSA"
19+
rsa_bits = 4096
20+
}
21+
22+
resource "humanitec_key" "operator_public_key" {
23+
key = tls_private_key.operator_private_key.public_key_pem
24+
}
25+
26+
resource "kubernetes_secret" "humanitec_operator" {
27+
metadata {
28+
name = "humanitec-operator-private-key"
29+
namespace = kubernetes_namespace.humanitec_operator.id
30+
}
31+
32+
data = {
33+
privateKey = tls_private_key.operator_private_key.private_key_pem
34+
humanitecOrganisationID = var.humanitec_org_id
35+
}
36+
}
37+
38+
resource "helm_release" "humanitec_operator" {
39+
name = "humanitec-operator"
40+
namespace = kubernetes_namespace.humanitec_operator.id
41+
42+
repository = "oci://ghcr.io/humanitec/charts"
43+
chart = "humanitec-operator"
44+
version = "0.2.4"
45+
wait = true
46+
timeout = 300
47+
48+
depends_on = [
49+
humanitec_key.operator_public_key,
50+
kubernetes_secret.humanitec_operator
51+
]
52+
}
53+
54+
# Configure the operator to be able to store secrets
55+
56+
locals {
57+
humanitec_operator_k8s_sa_name = "humanitec-operator-controller-manager"
58+
}
59+
60+
data "aws_iam_policy_document" "assume_role_policy" {
61+
version = "2012-10-17"
62+
63+
statement {
64+
actions = ["sts:AssumeRole", "sts:TagSession"]
65+
66+
principals {
67+
type = "Service"
68+
identifiers = ["pods.eks.amazonaws.com"]
69+
}
70+
}
71+
}
72+
73+
resource "aws_iam_role" "humanitec_operator" {
74+
name = "humanitec-operator"
75+
description = "Humanitec Operator EKS service account"
76+
assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
77+
}
78+
79+
resource "aws_eks_pod_identity_association" "humanitec_operator" {
80+
cluster_name = module.aws_eks.cluster_name
81+
namespace = kubernetes_namespace.humanitec_operator.id
82+
service_account = local.humanitec_operator_k8s_sa_name
83+
role_arn = aws_iam_role.humanitec_operator.arn
84+
}
85+
86+
data "aws_iam_policy_document" "humanitec_operator" {
87+
version = "2012-10-17"
88+
89+
statement {
90+
actions = [
91+
"secretsmanager:GetSecretValue",
92+
"secretsmanager:CreateSecret",
93+
"secretsmanager:DeleteSecret",
94+
"secretsmanager:PutSecretValue"
95+
]
96+
97+
resources = ["arn:aws:secretsmanager:${var.aws_region}:${var.aws_account_id}:secret:*"]
98+
}
99+
}
100+
101+
resource "aws_iam_policy" "humanitec_operator" {
102+
name = "humanitec-operator"
103+
description = "Humanitec Operator EKS service account policy"
104+
policy = data.aws_iam_policy_document.humanitec_operator.json
105+
}
106+
107+
resource "aws_iam_role_policy_attachment" "humanitec_operator" {
108+
role = aws_iam_role.humanitec_operator.name
109+
policy_arn = aws_iam_policy.humanitec_operator.arn
110+
}
111+
112+
113+
# Configure a primary secret store
114+
115+
locals {
116+
humanitec_secret_store_id = var.cluster_name
117+
}
118+
119+
resource "kubectl_manifest" "humanitec_operator_secret_store" {
120+
yaml_body = templatefile("${path.module}/manifests/humanitec-secret-store.yaml", {
121+
SECRET_STORE_ID = local.humanitec_secret_store_id,
122+
SECRETS_MANAGER_REGION = var.aws_region
123+
})
124+
override_namespace = kubernetes_namespace.humanitec_operator.id
125+
wait = true
126+
127+
depends_on = [
128+
helm_release.humanitec_operator
129+
]
130+
}
131+
132+
resource "humanitec_secretstore" "main" {
133+
id = local.humanitec_secret_store_id
134+
primary = true
135+
awssm = {
136+
region = var.aws_region
137+
}
138+
}

modules/base/humanitec.tf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ resource "humanitec_resource_definition" "k8s_cluster_driver" {
3535

3636
driver_account = humanitec_resource_account.cluster_account.id
3737
driver_inputs = {
38+
secrets_string = jsonencode({
39+
"agent_url" = "$${resources['agent#agent'].outputs.url}"
40+
})
3841
values_string = jsonencode({
3942
"name" = module.aws_eks.cluster_name
4043
"loadbalancer" = local.ingress_address
4144
"loadbalancer_hosted_zone" = data.aws_elb_hosted_zone_id.main.id
42-
"region" = var.region
45+
"region" = var.aws_region
4346
})
4447
}
4548
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: humanitec.io/v1alpha1
2+
kind: SecretStore
3+
metadata:
4+
name: ${SECRET_STORE_ID}
5+
namespace: humanitec-operator
6+
labels:
7+
app.humanitec.io/default-store: "true"
8+
spec:
9+
awssm:
10+
region: ${SECRETS_MANAGER_REGION}
11+
auth: {}

modules/base/outputs.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,8 @@ output "humanitec_resource_account_id" {
5353
description = "Humanitec resource account id for the cluster"
5454
value = humanitec_resource_account.cluster_account.id
5555
}
56+
57+
output "humanitec_secret_store_id" {
58+
description = "Humanitec secret store id"
59+
value = humanitec_secretstore.main.id
60+
}

0 commit comments

Comments
 (0)