Skip to content

federation follow up [draft] #565

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
56a854f
initial commit
madhav-db May 7, 2025
aedb3bf
update vars
madhav-db May 7, 2025
d06672c
mod
madhav-db May 7, 2025
9aff811
debugging patch
madhav-db May 7, 2025
299b5ae
mod
madhav-db May 7, 2025
10a5016
debug
madhav-db May 7, 2025
3bb9b3d
debug
madhav-db May 7, 2025
708c13b
debug
madhav-db May 7, 2025
a1e9894
fix
madhav-db May 7, 2025
00e015c
fix
madhav-db May 7, 2025
d538b75
fix
madhav-db May 7, 2025
4b48ac9
fix
madhav-db May 7, 2025
e8d4a48
debug
madhav-db May 8, 2025
5b74b60
debug
madhav-db May 8, 2025
edc6027
debug
madhav-db May 8, 2025
3613cb0
debug
madhav-db May 8, 2025
e87b52d
readability
madhav-db May 8, 2025
929191b
separate py script
madhav-db May 8, 2025
82d0be2
addresses codecheck errors
madhav-db May 8, 2025
1e60750
adds unit test
madhav-db May 8, 2025
de48411
Fix: Apply Black formatting to auth and token_federation modules
madhav-db May 8, 2025
d54ba93
Enhance token federation refresh to get fresh external tokens
madhav-db May 8, 2025
aa2d1b9
refresh
madhav-db May 9, 2025
34413f3
fmt
madhav-db May 9, 2025
a93dd4b
clean up
madhav-db May 9, 2025
76df22e
update and add todo for future work
madhav-db May 9, 2025
c37cd01
refactoring
madhav-db May 9, 2025
f2d4516
update test
madhav-db May 9, 2025
aeeca66
fmt
madhav-db May 9, 2025
ae28649
remove idp detection
madhav-db May 9, 2025
541e82f
fmt
madhav-db May 11, 2025
49eab2a
fmt
madhav-db May 11, 2025
e6733cb
Apply black formatting to auth files
madhav-db May 11, 2025
29f95f2
Fix token refresh to use fresh token from provider
madhav-db May 11, 2025
2e12935
general improvements
madhav-db May 12, 2025
e9de21a
minor
madhav-db May 12, 2025
efb9149
test improvements
madhav-db May 12, 2025
7ab4068
Refactor token exchange parameters to be instance-specific in Databri…
madhav-db May 12, 2025
9fc4c0c
Refactor token expiry handling in DatabricksTokenFederationProvider a…
madhav-db May 12, 2025
85d0cd9
addresses comments
madhav-db May 21, 2025
5040569
initial commit
madhav-db May 22, 2025
22a4681
change github test to adapt
madhav-db May 22, 2025
f1346b0
implement add headers to tf provider
madhav-db May 22, 2025
4c5bce1
Enhance authentication providers by implementing CredentialsProvider …
madhav-db May 22, 2025
bafef75
Add Databricks SQL Token Federation examples and enhance authenticati…
madhav-db May 28, 2025
19dc0b1
formatted
madhav-db May 28, 2025
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
78 changes: 78 additions & 0 deletions .github/workflows/token-federation-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Token Federation Test

# Tests token federation functionality with GitHub Actions OIDC tokens
on:
# Manual trigger with required inputs
workflow_dispatch:
inputs:
databricks_host:
description: 'Databricks host URL (e.g., example.cloud.databricks.com)'
required: true
databricks_http_path:
description: 'Databricks HTTP path (e.g., /sql/1.0/warehouses/abc123)'
required: true
identity_federation_client_id:
description: 'Identity federation client ID'
required: true

# Run on PRs that might affect token federation
pull_request:
branches: [main]
paths:
- 'src/databricks/sql/auth/**'
- 'examples/token_federation_*.py'
- 'tests/token_federation/**'
- '.github/workflows/token-federation-test.yml'

# Run on push to main that affects token federation
push:
branches: [main]
paths:
- 'src/databricks/sql/auth/**'
- 'examples/token_federation_*.py'
- 'tests/token_federation/**'
- '.github/workflows/token-federation-test.yml'

permissions:
id-token: write # Required for GitHub OIDC token
contents: read

jobs:
test-token-federation:
name: Test Token Federation
runs-on:
group: databricks-protected-runner-group
labels: linux-ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: '3.9'
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pyarrow

- name: Get GitHub OIDC token
id: get-id-token
uses: actions/github-script@v7
with:
script: |
const token = await core.getIDToken('https://github.com/databricks')
core.setSecret(token)
core.setOutput('token', token)

