Skip to content
Closed
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
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ $ git clone https://github.com/redhat-developer/dotnet-bunny && cd dotnet-bunny

### Dependencies

Dependencies(apk): babeltrace bash bash-completion binutils coreutils file findutils g++ jq libstdc++-dev lldb lttng-ust lttng-tools npm postgresql psqlodbc sed strace unixodbc zlib-dev
Dependencies(dnf): awk babeltrace bash-completion bc findutils gcc-c++ jq libstdc++-devel lttng-ust lttng-tools npm postgresql-odbc postgresql-server strace unixODBC /usr/bin/file /usr/bin/free /usr/bin/lldb /usr/bin/readelf /usr/bin/su which zlib-devel
Dependencies(apk): babeltrace bash bash-completion binutils coreutils file findutils g++ jq krb5-server krb5 libstdc++-dev lldb lttng-ust lttng-tools npm postgresql psqlodbc sed strace unixodbc zlib-dev
Dependencies(apt): krb5-kdc krb5-admin-server krb5-user
Dependencies(dnf): awk babeltrace bash-completion bc findutils gcc-c++ jq krb5-server krb5-workstation krb5-libs libstdc++-devel lttng-ust lttng-tools npm postgresql-odbc postgresql-server strace unixODBC /usr/bin/file /usr/bin/free /usr/bin/lldb /usr/bin/readelf /usr/bin/su which zlib-devel
62 changes: 62 additions & 0 deletions kerberos-auth/aspnet-server/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System;

var builder = WebApplication.CreateBuilder(args);

// Configure Kerberos/Negotiate authentication
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();

builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/", (HttpContext context) =>
{
var user = context.User.Identity;
if (user?.IsAuthenticated == true)
{
Console.WriteLine($"[SERVER] Authenticated user: {user.Name}");
return Results.Ok(new
{
authenticated = true,
username = user.Name,
authenticationType = user.AuthenticationType,
message = "Kerberos authentication successful"
});
}
else
{
Console.WriteLine("[SERVER] User not authenticated");
return Results.Unauthorized();
}
});

// Read configuration from environment
var port = Environment.GetEnvironmentVariable("SERVER_PORT") ?? "5000";
var keytabPath = Environment.GetEnvironmentVariable("KRB5_KTNAME");

if (string.IsNullOrEmpty(keytabPath))
{
Console.WriteLine("error: KRB5_KTNAME environment variable not set");
Environment.Exit(1);
}

Console.WriteLine($"[SERVER] Starting on port {port}");
Console.WriteLine($"[SERVER] Using keytab: {keytabPath}");

app.Urls.Add($"http://localhost:{port}");
app.Run();
14 changes: 14 additions & 0 deletions kerberos-auth/aspnet-server/aspnet-server.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(TestTargetFramework)</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Condition="'$(TargetFramework)' == 'net10.0'" Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="10.0.*"/>
<PackageReference Condition="'$(TargetFramework)' == 'net9.0'" Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="9.0.*"/>
<PackageReference Condition="'$(TargetFramework)' == 'net8.0'" Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="8.0.*"/>
</ItemGroup>

</Project>
64 changes: 64 additions & 0 deletions kerberos-auth/client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Net;
using System.Net.Http;
using System.Text.Json;

// Read configuration from environment
var serverUrl = Environment.GetEnvironmentVariable("SERVER_URL");
if (string.IsNullOrEmpty(serverUrl))
{
Console.WriteLine("error: SERVER_URL environment variable not set");
Environment.Exit(1);
return;
}

Console.WriteLine($"[CLIENT] Connecting to: {serverUrl}");

// Create HttpClient with default credentials (uses Kerberos)
var handler = new HttpClientHandler
{
UseDefaultCredentials = true,
Credentials = CredentialCache.DefaultCredentials
};

using var client = new HttpClient(handler);

try
{
var response = await client.GetAsync(serverUrl);

Console.WriteLine($"[CLIENT] Response status: {response.StatusCode}");

if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"[CLIENT] Response: {content}");

// Parse JSON to verify authentication
var jsonDoc = JsonDocument.Parse(content);
if (jsonDoc.RootElement.TryGetProperty("authenticated", out var authProp) &&
authProp.GetBoolean())
{
Console.WriteLine("[CLIENT] SUCCESS: Kerberos authentication verified");
Environment.Exit(0);
}
else
{
Console.WriteLine("[CLIENT] FAIL: Response does not indicate authentication");
Environment.Exit(1);
}
}
else
{
Console.WriteLine($"[CLIENT] FAIL: HTTP {response.StatusCode}");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"[CLIENT] Response body: {content}");
Environment.Exit(1);
}
}
catch (Exception ex)
{
Console.WriteLine($"[CLIENT] error: {ex.Message}");
Console.WriteLine($"[CLIENT] Stack trace: {ex.StackTrace}");
Environment.Exit(1);
}
8 changes: 8 additions & 0 deletions kerberos-auth/client/client.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(TestTargetFramework)</TargetFramework>
</PropertyGroup>

