Skip to content

Commit 89f868a

Browse files
lezzagokylehounslow
authored andcommitted
Add anonymous auth to helm charts (#10)
* Get anon auth on terraform Signed-off-by: Ashish Agrawal <ashisagr@amazon.com> * Add back metrics port Signed-off-by: Ashish Agrawal <ashisagr@amazon.com> --------- Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>Signed-off-by: Kyle Hounslow <kylhouns@amazon.com> Signed-off-by: Kyle Hounslow <kylhouns@amazon.com>
1 parent 0c6148b commit 89f868a

7 files changed

Lines changed: 264 additions & 9 deletions

File tree

charts/observability-stack/files/init-opensearch-dashboards.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
PROMETHEUS_HOST = os.getenv("PROMETHEUS_HOST", "prometheus")
1515
PROMETHEUS_PORT = os.getenv("PROMETHEUS_PORT", "9090")
1616
_opensearch_protocol = os.getenv("OPENSEARCH_PROTOCOL", "https")
17-
OPENSEARCH_ENDPOINT = f"{_opensearch_protocol}://{os.getenv('OPENSEARCH_HOST', 'opensearch')}:{os.getenv('OPENSEARCH_PORT', '9200')}"
17+
OPENSEARCH_ENDPOINT = os.getenv("OPENSEARCH_ENDPOINT", f"{_opensearch_protocol}://{os.getenv('OPENSEARCH_HOST', 'opensearch')}:{os.getenv('OPENSEARCH_PORT', '9200')}")
1818

1919
def wait_for_dashboards():
2020
"""Wait for OpenSearch Dashboards to be ready"""
@@ -100,6 +100,43 @@ def create_workspace():
100100
return "default"
101101

102102

103+
def set_default_workspace(workspace_id):
104+
"""Set the default workspace so all users land here on login.
105+
106+
When workspace.enabled is true, users see a workspace picker on first load.
107+
Setting defaultWorkspace directs all users (including anonymous) straight
108+
to the Observability Stack workspace instead.
109+
"""
110+
if not workspace_id or workspace_id == "default":
111+
print("⏭️ Skipping default workspace (using default)")
112+
return False
113+
114+
print(f"⭐ Setting default workspace: {workspace_id}")
115+
116+
url = f"{BASE_URL}/api/opensearch-dashboards/settings"
117+
payload = {"changes": {"defaultWorkspace": workspace_id}}
118+
119+
try:
120+
response = requests.post(
121+
url,
122+
auth=(USERNAME, PASSWORD),
123+
headers={"Content-Type": "application/json", "osd-xsrf": "true"},
124+
json=payload,
125+
verify=False,
126+
timeout=10,
127+
)
128+
129+
if response.status_code == 200:
130+
print("✅ Default workspace set")
131+
return True
132+
else:
133+
print(f"⚠️ Failed to set default workspace: {response.status_code} {response.text}")
134+
return False
135+
except requests.exceptions.RequestException as e:
136+
print(f"⚠️ Error setting default workspace: {e}")
137+
return False
138+
139+
103140
def get_existing_index_pattern(workspace_id, title):
104141
"""Check if an index pattern with the given title already exists"""
105142
try:
@@ -230,9 +267,13 @@ def create_prometheus_datasource(workspace_id):
230267

231268
prometheus_endpoint = f"http://{PROMETHEUS_HOST}:{PROMETHEUS_PORT}"
232269

270+
# Grant anonymous users access to the Prometheus datasource when anonymous auth is enabled
271+
anonymous_auth = os.getenv("ANONYMOUS_AUTH_ENABLED", "false").lower() == "true"
272+
allowed_roles = ["all_access", "opendistro_security_anonymous_role"] if anonymous_auth else ["all_access"]
273+
233274
payload = {
234275
"name": datasource_name,
235-
"allowedRoles": [],
276+
"allowedRoles": allowed_roles,
236277
"connector": "prometheus",
237278
"properties": {
238279
"prometheus.uri": prometheus_endpoint,
@@ -1253,6 +1294,9 @@ def main():
12531294
else:
12541295
workspace_id = create_workspace()
12551296

1297+
# Set as default workspace so users skip the workspace picker
1298+
set_default_workspace(workspace_id)
1299+
12561300
# Create index patterns (idempotent - will skip if already exist)
12571301
# Titles must match exactly what the APM plugin expects
12581302
logs_schema_mappings = '{"otelLogs":{"timestamp":"time","traceId":"traceId","spanId":"spanId","serviceName":"resource.attributes.service.name"}}'

charts/observability-stack/templates/init-dashboards-job.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ spec:
4444
value: "80"
4545
- name: OPENSEARCH_ENDPOINT
4646
value: "https://opensearch-cluster-master:9200"
47+
- name: ANONYMOUS_AUTH_ENABLED
48+
value: {{ ((.Values.anonymousAuth).enabled) | default false | quote }}
4749
volumeMounts:
4850
- name: init-script
4951
mountPath: /scripts
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Anonymous Authentication overlay for Observability Stack Helm chart.
2+
#
3+
# Usage:
4+
# helm install obs-stack . -f values-anonymous-auth.yaml
5+
# helm upgrade obs-stack . -f values-anonymous-auth.yaml
6+
#
7+
# This enables anonymous access to OpenSearch Dashboards — users can browse
8+
# data, view/create/modify saved objects, explore traces, and run queries
9+
# without logging in. They cannot delete existing saved objects or perform
10+
# admin operations.
11+
#
12+
# IMPORTANT: If toggling on an existing deployment, you must delete the
13+
# OpenSearch StatefulSet PVCs to force security config reinitialization:
14+
# helm uninstall obs-stack
15+
# kubectl delete pvc -l app.kubernetes.io/instance=obs-stack
16+
# helm install obs-stack . -f values-anonymous-auth.yaml
17+
18+
anonymousAuth:
19+
enabled: true
20+
21+
# OpenSearch — enable anonymous auth in the security plugin
22+
opensearch:
23+
securityConfig:
24+
config:
25+
dataComplete: false
26+
data:
27+
config.yml: |-
28+
_meta:
29+
type: "config"
30+
config_version: 2
31+
config:
32+
dynamic:
33+
http:
34+
anonymous_auth_enabled: true
35+
xff:
36+
enabled: false
37+
internalProxies: "192\\.168\\.0\\.10|192\\.168\\.0\\.11"
38+
authc:
39+
basic_internal_auth_domain:
40+
description: "Authenticate via HTTP Basic against internal users database"
41+
http_enabled: true
42+
transport_enabled: true
43+
order: 4
44+
http_authenticator:
45+
type: "basic"
46+
challenge: true
47+
authentication_backend:
48+
type: "intern"
49+
roles.yml: |-
50+
_meta:
51+
type: "roles"
52+
config_version: 2
53+
opendistro_security_anonymous_role:
54+
reserved: true
55+
cluster_permissions:
56+
- "read"
57+
- "cluster_monitor"
58+
- "cluster_composite_ops"
59+
- "indices:data/read/scroll*"
60+
- "cluster:admin/opensearch/ppl"
61+
- "cluster:admin/opensearch/sql"
62+
- "cluster:admin/opensearch/ql/datasources/read"
63+
- "cluster:admin/opensearch/ql/async_query/read"
64+
- "cluster:admin/opensearch/direct_query/read/query"
65+
index_permissions:
66+
- index_patterns:
67+
- ".kibana"
68+
- ".kibana-6"
69+
- ".kibana_*"
70+
- ".opensearch_dashboards"
71+
- ".opensearch_dashboards-6"
72+
- ".opensearch_dashboards_*"
73+
allowed_actions:
74+
- "read"
75+
- "indices:data/write/index*"
76+
- "indices:data/write/update*"
77+
- "indices:data/write/bulk*"
78+
- index_patterns:
79+
- ".tasks"
80+
- ".management-beats"
81+
- "*:.tasks"
82+
- "*:.management-beats"
83+
allowed_actions:
84+
- "read"
85+
- index_patterns:
86+
- '*'
87+
allowed_actions:
88+
- "read"
89+
- "indices:data/read/*"
90+
- "indices:admin/get"
91+
- "indices:admin/exists"
92+
- "indices:admin/aliases/exists*"
93+
- "indices:admin/aliases/get*"
94+
- "indices:admin/mappings/get"
95+
- "indices:admin/resolve/index"
96+
- "indices:monitor/settings/get"
97+
- "indices:monitor/stats"
98+
tenant_permissions:
99+
- tenant_patterns:
100+
- '*'
101+
allowed_actions:
102+
- "kibana_all_write"
103+
roles_mapping.yml: |-
104+
_meta:
105+
type: "rolesmapping"
106+
config_version: 2
107+
opendistro_security_anonymous_role:
108+
backend_roles:
109+
- "opendistro_security_anonymous_backendrole"
110+
all_access:
111+
reserved: true
112+
backend_roles:
113+
- "admin"
114+
description: "Maps admin to all_access"
115+
kibana_server:
116+
reserved: true
117+
users:
118+
- "kibanaserver"
119+
description: "Maps kibana_server role to kibanaserver user"
120+
121+
# OpenSearch Dashboards — enable anonymous login and disable saved-object
122+
# permission checks (required so anonymous users can access workspaces
123+
# created by the init script; OSD doesn't support per-workspace permission
124+
# grants via the API).
125+
opensearch-dashboards:
126+
config:
127+
opensearch_dashboards.yml: |
128+
server.host: "0.0.0.0"
129+
server.name: "observability-stack-dashboards"
130+
opensearch.hosts: ["https://opensearch-cluster-master:9200"]
131+
opensearch.username: "admin"
132+
opensearch.password: "My_password_123!@#"
133+
opensearch.ssl.verificationMode: none
134+
opensearch.requestTimeout: 30000
135+
opensearch.requestHeadersAllowlist: ["authorization", "securitytenant"]
136+
opensearch_security.auth.anonymous_auth_enabled: true
137+
savedObjects.permission.enabled: false
138+
opensearch_security.multitenancy.enabled: false
139+
opensearch_security.readonly_mode.roles: ["kibana_read_only"]
140+
console.enabled: true
141+
server.maxPayloadBytes: 1048576
142+
savedObjects.maxImportPayloadBytes: 26214400
143+
csp.strict: false
144+
explore.enabled: true
145+
explore.discoverTraces.enabled: true
146+
explore.discoverMetrics.enabled: true
147+
explore.agentTraces.enabled: true
148+
workspace.enabled: true
149+
data_source.enabled: true
150+
data_source.ssl.verificationMode: none
151+
datasetManagement.enabled: true
152+
data.savedQueriesNewUI.enabled: true
153+
opensearchDashboards.branding.useExpandedHeader: false
154+
uiSettings.overrides.home:useNewHomePage: true
155+
uiSettings.overrides.query:enhancements:enabled: true
156+
uiSettings.overrides.explore:experimental: true

charts/observability-stack/values.yaml

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,43 @@ opensearch:
2626
enabled: true
2727
size: 8Gi # Increase for production (e.g. 100Gi, 500Gi)
2828
# storageClass: "gp3" # Uncomment for AWS gp3 (better IOPS/$ than gp2)
29+
# JVM heap — set to 50% of resources.requests.memory, max 31g
30+
opensearchJavaOpts: "-Xms2g -Xmx2g"
2931
extraEnvs:
3032
- name: OPENSEARCH_INITIAL_ADMIN_PASSWORD
3133
value: "My_password_123!@#"
32-
# JVM heap — set to 50% of resources.requests.memory, max 31g
33-
- name: OPENSEARCH_JAVA_OPTS
34-
value: "-Xms2g -Xmx2g"
3534
config:
3635
opensearch.yml: |
3736
plugins.query.datasources.encryption.masterkey: "BTqK4Ytdz67La1kShIKV3Pu9"
37+
# Security config — controls anonymous authentication.
38+
# Default: anonymous auth disabled. To enable, use values-anonymous-auth.yaml overlay
39+
# or set opensearch.securityConfig.config.data."config.yml" with anonymous_auth_enabled: true.
40+
securityConfig:
41+
config:
42+
dataComplete: false
43+
data:
44+
config.yml: |-
45+
_meta:
46+
type: "config"
47+
config_version: 2
48+
config:
49+
dynamic:
50+
http:
51+
anonymous_auth_enabled: false
52+
xff:
53+
enabled: false
54+
internalProxies: "192\\.168\\.0\\.10|192\\.168\\.0\\.11"
55+
authc:
56+
basic_internal_auth_domain:
57+
description: "Authenticate via HTTP Basic against internal users database"
58+
http_enabled: true
59+
transport_enabled: true
60+
order: 4
61+
http_authenticator:
62+
type: "basic"
63+
challenge: true
64+
authentication_backend:
65+
type: "intern"
3866
3967
# -- OpenSearch Dashboards
4068
opensearch-dashboards:
@@ -430,6 +458,22 @@ prometheus:
430458
opensearchUsername: "admin"
431459
opensearchPassword: "My_password_123!@#"
432460

461+
# -- Anonymous Authentication
462+
# When enabled, users can access OpenSearch Dashboards without logging in.
463+
# Anonymous users can browse data, view/create/modify saved objects, explore
464+
# traces and service maps, run queries, and access the REST API.
465+
# They cannot delete existing saved objects or perform admin operations.
466+
#
467+
# To enable:
468+
# helm install obs-stack . -f values-anonymous-auth.yaml
469+
#
470+
# Or override individual values:
471+
# --set anonymousAuth.enabled=true
472+
# (plus the opensearch.securityConfig and opensearch-dashboards.config overrides
473+
# shown in values-anonymous-auth.yaml)
474+
anonymousAuth:
475+
enabled: false
476+
433477
# -- OpenSearch Prometheus Exporter
434478
opensearchExporter:
435479
enabled: true

terraform/aws/observability-stack.tf

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ resource "helm_release" "observability_stack" {
114114
wait_for_jobs = true
115115
cleanup_on_fail = true
116116

117-
values = [file("${path.module}/values-eks.yaml")]
117+
values = concat(
118+
[file("${path.module}/values-eks.yaml")],
119+
var.anonymous_auth ? [file("${path.module}/../../charts/observability-stack/values-anonymous-auth.yaml")] : []
120+
)
118121

119122
# --- TLS / Domain (conditional) ---
120123
dynamic "set" {
@@ -163,6 +166,12 @@ resource "helm_release" "observability_stack" {
163166
}
164167
}
165168

169+
# --- Examples (conditional) ---
170+
set {
171+
name = "examples.enabled"
172+
value = var.enable_examples ? "true" : "false"
173+
}
174+
166175
depends_on = [
167176
helm_release.aws_lb_controller,
168177
]

terraform/aws/values-eks.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ opensearch:
1919
limits:
2020
memory: "4Gi"
2121
cpu: "4000m"
22+
opensearchJavaOpts: "-Xms2g -Xmx2g"
2223
extraEnvs:
2324
- name: OPENSEARCH_INITIAL_ADMIN_PASSWORD
2425
value: "My_password_123!@#"
25-
- name: OPENSEARCH_JAVA_OPTS
26-
value: "-Xms2g -Xmx2g"
2726

2827
opensearch-dashboards:
2928
replicaCount: 3
@@ -58,6 +57,7 @@ prometheus:
5857
persistentVolume:
5958
enabled: true
6059
size: 50Gi
60+
storageClass: gp2
6161
resources:
6262
requests:
6363
memory: "2Gi"

terraform/aws/variables.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ variable "node_instance_type" {
3030
variable "node_count" {
3131
description = "Number of EKS worker nodes"
3232
type = number
33-
default = 2
33+
default = 3
3434
}
3535

3636
# ============================================================================

0 commit comments

Comments
 (0)