From c1b4211eb18ac2dadccd5166ebb26cac04a89cf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 22 Mar 2026 15:44:02 +0000 Subject: [PATCH 1/4] Bump urllib3 from 2.5.0 to 2.6.3 in /code/services/DHIdentity Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.5.0 to 2.6.3. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.3) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.6.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- code/services/DHIdentity/uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/services/DHIdentity/uv.lock b/code/services/DHIdentity/uv.lock index 1ab4878..6fb4711 100644 --- a/code/services/DHIdentity/uv.lock +++ b/code/services/DHIdentity/uv.lock @@ -656,11 +656,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.5.0" +version = "2.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, + { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] [[package]] From 7a0cb3d9abdd4d05e34b510e2617884ec52a9bc8 Mon Sep 17 00:00:00 2001 From: Sky Date: Wed, 25 Mar 2026 17:12:46 -0500 Subject: [PATCH 2/4] add basic dashboards for auto-deploy add basic dashboards for auto-deploy --- .../deepharbor_membership_overview.json | 654 ++++++++++++++++++ .../deepharbor_role_assignments.json | 151 ++++ 2 files changed, 805 insertions(+) create mode 100644 tools/grafana/provisioning/dashboards/deepharbor_membership_overview.json create mode 100644 tools/grafana/provisioning/dashboards/deepharbor_role_assignments.json diff --git a/tools/grafana/provisioning/dashboards/deepharbor_membership_overview.json b/tools/grafana/provisioning/dashboards/deepharbor_membership_overview.json new file mode 100644 index 0000000..b39dd1a --- /dev/null +++ b/tools/grafana/provisioning/dashboards/deepharbor_membership_overview.json @@ -0,0 +1,654 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Count of Deep Harbor members by membership level (type), with active/inactive breakdowns", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 0, + "links": [], + "panels": [ + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 0, + "y": 0 + }, + "id": 11, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT COUNT(*) AS \"Active Members\"\nFROM member\nWHERE UPPER(status->>'membership_status') = 'ACTIVE'", + "refId": "A" + } + ], + "title": "Active Members", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "yellow", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 5, + "y": 0 + }, + "id": 14, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT COUNT(*) AS \"Total Volunteers\"\nFROM member\nWHERE UPPER(status->>'membership_status') = 'ACTIVE'\n AND UPPER(COALESCE(status->>'membership_level', '')) IN (\n 'VOLUNTEER',\n 'AREA HOST',\n 'BOARD MEMBER / OFFICER',\n 'STRIPE VOLUNTEER W/ PAID STORAGE - $30',\n 'VOLUNTEER W/ STORAGE'\n )", + "refId": "A" + } + ], + "title": "Total Volunteers", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "purple", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 10, + "y": 0 + }, + "id": 13, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT COUNT(DISTINCT status->>'membership_level') AS \"Membership Levels\"\nFROM member\nWHERE status->>'membership_level' IS NOT NULL", + "refId": "A" + } + ], + "title": "Distinct Levels", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 15, + "y": 0 + }, + "id": 10, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT COUNT(*) AS \"Total Members\" FROM member", + "refId": "A" + } + ], + "title": "Total Contacts", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 15, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT COUNT(*) AS \"Total Contractors\"\nFROM member\nWHERE UPPER(status->>'membership_status') = 'ACTIVE'\n AND UPPER(COALESCE(status->>'membership_level', '')) LIKE '%CONTRACTOR%'", + "refId": "A" + } + ], + "title": "Total Contractors", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 20, + "y": 2 + }, + "id": 12, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT COUNT(*) AS \"Inactive Members\"\nFROM member\nWHERE UPPER(status->>'membership_status') != 'ACTIVE'", + "refId": "A" + } + ], + "title": "Inactive Members", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "footer": { + "reducers": [] + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": 0 + }, + { + "color": "green", + "value": 50 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "red", + "value": 500 + } + ] + } + }, + { + "id": "custom.footer.reducers", + "value": [ + "sum" + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "% of Total" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "decimals", + "value": 1 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 3, + "options": { + "cellHeight": "sm", + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n COALESCE(status->>'membership_level', '(not set)') AS \"Membership Level\",\n COUNT(*) AS \"Count\",\n ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER(), 1) AS \"% of Total\"\nFROM member\nWHERE UPPER(status->>'membership_status') = 'ACTIVE'\nGROUP BY status->>'membership_level'\nORDER BY COUNT(*) DESC", + "refId": "A" + } + ], + "title": "Membership Level Summary", + "type": "table" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "unit": "short" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "count", + "Stripe Member - $65" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 4, + "options": { + "displayLabels": [ + "name", + "percent" + ], + "legend": { + "displayMode": "table", + "placement": "right", + "showLegend": true, + "values": [ + "value", + "percent" + ] + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": true + }, + "sort": "desc", + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.3.3", + "targets": [ + { + "datasource": "DeepHarbor PostgreSQL", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n COALESCE(status->>'membership_level', '(not set)') AS \"membership_level\",\n COUNT(*) AS \"count\"\nFROM member\nWHERE UPPER(status->>'membership_status') = 'ACTIVE'\nGROUP BY status->>'membership_level'\nORDER BY COUNT(*) DESC", + "refId": "A" + } + ], + "title": "Active Members by Membership Level", + "type": "piechart" + } + ], + "preload": false, + "refresh": "5m", + "schemaVersion": 42, + "tags": [ + "deepharbor", + "members", + "membership" + ], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": [ + "$__all" + ] + }, + "datasource": "DeepHarbor PostgreSQL", + "definition": "SELECT DISTINCT COALESCE(status->>'membership_level', '(not set)') FROM member ORDER BY 1", + "includeAll": true, + "label": "Membership Level", + "multi": true, + "name": "membership_level", + "options": [], + "query": "SELECT DISTINCT COALESCE(status->>'membership_level', '(not set)') FROM member ORDER BY 1", + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "$__all", + "value": "$__all" + }, + "includeAll": true, + "label": "Membership Status", + "name": "membership_status", + "options": [ + { + "selected": false, + "text": "ACTIVE", + "value": "ACTIVE" + }, + { + "selected": false, + "text": "INACTIVE", + "value": "INACTIVE" + } + ], + "query": "ACTIVE,INACTIVE", + "type": "custom" + } + ] + }, + "time": { + "from": "now-30d", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Deep Harbor – Members by Membership Level", + "uid": "dh-members-by-type", + "version": 8 +} \ No newline at end of file diff --git a/tools/grafana/provisioning/dashboards/deepharbor_role_assignments.json b/tools/grafana/provisioning/dashboards/deepharbor_role_assignments.json new file mode 100644 index 0000000..4da3004 --- /dev/null +++ b/tools/grafana/provisioning/dashboards/deepharbor_role_assignments.json @@ -0,0 +1,151 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": "DeepHarbor PostgreSQL", + "description": "Count of members who currently have at least one role assigned.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "12.3.0", + "targets": [ + { + "dataset": "deepharbor", + "editorMode": "code", + "format": "table", + "rawSql": "SELECT COUNT(DISTINCT member_id) AS members_with_roles FROM member_to_role", + "refId": "A" + } + ], + "title": "Members With Roles", + "type": "stat" + }, + { + "datasource": "DeepHarbor PostgreSQL", + "description": "Current role assignments grouped by member. Includes only users who have one or more assigned roles.", + "fieldConfig": { + "defaults": { + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "footer": { + "reducers": [] + }, + "hideFrom": { + "viz": false + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 2, + "options": { + "cellHeight": "sm", + "showHeader": true + }, + "pluginVersion": "12.3.0", + "targets": [ + { + "dataset": "deepharbor", + "editorMode": "code", + "format": "table", + "rawSql": "SELECT m.id AS member_id,\n m.identity ->> 'first_name' AS first_name,\n m.identity ->> 'last_name' AS last_name,\n jsonb_path_query_first(m.identity, '$.emails[*] ? (@.type == \"primary\").email_address') #>> '{}' AS primary_email,\n COUNT(r.id) AS role_count,\n ARRAY_AGG(r.name ORDER BY r.name) AS assigned_roles,\n MAX(mtr.date_added) AS latest_role_assigned_at\nFROM member_to_role mtr\nJOIN member m ON m.id = mtr.member_id\nJOIN roles r ON r.id = mtr.role_id\nGROUP BY m.id, m.identity\nORDER BY m.identity ->> 'last_name', m.identity ->> 'first_name'", + "refId": "A" + } + ], + "title": "Current Role Assignments", + "type": "table" + } + ], + "refresh": "30s", + "schemaVersion": 42, + "tags": [ + "deepharbor", + "roles" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-30d", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "DeepHarbor Current Role Assignments", + "uid": "deepharbor_roles_current", + "version": 1 +} From ce08599352835538dde53b8fdd6957bd23b09aa1 Mon Sep 17 00:00:00 2001 From: Sky Date: Wed, 25 Mar 2026 18:00:25 -0500 Subject: [PATCH 3/4] configuration for grafana-okta sso adds: - okta configuration - mapping for security groups in okta to grafana permissions - .env file for configuring grafana / okta --- .env.grafana.okta.example | 35 +++++++++++++++++++++++++++++++++++ .gitignore | 7 ++++++- docker-compose.yaml | 4 ++-- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 .env.grafana.okta.example diff --git a/.env.grafana.okta.example b/.env.grafana.okta.example new file mode 100644 index 0000000..e7cead2 --- /dev/null +++ b/.env.grafana.okta.example @@ -0,0 +1,35 @@ +# Grafana server URL +GF_SERVER_ROOT_URL=http://localhost:3000 + +# Optional local admin override +GF_SECURITY_ADMIN_USER=admin +GF_SECURITY_ADMIN_PASSWORD=change-me-PLEASE + +# Enable Okta auth +GF_AUTH_OKTA_ENABLED=true +GF_AUTH_OKTA_NAME=Okta +GF_AUTH_OKTA_ALLOW_SIGN_UP=true +GF_AUTH_OKTA_AUTO_LOGIN=false + +# Okta OIDC app values +GF_AUTH_OKTA_CLIENT_ID=your-okta-client-id +GF_AUTH_OKTA_CLIENT_SECRET=your-okta-client-secret +GF_AUTH_OKTA_SCOPES=openid profile email groups +GF_AUTH_OKTA_AUTH_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/authorize +GF_AUTH_OKTA_TOKEN_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/token +GF_AUTH_OKTA_API_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/userinfo + +# Optional restrictions +# comma separated lists +GF_AUTH_OKTA_ALLOWED_DOMAINS= +GF_AUTH_OKTA_ALLOWED_GROUPS= + +# Claim/attribute mapping +GF_AUTH_OKTA_LOGIN_ATTRIBUTE_PATH=preferred_username +GF_AUTH_OKTA_NAME_ATTRIBUTE_PATH=name +GF_AUTH_OKTA_EMAIL_ATTRIBUTE_PATH=email +GF_AUTH_OKTA_GROUPS_ATTRIBUTE_PATH=groups + +# Role mapping +GF_AUTH_OKTA_ROLE_ATTRIBUTE_PATH=contains(groups[*], 'GrafanaAdmins') && 'Admin' || contains(groups[*], 'GrafanaEditors') && 'Editor' || 'Viewer' +GF_AUTH_OKTA_SKIP_ORG_ROLE_SYNC=false diff --git a/.gitignore b/.gitignore index 60c701b..c6233a1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,9 @@ flask_session/ .claude *.code-workspace pg/db-init/02-seed_data.sql -pg/sql/seed_data.local.sql \ No newline at end of file +pg/sql/seed_data.local.sql +.env.local* +.env.production* +.env.staging* +.env.development* +.env.*.production \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index c99058c..38137ea 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -421,14 +421,14 @@ services: restart: unless-stopped ports: - "3000:3000" + env_file: + - .env.grafana.okta.production volumes: - ./tools/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources - ./tools/grafana/provisioning/dashboards/main.yaml:/etc/grafana/provisioning/dashboards/main.yaml - ./tools/grafana/provisioning/dashboards:/var/lib/grafana/dashboards environment: TZ: "America/Chicago" - GF_SECURITY_ADMIN_USER: admin - GF_SECURITY_ADMIN_PASSWORD: admin depends_on: db: condition: service_healthy From 2d4b3f0fe1e55aa67c405c780076c881cc93f095 Mon Sep 17 00:00:00 2001 From: Sky Date: Wed, 25 Mar 2026 20:31:37 -0500 Subject: [PATCH 4/4] okta: add refresh token and JWT validation okta: add refresh token and JWT validation --- .env.grafana.okta.example | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.env.grafana.okta.example b/.env.grafana.okta.example index e7cead2..3c0c719 100644 --- a/.env.grafana.okta.example +++ b/.env.grafana.okta.example @@ -14,11 +14,18 @@ GF_AUTH_OKTA_AUTO_LOGIN=false # Okta OIDC app values GF_AUTH_OKTA_CLIENT_ID=your-okta-client-id GF_AUTH_OKTA_CLIENT_SECRET=your-okta-client-secret -GF_AUTH_OKTA_SCOPES=openid profile email groups +GF_AUTH_OKTA_SCOPES=openid profile email groups offline_access GF_AUTH_OKTA_AUTH_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/authorize GF_AUTH_OKTA_TOKEN_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/token GF_AUTH_OKTA_API_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/userinfo +# Enable refresh token flow +GF_AUTH_OKTA_USE_REFRESH_TOKEN=true + +# Enable JWT ID token signature validation +GF_AUTH_OKTA_VALIDATE_ID_TOKEN=true +GF_AUTH_OKTA_JWK_SET_URL=https://YOUR_OKTA_DOMAIN/oauth2/v1/keys + # Optional restrictions # comma separated lists GF_AUTH_OKTA_ALLOWED_DOMAINS=