Skip to content

Commit fb65659

Browse files
authored
feat: add sub-module to enable kube-audit in base-ocp clusters (#619)
1 parent fe1a2c5 commit fb65659

File tree

22 files changed

+791
-0
lines changed

22 files changed

+791
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Optionally, the module supports advanced security group management for the worke
2626
* [terraform-ibm-base-ocp-vpc](#terraform-ibm-base-ocp-vpc)
2727
* [Submodules](./modules)
2828
* [fscloud](./modules/fscloud)
29+
* [kube-audit](./modules/kube-audit)
2930
* [Examples](./examples)
3031
* [2 MZR clusters in same VPC example](./examples/multiple_mzr_clusters)
3132
* [Advanced example (mzr, auto-scale, kms, taints)](./examples/advanced)

examples/advanced/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ The following resources are provisioned by this example:
1010
- A multi-zone (3 zone) KMS encrypted OCP VPC cluster, with worker pools in each zone.
1111
- Auto scaling enabled for the default worker pool.
1212
- Taints against the workers in zone-2 and zone-3.
13+
- Enable Kubernetes API server audit logs.
14+
- A Cloud logs instance
15+
- Logs agent to send logs to the cloud logs.

examples/advanced/main.tf

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,85 @@ data "ibm_container_cluster_config" "cluster_config" {
184184
resource_group_id = module.ocp_base.resource_group_id
185185
config_dir = "${path.module}/../../kubeconfig"
186186
}
187+
188+
########################################################################################################################
189+
# Kube Audit
190+
########################################################################################################################
191+
192+
module "kube_audit" {
193+
depends_on = [module.ocp_base] # Wait for the cluster to completely deploy.
194+
source = "../../modules/kube-audit"
195+
cluster_id = module.ocp_base.cluster_id
196+
cluster_resource_group_id = module.resource_group.resource_group_id
197+
audit_log_policy = "WriteRequestBodies"
198+
region = var.region
199+
ibmcloud_api_key = var.ibmcloud_api_key
200+
}
201+
202+
203+
########################################################################################################################
204+
# Observability (Instance + Agents)
205+
########################################################################################################################
206+
207+
locals {
208+
logs_agent_namespace = "ibm-observe"
209+
logs_agent_name = "logs-agent"
210+
}
211+
212+
module "observability_instances" {
213+
source = "terraform-ibm-modules/observability-instances/ibm"
214+
version = "3.4.3"
215+
resource_group_id = module.resource_group.resource_group_id
216+
region = var.region
217+
cloud_logs_plan = "standard"
218+
cloud_monitoring_plan = "graduated-tier"
219+
enable_platform_metrics = false
220+
cloud_logs_instance_name = "${var.prefix}-cloud-logs"
221+
cloud_monitoring_provision = false
222+
}
223+
224+
module "trusted_profile" {
225+
source = "terraform-ibm-modules/trusted-profile/ibm"
226+
version = "2.0.1"
227+
trusted_profile_name = "${var.prefix}-profile"
228+
trusted_profile_description = "Logs agent Trusted Profile"
229+
# As a `Sender`, you can send logs to your IBM Cloud Logs service instance - but not query or tail logs. This role is meant to be used by agents and routers sending logs.
230+
trusted_profile_policies = [{
231+
roles = ["Sender"]
232+
resources = [{
233+
service = "logs"
234+
}]
235+
}]
236+
# Set up fine-grained authorization for `logs-agent` running in ROKS cluster in `ibm-observe` namespace.
237+
trusted_profile_links = [{
238+
cr_type = "ROKS_SA"
239+
links = [{
240+
crn = module.ocp_base.cluster_crn
241+
namespace = local.logs_agent_namespace
242+
name = local.logs_agent_name
243+
}]
244+
}
245+
]
246+
}
247+
248+
module "observability_agents" {
249+
depends_on = [module.kube_audit]
250+
source = "terraform-ibm-modules/observability-agents/ibm"
251+
version = "2.6.0"
252+
cluster_id = module.ocp_base.cluster_id
253+
cluster_resource_group_id = module.resource_group.resource_group_id
254+
# Cloud Logs agent
255+
logs_agent_trusted_profile = module.trusted_profile.trusted_profile.id
256+
logs_agent_namespace = local.logs_agent_namespace
257+
logs_agent_name = local.logs_agent_name
258+
cloud_logs_ingress_endpoint = module.observability_instances.cloud_logs_ingress_private_endpoint
259+
cloud_logs_ingress_port = 3443
260+
# example of how to add additional metadata to the logs agents
261+
logs_agent_additional_metadata = [{
262+
key = "cluster_id"
263+
value = module.ocp_base.cluster_id
264+
}]
265+
# example of how to add only kube-audit log source path
266+
logs_agent_selected_log_source_paths = ["/var/log/audit/*.log"]
267+
cloud_monitoring_enabled = false
268+
}

examples/advanced/provider.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,17 @@ provider "kubernetes" {
1212
token = data.ibm_container_cluster_config.cluster_config.token
1313
cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config.ca_certificate
1414
}
15+
16+
provider "helm" {
17+
kubernetes {
18+
host = data.ibm_container_cluster_config.cluster_config.host
19+
token = data.ibm_container_cluster_config.cluster_config.token
20+
cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config.ca_certificate
21+
}
22+
# IBM Cloud credentials are required to authenticate to the helm repo
23+
registry {
24+
url = "oci://icr.io/ibm/observe/logs-agent-helm"
25+
username = "iamapikey"
26+
password = var.ibmcloud_api_key
27+
}
28+
}

examples/advanced/version.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,9 @@ terraform {
1212
source = "hashicorp/kubernetes"
1313
version = ">= 2.16.1"
1414
}
15+
helm = {
16+
source = "hashicorp/helm"
17+
version = ">= 2.15.0"
18+
}
1519
}
1620
}

