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
75 changes: 34 additions & 41 deletions .github/workflows/integration-auth-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ on:
- 'pyproject.toml'
- 'requirements.txt'
- '.github/workflows/integration-auth-tests.yml' # This workflow
- 'scripts/integration-auth-tests.sh'

concurrency:
group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_id || github.ref }}
Expand Down Expand Up @@ -54,8 +55,10 @@ jobs:
if: ${{ matrix.auth-provider == 'oauth2_token' }}
run: |
kubectl create namespace llama-stack
kubectl create serviceaccount llama-stack-auth -n llama-stack
kubectl create token llama-stack-auth -n llama-stack > llama-stack-auth-token
for account in llama-stack-auth llama-stack-user1 llama-stack-user2; do
kubectl create serviceaccount $account -n llama-stack
kubectl create token $account -n llama-stack > $account-token
done

- name: Set Kubernetes Config
if: ${{ matrix.auth-provider == 'oauth2_token' }}
Expand All @@ -75,8 +78,18 @@ jobs:
cat <<EOF > $run_dir/run.yaml
version: '2'
image_name: kube
apis: []
providers: {}
apis:
- files
- inference
providers:
files:
- provider_id: meta-reference-files
provider_type: inline::localfs
config:
storage_dir: $run_dir/files
metadata_store:
table_name: files_metadata
backend: sql_default
storage:
backends:
kv_default:
Expand All @@ -100,6 +113,21 @@ jobs:
backend: kv_default
server:
port: 8321
auth:
access_policy:
- permit:
actions: [read, delete]
resource: sql_record::openai_files::*
when:
- user with system:serviceaccount:llama-stack:llama-stack-user1 in roles
- user in owners roles
description: User1 can read and delete their Files
- permit:
actions: [read]
resource: sql_record::openai_files::*
when:
- user in owners roles
description: Owners can read their Files
EOF
yq eval '.server.auth.provider_config.type = "${{ matrix.auth-provider }}"' -i $run_dir/run.yaml
yq eval '.server.auth.provider_config.tls_cafile = "${{ env.KUBERNETES_CA_CERT_PATH }}"' -i $run_dir/run.yaml
Expand Down Expand Up @@ -137,40 +165,5 @@ jobs:

- name: Test auth
run: |
# Function to test API endpoint with authentication
# Usage: test_endpoint <curl_args> <user_token_file> <expected_status> [output_file]
test_endpoint() {
local curl_args="$1"
local user_token_file=$2
local expected_status=$3
local output_file=${4:-/dev/null}

local status
local extra_curl_args=(-s -L -o "$output_file" -w "%{http_code}")

if [ "$user_token_file" != "none" ]; then
extra_curl_args+=(-H "Authorization: Bearer $(cat $user_token_file)")
fi

set -x
status=$(curl $curl_args "${extra_curl_args[@]}")
set +x

if [ "$status" = "$expected_status" ]; then
echo " ✓ Status: $status (expected $expected_status)"
return 0
else
echo " ✗ Status: $status (expected $expected_status)"
exit 1
fi
}

echo "Testing /v1/version without token (should succeed)..."
test_endpoint "http://127.0.0.1:8321/v1/version" "none" "200" || exit 1

echo "Testing /v1/providers without token (should fail with 401)..."
test_endpoint "http://127.0.0.1:8321/v1/providers" "none" "401" || exit 1

echo "Testing /v1/providers with valid token (should succeed)..."
test_endpoint "http://127.0.0.1:8321/v1/providers" "llama-stack-auth-token" "200" "providers.json" || exit 1
cat providers.json | jq . > /dev/null && echo " ✓ Valid JSON response"
# Run the auth tests
./scripts/integration-auth-tests.sh
101 changes: 101 additions & 0 deletions scripts/integration-auth-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/bin/bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree.

set -euo pipefail

# Integration auth tests for Llama Stack
# This script tests authentication and authorization (ABAC) functionality
# Expects token files to be created before running (e.g., by CI workflow or manual setup)

