@@ -7,10 +7,8 @@ import { AzureKeyVaultSecretProvider } from "./keyVaultSecretProvider.js";
77import { KeyVaultOptions } from "./keyVaultOptions.js" ;
88import { RefreshTimer } from "../refresh/refreshTimer.js" ;
99import { ArgumentError , KeyVaultReferenceError } from "../common/errors.js" ;
10- import { KeyVaultReferenceErrorMessages } from "../common/errorMessages.js" ;
10+ import { KeyVaultReferenceErrorMessages , buildKeyVaultReferenceErrorMessage } from "../common/errorMessages.js" ;
1111import { KeyVaultSecretIdentifier , parseKeyVaultSecretIdentifier } from "@azure/keyvault-secrets" ;
12- import { isRestError } from "@azure/core-rest-pipeline" ;
13- import { AuthenticationError } from "@azure/identity" ;
1412
1513export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter {
1614 #keyVaultOptions: KeyVaultOptions | undefined ;
@@ -29,22 +27,25 @@ export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter {
2927 if ( ! this . #keyVaultOptions) {
3028 throw new ArgumentError ( KeyVaultReferenceErrorMessages . KEY_VAULT_OPTIONS_UNDEFINED ) ;
3129 }
32- // Secret references are parsed, validated and resolved during preload; here we only read the
33- // cached value. Parsing is guaranteed to succeed because preload runs first.
34- const secretIdentifier = parseKeyVaultSecretIdentifier (
35- parseSecretReference ( setting ) . value . secretId
36- ) ;
37- const secretValue = this . #keyVaultSecretProvider. getSecretValue ( secretIdentifier ) ;
30+ let secretIdentifier : KeyVaultSecretIdentifier ;
31+ try {
32+ secretIdentifier = parseKeyVaultSecretIdentifier (
33+ parseSecretReference ( setting ) . value . secretId
34+ ) ;
35+ } catch ( error ) {
36+ throw new KeyVaultReferenceError ( buildKeyVaultReferenceErrorMessage ( "Invalid Key Vault reference." , undefined , setting ) , { cause : error } ) ;
37+ }
38+
39+ const secretValue = await this . #keyVaultSecretProvider. getSecretValue ( secretIdentifier ) ;
3840 return [ setting . key , secretValue ] ;
3941 }
4042
4143 async preload ( settings : ConfigurationSetting [ ] ) : Promise < void > {
4244 if ( ! this . #keyVaultOptions) {
4345 return ; // no-op when keyVaultOptions is not configured
4446 }
45- // Deduplicate references by secret identifier (sourceId)
46- // ConfigurationSetting is for Key Vault reference error building.
47- const uniqueSecrets = new Map < string , { secretIdentifier : KeyVaultSecretIdentifier ; setting : ConfigurationSetting } > ( ) ;
47+ // Deduplicate references by secret identifier (sourceId).
48+ const uniqueSecrets = new Map < string , KeyVaultSecretIdentifier > ( ) ;
4849 for ( const setting of settings ) {
4950 if ( ! this . canProcess ( setting ) ) {
5051 continue ;
@@ -55,30 +56,20 @@ export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter {
5556 parseSecretReference ( setting ) . value . secretId
5657 ) ;
5758 } catch ( error ) {
58- throw new KeyVaultReferenceError ( buildKeyVaultReferenceErrorMessage ( "Invalid Key Vault reference." , setting ) , { cause : error } ) ;
59+ throw new KeyVaultReferenceError ( buildKeyVaultReferenceErrorMessage ( "Invalid Key Vault reference." , undefined , setting ) , { cause : error } ) ;
5960 }
6061 if ( ! uniqueSecrets . has ( secretIdentifier . sourceId ) ) {
61- uniqueSecrets . set ( secretIdentifier . sourceId , { secretIdentifier, setting } ) ;
62+ uniqueSecrets . set ( secretIdentifier . sourceId , secretIdentifier ) ;
6263 }
6364 }
6465
65- const loadSecret = async ( { secretIdentifier, setting } : { secretIdentifier : KeyVaultSecretIdentifier ; setting : ConfigurationSetting } ) => {
66- try {
67- await this . #keyVaultSecretProvider. loadSecretValue ( secretIdentifier ) ;
68- } catch ( error ) {
69- if ( isRestError ( error ) || error instanceof AuthenticationError ) {
70- throw new KeyVaultReferenceError ( buildKeyVaultReferenceErrorMessage ( "Failed to resolve Key Vault reference." , setting , secretIdentifier . sourceId ) , { cause : error } ) ;
71- }
72- throw error ;
73- }
74- } ;
75-
76- const uniqueSecretEntries = [ ...uniqueSecrets . values ( ) ] ;
66+ // Resolve failures surface as KeyVaultReferenceError from the provider, identified by secret identifier.
67+ const uniqueSecretIdentifiers = [ ...uniqueSecrets . values ( ) ] ;
7768 if ( this . #keyVaultOptions. parallelSecretResolutionEnabled ) {
78- await Promise . all ( uniqueSecretEntries . map ( loadSecret ) ) ;
69+ await Promise . all ( uniqueSecretIdentifiers . map ( secretIdentifier => this . #keyVaultSecretProvider . loadSecretValue ( secretIdentifier ) ) ) ;
7970 } else {
80- for ( const entry of uniqueSecretEntries ) {
81- await loadSecret ( entry ) ;
71+ for ( const secretIdentifier of uniqueSecretIdentifiers ) {
72+ await this . #keyVaultSecretProvider . loadSecretValue ( secretIdentifier ) ;
8273 }
8374 }
8475 }
@@ -88,7 +79,3 @@ export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter {
8879 return ;
8980 }
9081}
91-
92- function buildKeyVaultReferenceErrorMessage ( message : string , setting : ConfigurationSetting , secretIdentifier ?: string ) : string {
93- return `${ message } Key: '${ setting . key } ' Label: '${ setting . label ?? "" } ' ETag: '${ setting . etag ?? "" } ' ${ secretIdentifier ? ` SecretIdentifier: '${ secretIdentifier } '` : "" } ` ;
94- }
0 commit comments