- name: Test token federation with GitHub OIDC token
env:
DATABRICKS_HOST_FOR_TF: ${{ github.event_name == 'workflow_dispatch' && inputs.databricks_host || secrets.DATABRICKS_HOST_FOR_TF }}
DATABRICKS_HTTP_PATH_FOR_TF: ${{ github.event_name == 'workflow_dispatch' && inputs.databricks_http_path || secrets.DATABRICKS_HTTP_PATH_FOR_TF }}
IDENTITY_FEDERATION_CLIENT_ID: ${{ github.event_name == 'workflow_dispatch' && inputs.identity_federation_client_id || secrets.IDENTITY_FEDERATION_CLIENT_ID }}
OIDC_TOKEN: ${{ steps.get-id-token.outputs.token }}
run: python tests/token_federation/github_oidc_test.py
109 changes: 109 additions & 0 deletions examples/token_federation_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
Databricks SQL Token Federation Examples

This script token federation flows:
1. U2M + Account-wide federation
2. U2M + Workflow-level federation
3. M2M + Account-wide federation
4. M2M + Workflow-level federation
5. Access Token + Workflow-level federation
6. Access Token + Account-wide federation

Token Federation Documentation:
------------------------------
For detailed setup instructions, refer to the official Databricks documentation:

- General Token Federation Overview:
https://docs.databricks.com/aws/en/dev-tools/auth/oauth-federation.html

- Token Exchange Process:
https://docs.databricks.com/aws/en/dev-tools/auth/oauth-federation-howto.html

- Azure OAuth Token Federation:
https://learn.microsoft.com/en-us/azure/databricks/dev-tools/auth/oauth-federation

Environment variables required:
- DATABRICKS_HOST: Databricks workspace hostname
- DATABRICKS_HTTP_PATH: HTTP path for the SQL warehouse
- AZURE_TENANT_ID: Azure tenant ID
- AZURE_CLIENT_ID: Azure client ID for service principal
- AZURE_CLIENT_SECRET: Azure client secret
- DATABRICKS_SERVICE_PRINCIPAL_ID: Databricks service principal ID for workflow federation
"""

import os
from databricks import sql

def run_query(connection, description):
cursor = connection.cursor()
cursor.execute("SELECT 1+1 AS result")
result = cursor.fetchall()
print(f"Query result: {result[0][0]}")

cursor.close()

def demonstrate_m2m_federation(env_vars, use_workflow_federation=False):
"""Demonstrate M2M (service principal) token federation"""

connection_params = {
"server_hostname": env_vars["DATABRICKS_HOST"],
"http_path": env_vars["DATABRICKS_HTTP_PATH"],
"auth_type": "client-credentials",
"oauth_client_id": env_vars["AZURE_CLIENT_ID"],
"client_secret": env_vars["AZURE_CLIENT_SECRET"],
"tenant_id": env_vars["AZURE_TENANT_ID"],
"use_token_federation": True
}

if use_workflow_federation and env_vars["DATABRICKS_SERVICE_PRINCIPAL_ID"]:
connection_params["identity_federation_client_id"] = env_vars["DATABRICKS_SERVICE_PRINCIPAL_ID"]
description = "M2M + Workflow-level Federation"
else:
description = "M2M + Account-wide Federation"

with sql.connect(**connection_params) as connection:
run_query(connection, description)


def demonstrate_u2m_federation(env_vars, use_workflow_federation=False):
"""Demonstrate U2M (interactive) token federation"""

connection_params = {
"server_hostname": env_vars["DATABRICKS_HOST"],
"http_path": env_vars["DATABRICKS_HTTP_PATH"],
"auth_type": "databricks-oauth", # Will open browser for interactive auth
"use_token_federation": True
}

if use_workflow_federation and env_vars["DATABRICKS_SERVICE_PRINCIPAL_ID"]:
connection_params["identity_federation_client_id"] = env_vars["DATABRICKS_SERVICE_PRINCIPAL_ID"]
description = "U2M + Workflow-level Federation (Interactive)"
else:
description = "U2M + Account-wide Federation (Interactive)"

# This will open a browser for interactive auth
with sql.connect(**connection_params) as connection:
run_query(connection, description)

def demonstrate_access_token_federation(env_vars):
"""Demonstrate access token token federation"""

access_token = os.environ.get("ACCESS_TOKEN") # This is to demonstrate a token obtained from an identity provider

connection_params = {
"server_hostname": env_vars["DATABRICKS_HOST"],
"http_path": env_vars["DATABRICKS_HTTP_PATH"],
"access_token": access_token,
"use_token_federation": True
}

# Add workflow federation if available
if env_vars["DATABRICKS_SERVICE_PRINCIPAL_ID"]:
connection_params["identity_federation_client_id"] = env_vars["DATABRICKS_SERVICE_PRINCIPAL_ID"]
description = "Access Token + Workflow-level Federation"
else:
description = "Access Token + Account-wide Federation"

with sql.connect(**connection_params) as connection:
run_query(connection, description)

Loading
Loading