# Function to test API endpoint with authentication
# Usage: test_endpoint <curl_args> <user_token_file> <expected_status> [output_file]
test_endpoint() {
local curl_args="$1"
local user_token_file=$2
local expected_status=$3
local output_file=${4:-/dev/null}

local status
local extra_curl_args=(-s -L -o "$output_file" -w "%{http_code}")

if [ "$user_token_file" != "none" ]; then
extra_curl_args+=(-H "Authorization: Bearer $(cat $user_token_file)")
fi

set -x
status=$(curl $curl_args "${extra_curl_args[@]}")
set +x

if [ "$status" = "$expected_status" ]; then
echo " ✓ Status: $status (expected $expected_status)"
return 0
else
echo " ✗ Status: $status (expected $expected_status)"
exit 1
fi
}

# Check if user tokens exist for ABAC testing
if [ ! -f "llama-stack-auth-token" ] || [ ! -f "llama-stack-user1-token" ] || [ ! -f "llama-stack-user2-token" ]; then
echo ""
echo "❌ User tokens not found - expected llama-stack-user1-token and llama-stack-user2-token"
exit 1
fi

echo "Testing /v1/version without token (should succeed)..."
test_endpoint "http://127.0.0.1:8321/v1/version" "none" "200" || exit 1

echo "Testing /v1/providers without token (should fail with 401)..."
test_endpoint "http://127.0.0.1:8321/v1/providers" "none" "401" || exit 1

echo "Testing /v1/providers with valid token (should succeed)..."
test_endpoint "http://127.0.0.1:8321/v1/providers" "llama-stack-auth-token" "200" "providers.json" || exit 1
cat providers.json | jq . > /dev/null && echo " ✓ Valid JSON response"

echo ""
echo "Running ABAC tests with user tokens..."

# Create test file
echo "test content" > test-file.txt

echo "Both user1 and user2 can create files..."
test_endpoint "http://127.0.0.1:8321/v1/files -F [email protected] -F purpose=assistants" "llama-stack-user1-token" "200" "user1-files.json" || exit 1
test_endpoint "http://127.0.0.1:8321/v1/files -F [email protected] -F purpose=assistants" "llama-stack-user2-token" "200" "user2-files.json" || exit 1

echo "user1 can only read their own files..."
test_endpoint "http://127.0.0.1:8321/v1/files" "llama-stack-user1-token" "200" "user1-files-list.json" || exit 1
USER1_FILE_COUNT=$(jq '.data|length' user1-files-list.json)
echo "User1 has $USER1_FILE_COUNT file(s)"
[ $USER1_FILE_COUNT -eq 1 ] || ( echo " ✗ User1 should have 1 file, but has $USER1_FILE_COUNT" && exit 1 )
echo " ✓ User1 can see exactly 1 file"

echo "user2 can read their own file..."
test_endpoint "http://127.0.0.1:8321/v1/files" "llama-stack-user2-token" "200" "user2-files-list.json" || exit 1
USER2_FILE_COUNT=$(jq '.data|length' user2-files-list.json)
echo "User2 has $USER2_FILE_COUNT file(s)"
[ $USER2_FILE_COUNT -eq 1 ] || ( echo " ✗ User2 should have 1 file, but has $USER2_FILE_COUNT" && exit 1 )
echo " ✓ User2 can see their own file"

echo "Both file ids should differ"
FILEID_USER1=$(jq -r '.data[0].id' user1-files-list.json)
FILEID_USER2=$(jq -r '.data[0].id' user2-files-list.json)
[ "$FILEID_USER1" != "$FILEID_USER2" ] || ( echo " ✗ File IDs should differ" && exit 1 )
echo " ✓ File IDs differ"

echo "user2 can't delete their own file or other users' files..."
test_endpoint "http://127.0.0.1:8321/v1/files/$FILEID_USER2 -X DELETE" "llama-stack-user2-token" "404" || exit 1
test_endpoint "http://127.0.0.1:8321/v1/files/$FILEID_USER1 -X DELETE" "llama-stack-user2-token" "404" || exit 1
echo " ✓ Delete correctly blocked"

echo "user1 can delete their own files but not other users' files..."
test_endpoint "http://127.0.0.1:8321/v1/files/$FILEID_USER1 -X DELETE" "llama-stack-user1-token" "200" || exit 1
echo " ✓ Delete successful"
test_endpoint "http://127.0.0.1:8321/v1/files/$FILEID_USER2 -X DELETE" "llama-stack-user1-token" "404" || exit 1
echo " ✓ Delete correctly blocked"

echo ""
echo "✓ ABAC test completed successfully!"