From acae63463c0656f14c6ce21457f37452ed6ba4cb Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 6 May 2024 18:34:09 +0100 Subject: [PATCH] * Prune sawtooth references from chronicle chart * WIP Terraform for vault, vault-config, signoz and chronicle-substrate Signed-off-by: Ryan --- charts/chronicle/Chart.lock | 6 +- charts/chronicle/Chart.yaml | 7 +- charts/chronicle/charts/node-5.6.1.tgz | Bin 27209 -> 0 bytes .../chronicle/charts/standard-defs-0.1.3.tgz | Bin 15069 -> 15068 bytes charts/chronicle/templates/_chronicle.tpl | 14 +- .../chronicle/templates/chronicle-config.yaml | 9 +- .../chronicle/templates/chronicle-init.yaml | 231 ------------------ charts/chronicle/templates/statefulset.yaml | 55 +---- .../chronicle/templates/tests/api-test.yaml | 130 ---------- .../templates/tests/auth-endpoints-test.yaml | 160 ------------ charts/chronicle/values.yaml | 22 +- terraform/chronicle-substrate/.gitignore | 25 ++ terraform/chronicle-substrate/bootnode.tf | 25 ++ terraform/chronicle-substrate/provider.tf | 10 + .../templates/bootnode.tmpl | 110 +++++++++ terraform/chronicle-substrate/variables.tf | 60 +++++ terraform/chronicle/.gitignore | 25 ++ terraform/signoz/.gitignore | 26 ++ terraform/signoz/output.tf | 32 +++ terraform/signoz/provider.tf | 9 + terraform/signoz/signoz.tf | 22 ++ terraform/signoz/variables.tf | 37 +++ terraform/vault-configuration/.gitignore | 25 ++ terraform/vault-configuration/BOOTNODE_KEY | 1 + .../vault-configuration/BOOTNODE_PEER_ID | 1 + .../vault-configuration/policies/admin.hcl | 58 +++++ .../vault-configuration/policies/bootnode.hcl | 4 + .../policies/chronicle.hcl | 4 + terraform/vault-configuration/provider.tf | 4 + terraform/vault-configuration/variables.tf | 48 ++++ terraform/vault-configuration/vault.tf | 62 +++++ terraform/vault-deployment/.gitignore | 25 ++ terraform/vault-deployment/locals.tf | 3 + terraform/vault-deployment/provider.tf | 10 + .../vault-deployment/templates/values.tmpl | 95 +++++++ terraform/vault-deployment/tls.tf | 82 +++++++ terraform/vault-deployment/variables.tf | 126 ++++++++++ terraform/vault-deployment/vault.ca.pem | 22 ++ terraform/vault-deployment/vault.tf | 82 +++++++ 39 files changed, 1065 insertions(+), 602 deletions(-) delete mode 100644 charts/chronicle/charts/node-5.6.1.tgz delete mode 100644 charts/chronicle/templates/chronicle-init.yaml delete mode 100644 charts/chronicle/templates/tests/api-test.yaml delete mode 100644 charts/chronicle/templates/tests/auth-endpoints-test.yaml create mode 100644 terraform/chronicle-substrate/.gitignore create mode 100644 terraform/chronicle-substrate/bootnode.tf create mode 100644 terraform/chronicle-substrate/provider.tf create mode 100644 terraform/chronicle-substrate/templates/bootnode.tmpl create mode 100644 terraform/chronicle-substrate/variables.tf create mode 100644 terraform/chronicle/.gitignore create mode 100644 terraform/signoz/.gitignore create mode 100644 terraform/signoz/output.tf create mode 100644 terraform/signoz/provider.tf create mode 100644 terraform/signoz/signoz.tf create mode 100644 terraform/signoz/variables.tf create mode 100644 terraform/vault-configuration/.gitignore create mode 100644 terraform/vault-configuration/BOOTNODE_KEY create mode 100644 terraform/vault-configuration/BOOTNODE_PEER_ID create mode 100644 terraform/vault-configuration/policies/admin.hcl create mode 100644 terraform/vault-configuration/policies/bootnode.hcl create mode 100644 terraform/vault-configuration/policies/chronicle.hcl create mode 100644 terraform/vault-configuration/provider.tf create mode 100644 terraform/vault-configuration/variables.tf create mode 100644 terraform/vault-configuration/vault.tf create mode 100644 terraform/vault-deployment/.gitignore create mode 100644 terraform/vault-deployment/locals.tf create mode 100644 terraform/vault-deployment/provider.tf create mode 100644 terraform/vault-deployment/templates/values.tmpl create mode 100644 terraform/vault-deployment/tls.tf create mode 100644 terraform/vault-deployment/variables.tf create mode 100755 terraform/vault-deployment/vault.ca.pem create mode 100644 terraform/vault-deployment/vault.tf diff --git a/charts/chronicle/Chart.lock b/charts/chronicle/Chart.lock index 7db551ef5..c5cf6ffc8 100644 --- a/charts/chronicle/Chart.lock +++ b/charts/chronicle/Chart.lock @@ -4,9 +4,9 @@ dependencies: version: 0.1.3 - name: node repository: https://paritytech.github.io/helm-charts/ - version: 5.6.1 + version: 5.7.1 - name: vault repository: https://helm.releases.hashicorp.com version: 0.27.0 -digest: sha256:19c6ade52b5c53daab6fd0a8a2c42a81e5371b99eb9de8a5f102b215930dce40 -generated: "2024-03-05T14:03:42.428673+03:00" +digest: sha256:6073af2c490fa86b821ac5188b14cd4f9bd9f2c8e61a778d2acbde9861470a0c +generated: "2024-05-01T20:31:33.345331+01:00" diff --git a/charts/chronicle/Chart.yaml b/charts/chronicle/Chart.yaml index 71e556676..96feb98c4 100644 --- a/charts/chronicle/Chart.yaml +++ b/charts/chronicle/Chart.yaml @@ -27,9 +27,4 @@ dependencies: - name: standard-defs version: ~0.1.0 repository: https://btp-charts-stable.s3.amazonaws.com/charts/ - - name: node - version: ~5.6.1 - repository: https://paritytech.github.io/helm-charts/ - - name: vault - version: ~0.27 - repository: https://helm.releases.hashicorp.com + diff --git a/charts/chronicle/charts/node-5.6.1.tgz b/charts/chronicle/charts/node-5.6.1.tgz deleted file mode 100644 index 67cc59a760610e566150ff96aa875ad59d85bb51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27209 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 diff --git a/charts/chronicle/charts/standard-defs-0.1.3.tgz b/charts/chronicle/charts/standard-defs-0.1.3.tgz index 2f63806a9b2c5c77e244ce2207547ea37f52c009..d5ac17a146f30f16132ff5f39cc1963b7ea6371e 100644 GIT binary patch delta 14293 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 DndCnN delta 14294 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 E01%{WjQ{`u diff --git a/charts/chronicle/templates/_chronicle.tpl b/charts/chronicle/templates/_chronicle.tpl index 0b6d04868..c1bda86c9 100644 --- a/charts/chronicle/templates/_chronicle.tpl +++ b/charts/chronicle/templates/_chronicle.tpl @@ -3,7 +3,7 @@ {{- end -}} {{- define "tp.replicas" -}} -{{ include "lib.call-nested" (list . "sawtooth" "sawtooth.replicas") | int }} +{{ include "lib.call-nested" (list . "node" "node.replicas") | int }} {{- end -}} {{- define "chronicle.service.name" -}} @@ -26,16 +26,12 @@ chronicle: {{ include "common.names.fullname" . }} {{ include "chronicle.labels.appLabels" . }} {{- end -}} -{{- define "chronicle.sawtooth.sawcomp" -}} -{{ include "lib.call-nested" (list . "sawtooth" "sawtooth.ports.sawcomp") | int }} +{{- define "chronicle.substrate.rpc" -}} +9982 {{- end -}} -{{- define "chronicle.sawtooth.rest" -}} -{{ include "lib.call-nested" (list . "sawtooth" "sawtooth.ports.rest") | int }} -{{- end -}} - -{{- define "chronicle.sawtooth.service" -}} -{{- $svc := include "lib.call-nested" (list . "sawtooth" "common.names.fullname") -}} +{{- define "chronicle.substrate.service" -}} +{{- $svc := include "lib.call-nested" (list . "node" "common.names.fullname") -}} {{- $ns := .Release.Namespace -}} {{- $domain := "svc.cluster.local" -}} {{ printf "%s.%s.%s" $svc $ns $domain }} diff --git a/charts/chronicle/templates/chronicle-config.yaml b/charts/chronicle/templates/chronicle-config.yaml index f0f114b48..640f5f71d 100644 --- a/charts/chronicle/templates/chronicle-config.yaml +++ b/charts/chronicle/templates/chronicle-config.yaml @@ -1,17 +1,10 @@ --- -{{$stlServiceName := include "lib.call-nested" (list . "sawtooth" "common.names.fullname")}} +{{$stlServiceName := include "lib.call-nested" (list . "node" "common.names.fullname")}} apiVersion: v1 kind: ConfigMap metadata: name: {{.Release.Name}}-chronicle-config data: config.toml: | - [secrets] - path = "/var/lib/chronicle/secrets/" - [store] - path = "/var/lib/chronicle/store/" - address = "postgresql://{{ .Values.postgres.user }}@{{ .Values.postgres.host }}:5432/{{ .Values.postgres.database }}" - [validator] - address = "tcp://{{ include "chronicle.sawtooth.service" . }}:{{ include "chronicle.sawtooth.sawcomp" . }}" [namespace_bindings] default = "fd717fd6-70f1-44c1-81de-287d5e101089" diff --git a/charts/chronicle/templates/chronicle-init.yaml b/charts/chronicle/templates/chronicle-init.yaml deleted file mode 100644 index 90fdd1581..000000000 --- a/charts/chronicle/templates/chronicle-init.yaml +++ /dev/null @@ -1,231 +0,0 @@ -{{$stlServiceName := include "lib.call-nested" (list . "sawtooth" "common.names.fullname")}} ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "common.names.fullname" . }}-init - labels: {{ include "chronicle.labels" . | nindent 4 }} - component: chronicle -spec: - ttlSecondsAfterFinished: 100 - template: - metadata: - labels: {{ include "chronicle.labels" . | nindent 8 }} - component: chronicle - spec: - restartPolicy: Never - serviceAccountName: {{ include "lib.serviceAccountName" . }} - automountServiceAccountToken: true - volumes: {{- include "lib.volumes" .Values.opa.tp.extraVolumes | nindent 8 }} - - name: shared-data - emptyDir: {} - initContainers: - - name: get-secret - image: alpine/k8s:1.24.13 - command: [ "sh", "-ec" ] - args: - - | - if kubectl get secret {{ include "chronicle.root-key.secret" . }} -n {{.Release.Namespace}} >/dev/null 2>&1; then - echo "Secret found." - kubectl get secret {{ include "chronicle.root-key.secret" . }} -n {{.Release.Namespace}} -o jsonpath='{.data.*}' | base64 -d > /shared-data/root.pem - touch /shared-data/secret-found - else - echo "Secret not found." - fi - volumeMounts: - - name: shared-data - mountPath: /shared-data - - name: generate-secret - {{- include "lib.image" (dict "imageRoot" .Values.opa.opaInit.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-ec"] - args: - - | - if [[ ! -f "/shared-data/root.pem" ]]; then - echo "Generating new root key." - opactl generate --output /shared-data/root.pem - else - echo "Root key already exists." - fi - env: {{ include "lib.safeToYaml" .Values.env | nindent 12 }} - - name: RUST_LOG - value: {{ .Values.logLevel }} - - name: RUST_BACKTRACE - value: {{ .Values.backtraceLevel }} - volumeMounts: - - name: shared-data - mountPath: /shared-data - - name: create-secret - image: alpine/k8s:1.24.13 - command: [ "sh", "-ec" ] - args: - - | - if [ -f "/shared-data/secret-found" ]; then - echo "Secret already exists." - else - echo "Creating k8s secret from key." - kubectl create secret generic {{ include "chronicle.root-key.secret" . }} \ - -n {{ .Release.Namespace }} \ - --from-file=/shared-data/root.pem - fi - volumeMounts: - - name: shared-data - mountPath: /shared-data - {{ if .Values.opa.enabled }} - - name: opa-bootstrap-root - {{- include "lib.image" (dict "imageRoot" .Values.opa.opaInit.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-ec"] - args: - - | - wait-for-it $HOST:$PORT --timeout=0 - echo "Waiting to ensure Sawtooth validator is ready ..." - sleep 100 - - if [[ -f "/shared-data/secret-found" ]]; then - echo "Skipping root key bootstrap." - else - opactl \ - --sawtooth-address tcp://$HOST:$PORT \ - bootstrap \ - --root-key /shared-data/root.pem - fi - env: {{ include "lib.safeToYaml" .Values.env | nindent 12 }} - - name: HOST - value: {{ $stlServiceName }}.{{ .Release.Namespace }}.svc.cluster.local - - name: PORT - value: "{{ include "chronicle.sawtooth.sawcomp" . }}" - - name: RUST_LOG - value: {{ .Values.logLevel }} - - name: RUST_BACKTRACE - value: {{ .Values.backtraceLevel }} - volumeMounts: - - name: shared-data - mountPath: /shared-data - {{ if .Values.opa.policy.url }} - - name: wait-for-sawtooth-rest-api - {{- include "lib.image" (dict "imageRoot" .Values.opa.opaInit.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-ec"] - args: - - | - wait-for-it $HOST:$PORT --timeout=0 - echo "Sawtooth rest API is ready." - env: - - name: HOST - value: {{ $stlServiceName }}.{{ .Release.Namespace }}.svc.cluster.local - - name: PORT - value: "{{ include "chronicle.sawtooth.rest" . }}" - - name: RUST_LOG - value: {{ .Values.logLevel }} - - name: RUST_BACKTRACE - value: {{ .Values.backtraceLevel }} - volumeMounts: - - name: shared-data - mountPath: /shared-data - - name: opa-settings - {{- include "lib.image" (dict "imageRoot" .Values.sawset.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-ec"] - args: - - | - if sawtooth settings list --url http://$HOST:$PORT | grep -q "chronicle.opa.policy_name"; then - echo "Skipping setting Sawtooth OPA settings." - exit 0 - else - echo "Creating Sawtooth settings batch." - sawset proposal create \ - -k /etc/sawtooth/keys/{{ $stlServiceName }}-0 \ - chronicle.opa.policy_name={{ required "opa.policy.id required!" .Values.opa.policy.id }} \ - chronicle.opa.entrypoint={{ required "opa.policy.entrypoint required!" .Values.opa.policy.entrypoint }} \ - -o /shared-data/opa-settings.batch - - echo "Submitting Sawtooth OPA settings batch." - sawtooth batch submit \ - -f /shared-data/opa-settings.batch \ - --url http://$HOST:$PORT \ - --wait 60 - fi - env: - - name: HOST - value: {{ $stlServiceName }}.{{ .Release.Namespace }}.svc.cluster.local - - name: PORT - value: "{{ include "chronicle.sawtooth.rest" . }}" - volumeMounts: - - name: shared-data - mountPath: /shared-data - - name: validator-secret - mountPath: /etc/sawtooth/keys - readOnly: true - - name: get-policy - {{- include "lib.image" (dict "imageRoot" .Values.opa.opaInit.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-ec"] - args: - - | - echo "Attempting to get policy." - opactl \ - --sawtooth-address tcp://$HOST:$PORT \ - get-policy \ - --id {{ .Values.opa.policy.id }} \ - --output /shared-data/policy.bin - - if [ -f "/shared-data/policy.bin" ]; then - echo "Policy already set." - touch /shared-data/policy-already-set - exit 0 - else - echo "Policy not found." - exit 0 - fi - env: {{ include "lib.safeToYaml" .Values.env | nindent 12 }} - - name: HOST - value: {{ $stlServiceName }}.{{ .Release.Namespace }}.svc.cluster.local - - name: PORT - value: "{{ include "chronicle.sawtooth.sawcomp" . }}" - - name: RUST_LOG - value: {{ .Values.logLevel }} - - name: RUST_BACKTRACE - value: {{ .Values.backtraceLevel }} - volumeMounts: - - name: shared-data - mountPath: /shared-data - - name: set-policy - {{- include "lib.image" (dict "imageRoot" .Values.opa.opaInit.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-ec"] - args: - - | - if [[ -f "/shared-data/policy-already-set" ]]; then - echo "Skipping setting policy." - exit 0 - else - echo "Policy not found on chain. Setting policy." - opactl \ - --sawtooth-address tcp://$HOST:$PORT \ - set-policy \ - --id {{ .Values.opa.policy.id }} \ - -p {{ .Values.opa.policy.url }} \ - --root-key /shared-data/root.pem - fi - env: {{ include "lib.safeToYaml" .Values.env | nindent 12 }} - - name: HOST - value: {{ $stlServiceName }}.{{ .Release.Namespace }}.svc.cluster.local - - name: PORT - value: "{{ include "chronicle.sawtooth.sawcomp" . }}" - - name: RUST_LOG - value: {{ .Values.logLevel }} - - name: RUST_BACKTRACE - value: {{ .Values.backtraceLevel }} - volumeMounts: - - name: shared-data - mountPath: /shared-data - {{ end }} - {{ end }} - containers: - - name: chronicle-init - image: busybox:1.36 - command: [ "sh", "-c"] - args: - - | - echo "Chronicle bootstrap and OPA settings initialization complete." - volumes: - - name: shared-data - emptyDir: {} - - name: validator-secret - configMap: - name: validator-secret diff --git a/charts/chronicle/templates/statefulset.yaml b/charts/chronicle/templates/statefulset.yaml index 0f3116a8d..cff0e60a1 100644 --- a/charts/chronicle/templates/statefulset.yaml +++ b/charts/chronicle/templates/statefulset.yaml @@ -1,4 +1,4 @@ -{{$stlServiceName := include "lib.call-nested" (list . "sawtooth" "common.names.fullname")}} +{{$substrateServiceName := include "lib.call-nested" (list . "node" "common.names.fullname")}} --- apiVersion: apps/v1 kind: StatefulSet @@ -19,57 +19,6 @@ spec: spec: serviceAccountName: {{ include "lib.serviceAccountName" . }} affinity: {{ include "lib.safeToYaml" .Values.affinity | nindent 8 }} - initContainers: - - name: chronicle-permissions - image: busybox:1.36 - command: [ "sh", "-c"] - args: - - | - chown -R 999:999 /var/lib/chronicle || true - volumeMounts: - - name: chronicle-config - mountPath: /etc/chronicle/config/ - - name: chronicle-secrets - mountPath: /var/lib/chronicle/secrets/ - readOnly: false - - name: chronicle-keystore - {{- include "lib.image" (dict "imageRoot" .Values.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-c"] - args: - - | - /usr/local/bin/chronicle \ - -c /etc/chronicle/config/config.toml \ - verify-keystore - env: {{ include "lib.safeToYaml" .Values.env | nindent 12 }} - - name: RUST_LOG - value: {{ .Values.logLevel }} - volumeMounts: - - name: chronicle-config - mountPath: /etc/chronicle/config/ - - name: chronicle-secrets - mountPath: /var/lib/chronicle/secrets/ - readOnly: false - {{- if and .Values.opa.enabled .Values.opa.policy.url }} - - name: wait-for-opa-settings - {{- include "lib.image" (dict "imageRoot" .Values.sawset.image "global" .Values.global ) | nindent 10 }} - command: [ "bash", "-exc"] - args: - - | - keepTrying=true - while [ $keepTrying = "true" ]; do - if sawtooth settings list --url http://$HOST:$PORT | grep -q "chronicle.opa.policy_name"; then - break - else - echo "Waiting for OPA policy id." - sleep 10 - fi - done - env: - - name: HOST - value: {{ $stlServiceName }}.{{ .Release.Namespace }}.svc.cluster.local - - name: PORT - value: "{{ include "chronicle.sawtooth.rest" . }}" - {{- end }} containers: {{- if .Values.postgres.enabled }} - name: postgres @@ -113,7 +62,7 @@ spec: chronicle \ -c /etc/chronicle/config/config.toml \ --console-logging json \ - --sawtooth tcp://{{ include "chronicle.sawtooth.service" . }}:{{ include "chronicle.sawtooth.sawcomp" . }} \ + --substrate grpc://{{ include "chronicle.substrate.service" . }}:{{ include "chronicle.substrate.rpc" . }} \ --remote-database \ --database-name {{ .Values.postgres.database }} \ --database-username {{ .Values.postgres.user }} \ diff --git a/charts/chronicle/templates/tests/api-test.yaml b/charts/chronicle/templates/tests/api-test.yaml deleted file mode 100644 index 354a69d7f..000000000 --- a/charts/chronicle/templates/tests/api-test.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{- if .Values.test.api.enabled }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "common.names.fullname" . }}-api-test - labels: {{ include "chronicle.labels" . | nindent 4 }} - component: api-test - annotations: - "helm.sh/hook": test - "helm.sh/hook-delete-policy": hook-succeeded -spec: - backoffLimit: 0 - template: - spec: - restartPolicy: Never - serviceAccountName: {{ include "lib.serviceAccountName" . }} - automountServiceAccountToken: true - {{- if .Values.auth.required }} - {{ if not .Values.test.auth.token }} - {{ if not .Values.devIdProvider.enabled }} - {{ required "If 'auth.required' when using the api-test 'test.auth.token' must be provided or 'devIdProvider.enabled' must be set to 'true'!" .Values.devIdProvider.enabled }} - {{ end }} - initContainers: - - name: wait-for-id-provider - {{- include "lib.image" (dict "imageRoot" .Values.test.api.image "global" .Values.global ) | nindent 10 }} - command: [ "sh", "-c" ] - args: - - | - URL="{{ include "chronicle.id-provider.service.jwks.url" . }}" - - wait_for_url() { - local url=$1 - scheme=$(echo "$url" | cut -f 1 -d :) - hostAndPort=$(echo "$url" | cut -f 3 -d /) - HOST=$(echo "$hostAndPort" | cut -f 1 -d :) - port=$(echo "$hostAndPort" | awk -F: '{print $2}') - - case $scheme in - "http") - defaultPort=80 - ;; - "https") - defaultPort=443 - ;; - *) - defaultPort=80 - ;; - esac - - PORT=${port:-$defaultPort} - wait-for-it "$HOST:$PORT" --timeout=120 - } - - echo "Waiting for id-provider to be ready ..." - wait_for_url "$URL" - - if [ $? -eq 0 ]; then - echo "Id-provider is ready. Exiting." - exit 0 - else - echo "Timeout occurred. Please check if the correct URL has been provided." - exit 1 - fi - - name: token-loader - image: alpine/k8s:1.24.13 - command: [ "sh", "-ec" ] - args: - - | - echo "Waiting to ensure id-provider is ready ..." - sleep 20 - echo "Getting token from id-provider ..." - kubectl exec {{ include "chronicle.id-provider.service" . }}-0 -c id-provider -- oauth-token > /shared-data/jwks-token - echo "Token loaded. Exiting." - volumeMounts: - - name: shared-data - mountPath: /shared-data - {{ end }} - {{- end }} - containers: - - name: test - {{- include "lib.image" (dict "imageRoot" .Values.test.api.image "global" .Values.global ) | nindent 10 }} - command: [ "sh", "-ec" ] - args: - - | - {{ if not .Values.test.auth.token }} - {{ if or .Values.auth.jwks.url .Values.auth.userinfo.url }} - echo "Auth endpoints provided but no token provided." - echo "Please provide 'test.auth.token' in the values.yaml file." - exit 1 - {{ end }} - {{ end }} - - API={{ include "chronicle.api.service" . }} - export PORT={{ .Values.port }} - echo "Waiting for API to be ready ..." - wait-for-it $API:$PORT --timeout=0 - echo "Getting IP address for API ..." - getent hosts $API | cut -f 1 -d \ | head -n 1 > /shared-data/api-ip || exit 1 - - {{- if .Values.test.auth.token }} - echo "{{ .Values.test.auth.token }}" > /shared-data/jwks-token - {{- end }} - - if [ -f "/shared-data/jwks-token" ]; then - echo "Found token." - sleep 5 - export TOKEN=$(cat "/shared-data/jwks-token") - fi - - export HOST=$(cat /shared-data/api-ip) - echo "Testing API with subscribe-submit-test..." - subscribe-submit-test - exit_code=$? - if [ $exit_code -eq 0 ]; then - echo "Test complete." - exit $exit_code - else - echo "Test failed." - exit $exit_code - fi - env: - - name: REQUIRE_AUTH - value: {{ .Values.auth.required | quote }} - volumeMounts: - - name: shared-data - mountPath: /shared-data - volumes: {{- include "lib.volumes" .Values.opa.tp.extraVolumes | nindent 8 }} - - name: shared-data - emptyDir: {} -{{- end }} diff --git a/charts/chronicle/templates/tests/auth-endpoints-test.yaml b/charts/chronicle/templates/tests/auth-endpoints-test.yaml deleted file mode 100644 index 79f80f9e9..000000000 --- a/charts/chronicle/templates/tests/auth-endpoints-test.yaml +++ /dev/null @@ -1,160 +0,0 @@ -{{- if .Values.test.auth.enabled }} -{{ if not (or (.Values.devIdProvider.enabled) (or (.Values.auth.jwks.url) (.Values.auth.userinfo.url)))}} -{{ required "If 'test.auth.enabled' you need to provide 'auth.jwks.url', 'auth.userinfo.url', or enable the `devIdProvider`!" .Values.devIdProvider.enabled }} -{{ end }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "common.names.fullname" . }}-auth-endpoints-test - labels: {{ include "chronicle.labels" . | nindent 4 }} - component: auth-endpoints-test - annotations: - "helm.sh/hook": test - "helm.sh/hook-delete-policy": hook-succeeded -spec: - backoffLimit: 0 - template: - spec: - restartPolicy: Never - serviceAccountName: {{ include "lib.serviceAccountName" . }} - {{- if .Values.devIdProvider.enabled }} - automountServiceAccountToken: true - initContainers: - - name: wait - {{- include "lib.image" (dict "imageRoot" .Values.test.api.image "global" .Values.global ) | nindent 10 }} - command: [ "sh", "-c" ] - args: - - | - URL="{{ include "chronicle.id-provider.service.jwks.url" . }}" - - wait_for_url() { - local url=$1 - scheme=$(echo "$url" | cut -f 1 -d :) - hostAndPort=$(echo "$url" | cut -f 3 -d /) - HOST=$(echo "$hostAndPort" | cut -f 1 -d :) - port=$(echo "$hostAndPort" | awk -F: '{print $2}') - - case $scheme in - "http") - defaultPort=80 - ;; - "https") - defaultPort=443 - ;; - *) - defaultPort=80 - ;; - esac - - PORT=${port:-$defaultPort} - wait-for-it "$HOST:$PORT" --timeout=120 - } - - echo "Waiting for id-provider to be ready ..." - wait_for_url "$URL" - - if [ $? -eq 0 ]; then - echo "Id-provider is ready. Exiting." - exit 0 - else - echo "Timeout occurred. Please check if the correct URL has been provided." - exit 1 - fi - - name: tok - image: alpine/k8s:1.24.13 - command: [ "sh", "-ec" ] - args: - - | - echo "Waiting to ensure id-provider is ready ..." - sleep 20 - echo "Getting token from id-provider ..." - kubectl exec {{ include "chronicle.id-provider.service" . }}-0 -c id-provider -- oauth-token > /shared-data/jwks-token - echo "Token loaded. Exiting." - volumeMounts: - - name: shared-data - mountPath: /shared-data - {{- end }} - containers: - - name: jwks - image: alpine/k8s:1.24.13 - command: [ "sh", "-c"] - args: - - | - {{ if or (.Values.auth.jwks.url) (.Values.devIdProvider.enabled) }} - {{ if .Values.auth.jwks.url }} - echo "Checking provided JWKS endpoint: {{ .Values.auth.jwks.url }}." - endPoint="{{ .Values.auth.jwks.url }}" - {{ else if .Values.auth.userinfo.url }} - echo "JWKS endpoint not set but userinfo url is set - skipping JWKS check." - exit 0 - {{ else }} - echo "Checking JWKS endpoint from id-provider: {{ include "chronicle.id-provider.service.jwks.url" . }}." - endPoint="{{ include "chronicle.id-provider.service.jwks.url" . }}" - {{ end }} - - time curl -s -o /shared-data/jwks.json $endPoint - - cat /shared-data/jwks.json | jq . > /dev/null \ - || { echo "JWKS endpoint did not return a valid JSON object."; echo "DEBUG: $(cat /shared-data/jwks.json)"; exit 1; } - echo "JWKS endpoint returned a valid JSON object:" - cat /shared-data/jwks.json - echo - {{ else }} - echo "Skipping JWKS endpoint check." - {{ end }} - - echo -e "Exiting." - volumeMounts: - - name: shared-data - mountPath: /shared-data - - name: userinfo - image: alpine/k8s:1.24.13 - command: [ "sh", "-c"] - args: - - | - {{ if or (.Values.auth.userinfo.url) (.Values.devIdProvider.enabled) }} - {{ if .Values.auth.userinfo.url }} - {{ if not .Values.test.auth.token }} - {{ required "If providing 'auth.userinfo.url' you need to provide a 'test.auth.token'!" .Values.test.auth.token}} - {{ end }} - echo "Checking user-provided userinfo endpoint: $endPoint" - endPoint="{{ .Values.auth.userinfo.url }}" - {{ else if .Values.auth.jwks.url }} - echo "Userinfo endpoint not set but JWKS url is set - skipping userinfo check." - exit 0 - {{ else }} - echo "Checking id-provider userinfo endpoint: $endPoint" - endPoint="{{ include "chronicle.id-provider.service.userinfo.url" . }}" - {{ end }} - - {{ if .Values.test.auth.token }} - {{ if not .Values.auth.userinfo.url }} - {{ required "If providing 'test.auth.token' you need to provide a 'auth.userinfo.url'!" .Values.auth.userinfo.url }} - {{ end }} - echo "Using 'test.auth.token' to check userinfo endpoint." - time curl -s -H "Authorization: Bearer {{ .Values.test.auth.token }}" -o /shared-data/userinfo.json $endPoint - {{ else }} - echo "Using token from id-provider to check userinfo endpoint." - time curl -s -H "Authorization: Bearer $(cat /shared-data/jwks-token)" -o /shared-data/userinfo.json $endPoint - {{ end }} - - if jq -e 'has("error")' /shared-data/userinfo.json > /dev/null; then - echo "Userinfo endpoint returned an error:" - echo "DEBUG: $(cat /shared-data/userinfo.json)" - exit 1 - else - echo "Userinfo endpoint returned a valid JSON object: $(cat /shared-data/userinfo.json)" - echo - fi - {{ else }} - echo "Skipping userinfo endpoint check." - {{ end }} - - echo -e "Exiting." - volumeMounts: - - name: shared-data - mountPath: /shared-data - volumes: - - name: shared-data - emptyDir: {} -{{- end }} diff --git a/charts/chronicle/values.yaml b/charts/chronicle/values.yaml index 945a12087..470279e1d 100644 --- a/charts/chronicle/values.yaml +++ b/charts/chronicle/values.yaml @@ -36,8 +36,13 @@ devIdProvider: ## @md | `devIdProvider.image.tag` | the image tag | latest | tag: BTP2.1.0-0.7.4 -## @md | `endpoints` | which API endpoints to offer | data, graphql | +opa: + enabled: false + +## @md | `endpoints` | which API endpoints to offer | arrow, json-ld, graphql | endpoints: + arrow: + enabled: true data: enabled: true graphql: @@ -184,8 +189,19 @@ resources: volumes: {} -## @md | `sawtooth` | sawtooth options may be configured | see [Sawtooth](../sawtooth/README.md) | node: + vault: + keys: + - name: aura + type: aura + scheme: secp256k1 + vaultPath: kv/secret/chronicle-node # path at which the secret is located in Vault + vaultKey: aura # key under which the secret value is stored in Vault + extraDerivation: "//${HOSTNAME}//aura" # allows to have unique derived keys for each pod of the statefulset + nodeKey: + name: nodekey + vaultPath: kv/secret/chronicle-node + vaultKey: nodekey image: ## @md | `test.api.image.pullPolicy` | the image pull policy | IfNotPresent | pullPolicy: IfNotPresent @@ -196,3 +212,5 @@ node: node: chain: "chronicle" command: "node-chronicle" + + diff --git a/terraform/chronicle-substrate/.gitignore b/terraform/chronicle-substrate/.gitignore new file mode 100644 index 000000000..00b1cb0d8 --- /dev/null +++ b/terraform/chronicle-substrate/.gitignore @@ -0,0 +1,25 @@ +# Local .terraform directories +**/.terraform/* +.terraform.lock.hcl +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which might contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version control +# as they are data points which are potentially sensitive and subject to change depending on the environment. +*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# should not be checked into version control +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/terraform/chronicle-substrate/bootnode.tf b/terraform/chronicle-substrate/bootnode.tf new file mode 100644 index 000000000..3b1cf162d --- /dev/null +++ b/terraform/chronicle-substrate/bootnode.tf @@ -0,0 +1,25 @@ +#------------------------------------------------------------------------------ +# Bootnode deployment +#------------------------------------------------------------------------------ +resource "helm_release" "bootnode" { + name = var.helm_release_name + repository = "https://paritytech.github.io/helm-charts/" + chart = "node" + namespace = var.kubernetes_namespace + + values = [ + templatefile("templates/bootnode.tmpl", { + helm_release_name = var.helm_release_name + + kubernetes_namespace = var.kubernetes_namespace + kubernetes_image_pull_secrets = var.kubernetes_image_pull_secrets + + chronicle_node_repository = var.chronicle-node-repository + bootnode_key = var.bootnode-key + + node = { + command = "node-chronicle" + } + }) + ] +} diff --git a/terraform/chronicle-substrate/provider.tf b/terraform/chronicle-substrate/provider.tf new file mode 100644 index 000000000..d9112c608 --- /dev/null +++ b/terraform/chronicle-substrate/provider.tf @@ -0,0 +1,10 @@ +provider "kubernetes" { + config_path = "~/.kube/config" +} + +provider "helm" { + kubernetes { + config_path = "~/.kube/config" + } +} + diff --git a/terraform/chronicle-substrate/templates/bootnode.tmpl b/terraform/chronicle-substrate/templates/bootnode.tmpl new file mode 100644 index 000000000..948a4d096 --- /dev/null +++ b/terraform/chronicle-substrate/templates/bootnode.tmpl @@ -0,0 +1,110 @@ +fullnameOverride: bootnode +image: + repository: ${chronicle_node_repository} + tag: local + pullPolicy: IfNotPresent +node: + chain: local + customChainspec: true # see extraInitContainers, chainspec-generator + role: full + replicas: 1 + command: node-chronicle + chainData: + pruning: archive + storageClass: "" + chainKeystore: + mountInMemory: + enabled: true + perNodeServices: + relayP2pService: + enabled: true + vault: + enabled: false + keys: + - name: aura + type: aura + scheme: sr25519 + vaultPath: kv/chronicle_substrate/aura # path at which the secret is located in Vault + vaultKey: secretSeed # key under which the secret value is stored in Vault + extraDerivation: "//$${HOSTNAME}//aura" # allows to have unique derived keys for each pod of the statefulset + nodeKey: + name: nodekey + vaultPath: kv/chronicle-substrate/bootnode_key + vaultKey: key + + customNodeKey: ${bootnode_key} + flags: + - "--allow-private-ipv4" + - "--discover-local" + +ingress: + enabled: false + annotations: + kubernetes.io/ingress.class: TODO + external-dns.alpha.kubernetes.io/target: TODO + cert-manager.io/cluster-issuer: TODO + rules: + - host: chronicle-bootnode.paravela.io + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: bootnode + port: + number: 9944 + tls: + - secretName: chronicle-bootnode.paravela.io + hosts: + - chronicle-bootnode.paravela.io + +# Generate chainspec, and expose it as url +extraInitContainers: + - name: chainspec-generator + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + annotations: + vault.hashicorp.com/agent-inject: "true" + vault.hashicorp.com/role: 'bootnode' + vault.hashicorp.com/agent-inject-secret-bootnode_key: 'kv/chronicle_substrate/bootnode_key' + vault.hashicorp.com/agent-inject-secret-bootnode_peer: 'kv/chronicle_substrate/bootnode_peer' + vault.hashicorp.com/ca-cert: "/vault/tls/ca.crt" + securityContext: + runAsUser: 0 + command: [ "/bin/bash" ] + args: + - -c + - | + apt update && apt install -y jq + {{ .Values.node.command }} build-spec --chain {{ .Values.node.chain }} > base.json + if [ ! -s base.json ]; then + echo "base.json is empty or missing." + exit 1 + fi + echo '{"bootNodes":["/dns/bootnode-0/tcp/30333/p2p/12D3KooWRpzRTivvJ5ySvgbFnPeEE6rDhitQKL1fFJvvBGhnenSk"]}' > override1.json + jq -s '.[0] * .[1]' base.json override1.json | sed 's/1e+18/1000000000000000000/' > plain.json + if [ ! -s plain.json ]; then + echo "plain.json is empty or malformed after jq processing." + exit 1 + fi + cut -c -256 plain.json + {{ .Values.node.command }} build-spec --chain plain.json --raw > chainspec.json + if [ ! -s chainspec.json ]; then + echo "chainspec.json failed to generate." + exit 1 + fi + cp chainspec.json {{ .Values.node.customChainspecPath }} + volumeMounts: + - mountPath: /chain-data + name: chain-data +extraContainers: + - name: chainspec + image: nginxinc/nginx-unprivileged:stable + ports: + - containerPort: 8080 + name: web + volumeMounts: + - name: chain-data + subPath: chainspec.json + mountPath: /usr/share/nginx/html/chainspec.json + readOnly: true diff --git a/terraform/chronicle-substrate/variables.tf b/terraform/chronicle-substrate/variables.tf new file mode 100644 index 000000000..ec7c13fbc --- /dev/null +++ b/terraform/chronicle-substrate/variables.tf @@ -0,0 +1,60 @@ +variable "chronicle-node-repository" { + type = string + description = "The repository to pull the chronicle node image from" + default = "node-chronicle-arm64" +} + +variable "kubernetes_namespace" { + type = string + description = "The Kubernetes namespace to deploy Vault into" + default = "vault" +} + +variable "kubernetes_sa_name" { + type = string + description = "The Kubernetes Service Account that Vault will use" + default = "vault-sa" +} + +variable "kubernetes_image_pull_secrets" { + type = list(string) + description = "A list of Kubernetes secrets that hold any required image registry credentials" + default = null +} + +variable "kubernetes_extra_secret_environment_variables" { + type = list(map(string)) + description = "A list of maps referencing Kubernetes secrets and their environment variable to mount to the Vault pods" + default = null +} + + +variable "bootnode-key" { + type = string + description = "The bootnode key" + default = "80c30ac6ba927c6e5c0c9681aa9674f1d181d180853bcd3485cee9d18e931238" +} + +variable "helm_release_name" { + type = string + description = "The name of the Helm release" + default = "chronicle-substrate" +} + +variable "helm_chart_name" { + type = string + description = "The chart name in the Helm repository" + default = "node" +} + +variable "helm_repository" { + type = string + description = "The location of the Helm repository" + default = "hhttps://paritytech.github.io/helm-charts/" +} + +variable "vault_replicas" { + type = number + description = "The number of Vault replicas to deploy" + default = 3 +} diff --git a/terraform/chronicle/.gitignore b/terraform/chronicle/.gitignore new file mode 100644 index 000000000..00b1cb0d8 --- /dev/null +++ b/terraform/chronicle/.gitignore @@ -0,0 +1,25 @@ +# Local .terraform directories +**/.terraform/* +.terraform.lock.hcl +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which might contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version control +# as they are data points which are potentially sensitive and subject to change depending on the environment. +*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# should not be checked into version control +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/terraform/signoz/.gitignore b/terraform/signoz/.gitignore new file mode 100644 index 000000000..d9a804e87 --- /dev/null +++ b/terraform/signoz/.gitignore @@ -0,0 +1,26 @@ +# Local .terraform directories +**/.terraform/* +.terraform.lock.hcl + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which might contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version control +# as they are data points which are potentially sensitive and subject to change depending on the environment. +*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# should not be checked into version control +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/terraform/signoz/output.tf b/terraform/signoz/output.tf new file mode 100644 index 000000000..4bf1b4a3e --- /dev/null +++ b/terraform/signoz/output.tf @@ -0,0 +1,32 @@ +output "otel_collector_service_name" { + value = "${helm_release.signoz.name}-otel-collector" + description = "The service name of the OpenTelemetry collector deployed with SigNoz." +} + +output "otel_collector_service_url" { + value = "http://${helm_release.signoz.name}-otel-collector.${var.signoz_namespace}.svc.cluster.local" + description = "The URL to access the OpenTelemetry collector service." +} + +output "otel_collector_service_port" { + value = "4317" + description = "The default gRPC port for the OpenTelemetry collector service." +} + +output "signoz_frontend_service_name" { + value = "${helm_release.signoz.name}-frontend" + description = "The service name of the SigNoz frontend." +} + +output "signoz_frontend_service_url" { + value = "http://${helm_release.signoz.name}-frontend.${var.signoz_namespace}.svc.cluster.local" + description = "The URL to access the SigNoz frontend service." +} + +output "signoz_frontend_service_port" { + value = "3000" + description = "The default port for the SigNoz frontend service." +} + + + diff --git a/terraform/signoz/provider.tf b/terraform/signoz/provider.tf new file mode 100644 index 000000000..912fdd629 --- /dev/null +++ b/terraform/signoz/provider.tf @@ -0,0 +1,9 @@ +provider "kubernetes" { + config_path = "~/.kube/config" +} + +provider "helm" { + kubernetes { + config_path = "~/.kube/config" + } +} diff --git a/terraform/signoz/signoz.tf b/terraform/signoz/signoz.tf new file mode 100644 index 000000000..97cb64dd4 --- /dev/null +++ b/terraform/signoz/signoz.tf @@ -0,0 +1,22 @@ +resource "helm_release" "signoz" { + name = "signoz" + repository = var.signoz_helm_repository + chart = var.signoz_helm_chart_name + namespace = var.signoz_namespace + create_namespace = true + + set { + name = "frontend.replicaCount" + value = var.signoz_fe_replicas + } + + set { + name = "queryService.replicaCount" + value = var.signoz_query_replicas + } + + set { + name = "storage.size" + value = var.signoz_storage_size + } +} diff --git a/terraform/signoz/variables.tf b/terraform/signoz/variables.tf new file mode 100644 index 000000000..e7a2f9ebb --- /dev/null +++ b/terraform/signoz/variables.tf @@ -0,0 +1,37 @@ +variable "signoz_namespace" { + type = string + description = "The Kubernetes namespace to deploy SigNoz into" + default = "observabilty" +} + +variable "signoz_helm_chart_name" { + type = string + description = "The chart name in the Helm repository for SigNoz" + default = "signoz" +} + +variable "signoz_helm_repository" { + type = string + description = "The location of the Helm repository for SigNoz" + default = "https://charts.signoz.io/" +} + +variable "signoz_fe_replicas" { + type = number + description = "The number of SigNoz replicas to deploy" + default = 1 +} + + +variable "signoz_query_replicas" { + type = number + description = "The number of SigNoz replicas to deploy" + default = 1 +} + +variable "signoz_storage_size" { + type = string + description = "The size, in Gi, of the storage volume for SigNoz" + default = "20" +} + diff --git a/terraform/vault-configuration/.gitignore b/terraform/vault-configuration/.gitignore new file mode 100644 index 000000000..f8bc12791 --- /dev/null +++ b/terraform/vault-configuration/.gitignore @@ -0,0 +1,25 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which might contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version control +# as they are data points which are potentially sensitive and subject to change depending on the environment. +*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# should not be checked into version control +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/terraform/vault-configuration/BOOTNODE_KEY b/terraform/vault-configuration/BOOTNODE_KEY new file mode 100644 index 000000000..41ffceccc --- /dev/null +++ b/terraform/vault-configuration/BOOTNODE_KEY @@ -0,0 +1 @@ +4c0f9119a13ddc0d0382b7798fbbd08c639ca26f9fe344170ab93bad26b3c577 \ No newline at end of file diff --git a/terraform/vault-configuration/BOOTNODE_PEER_ID b/terraform/vault-configuration/BOOTNODE_PEER_ID new file mode 100644 index 000000000..41ffceccc --- /dev/null +++ b/terraform/vault-configuration/BOOTNODE_PEER_ID @@ -0,0 +1 @@ +4c0f9119a13ddc0d0382b7798fbbd08c639ca26f9fe344170ab93bad26b3c577 \ No newline at end of file diff --git a/terraform/vault-configuration/policies/admin.hcl b/terraform/vault-configuration/policies/admin.hcl new file mode 100644 index 000000000..02c929008 --- /dev/null +++ b/terraform/vault-configuration/policies/admin.hcl @@ -0,0 +1,58 @@ +# Manage auth methods broadly across Vault +path "auth/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# Create, update, and delete auth methods +path "sys/auth/*" +{ + capabilities = ["create", "update", "delete", "sudo"] +} + +# List auth methods +path "sys/auth" +{ + capabilities = ["read"] +} + +# List existing policies +path "sys/policies/acl" +{ + capabilities = ["list"] +} + +# Create and manage ACL policies +path "sys/policies/acl/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# List, create, update, and delete key/value secrets +path "secret/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# Manage secrets engines +path "sys/mounts/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# List existing secrets engines. +path "sys/mounts" +{ + capabilities = ["read"] +} + +# Read health checks +path "sys/health" +{ + capabilities = ["read", "sudo"] +} + +path "kv/*" +{ + capabilities = ["create", "read", "update", "delete", "list"] +} diff --git a/terraform/vault-configuration/policies/bootnode.hcl b/terraform/vault-configuration/policies/bootnode.hcl new file mode 100644 index 000000000..13c870352 --- /dev/null +++ b/terraform/vault-configuration/policies/bootnode.hcl @@ -0,0 +1,4 @@ +path "kv/chronicle-substrate/*" +{ + capabilities = ["create", "read", "update", "delete", "list"] +} diff --git a/terraform/vault-configuration/policies/chronicle.hcl b/terraform/vault-configuration/policies/chronicle.hcl new file mode 100644 index 000000000..0966630e5 --- /dev/null +++ b/terraform/vault-configuration/policies/chronicle.hcl @@ -0,0 +1,4 @@ +path "kv/chronicle/*" +{ + capabilities = ["create", "read", "update", "delete", "list"] +} diff --git a/terraform/vault-configuration/provider.tf b/terraform/vault-configuration/provider.tf new file mode 100644 index 000000000..da874ddf3 --- /dev/null +++ b/terraform/vault-configuration/provider.tf @@ -0,0 +1,4 @@ +provider vault { + address = "https://localhost:8200" + ca_cert_file = var.vault_service_ca +} diff --git a/terraform/vault-configuration/variables.tf b/terraform/vault-configuration/variables.tf new file mode 100644 index 000000000..2ab862992 --- /dev/null +++ b/terraform/vault-configuration/variables.tf @@ -0,0 +1,48 @@ +variable "node_service_account" { + description = "The service account for the Chronicle Substrate node." + type = string + sensitive = false + default = "bootnode" +} + +variable "vault_token" { + description = "A vault access token with root permission" + type = string + sensitive = true + default = "s.VL1OYyHeeQ1Qxyg9FqSyKjBe" +} + +variable "bootnode_key" { + description = "The bootnode key for the Chronicle Substrate node." + type = string + sensitive = true +} + +variable "aura_key" { + description = "The bootnode key for the Chronicle Substrate node." + type = string + default = <