@@ -26,6 +26,9 @@ import {
2626 SASProtocol ,
2727 generateBlobSASQueryParameters ,
2828} from '@azure/storage-blob' ;
29+ import {
30+ DefaultAzureCredential ,
31+ } from '@azure/identity' ;
2932
3033import { cancelCombinator } from './utils' ;
3134import {
@@ -52,9 +55,30 @@ import {
5255 ForeignKeysQueryResult ,
5356} from './driver.interface' ;
5457
58+ /**
59+ * @see {@link DefaultAzureCredential } constructor options
60+ */
5561export type AzureStorageClientConfig = {
56- azureKey : string ,
62+ azureKey ? : string ,
5763 sasToken ?: string ,
64+ /**
65+ * The client ID of a Microsoft Entra app registration.
66+ * In case of DefaultAzureCredential flow if it is omitted
67+ * the Azure library will try to use the AZURE_CLIENT_ID env
68+ */
69+ clientId ?: string ,
70+ /**
71+ * ID of the application's Microsoft Entra tenant. Also called its directory ID.
72+ * In case of DefaultAzureCredential flow if it is omitted
73+ * the Azure library will try to use the AZURE_TENANT_ID env
74+ */
75+ tenantId ?: string ,
76+ /**
77+ * The path to a file containing a Kubernetes service account token that authenticates the identity.
78+ * In case of DefaultAzureCredential flow if it is omitted
79+ * the Azure library will try to use the AZURE_FEDERATED_TOKEN_FILE env
80+ */
81+ tokenFilePath ?: string ,
5882} ;
5983
6084export type GoogleStorageClientConfig = {
@@ -730,9 +754,52 @@ export abstract class BaseDriver implements DriverInterface {
730754 const parts = bucketName . split ( '.blob.core.windows.net/' ) ;
731755 const account = parts [ 0 ] ;
732756 const container = parts [ 1 ] . split ( '/' ) [ 0 ] ;
733- const credential = new StorageSharedKeyCredential ( account , azureConfig . azureKey ) ;
757+ let credential : StorageSharedKeyCredential | DefaultAzureCredential ;
758+ let blobServiceClient : BlobServiceClient ;
759+ let getSas ;
760+
761+ if ( azureConfig . azureKey ) {
762+ credential = new StorageSharedKeyCredential ( account , azureConfig . azureKey ) ;
763+ getSas = async ( name : string , startsOn : Date , expiresOn : Date ) => generateBlobSASQueryParameters (
764+ {
765+ containerName : container ,
766+ blobName : name ,
767+ permissions : ContainerSASPermissions . parse ( 'r' ) ,
768+ startsOn,
769+ expiresOn,
770+ protocol : SASProtocol . Https ,
771+ version : '2020-08-04' ,
772+ } ,
773+ credential as StorageSharedKeyCredential
774+ ) . toString ( ) ;
775+ } else {
776+ const opts = {
777+ tenantId : azureConfig . tenantId ,
778+ clientId : azureConfig . clientId ,
779+ tokenFilePath : azureConfig . tokenFilePath ,
780+ } ;
781+ credential = new DefaultAzureCredential ( opts ) ;
782+ getSas = async ( name : string , startsOn : Date , expiresOn : Date ) => {
783+ // getUserDelegationKey works only for authorization with Microsoft Entra ID
784+ const userDelegationKey = await blobServiceClient . getUserDelegationKey ( startsOn , expiresOn ) ;
785+ return generateBlobSASQueryParameters (
786+ {
787+ containerName : container ,
788+ blobName : name ,
789+ permissions : ContainerSASPermissions . parse ( 'r' ) ,
790+ startsOn,
791+ expiresOn,
792+ protocol : SASProtocol . Https ,
793+ version : '2020-08-04' ,
794+ } ,
795+ userDelegationKey ,
796+ account ,
797+ ) . toString ( ) ;
798+ } ;
799+ }
800+
734801 const url = `https://${ account } .blob.core.windows.net` ;
735- const blobServiceClient = azureConfig . sasToken ?
802+ blobServiceClient = azureConfig . sasToken ?
736803 new BlobServiceClient ( `${ url } ?${ azureConfig . sasToken } ` ) :
737804 new BlobServiceClient ( url , credential ) ;
738805
@@ -741,19 +808,9 @@ export abstract class BaseDriver implements DriverInterface {
741808 const blobsList = containerClient . listBlobsFlat ( { prefix : `${ tableName } /` } ) ;
742809 for await ( const blob of blobsList ) {
743810 if ( blob . name && ( blob . name . endsWith ( '.csv.gz' ) || blob . name . endsWith ( '.csv' ) ) ) {
744- const sas = generateBlobSASQueryParameters (
745- {
746- containerName : container ,
747- blobName : blob . name ,
748- permissions : ContainerSASPermissions . parse ( 'r' ) ,
749- startsOn : new Date ( new Date ( ) . valueOf ( ) ) ,
750- expiresOn :
751- new Date ( new Date ( ) . valueOf ( ) + 1000 * 60 * 60 ) ,
752- protocol : SASProtocol . Https ,
753- version : '2020-08-04' ,
754- } ,
755- credential ,
756- ) . toString ( ) ;
811+ const starts = new Date ( ) ;
812+ const expires = new Date ( starts . valueOf ( ) + 1000 * 60 * 60 ) ;
813+ const sas = await getSas ( blob . name , starts , expires ) ;
757814 csvFiles . push ( `${ url } /${ container } /${ blob . name } ?${ sas } ` ) ;
758815 }
759816 }
0 commit comments