Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/helm-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.x'
python-version: '3.12.0'
check-latest: true

- name: Extract Helm repo dependencies from Chart.yaml
Expand Down
93 changes: 0 additions & 93 deletions .github/workflows/server-develop.yaml

This file was deleted.

16 changes: 12 additions & 4 deletions .github/workflows/server-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SEMANTIC_RELEASE_PACKAGE: ${{ github.repository }}
GO_VERSION: '1.24'
JF_REPOSITORY: obs-builds

permissions:
contents: write
Expand Down Expand Up @@ -119,6 +120,7 @@ jobs:
echo $BUILD_VERSION > ./diode-server/version/BUILD_VERSION.txt

- name: Build image and push
id: docker-build
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6
with:
context: diode-server
Expand All @@ -128,14 +130,20 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
tags: |
netboxlabs/diode-${{ matrix.app }}:latest
netboxlabs/diode-${{ matrix.app }}:${{ env.BUILD_VERSION }}
netboxlabs.jfrog.io/obs-builds/diode-${{ matrix.app }}:latest
netboxlabs.jfrog.io/obs-builds/diode-${{ matrix.app }}:${{ env.BUILD_VERSION }}
netboxlabs/${{ env.APP_NAME }}:latest
netboxlabs/${{ env.APP_NAME }}:${{ env.BUILD_VERSION }}
netboxlabs.jfrog.io/${{ env.JF_REPOSITORY }}/${{ env.APP_NAME }}:latest
netboxlabs.jfrog.io/${{ env.JF_REPOSITORY }}/${{ env.APP_NAME }}:${{ env.BUILD_VERSION }}
build-args: |
GO_VERSION=${{ env.GO_VERSION }}
SVC=${{ matrix.app }}

- name: Create and publish JFrog build
run: |
echo '${{ steps.docker-build.outputs.metadata }}' > build-metadata
jf rt build-docker-create ${{ env.JF_REPOSITORY }} --image-file build-metadata --build-name ${{ env.APP_NAME }} --build-number ${{ env.BUILD_VERSION }}
jf rt build-publish ${{ env.APP_NAME }} ${{ env.BUILD_VERSION }}

semantic-release:
name: Semantic release - ${{ matrix.app }}
uses: netboxlabs/diode/.github/workflows/reusable_semantic_release.yaml@develop
Expand Down
2 changes: 1 addition & 1 deletion charts/diode/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: diode
description: A Helm chart for Diode
type: application
version: 1.8.1
version: "1.9.0"
appVersion: "1.5.0"
home: https://github.com/netboxlabs/diode
sources:
Expand Down
7 changes: 6 additions & 1 deletion charts/diode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

A Helm chart for Diode

