Skip to content

Commit

Permalink
Added multiple features to helm chart example as well as docs (#290)
Browse files Browse the repository at this point in the history
* added multiple features to helm chart example as well as docs

Signed-off-by: Trent V <[email protected]>

* fixed spelling mistaeks

Signed-off-by: Trent V <[email protected]>

* added additional templating to consolidate configuration

Signed-off-by: Trent V <[email protected]>

---------

Signed-off-by: Trent V <[email protected]>
  • Loading branch information
Trent V authored Jan 16, 2024
1 parent 3bb7887 commit 331c298
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 17 deletions.
4 changes: 2 additions & 2 deletions examples/helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# SPDX-License-Identifier: Apache-2.0

apiVersion: v2
name: BloodhoundAD
description: A Helm Chart for deploying BloodHoundAD on Kubernetes
name: Bloodhound
description: A Helm Chart for deploying BloodHound on Kubernetes
type: application
version: 0.1.0
appVersion: "5.3.1"
78 changes: 78 additions & 0 deletions examples/helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# BloodHound Community Edition Helm Chart Example

BloodHound Community Edition is composed of three distinct parts:

- A PostgreSQL database used for application state storage
- A Neo4J graph database used for storing all the graph data
- A single binary containing the BloodHound API server and the UI assets

This Helm chart templates these three services and facilitates communication between them inside a Kubernetes cluster. This chart uses the Prebuilt docker images to run inside of Kubernetes. Helm will allow you to template important information about your deployment. Please use the included `values.yaml` to customize deployment configuration.

## Prerequisites

In order to run this chart you will need the following:
- A Kubernetes Cluster in which to deploy (any supported version should work with this chart).
- Admin access or the ability to create Helm charts and the associated Objects in this chart (validate RBAC Policies and Policy Engine configuration)
- Helm (v3+) installed on a local workstation or CI Pipeline.

## Quick start

To install this chart inside of a Kubernetes cluster **make sure helm is properly configured to point at the correct cluster within the kubeconfig**. Once You have validated your helm install, clone this repo and run the following command from your workstation or pipeline:

```
$ helm install bhce $BH_ROOT/examples/helm/.
```

## Accessing
By default, the ingress is enabled. This means the application will be available on the ingress endpoint with the host set to `bloodhound.example.com` (Each of these values can be configured in the values.yaml). As long as you have a properly configured ingress controller and valid DNS configuration the application will be available at `https://bloodhound.example.com`, else without DNS you can test with curl by passing the 'Host' Header: `curl -H 'Host: bloodhound.example.com' https://$endpointIP`.

If you have a TLS cert you can enable `bloodhound.tls.customCert` in the values.yaml and provide the ingress secret in `bloodhound.tls.certSecret`. Else, the provided cert will be self signed from the ingress controller.

## Configuring BloodHound Community Edition

To configure the Helm Chart deployment of BloodHound Community Edition you can use the two files specified below:

- `values.yaml` - A general Helm Chart configuration file - you can use this to configure aspects of the deployment of BloodHound and set Environment Variables. This file generally will be the single source of truth for application and deployment configuration.
- `templates/cmbh.yaml` - This is the Kubernetes configmap used for the BloodHound Application - you can add your own custom configuration in the `bloodhound-config.json` section of this file. Some of it is populated with the `values.yaml` as well for portibility

If using a custom Certificate for TLS please terminate it on the ingress and not the application directly for easier Kubernetes native management.

Changing the database credentials is not a requirement for development/testing but is **Highly** Recommended for production environments.

## Ports
The default ports are as follows:

- 8080 - BloodHound Web Port. This is the backend port of the service used by BloodHound.
- 7474 - Neo4J Web Interface. Useful for when you need to run queries directly against the Neo4J database. (Note: this is not exposed externally by default)
- 7687 - Neo4J Database Port. This is provided in case you want to access the Neo4J database from some other application on your machine. (Note: this is not exposed externally by default)


## Choosing a BloodHound Version

BloodHound docker images are tagged for each release:

- `latest` will give you the most recent stable release
- `X` (e.g. `5`) will give you the latest stable release for that major version
- `X.X` (e.g. `5.0`) will give you the latest stable release for that minor version
- `X.X.X` (e.g. `5.0.0`) will give you the release for that specific patch version
- `X.X.X-rcX` (e.g. `5.0.0-rc1`) will give you a specific release candidate for an upcoming release
- `edge` will give you the most recent main commit (not guaranteed to be stable)

By Default the `latest` tag is set. You can change this by setting the `bloodhound.container.version` in the values.yaml

## Troubleshooting

Please assure any local host-based firewall frontends such as `firewalld` or `ufw` on the node is disabled. Please use Kubernetes NetworkPolicies and admission controllers instead.

Validate all 3 of the Deployments are healthy, Services are active and the ingress is properly configured with `kubectl get -n bloodhoundad deployments,svc,ingress`

Assure the cluster DNS is resolving the dns for the 'app-db' service and the 'graph-db' service. An easy way to validate this is to spin up a busybox pod in the bloodhoundad namespace and use nslookup to check for resolution issues.

```
$ kubectl run -it --rm dns-test -n bloodhoundad --image busybox:latest
# for name in app-db graph-db; do nslookup $name; done
```
If you are having trouble with cluster DNS please refer to the upstream Kubernetes documentation:
https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/

Else, please refer to the upstream Kubernetes Documentation for General cluster troubleshooting: https://kubernetes.io/docs/tasks/debug/debug-cluster/.
32 changes: 32 additions & 0 deletions examples/helm/templates/cmbh.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.bloodhound.configMap.name }}
namespace: {{ .Values.namespace }}
data:
bloodhound.config.json: |
{
"version": 1,
"bind_addr": "0.0.0.0:{{ .Values.bloodhound.service.port }}",
"metrics_port": ":{{ (index .Values.bloodhound.container.ports 1).containerPort }}",
"root_url": "http://{{ .Values.bloodhound.ingress.host }}",
"work_dir": "/opt/bloodhound/work",
"log_level": "INFO",
"log_path": "bloodhound.log",
"features": {
"enable_auth": true
},
"database": {
"connection": "user={{ .Values.appdb.container.env.POSTGRES_USER }} password={{ .Values.appdb.container.env.POSTGRES_PASSWORD }} dbname={{ .Values.appdb.container.env.POSTGRES_DB }} host={{ .Values.appdb.service.name }}"
},
"neo4j": {
"connection": "neo4j://{{ .Values.graphdb.container.env.NEO4J_AUTH_USER }}:{{ .Values.graphdb.container.env.NEO4J_AUTH_PASS }}@{{ .Values.graphdb.service.name }}:{{ (index .Values.graphdb.service.ports 0).port }}/"
},
"collectors_base_path": "/etc/bloodhound/collectors",
"default_admin": {
"principal_name": "admin",
"first_name": "Bloodhound",
"last_name": "Admin",
"email_address": "[email protected]"
}
}
15 changes: 13 additions & 2 deletions examples/helm/templates/deploybh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,19 @@ spec:
labels:
app: {{ .Values.bloodhound.appName }}
spec:
initContainers:
- name: check-db-availability
image: busybox
command: ['/bin/sh', '-c']
args:
- >
until nc -z {{ .Values.graphdb.service.name }} {{ (index .Values.graphdb.service.ports 0).port }} && nc -z {{ .Values.appdb.service.name }} {{ .Values.appdb.service.port }}; do
echo "Waiting for databases to be ready";
sleep 5;
done;
containers:
- name: {{ .Values.bloodhound.container.name }}
image: {{ .Values.bloodhound.container.image }}
image: {{ .Values.bloodhound.container.image }}:{{ .Values.bloodhound.container.version }}
env:
- name: bhe_disable_cypher_qc
value: "{{ .Values.bloodhound.container.env.bhe_disable_cypher_qc }}"
Expand All @@ -40,7 +50,8 @@ spec:
{{- if .Values.bloodhound.configMap.enabled }}
volumeMounts:
- name: bloodhound-config
mountPath: /path/to/config # Update with actual mount path
mountPath: /bloodhound.config.json
subPath: bloodhound.config.json
{{- end }}
{{- if .Values.bloodhound.configMap.enabled }}
volumes:
Expand Down
4 changes: 2 additions & 2 deletions examples/helm/templates/deploygraphdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ spec:
image: {{ .Values.graphdb.container.image }}
env:
- name: NEO4J_AUTH
value: "{{ .Values.graphdb.container.env.NEO4J_AUTH }}"
value: "{{ .Values.graphdb.container.env.NEO4J_AUTH_USER }}/{{ .Values.graphdb.container.env.NEO4J_AUTH_PASS }}"
- name: NEO4J_dbms_allow__upgrade
value: "{{ .Values.graphdb.container.env.NEO4J_dbms_allow__upgrade }}"
ports:
Expand All @@ -47,7 +47,7 @@ spec:
- -O
- /dev/null
- -q
- http://localhost:7474
- http://127.0.0.1:{{ (index .Values.graphdb.container.ports 1).containerPort }}
initialDelaySeconds: {{ .Values.graphdb.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.graphdb.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.graphdb.livenessProbe.timeoutSeconds }}
Expand Down
5 changes: 4 additions & 1 deletion examples/helm/templates/ingressbh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ spec:
name: {{ .Values.bloodhound.name }}-service
port:
number: {{ .Values.bloodhound.service.port }}
{{- if .Values.bloodhound.ingress.tls }}
{{- if .Values.bloodhound.tls.enabled }}
tls:
- hosts:
- {{ .Values.bloodhound.ingress.host }}
{{- if .Values.bloodhound.tls.customCert }}
secretName: {{ .Values.bloodhound.tls.certSecret }}
{{- end }}
{{- end }}
{{- end }}
27 changes: 27 additions & 0 deletions examples/helm/templates/ingressgraphdb.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{{- if .Values.graphdb.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Values.graphdb.name }}-ingress
namespace: {{ .Values.namespace }}
spec:
rules:
- host: {{ .Values.graphdb.ingress.host }}
http:
paths:
- path: {{ .Values.graphdb.ingress.path }}
pathType: Prefix
backend:
service:
name: graph-db
port:
number: {{ (index .Values.graphdb.service.ports 0).http }}
{{- if .Values.graphdb.tls.enabled }}
tls:
- hosts:
- {{ .Values.graphdb.ingress.host }}
{{- if .Values.graphdb.tls.customCert }}
secretName: {{ .Values.graphdb.tls.certSecret }}
{{- end }}
{{- end }}
{{- end }}
2 changes: 1 addition & 1 deletion examples/helm/templates/nsbloodhound.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: bloodhoundad
name: bloodhound
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5" # ensures this is executed first
Expand Down
2 changes: 1 addition & 1 deletion examples/helm/templates/svcappdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
apiVersion: v1
kind: Service
metadata:
name: app-db
name: {{ .Values.appdb.service.name }}
namespace: {{ .Values.namespace }}
spec:
type: {{ .Values.appdb.service.type }}
Expand Down
2 changes: 1 addition & 1 deletion examples/helm/templates/svcgraphdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
apiVersion: v1
kind: Service
metadata:
name: graph-db
name: {{ .Values.graphdb.service.name }}
namespace: {{ .Values.namespace }}
spec:
selector:
Expand Down
30 changes: 23 additions & 7 deletions examples/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
#
# SPDX-License-Identifier: Apache-2.0