</Project>
134 changes: 134 additions & 0 deletions kerberos-auth/setup-kdc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env bash

# Setup a local MIT Kerberos KDC for testing
# This script creates an ephemeral, isolated Kerberos environment

set -euo pipefail

# Check for required Kerberos tools
if ! command -v kdb5_util &> /dev/null; then
echo "error: kdb5_util not found. Please install Kerberos server packages."
exit 1
fi

if ! command -v krb5kdc &> /dev/null; then
echo "error: krb5kdc not found. Please install Kerberos server packages."
exit 1
fi

if ! command -v kadmin.local &> /dev/null; then
echo "error: kadmin.local not found. Please install Kerberos admin packages."
exit 1
fi

# Environment setup
export TEST_DIR="${1:-}"
if [[ -z "${TEST_DIR}" ]]; then
echo "error: TEST_DIR not provided"
exit 1
fi

export REALM="${2:-}"
if [[ -z "${REALM}" ]]; then
echo "error: REALM not provided"
exit 1
fi

export KDC_PORT="${3:-}"
if [[ -z "${KDC_PORT}" ]]; then
echo "error: KDC_PORT not provided"
exit 1
fi

export KRB5_CONFIG="${TEST_DIR}/krb5.conf"
export KRB5_KDC_PROFILE="${TEST_DIR}/kdc.conf"

echo "Setting up KDC in ${TEST_DIR}"
echo "Realm: ${REALM}"
echo "KDC Port: ${KDC_PORT}"

# Create krb5.conf
cat > "${KRB5_CONFIG}" << EOF
[libdefaults]
default_realm = ${REALM}
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_ccache_name = FILE:${TEST_DIR}/krb5cc

[realms]
${REALM} = {
kdc = localhost:${KDC_PORT}
admin_server = localhost:${KDC_PORT}
default_domain = localhost
}

[domain_realm]
.localhost = ${REALM}
localhost = ${REALM}
EOF

# Create kdc.conf
cat > "${KRB5_KDC_PROFILE}" << EOF
[kdcdefaults]
kdc_ports = ${KDC_PORT}
kdc_tcp_ports = ${KDC_PORT}

[realms]
${REALM} = {
database_name = ${TEST_DIR}/principal
admin_keytab = FILE:${TEST_DIR}/kadm5.keytab
acl_file = ${TEST_DIR}/kadm5.acl
key_stash_file = ${TEST_DIR}/.k5.${REALM}
max_life = 10h 0m 0s
max_renewable_life = 7d 0h 0m 0s
master_key_type = aes256-cts
supported_enctypes = aes256-cts:normal aes128-cts:normal
default_principal_flags = +preauth
}
EOF

# Create ACL file for kadmin
echo "*/admin@${REALM} *" > "${TEST_DIR}/kadm5.acl"

# Initialize KDC database
echo "Initializing KDC database..."
kdb5_util create -s -P masterpassword -r "${REALM}" -d "${TEST_DIR}/principal" 2>&1 | grep -v "^Loading" || true

# Start KDC
echo "Starting KDC..."
krb5kdc -n &
KDC_PID=$!
echo "${KDC_PID}" > "${TEST_DIR}/kdc.pid"

# Wait for KDC to be ready
sleep 2

# Verify KDC is running
if ! ps -p "${KDC_PID}" > /dev/null 2>&1; then
echo "error: KDC failed to start"
exit 1
fi

echo "KDC started successfully (PID: ${KDC_PID})"

# Create principals
echo "Creating principals..."
kadmin.local -r "${REALM}" -q "addprinc -randkey HTTP/localhost@${REALM}" 2>&1 | grep -v "^Authenticating" || true
kadmin.local -r "${REALM}" -q "addprinc -pw clientpassword testclient@${REALM}" 2>&1 | grep -v "^Authenticating" || true

# Export keytabs
echo "Exporting keytabs..."
kadmin.local -r "${REALM}" -q "ktadd -k ${TEST_DIR}/http.keytab HTTP/localhost@${REALM}" 2>&1 | grep -v "^Authenticating" || true
kadmin.local -r "${REALM}" -q "ktadd -k ${TEST_DIR}/client.keytab testclient@${REALM}" 2>&1 | grep -v "^Authenticating" || true

# Set proper permissions
chmod 600 "${TEST_DIR}"/*.keytab

echo "KDC setup complete!"
echo "KRB5_CONFIG=${KRB5_CONFIG}"
echo "Service keytab: ${TEST_DIR}/http.keytab"
echo "Client keytab: ${TEST_DIR}/client.keytab"
14 changes: 14 additions & 0 deletions kerberos-auth/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "kerberos-auth",
"enabled": true,
"requiresSdk": true,
"version": "8.0",
"versionSpecific": false,
"type": "bash",
"cleanup": true,
"skipWhen": [
"ubi8-repos", // ubi repos don't contain kerberos utils
"ubi9-repos", // ubi repos don't contain kerberos utils
"ubi10-repos" // ubi repos don't contain kerberos utils
]
}
Loading
Loading