Skip to content
Merged
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
8 changes: 5 additions & 3 deletions cli/azd/extensions/azure.ai.agents/internal/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -3298,6 +3298,7 @@ func extractToolboxAndConnectionConfigs(
// External tools with target/authType need a connection
toolName, _ := toolMap["name"].(string)
authType, _ := toolMap["authType"].(string)
authType = string(agent_yaml.NormalizeConnectionAuthType(agent_yaml.AuthType(authType)))
credentials, _ := toolMap["credentials"].(map[string]any)

connName := toolName
Expand Down Expand Up @@ -3455,13 +3456,14 @@ func extractConnectionConfigs(
}

creds := maps.Clone(connResource.Credentials)
authType := string(connResource.AuthType)
authType := string(agent_yaml.NormalizeConnectionAuthType(connResource.AuthType))

// Surface credentials.type to top-level authType when not explicitly set.
// This must happen before externalization so we capture the raw value.
// Do this before externalization so "type" isn't converted into an env var entry,
// and normalize legacy auth types for provisioning compatibility.
if authType == "" && len(creds) > 0 {
if credType, ok := creds["type"].(string); ok && credType != "" {
authType = credType
authType = string(agent_yaml.NormalizeConnectionAuthType(agent_yaml.AuthType(credType)))
delete(creds, "type")
}
}
Expand Down
76 changes: 76 additions & 0 deletions cli/azd/extensions/azure.ai.agents/internal/cmd/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,46 @@ func TestExtractToolboxAndConnectionConfigs_RawToolsFallback(t *testing.T) {
}
}

func TestExtractToolboxAndConnectionConfigs_NormalizesAgenticIdentityAuthType(t *testing.T) {
t.Parallel()

manifest := &agent_yaml.AgentManifest{
Resources: []any{
agent_yaml.ToolboxResource{
Resource: agent_yaml.Resource{
Name: "platform-tools",
Kind: agent_yaml.ResourceKindToolbox,
},
Tools: []any{
map[string]any{
"type": "mcp",
"name": "agentic-tool",
"target": "https://example.com/mcp",
"authType": "AgenticIdentity",
},
},
},
},
}

_, connections, _, err := extractToolboxAndConnectionConfigs(manifest)
if err != nil {
t.Fatalf("extractToolboxAndConnectionConfigs failed: %v", err)
}

if len(connections) != 1 {
t.Fatalf("Expected 1 connection, got %d", len(connections))
}

if connections[0].AuthType != string(agent_yaml.AuthTypeAgenticIdentityToken) {
t.Errorf(
"Expected authType %q, got %q",
agent_yaml.AuthTypeAgenticIdentityToken,
connections[0].AuthType,
)
}
}