namespace: bloodhoundad
namespace: bloodhound

appdb:
name: bloodhound-postgres
name: postgres
replicas: 1
appName: bloodhound-postgres
appName: postgres
container:
name: postgres
image: docker.io/library/postgres:13.2
Expand All @@ -39,6 +39,7 @@ appdb:
failureThreshold: 5
service:
enabled: true
name: app-db
type: ClusterIP
port: 5432
targetPort: 5432
Expand All @@ -56,13 +57,15 @@ graphdb:
name: neo4j
image: docker.io/library/neo4j:4.4
env:
NEO4J_AUTH: "neo4j/bloodhoundcommunityedition"
NEO4J_AUTH_USER: "neo4j"
NEO4J_AUTH_PASS: "bloodhoundcommunityedition"
NEO4J_dbms_allow__upgrade: "true"
ports:
- containerPort: 7687
- containerPort: 7474
service:
enabled: true
name: graph-db
type: ClusterIP
ports:
- name: graphdb
Expand All @@ -83,18 +86,28 @@ graphdb:
persistentVolumeClaim:
claimName: graphdb-neo4j-data-pvc
size: "1Gi" # Configurable storage size
ingress:
enabled: false
host: graphdb.example.com
path: /
tls:
enabled: true
customCert: false
certSecret: graphdb-tls

bloodhound:
name: bloodhound
replicas: 1
appName: bloodhound
container:
name: bloodhound
image: docker.io/specterops/bloodhound:latest
image: docker.io/specterops/bloodhound
version: latest
env:
bhe_disable_cypher_qc: "false"
ports:
- containerPort: 8080
- containerPort: 2112
service:
enabled: true
type: ClusterIP
Expand All @@ -104,7 +117,10 @@ bloodhound:
enabled: true
host: bloodhound.example.com
path: /
tls: false
tls:
enabled: true
customCert: false
certSecret: bloodhound-tls
configMap:
enabled: false
enabled: true
name: bloodhound-config

0 comments on commit 331c298

Please sign in to comment.