![Version: 1.8.1](https://img.shields.io/badge/Version-1.8.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.5.0](https://img.shields.io/badge/AppVersion-1.5.0-informational?style=flat-square)
![Version: 1.9.0](https://img.shields.io/badge/Version-1.9.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.5.0](https://img.shields.io/badge/AppVersion-1.5.0-informational?style=flat-square)

## Prerequisites

Expand Down Expand Up @@ -314,6 +314,11 @@ helm show values diode/diode
| externalPostgresql.username | string | `"diode"` | username |
| externalRedis.hostname | string | `"localhost"` | hostname |
| externalRedis.port | int | `6379` | port |
| externalRedis.tls.caPath | string | `""` | path to CA certificate to verify server |
| externalRedis.tls.clientCertPath | string | `""` | path to client certificate for mutual TLS |
| externalRedis.tls.clientKeyPath | string | `""` | path to client private key for mutual TLS |
| externalRedis.tls.enabled | bool | `false` | enable TLS |
| externalRedis.tls.skipVerify | bool | `false` | skip TLS verify |
| global.commonAnnotations | object | `{}` | common annotations for all resources |
| global.commonLabels | object | `{}` | common labels for all resources |
| global.diode | object | `{"busybox":{"image":"busybox:latest","imagePullPolicy":"IfNotPresent"},"hydra":{"waitForPostgres":true},"ingester":{"waitForRedis":true},"reconciler":{"waitForPostgres":true,"waitForRedis":true}}` | diode global configuration |
Expand Down
7 changes: 7 additions & 0 deletions charts/diode/templates/diode-ingester-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ data:
SENTRY_DSN: {{ $config.sentryDsn | quote }}
REDIS_HOST: {{ include "diode.redis.hostname" . | quote }}
REDIS_PORT: {{ include "diode.redis.port" . | quote }}
{{- if and .Values.externalRedis.tls .Values.externalRedis.tls.enabled }}
REDIS_TLS_ENABLED: "true"
REDIS_TLS_SKIP_VERIFY: {{ .Values.externalRedis.tls.skipVerify | default false | quote }}
REDIS_TLS_CA_PATH: {{ .Values.externalRedis.tls.caPath | default "" | quote }}
REDIS_TLS_CLIENT_KEY_PATH: {{ .Values.externalRedis.tls.clientKeyPath | default "" | quote }}
REDIS_TLS_CLIENT_CERT_PATH: {{ .Values.externalRedis.tls.clientCertPath | default "" | quote }}
{{- end }}
REDIS_STREAM_DB: {{ $config.redisStreamDb | default "1" | quote }}
TELEMETRY_METRICS_EXPORTER: {{ $config.telemetryMetricsExporter | quote }}
TELEMETRY_TRACES_EXPORTER: {{ $config.telemetryTracesExporter | default "none" | quote }}
Expand Down
7 changes: 7 additions & 0 deletions charts/diode/templates/diode-reconciler-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ data:
REDIS_PORT: {{ include "diode.redis.port" . | quote }}
REDIS_DB: {{ $config.redisDb | default "0" | quote }}
REDIS_STREAM_DB: {{ $config.redisStreamDb | default "1" | quote }}
{{- if and .Values.externalRedis.tls .Values.externalRedis.tls.enabled }}
REDIS_TLS_ENABLED: "true"
REDIS_TLS_SKIP_VERIFY: {{ .Values.externalRedis.tls.skipVerify | default false | quote }}
REDIS_TLS_CA_PATH: {{ .Values.externalRedis.tls.caPath | default "" | quote }}
REDIS_TLS_CLIENT_KEY_PATH: {{ .Values.externalRedis.tls.clientKeyPath | default "" | quote }}
REDIS_TLS_CLIENT_CERT_PATH: {{ .Values.externalRedis.tls.clientCertPath | default "" | quote }}
{{- end }}
MIGRATION_ENABLED: {{ $config.migrationEnabled | default "true" | quote }}
AUTO_APPLY_CHANGESETS: {{ $config.autoApplyChangesets | default "true" | quote }}
RECONCILER_RATE_LIMITER_RPS: {{ $config.reconcilerRateLimiterRps | default "20" | quote }}
Expand Down
11 changes: 11 additions & 0 deletions charts/diode/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ externalRedis:
hostname: localhost
# -- port
port: 6379
tls:
# -- enable TLS
enabled: false
# -- skip TLS verify
skipVerify: false
# -- path to CA certificate to verify server
caPath: ""
# -- path to client private key for mutual TLS
clientKeyPath: ""
# -- path to client certificate for mutual TLS
clientCertPath: ""

# Diode Auth configuration
diodeAuth:
Expand Down
14 changes: 11 additions & 3 deletions diode-server/cmd/ingester/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,18 @@ func main() {

metricRecorder.SetServiceInfo(ctx, fmt.Sprintf("%s.%s", version.GetBuildVersion(), version.GetBuildCommit()))

redisTLSConfig, err := cfg.RedisTLS.ToTLSConfig()
if err != nil {
s.Logger().Error("failed to create TLS config for Redis", "error", err)
metricRecorder.RecordServiceStartupAttempt(ctx, false)
os.Exit(1)
}

redisStreamClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisStreamDB,
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisStreamDB,
TLSConfig: redisTLSConfig,
})

if _, err := redisStreamClient.Ping(ctx).Result(); err != nil {
Expand Down
21 changes: 15 additions & 6 deletions diode-server/cmd/reconciler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,18 @@ func main() {
}
}

redisTLSConfig, err := cfg.RedisTLS.ToTLSConfig()
if err != nil {
s.Logger().Error("failed to create TLS config for Redis", "error", err)
metricRecorder.RecordServiceStartupAttempt(ctx, false)
os.Exit(1)
}

redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisDB,
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisDB,
TLSConfig: redisTLSConfig,
})