func TestExtractToolboxAndConnectionConfigs_NilManifest(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1203,6 +1243,42 @@ func TestExtractConnectionConfigs_SurfacesCredentialsType(t *testing.T) {
wantCredKeyCount: 2,
wantEnvVarCount: 2, // both "type" and "key" externalized
},
{
name: "normalizes explicit AgenticIdentity authType",
connResource: agent_yaml.ConnectionResource{
Resource: agent_yaml.Resource{
Name: "my-conn",
Kind: agent_yaml.ResourceKindConnection,
},
Target: "https://example.com",
AuthType: agent_yaml.AuthTypeAgenticIdentity,
Credentials: map[string]any{
"key": "val",
},
},
wantAuthType: string(agent_yaml.AuthTypeAgenticIdentityToken),
wantCredHasType: false,
wantCredKeyCount: 1,
wantEnvVarCount: 1,
},
{
name: "normalizes credentials.type AgenticIdentity when authType is empty",
connResource: agent_yaml.ConnectionResource{
Resource: agent_yaml.Resource{
Name: "my-conn",
Kind: agent_yaml.ResourceKindConnection,
},
Target: "https://example.com",
Credentials: map[string]any{
"type": "AgenticIdentity",
"key": "secret-value",
},
},
wantAuthType: string(agent_yaml.AuthTypeAgenticIdentityToken),
wantCredHasType: false,
wantCredKeyCount: 1,
wantEnvVarCount: 1,
},
{
name: "no credentials.type and no authType stays empty",
connResource: agent_yaml.ConnectionResource{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@ func TestExtractResourceDefinitions_ConnectionAllAuthTypes(t *testing.T) {
AuthTypeNone,
AuthTypeOAuth2,
AuthTypePAT,
AuthTypeAgenticIdentity,
AuthTypeAgenticIdentityToken,
}

for _, authType := range authTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,35 @@ func NormalizeToolKind(kind ToolKind) ToolKind {
type AuthType string

const (
AuthTypeAAD AuthType = "AAD"
AuthTypeApiKey AuthType = "ApiKey"
AuthTypeCustomKeys AuthType = "CustomKeys"
AuthTypeNone AuthType = "None"
AuthTypeOAuth2 AuthType = "OAuth2"
AuthTypePAT AuthType = "PAT"
AuthTypeUserEntraToken AuthType = "UserEntraToken"
AuthTypeAgenticIdentity AuthType = "AgenticIdentity"
AuthTypeManagedIdentity AuthType = "ProjectManagedIdentity"
AuthTypeServicePrincipal AuthType = "ServicePrincipal"
AuthTypeUsernamePassword AuthType = "UsernamePassword"
AuthTypeAccessKey AuthType = "AccessKey"
AuthTypeAccountKey AuthType = "AccountKey"
AuthTypeSAS AuthType = "SAS"
AuthTypeAAD AuthType = "AAD"
AuthTypeApiKey AuthType = "ApiKey"
AuthTypeCustomKeys AuthType = "CustomKeys"
AuthTypeNone AuthType = "None"
AuthTypeOAuth2 AuthType = "OAuth2"
AuthTypePAT AuthType = "PAT"
AuthTypeUserEntraToken AuthType = "UserEntraToken"
AuthTypeAgenticIdentity AuthType = "AgenticIdentity"
AuthTypeAgenticIdentityToken AuthType = "AgenticIdentityToken"
AuthTypeManagedIdentity AuthType = "ProjectManagedIdentity"
AuthTypeServicePrincipal AuthType = "ServicePrincipal"
AuthTypeUsernamePassword AuthType = "UsernamePassword"
AuthTypeAccessKey AuthType = "AccessKey"
AuthTypeAccountKey AuthType = "AccountKey"
AuthTypeSAS AuthType = "SAS"
)

// NormalizeConnectionAuthType maps auth types accepted in agent.yaml to
// the management-plane value required for project connection provisioning.
// Legacy AgenticIdentity values are normalized to AgenticIdentityToken
// for API compatibility.
func NormalizeConnectionAuthType(authType AuthType) AuthType {
if authType == AuthTypeAgenticIdentity {
return AuthTypeAgenticIdentityToken
}

return authType
}

// CategoryKind represents the category of a connection resource.
type CategoryKind string

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,19 @@ func TestConnectionResourceNewFieldsYAMLRoundTrip(t *testing.T) {
t.Errorf("scopes dropped: got %v", got.Scopes)
}
}

func TestNormalizeConnectionAuthType(t *testing.T) {
t.Parallel()

if got := NormalizeConnectionAuthType(AuthTypeAgenticIdentity); got != AuthTypeAgenticIdentityToken {
t.Fatalf("NormalizeConnectionAuthType(AgenticIdentity) = %q, want %q", got, AuthTypeAgenticIdentityToken)
}

if got := NormalizeConnectionAuthType(AuthTypeAgenticIdentityToken); got != AuthTypeAgenticIdentityToken {
t.Fatalf("NormalizeConnectionAuthType(AgenticIdentityToken) = %q, want %q", got, AuthTypeAgenticIdentityToken)
}

if got := NormalizeConnectionAuthType(AuthTypeOAuth2); got != AuthTypeOAuth2 {
t.Fatalf("NormalizeConnectionAuthType(OAuth2) = %q, want %q", got, AuthTypeOAuth2)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"authType": {
"type": "string",
"description": "Authentication type for the connection.",
"enum": ["AAD", "AccessKey", "AccountKey", "ApiKey", "CustomKeys", "ManagedIdentity", "None", "OAuth2", "PAT", "ServicePrincipal", "UsernamePassword", "ProjectManagedIdentity", "UserEntraToken"]
"enum": ["AAD", "AccessKey", "AccountKey", "ApiKey", "CustomKeys", "ManagedIdentity", "None", "OAuth2", "PAT", "ServicePrincipal", "UsernamePassword", "ProjectManagedIdentity", "UserEntraToken", "AgenticIdentityToken"]
},
"credentials": {
"type": "object",
Expand Down Expand Up @@ -165,7 +165,7 @@
"authType": {
"type": "string",
"description": "Authentication type.",
"enum": ["AAD", "AccessKey", "AccountKey", "AgenticIdentity", "ApiKey", "CustomKeys", "ManagedIdentity", "None", "OAuth2", "PAT", "SAS", "ServicePrincipal", "UsernamePassword", "UserEntraToken", "ProjectManagedIdentity"]
"enum": ["AAD", "AccessKey", "AccountKey", "AgenticIdentity", "AgenticIdentityToken", "ApiKey", "CustomKeys", "ManagedIdentity", "None", "OAuth2", "PAT", "SAS", "ServicePrincipal", "UsernamePassword", "UserEntraToken", "ProjectManagedIdentity"]
},
Comment thread
trangevi marked this conversation as resolved.
"credentials": {
"type": "object",
Expand All @@ -184,7 +184,7 @@
"description": "OAuth2 scopes to request (optional for OAuth2 authType).",
"items": { "type": "string" }
},
"audience": { "type": "string", "description": "Token audience for AAD/ProjectManagedIdentity/AgenticIdentity/UserEntraToken auth types." },
"audience": { "type": "string", "description": "Token audience for AAD/ProjectManagedIdentity/AgenticIdentity/AgenticIdentityToken/UserEntraToken auth types." },
"connectorName": { "type": "string", "description": "Connector name for Oauth2 auth type." },
"expiryTime": { "type": "string", "description": "Connection expiry time." },
"isSharedToAll": { "type": "boolean", "description": "Whether the connection is shared to all users." },
Expand Down
Loading