first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
package azure
import (
"context"
"fmt"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/maximhq/bifrost/core/providers/openai"
providerUtils "github.com/maximhq/bifrost/core/providers/utils"
"github.com/maximhq/bifrost/core/schemas"
"github.com/valyala/fasthttp"
)
// setAzureAuth sets the Azure authentication header on the request for OpenAI models.
// It handles authentication in order of priority:
// 1. Service Principal (client ID/secret/tenant ID) - uses Bearer token
// 2. Context token - uses Bearer token
// 3. API key - uses api-key header
// 4. DefaultAzureCredential auto-detection (managed identity, workload identity, env vars, CLI)
func (provider *AzureProvider) setAzureAuth(ctx context.Context, req *fasthttp.Request, key schemas.Key) *schemas.BifrostError {
// Service Principal authentication
if key.AzureKeyConfig != nil && key.AzureKeyConfig.ClientID != nil &&
key.AzureKeyConfig.ClientSecret != nil && key.AzureKeyConfig.TenantID != nil && key.AzureKeyConfig.ClientID.GetValue() != "" && key.AzureKeyConfig.ClientSecret.GetValue() != "" && key.AzureKeyConfig.TenantID.GetValue() != "" {
cred, err := provider.getOrCreateAuth(key.AzureKeyConfig.TenantID.GetValue(), key.AzureKeyConfig.ClientID.GetValue(), key.AzureKeyConfig.ClientSecret.GetValue())
if err != nil {
return providerUtils.NewBifrostOperationError("failed to get or create Azure authentication", err)
}
scopes := getAzureScopes(key.AzureKeyConfig.Scopes)
token, err := cred.GetToken(ctx, policy.TokenRequestOptions{
Scopes: scopes,
})
if err != nil {
return providerUtils.NewBifrostOperationError("failed to get Azure access token", err)
}
if token.Token == "" {
return providerUtils.NewBifrostOperationError("azure access token is empty", fmt.Errorf("token is empty"))
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.Token))
req.Header.Del("api-key")
return nil
}
// Context token authentication
if authToken, ok := ctx.Value(AzureAuthorizationTokenKey).(string); ok && authToken != "" {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", authToken))
req.Header.Del("api-key")
return nil
}
// API key authentication
value := key.Value.GetValue()
if value != "" {
req.Header.Del("Authorization")
req.Header.Set("api-key", value)
return nil
}
// No explicit credentials - attempt DefaultAzureCredential auto-detection.
scopes := getAzureScopes(nil)
if key.AzureKeyConfig != nil {
scopes = getAzureScopes(key.AzureKeyConfig.Scopes)
}
cred, err := provider.getOrCreateDefaultAzureCredential()
if err != nil {
return providerUtils.NewBifrostOperationError("no credentials provided and DefaultAzureCredential unavailable", err)
}
token, err := cred.GetToken(ctx, policy.TokenRequestOptions{Scopes: scopes})
if err != nil {
return providerUtils.NewBifrostOperationError("no credentials provided and DefaultAzureCredential failed to get token", err)
}
if token.Token == "" {
return providerUtils.NewBifrostOperationError("no credentials provided and DefaultAzureCredential returned empty token", fmt.Errorf("token is empty"))
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.Token))
req.Header.Del("api-key")
return nil
}
// AzureFileResponse represents an Azure file response (same as OpenAI).
type AzureFileResponse struct {
ID string `json:"id"`
Object string `json:"object"`
Bytes int64 `json:"bytes"`
CreatedAt int64 `json:"created_at"`
Filename string `json:"filename"`
Purpose schemas.FilePurpose `json:"purpose"`
Status string `json:"status,omitempty"`
StatusDetails *string `json:"status_details,omitempty"`
}
// ToBifrostFileUploadResponse converts Azure file response to Bifrost response.
func (r *AzureFileResponse) ToBifrostFileUploadResponse(providerName schemas.ModelProvider, latency time.Duration, sendBackRawResponse bool, rawResponse interface{}) *schemas.BifrostFileUploadResponse {
resp := &schemas.BifrostFileUploadResponse{
ID: r.ID,
Object: r.Object,
Bytes: r.Bytes,
CreatedAt: r.CreatedAt,
Filename: r.Filename,
Purpose: r.Purpose,
Status: openai.ToBifrostFileStatus(r.Status),
StatusDetails: r.StatusDetails,
StorageBackend: schemas.FileStorageAPI,
ExtraFields: schemas.BifrostResponseExtraFields{
Latency: latency.Milliseconds(),
},
}
if sendBackRawResponse {
resp.ExtraFields.RawResponse = rawResponse
}
return resp
}