if _, err := redisClient.Ping(ctx).Result(); err != nil {
Expand All @@ -90,9 +98,10 @@ func main() {
}

redisStreamClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisStreamDB,
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisStreamDB,
TLSConfig: redisTLSConfig,
})

if _, err := redisStreamClient.Ping(ctx).Result(); err != nil {
Expand Down
6 changes: 5 additions & 1 deletion diode-server/ingester/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package ingester

import "github.com/netboxlabs/diode/diode-server/telemetry"
import (
"github.com/netboxlabs/diode/diode-server/telemetry"
"github.com/netboxlabs/diode/diode-server/tls"
)

// Config is the configuration for the ingester service
type Config struct {
Expand All @@ -10,5 +13,6 @@ type Config struct {
RedisPassword string `envconfig:"REDIS_PASSWORD" required:"true"`
RedisStreamDB int `envconfig:"REDIS_STREAM_DB" default:"1"`

RedisTLS tls.Config `envconfig:"REDIS_TLS"`
Telemetry telemetry.Config `envconfig:"TELEMETRY"`
}
6 changes: 5 additions & 1 deletion diode-server/reconciler/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package reconciler

import "github.com/netboxlabs/diode/diode-server/telemetry"
import (
"github.com/netboxlabs/diode/diode-server/telemetry"
"github.com/netboxlabs/diode/diode-server/tls"
)

// Config is the configuration for the reconciler service
type Config struct {
Expand Down Expand Up @@ -29,5 +32,6 @@ type Config struct {
DiodeToNetBoxClientID string `envconfig:"DIODE_TO_NETBOX_CLIENT_ID" required:"true"`
DiodeToNetBoxClientSecret string `envconfig:"DIODE_TO_NETBOX_CLIENT_SECRET" required:"true"`

RedisTLS tls.Config `envconfig:"REDIS_TLS"`
Telemetry telemetry.Config `envconfig:"TELEMETRY"`
}
12 changes: 9 additions & 3 deletions diode-server/reconciler/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ func NewServer(ctx context.Context, logger *slog.Logger, repository Repository,
var cfg Config
envconfig.MustProcess("", &cfg)

redisTLSConfig, err := cfg.RedisTLS.ToTLSConfig()
if err != nil {
return nil, fmt.Errorf("failed to create TLS config for Redis: %v", err)
}

redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisDB,
Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort),
Password: cfg.RedisPassword,
DB: cfg.RedisDB,
TLSConfig: redisTLSConfig,
})

if _, err := redisClient.Ping(ctx).Result(); err != nil {
Expand Down
55 changes: 55 additions & 0 deletions diode-server/tls/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package tls

import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"
)

// Config is the configuration for SSL/TLS settings
// Note the environment variables may be prefixed with REDIS_TLS_
// based on the application's configuration structure
type Config struct {
Enabled bool `envconfig:"ENABLED" default:"false"`
SkipVerify bool `envconfig:"SKIP_VERIFY" default:"false"`
CaPath string `envconfig:"CA_PATH" default:""`
ClientKeyPath string `envconfig:"CLIENT_KEY_PATH" default:""`
ClientCertPath string `envconfig:"CLIENT_CERT_PATH" default:""`
}

// ToTLSConfig converts the Diode TLS config to a Go Crypto TLS config
func (cfg *Config) ToTLSConfig() (*tls.Config, error) {
if !cfg.Enabled {
return nil, nil
}

tlsConfig := &tls.Config{
InsecureSkipVerify: cfg.SkipVerify,
MinVersion: tls.VersionTLS12,
}

// Load CA certificate if provided
if cfg.CaPath != "" {
caCert, err := os.ReadFile(cfg.CaPath)
if err != nil {
return nil, fmt.Errorf("failed to read CA certificate: %w", err)
}
caCertPool := x509.NewCertPool()
if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
return nil, fmt.Errorf("failed to append CA certificate to pool")
}
tlsConfig.RootCAs = caCertPool
}

// Load client certificate and key if provided
if cfg.ClientCertPath != "" && cfg.ClientKeyPath != "" {
cert, err := tls.LoadX509KeyPair(cfg.ClientCertPath, cfg.ClientKeyPath)
if err != nil {
return nil, fmt.Errorf("failed to load client certificate and key: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
}

return tlsConfig, nil
}
Loading