Skip to content
Open
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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,27 @@ mysql:/var/run/mysqld/mysqld.sock - for Unix socket connection

For additional details please refer to [xo/dburl](https://github.com/xo/dburl) documentation.

> When using the Helm chart, you can automatically append the `application_name` parameter to PostgreSQL DSNs by setting `dynamicConfig.useApplicationName: true` for better connection tracking and monitoring. See [Helm chart documentation](helm/README.md) for details.

> When running on Kubernetes, the DSN can be sourced from an existing Secret for secure and dynamic configuration. See the [dynamic-config-only example](examples/dynamic-config-only/) for details.


## Security Features

The Helm chart provides enterprise-grade security capabilities for protecting your metrics endpoint:

### TLS/HTTPS Encryption
Secure metrics transport using TLS certificates from Kubernetes secrets. Supports TLS 1.3 with configurable cipher suites. See [tls-only example](examples/tls-only/).

### Basic Authentication
Password-protected metrics endpoint with bcrypt-hashed credentials. Passwords are automatically hashed during pod initialization from plaintext secrets. See [auth-only example](examples/auth-only/).

### Combined Security
TLS and authentication can be used together, with support for shared or separate Kubernetes secrets for maximum flexibility. See [tls-auth-dynamic example](examples/tls-auth-dynamic/).

### Prometheus Integration
Kubernetes-native ServiceMonitor automatically configures Prometheus for HTTPS scraping and basic authentication when enabled.


## Miscellaneous

Expand Down
25 changes: 25 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# SQL Exporter Examples

This directory contains example configurations for various use cases of the SQL Exporter.

## Directory Structure

### Database-specific Examples
- **`postgres/`** - PostgreSQL-specific collectors and queries
- **`mssql/`** - Microsoft SQL Server collectors
- **`azure-sql-mi/`** - Azure SQL Managed Instance with Grafana dashboards

### Helm Configuration Examples
- **`tls-only/`** - TLS encryption with certificates from Kubernetes secret
- **`auth-only/`** - Basic authentication with bcrypt password hashing
- **`dynamic-config-only/`** - Dynamic configuration from external secret (DSN)
- **`tls-auth-dynamic/`** - Combined TLS, authentication, and dynamic config

## Contributing

When adding new examples:
1. Create a new subdirectory
2. Include `values.yaml`, `README.md`, and any `secret-*.yaml` files
3. Update this main README with a link
4. Test the example in a real Kubernetes cluster
5. Document all prerequisites and customization options
88 changes: 88 additions & 0 deletions examples/auth-only/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Example: Basic Authentication Only

This example demonstrates how to deploy SQL Exporter with basic authentication for the metrics endpoint, without TLS encryption.

## Use Case

- You need access control via username/password
- TLS is handled at infrastructure level (e.g., service mesh, ingress with TLS termination)
- Want to restrict who can access metrics

## Files

- **`values-example.yaml`** - Helm values file configuring basic auth
- **`secret-auth.yaml`** - Complete guide for creating auth password secret (multiple methods)

## Prerequisites

Create a Kubernetes secret with plaintext password:

```bash
kubectl create secret generic sql-exporter-auth \
--from-literal=password='your-secure-password' \
--namespace=your-namespace
```

For more options (External Secrets, Sealed Secrets), see `secret-auth.yaml`.

## Deployment

```bash
helm install sql-exporter ../../helm -f values-example.yaml
```

## Key Features

- **Basic authentication** with username/password
- Password automatically hashed with bcrypt at pod startup (cost: 12)
- HTTP metrics endpoint (no TLS)
- Health probes use `tcpSocket` (httpGet doesn't support auth headers)
- Init container reads plaintext password and generates bcrypt hash

## Verification

```bash
# Check pod status
kubectl get pods -l app.kubernetes.io/name=sql-exporter

# Test metrics endpoint (with auth)
kubectl port-forward svc/sql-exporter 9399:9399
curl -u prometheus:your-secure-password http://localhost:9399/metrics
```

## Important Notes

**Prometheus ServiceMonitor with Basic Auth:**
ServiceMonitor supports basic auth credentials only when referenced from a Kubernetes secret. You'll need to:
1. Create a secret with username and password for Prometheus to use
2. Configure the ServiceMonitor to reference this secret via `basicAuth` field
3. This is separate from the password secret used by sql-exporter itself

For production, consider using TLS + auth combination (`tls-auth-dynamic` example) for better security.

**Security Considerations:**
- Password is transmitted in plaintext (no TLS) - use only in trusted networks
- For production, **strongly recommend** using TLS + auth combination
- See `../tls-auth-dynamic/` example for complete security

## Customization

Edit `values-example.yaml` to:
- Change username (default: `prometheus`)
- Change database connection string
- Adjust bcrypt cost (higher = more secure but slower)
- Add/modify collectors
- Configure resource limits

## How It Works

1. Init container (`httpd:alpine`) runs at pod startup
2. Reads plaintext password from secret
3. Hashes password using `htpasswd` with bcrypt
4. Writes `web-config.yml` with hashed password to emptyDir
5. Main container mounts the generated web-config and enforces auth

## Logs

You may see harmless TLS handshake EOF errors from tcpSocket probes - this is expected behavior.

73 changes: 73 additions & 0 deletions examples/auth-only/secret-auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Example: Kubernetes Secret for Basic Authentication Password
# This file shows how to create a secret containing a plaintext password for sql-exporter basic auth
#
# There are multiple ways to create this secret:

# ============================================================================
# Method 1: kubectl create secret (Recommended - simplest)
# ============================================================================
# Create a secret with a plaintext password:
#
# kubectl create secret generic sql-exporter-auth \
# --from-literal=password='your-secure-password' \
# --namespace=your-namespace
#
# The password should be:
# - Strong and unique
# - At least 16 characters
# - Not shared with other services

# ============================================================================
# Method 2: kubectl apply -f (from YAML manifest)
# ============================================================================
# If you want to store the secret definition in version control:
#
# Step 1: Base64 encode your password:
# Linux/Mac:
# echo -n 'your-secure-password' | base64
# Windows PowerShell:
# [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('your-secure-password'))
#
# Step 2: Copy the base64 value into the YAML below and apply:
# kubectl apply -f secret-auth.yaml

---
apiVersion: v1
kind: Secret
metadata:
name: sql-exporter-auth
namespace: default # Change to your namespace
labels:
app: sql-exporter
type: Opaque
data:
# Base64-encoded plaintext password
# This example encodes: "MySecurePassword123!"
# Replace this with your actual base64-encoded password
password: TXlTZWN1cmVQYXNzd29yZDEyMyE=

# ============================================================================
# Verify the secret
# ============================================================================
# After creating the secret, verify it:
#
# kubectl get secret sql-exporter-auth
# kubectl describe secret sql-exporter-auth
#
# Retrieve the plaintext password (for verification):
#
# kubectl get secret sql-exporter-auth -o jsonpath='{.data.password}' | base64 -d

# ============================================================================
# Important Notes
# ============================================================================
# 1. The secret MUST be in the same namespace as the sql-exporter pod
# 2. The password is stored in PLAINTEXT (not bcrypt) - it will be hashed at pod startup
# 3. The default key name is 'password' but can be customized via:
# webConfig.basicAuth.initFromSecret.secretKey
# 4. For production, use a proper secrets management solution (Vault, External Secrets, etc.)
# 5. Never commit plaintext passwords to version control
# 6. Rotate passwords regularly
# 7. The init container (httpd:alpine) uses htpasswd to bcrypt hash the password
# with the cost specified in webConfig.basicAuth.bcryptCost (default: 12)

74 changes: 74 additions & 0 deletions examples/auth-only/values-example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Example: Helm values for Basic Authentication-only configuration
# This example shows how to enable basic authentication using a password from a Kubernetes secret
#
# Prerequisites:
# 1. Create a secret with plaintext password:
# kubectl create secret generic sql-exporter-auth \
# --from-literal=password='your-secure-password'
#
# Usage:
# helm install sql-exporter ../../helm -f values-example.yaml

image:
repository: burningalchemist/sql_exporter
tag: "0.18.6"

# Static configuration with target and collectors
createConfig: true
config:
global:
scrape_timeout: 10s
target:
data_source_name: "postgres://username:password@hostname:5432/database?sslmode=disable"
collectors:
- pg_stat_activity
collectors:
- collector_name: pg_stat_activity
metrics:
- metric_name: pg_stat_activity_count
type: gauge
help: 'Number of connections by state'
key_labels:
- state
values:
- count
query: |
SELECT
state,
COUNT(*) as count
FROM pg_stat_activity
GROUP BY state

# Enable web configuration with basic authentication (no TLS)
webConfig:
enabled: true
basicAuth:
# Enable basic authentication
enabled: true
# Username for /metrics endpoint
username: prometheus
# Bcrypt cost for password hashing (higher = more secure but slower)
bcryptCost: 12
# Use initContainer to read plaintext password from secret and hash it
initFromSecret:
enabled: true
# Secret containing plaintext password
secretName: sql-exporter-auth
# Key in the secret containing the password
secretKey: password
# Image with htpasswd for bcrypt hashing
image: httpd:alpine
imagePullPolicy: IfNotPresent

# ServiceMonitor configuration for Prometheus Operator
# Note: This chart uses ServiceMonitor (enabled by default) for Prometheus discovery.
# The prometheus.io/* annotations are NOT needed and are ignored by Prometheus Operator.
serviceMonitor:
enabled: true
interval: 30s
# Note: Prometheus ServiceMonitor does not support basic auth credentials
# You'll need to use a different scraping method or add TLS with basic auth

# Note: When basic auth is enabled, the health probes use tcpSocket instead of httpGet
# This is because httpGet probes don't support authentication headers

Loading
Loading