Skip to content

Commit 56a854f

Browse files
committed
initial commit
1 parent d45910d commit 56a854f

File tree

6 files changed

+710
-11
lines changed

6 files changed

+710
-11
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
name: Token Federation Test
2+
3+
# This workflow tests token federation functionality with GitHub Actions OIDC tokens
4+
# in the databricks-sql-python connector to ensure CI/CD functionality
5+
6+
on:
7+
# Manual trigger with required inputs
8+
workflow_dispatch:
9+
inputs:
10+
databricks_host:
11+
description: 'Databricks host URL (e.g., example.cloud.databricks.com)'
12+
required: true
13+
databricks_http_path:
14+
description: 'Databricks HTTP path (e.g., /sql/1.0/warehouses/abc123)'
15+
required: true
16+
identity_federation_client_id:
17+
description: 'Identity federation client ID'
18+
required: true
19+
20+
# Automatically run on PR that changes token federation files
21+
pull_request:
22+
branches:
23+
- main
24+
25+
# Run on push to main that affects token federation
26+
push:
27+
paths:
28+
- 'src/databricks/sql/auth/token_federation.py'
29+
- 'src/databricks/sql/auth/auth.py'
30+
- 'examples/token_federation_*.py'
31+
branches:
32+
- main
33+
34+
permissions:
35+
# Required for GitHub OIDC token
36+
id-token: write
37+
contents: read
38+
39+
jobs:
40+
test-token-federation:
41+
runs-on: ubuntu-latest
42+
43+
steps:
44+
- name: Checkout code
45+
uses: actions/checkout@v4
46+
47+
- name: Set up Python 3.9
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: '3.9'
51+
52+
- name: Install dependencies
53+
run: |
54+
python -m pip install --upgrade pip
55+
pip install -e .
56+
pip install pyarrow
57+
58+
- name: Get GitHub OIDC token
59+
id: get-id-token
60+
uses: actions/github-script@v7
61+
with:
62+
script: |
63+
const token = await core.getIDToken('https://github.com')
64+
core.setSecret(token)
65+
core.setOutput('token', token)
66+
67+
- name: Create test script
68+
run: |
69+
cat > test_github_token_federation.py << 'EOF'
70+
#!/usr/bin/env python3
71+
72+
"""
73+
Test script for Databricks SQL token federation with GitHub Actions OIDC tokens.
74+
75+
This script demonstrates how to use the Databricks SQL connector with token federation
76+
using a GitHub Actions OIDC token. It connects to a Databricks SQL warehouse,
77+
runs a simple query, and shows the connected user.
78+
"""
79+
80+
import os
81+
import sys
82+
import json
83+
import base64
84+
from databricks import sql
85+
86+
def decode_jwt(token):
87+
"""Decode and return the claims from a JWT token."""
88+
try:
89+
parts = token.split(".")
90+
if len(parts) != 3:
91+
raise ValueError("Invalid JWT format")
92+
93+
payload = parts[1]
94+
padding = '=' * (4 - len(payload) % 4)
95+
payload += padding
96+
97+
decoded = base64.b64decode(payload)
98+
return json.loads(decoded)
99+
except Exception as e:
100+
print(f"Failed to decode token: {str(e)}")
101+
return None
102+
103+
def main():
104+
# Get GitHub OIDC token
105+
github_token = os.environ.get("OIDC_TOKEN")
106+
if not github_token:
107+
print("GitHub OIDC token not available")
108+
sys.exit(1)
109+
110+
# Get Databricks connection parameters
111+
host = os.environ.get("DATABRICKS_HOST")
112+
http_path = os.environ.get("DATABRICKS_HTTP_PATH")
113+
identity_federation_client_id = os.environ.get("IDENTITY_FEDERATION_CLIENT_ID")
114+
115+
if not host or not http_path:
116+
print("Missing Databricks connection parameters")
117+
sys.exit(1)
118+
119+
claims = decode_jwt(github_token)
120+
if claims:
121+
print(f"Token issuer: {claims.get('iss', 'unknown')}")
122+
print(f"Token subject: {claims.get('sub', 'unknown')}")
123+
print(f"Token audience: {claims.get('aud', 'unknown')}")
124+
125+
try:
126+
# Connect to Databricks using token federation
127+
print(f"Connecting to Databricks at {host}{http_path}")
128+
with sql.connect(
129+
server_hostname=host,
130+
http_path=http_path,
131+
access_token=github_token,
132+
auth_type="token-federation",
133+
identity_federation_client_id=identity_federation_client_id
134+
) as connection:
135+
print("Connection established successfully")
136+
137+
# Execute a simple query
138+
cursor = connection.cursor()
139+
cursor.execute("SELECT 1 + 1 as result")
140+
result = cursor.fetchall()
141+
print(f"Query result: {result[0][0]}")
142+
143+
# Show current user
144+
cursor.execute("SELECT current_user() as user")
145+
result = cursor.fetchall()
146+
print(f"Connected as user: {result[0][0]}")
147+
148+
print("Token federation test successful!")
149+
return True
150+
except Exception as e:
151+
print(f"Error connecting to Databricks: {str(e)}")
152+
sys.exit(1)
153+
154+
if __name__ == "__main__":
155+
main()
156+
EOF
157+
chmod +x test_github_token_federation.py
158+
159+
- name: Test token federation with GitHub OIDC token
160+
env:
161+
DATABRICKS_HOST: ${{ github.event_name == 'workflow_dispatch' && inputs.databricks_host || secrets.DATABRICKS_HOST }}
162+
DATABRICKS_HTTP_PATH: ${{ github.event_name == 'workflow_dispatch' && inputs.databricks_http_path || secrets.DATABRICKS_HTTP_PATH }}
163+
IDENTITY_FEDERATION_CLIENT_ID: ${{ github.event_name == 'workflow_dispatch' && inputs.identity_federation_client_id || secrets.IDENTITY_FEDERATION_CLIENT_ID }}
164+
OIDC_TOKEN: ${{ steps.get-id-token.outputs.token }}
165+
run: |
166+
python test_github_token_federation.py

0 commit comments

Comments
 (0)