@@ -26,6 +26,7 @@ public class KeyVaultSecretsRepository : BaseSecretsRepository
26
26
private const string FunctionKeyPrefix = "host--functionKey--" ;
27
27
private const string SystemKeyPrefix = "host--systemKey--" ;
28
28
29
+ private readonly Lazy < TokenCredential > _tokenCredential ;
29
30
private readonly Lazy < SecretClient > _secretClient ;
30
31
private readonly IEnvironment _environment ;
31
32
@@ -38,19 +39,38 @@ public KeyVaultSecretsRepository(string secretsSentinelFilePath, string vaultUri
38
39
39
40
Uri keyVaultUri = string . IsNullOrEmpty ( vaultUri ) ? throw new ArgumentException ( nameof ( vaultUri ) ) : new Uri ( vaultUri ) ;
40
41
41
- _secretClient = new Lazy < SecretClient > ( ( ) =>
42
+ _tokenCredential = new Lazy < TokenCredential > ( ( ) =>
42
43
{
43
- // If clientSecret and tenantId are provided, use ClientSecret credential; otherwise use managed identity
44
- TokenCredential credential = ! string . IsNullOrEmpty ( clientSecret ) && ! string . IsNullOrEmpty ( tenantId )
45
- ? new ClientSecretCredential ( tenantId , clientId , clientSecret )
46
- : new ChainedTokenCredential ( new ManagedIdentityCredential ( clientId ) , new ManagedIdentityCredential ( ) ) ;
44
+ if ( ! TryCreateTokenCredential ( clientId , clientSecret , tenantId , out TokenCredential credential ) )
45
+ {
46
+ throw new InvalidOperationException ( "Failed to create token credential for KeyVaultSecretsRepository" ) ;
47
+ }
47
48
48
- return new SecretClient ( keyVaultUri , credential ) ;
49
+ return credential ;
50
+ } ) ;
51
+
52
+ _secretClient = new Lazy < SecretClient > ( ( ) =>
53
+ {
54
+ return new SecretClient ( keyVaultUri , _tokenCredential . Value ) ;
49
55
} ) ;
50
56
51
57
_environment = environment ?? throw new ArgumentNullException ( nameof ( environment ) ) ;
52
58
}
53
59
60
+ internal KeyVaultSecretsRepository ( string secretsSentinelFilePath , string vaultUri , ILogger logger , IEnvironment environment , TokenCredential testEnvironmentTokenCredential )
61
+ : this ( secretsSentinelFilePath , vaultUri , null , null , null , logger , environment )
62
+ {
63
+ _tokenCredential = new Lazy < TokenCredential > ( ( ) =>
64
+ {
65
+ if ( ! TryCreateTokenCredential ( null , null , null , out TokenCredential credential ) )
66
+ {
67
+ throw new InvalidOperationException ( "Failed to create token credential for KeyVaultSecretsRepository" ) ;
68
+ }
69
+
70
+ return new ChainedTokenCredential ( testEnvironmentTokenCredential , credential ) ;
71
+ } ) ;
72
+ }
73
+
54
74
// For testing
55
75
internal KeyVaultSecretsRepository ( SecretClient secretClient , string secretsSentinelFilePath , ILogger logger , IEnvironment environment ) : base ( secretsSentinelFilePath , logger , environment )
56
76
{
@@ -72,6 +92,25 @@ public override async Task<ScriptSecrets> ReadAsync(ScriptSecretsType type, stri
72
92
return type == ScriptSecretsType . Host ? await ReadHostSecrets ( ) : await ReadFunctionSecrets ( functionName ) ;
73
93
}
74
94
95
+ private static bool TryCreateTokenCredential ( string clientId , string clientSecret , string tenantId , out TokenCredential credential )
96
+ {
97
+ if ( ! string . IsNullOrEmpty ( clientId ) && ! string . IsNullOrEmpty ( clientSecret ) && ! string . IsNullOrEmpty ( tenantId ) )
98
+ {
99
+ credential = new ClientSecretCredential ( tenantId , clientId , clientSecret ) ;
100
+ return true ;
101
+ }
102
+ else if ( ! string . IsNullOrEmpty ( clientId ) )
103
+ {
104
+ credential = new ManagedIdentityCredential ( clientId ) ;
105
+ return true ;
106
+ }
107
+ else
108
+ {
109
+ credential = new ManagedIdentityCredential ( ) ;
110
+ return true ;
111
+ }
112
+ }
113
+
75
114
public override async Task WriteAsync ( ScriptSecretsType type , string functionName , ScriptSecrets secrets )
76
115
{
77
116
// Get secrets as dictionary
0 commit comments