modules/kube-audit/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Kubernetes API server audit logs
2+
3+
To monitor user-initiated, Kubernetes administrative activity made within your cluster, you can collect and forward audit events that are passed through your Kubernetes API server to IBM Cloud Logs or an external server.
4+
5+
This sub-module helps you to create a Kubernetes audit system by using the provided image and deployment in your existing cluster. [Learn more](https://cloud.ibm.com/docs/openshift?topic=openshift-health-audit)
6+
7+
**Important**: The sub-module uses the `icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs` image to forward logs to IBM Cloud Logs. This image is for demonstration purposes only. For a production solution, configure and maintain your own log forwarding image.
8+
9+
### Usage
10+
11+
```hcl
12+
# ############################################################################
13+
# Init cluster config for helm
14+
# ############################################################################
15+
16+
data "ibm_container_cluster_config" "cluster_config" {
17+
# update this value with the Id of the cluster where these agents will be provisioned
18+
cluster_name_id = "cluster_id"
19+
}
20+
21+
# ############################################################################
22+
# Config providers
23+
# ############################################################################
24+
25+
provider "ibm" {
26+
# update this value with your IBM Cloud API key value
27+
ibmcloud_api_key = "XXXXXXXXXXXXXXXXX" #pragma: allowlist secret
28+
}
29+
30+
provider "helm" {
31+
kubernetes {
32+
host = data.ibm_container_cluster_config.cluster_config.host
33+
token = data.ibm_container_cluster_config.cluster_config.token
34+
cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config.ca_certificate
35+
}
36+
}
37+
38+
provider "kubernetes" {
39+
host = data.ibm_container_cluster_config.cluster_config.host
40+
token = data.ibm_container_cluster_config.cluster_config.token
41+
cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config.ca_certificate
42+
}
43+
44+
module "kube_audit" {
45+
source = "terraform-ibm-modules/terraform-ibm-base-ocp-vpc/ibm//modules/kube-audit"
46+
version = "X.X.X" # Replace "X.X.X" with a release version to lock into a specific release
47+
cluster_id = "cluster_id"
48+
cluster_resource_group_id = "resource group id"
49+
region = "us-south"
50+
}
51+
```
52+
53+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
54+
### Requirements
55+
56+
| Name | Version |
57+
|------|---------|
58+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >=1.9.0 |
59+
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.15.0, <3.0.0 |
60+
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.70.0, <2.0.0 |
61+
| <a name="requirement_null"></a> [null](#requirement\_null) | >= 3.2.1, < 4.0.0 |
62+
| <a name="requirement_time"></a> [time](#requirement\_time) | >= 0.9.1, < 1.0.0 |
63+
64+
### Modules
65+
66+
No modules.
67+
68+
### Resources
69+
70+
| Name | Type |
71+
|------|------|
72+
| [helm_release.kube_audit](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
73+
| [null_resource.set_audit_log_policy](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
74+
| [null_resource.set_audit_webhook](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
75+
| [time_sleep.wait_for_kube_audit](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
76+
| [ibm_container_cluster_config.cluster_config](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/data-sources/container_cluster_config) | data source |
77+
| [ibm_container_vpc_cluster.cluster](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/data-sources/container_vpc_cluster) | data source |
78+
79+
### Inputs
80+
81+
| Name | Description | Type | Default | Required |
82+
|------|-------------|------|---------|:--------:|
83+
| <a name="input_audit_deployment_name"></a> [audit\_deployment\_name](#input\_audit\_deployment\_name) | The name of log collection deployement and service. | `string` | `"ibmcloud-kube-audit"` | no |
84+
| <a name="input_audit_log_policy"></a> [audit\_log\_policy](#input\_audit\_log\_policy) | Specify the amount of information that is logged to the API server audit logs by choosing the audit log policy profile to use. Supported values are `default` and `WriteRequestBodies`. | `string` | `"default"` | no |
85+
| <a name="input_audit_namespace"></a> [audit\_namespace](#input\_audit\_namespace) | The name of the namespace where log collection service and a deployment will be created. | `string` | `"ibm-kube-audit"` | no |
86+
| <a name="input_audit_webhook_listener_image"></a> [audit\_webhook\_listener\_image](#input\_audit\_webhook\_listener\_image) | The audit webhook listener image reference in the format of `[registry-url]/[namespace]/[image]`.The sub-module uses the `icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs` image to forward logs to IBM Cloud Logs. This image is for demonstration purposes only. For a production solution, configure and maintain your own log forwarding image. | `string` | `"icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs"` | no |
87+
| <a name="input_audit_webhook_listener_image_version"></a> [audit\_webhook\_listener\_image\_version](#input\_audit\_webhook\_listener\_image\_version) | The tag or digest for the audit webhook listener image to deploy. If changing the value, ensure it is compatible with `audit_webhook_listener_image`. | `string` | `"deaabcb8225e800385413ba420cf3f819d3b0671@sha256:acf123f4dba63534cbc104c6886abedff9d25a22a34ab7b549ede988ed6e7144"` | no |
88+
| <a name="input_cluster_config_endpoint_type"></a> [cluster\_config\_endpoint\_type](#input\_cluster\_config\_endpoint\_type) | Specify which type of endpoint to use for for cluster config access: 'default', 'private', 'vpe', 'link'. 'default' value will use the default endpoint of the cluster. | `string` | `"default"` | no |
89+
| <a name="input_cluster_id"></a> [cluster\_id](#input\_cluster\_id) | The ID of the cluster to deploy the log collection service in. | `string` | n/a | yes |
90+
| <a name="input_cluster_resource_group_id"></a> [cluster\_resource\_group\_id](#input\_cluster\_resource\_group\_id) | The resource group ID of the cluster. | `string` | n/a | yes |
91+
| <a name="input_ibmcloud_api_key"></a> [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The IBM Cloud api key to generate an IAM token. | `string` | n/a | yes |
92+
| <a name="input_region"></a> [region](#input\_region) | The IBM Cloud region where the cluster is provisioned. | `string` | n/a | yes |
93+
| <a name="input_use_private_endpoint"></a> [use\_private\_endpoint](#input\_use\_private\_endpoint) | Set this to true to force all api calls to use the IBM Cloud private endpoints. | `bool` | `false` | no |
94+
| <a name="input_wait_till"></a> [wait\_till](#input\_wait\_till) | To avoid long wait times when you run your Terraform code, you can specify the stage when you want Terraform to mark the cluster resource creation as completed. Depending on what stage you choose, the cluster creation might not be fully completed and continues to run in the background. However, your Terraform code can continue to run without waiting for the cluster to be fully created. Supported args are `MasterNodeReady`, `OneWorkerNodeReady`, `IngressReady` and `Normal` | `string` | `"IngressReady"` | no |
95+
| <a name="input_wait_till_timeout"></a> [wait\_till\_timeout](#input\_wait\_till\_timeout) | Timeout for wait\_till in minutes. | `number` | `90` | no |
96+
97+
### Outputs
98+
99+
No outputs.
100+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Patterns to ignore when building packages.
2+
# This supports shell glob matching, relative path matching, and
3+
# negation (prefixed with !). Only one pattern per line.
4+
.DS_Store
5+
# Common VCS dirs
6+
.git/
7+
.gitignore
8+
.bzr/
9+
.bzrignore
10+
.hg/
11+
.hgignore
12+
.svn/
13+
# Common backup files
14+
*.swp
15+
*.bak
16+
*.tmp
17+
*.orig
18+
*~
19+
# Various IDEs
20+
.project
21+
.idea/
22+
*.tmproj
23+
.vscode/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: v2
2+
name: kube-audit
3+
description: A Helm chart for kube-audit
4+
5+
# A chart can be either an 'application' or a 'library' chart.
6+
#
7+
# Application charts are a collection of templates that can be packaged into versioned archives
8+
# to be deployed.
9+
#
10+
# Library charts provide useful utilities or functions for the chart developer. They're included as
11+
# a dependency of application charts to inject those utilities and functions into the rendering
12+
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
13+
type: application
14+
15+
# This is the chart version. This version number should be incremented each time you make changes
16+
# to the chart and its templates, including the app version.
17+
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18+
version: 0.0.1
19+
20+
# This is the version number of the application being deployed. This version number should be
21+
# incremented each time you make changes to the application. Versions are not expected to
22+
# follow Semantic Versioning. They should reflect the version the application is using.
23+
# It is recommended to use it with quotes.
24+
appVersion: "1.0.0"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: "{{ .Values.metadata.name }}"
5+
namespace: "{{ .Values.metadata.namespace }}"
6+
labels:
7+
app: "{{ .Values.metadata.name }}"
8+
spec:
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: "{{ .Values.metadata.name }}"
13+
template:
14+
metadata:
15+
labels:
16+
app: "{{ .Values.metadata.name }}"
17+
spec:
18+
containers:
19+
- name: "{{ .Values.metadata.name }}"
20+
image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
21+
imagePullPolicy: Always
22+
ports:
23+
- containerPort: 3000
24+
securityContext:
25+
allowPrivilegeEscalation: false
26+
runAsNonRoot: true
27+
capabilities:
28+
drop:
29+
- ALL
30+
seccompProfile:
31+
type: RuntimeDefault
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: "{{ .Values.metadata.namespace }}"
5+
labels:
6+
pod-security.kubernetes.io/enforce: restricted
7+
pod-security.kubernetes.io/enforce-version: latest
8+
pod-security.kubernetes.io/audit: restricted
9+
pod-security.kubernetes.io/audit-version: latest
10+
pod-security.kubernetes.io/warn: restricted
11+
pod-security.kubernetes.io/warn-version: latest
12+
security.openshift.io/scc.podSecurityLabelSync: "false"

0 commit comments

Comments
 (0)