2121
2222import  com .microsoft .azure .storage .LocationMode ;
2323import  com .microsoft .azure .storage .RetryPolicy ;
24+ import  org .elasticsearch .common .Nullable ;
2425import  org .elasticsearch .common .Strings ;
2526import  org .elasticsearch .common .collect .MapBuilder ;
2627import  org .elasticsearch .common .collect .Tuple ;
@@ -57,6 +58,10 @@ public final class AzureStorageSettings {
5758    public  static  final  AffixSetting <SecureString > KEY_SETTING  = Setting .affixKeySetting (AZURE_CLIENT_PREFIX_KEY , "key" ,
5859        key  -> SecureSetting .secureString (key , null ));
5960
61+     /** Azure SAS token */ 
62+     public  static  final  AffixSetting <SecureString > SAS_TOKEN_SETTING  = Setting .affixKeySetting (AZURE_CLIENT_PREFIX_KEY , "sas_token" ,
63+         key  -> SecureSetting .secureString (key , null ));
64+ 
6065    /** max_retries: Number of retries in case of Azure errors. Defaults to 3 (RetryPolicy.DEFAULT_CLIENT_RETRY_COUNT). */ 
6166    public  static  final  Setting <Integer > MAX_RETRIES_SETTING  =
6267        Setting .affixKeySetting (AZURE_CLIENT_PREFIX_KEY , "max_retries" ,
@@ -118,7 +123,7 @@ public interface Storage {
118123    @ Deprecated 
119124    private  final  String  name ;
120125    private  final  String  account ;
121-     private  final  String  key ;
126+     private  final  String  connectString ;
122127    private  final  String  endpointSuffix ;
123128    private  final  TimeValue  timeout ;
124129    @ Deprecated 
@@ -128,11 +133,11 @@ public interface Storage {
128133    private  final  LocationMode  locationMode ;
129134
130135    // copy-constructor 
131-     private  AzureStorageSettings (String  name , String  account , String  key , String  endpointSuffix , TimeValue  timeout ,  boolean   activeByDefault ,
132-             int  maxRetries , Proxy  proxy , LocationMode  locationMode ) {
136+     private  AzureStorageSettings (String  name , String  account , String  connectString , String  endpointSuffix , TimeValue  timeout ,
137+                                   boolean   activeByDefault ,  int  maxRetries , Proxy  proxy , LocationMode  locationMode ) {
133138        this .name  = name ;
134139        this .account  = account ;
135-         this .key  = key ;
140+         this .connectString  = connectString ;
136141        this .endpointSuffix  = endpointSuffix ;
137142        this .timeout  = timeout ;
138143        this .activeByDefault  = activeByDefault ;
@@ -145,7 +150,7 @@ private AzureStorageSettings(String name, String account, String key, String end
145150    public  AzureStorageSettings (String  name , String  account , String  key , TimeValue  timeout , boolean  activeByDefault , int  maxRetries ) {
146151        this .name  = name ;
147152        this .account  = account ;
148-         this .key  = key ;
153+         this .connectString  = buildConnectString ( account ,  key ,  null ,  null ) ;
149154        this .endpointSuffix  = null ;
150155        this .timeout  = timeout ;
151156        this .activeByDefault  = activeByDefault ;
@@ -154,11 +159,11 @@ public AzureStorageSettings(String name, String account, String key, TimeValue t
154159        this .locationMode  = LocationMode .PRIMARY_ONLY ;
155160    }
156161
157-     AzureStorageSettings (String  account , String  key , String  endpointSuffix , TimeValue  timeout , int  maxRetries ,
158-                                 Proxy .Type  proxyType , String  proxyHost , Integer  proxyPort ) {
162+     private   AzureStorageSettings (String  account , String  key ,  String   sasToken , String  endpointSuffix , TimeValue  timeout , int  maxRetries ,
163+                                   Proxy .Type  proxyType , String  proxyHost , Integer  proxyPort ) {
159164        this .name  = null ;
160165        this .account  = account ;
161-         this .key  = key ;
166+         this .connectString  = buildConnectString ( account ,  key ,  sasToken ,  endpointSuffix ) ;
162167        this .endpointSuffix  = endpointSuffix ;
163168        this .timeout  = timeout ;
164169        this .activeByDefault  = false ;
@@ -189,10 +194,6 @@ public String getName() {
189194        return  name ;
190195    }
191196
192-     public  String  getKey () {
193-         return  key ;
194-     }
195- 
196197    public  String  getAccount () {
197198        return  account ;
198199    }
@@ -218,13 +219,26 @@ public Proxy getProxy() {
218219        return  proxy ;
219220    }
220221
221-     public  String  buildConnectionString () {
222+     public  String  getConnectString () {
223+         return  connectString ;
224+     }
225+ 
226+     private  static  String  buildConnectString (String  account , @ Nullable  String  key , @ Nullable  String  sasToken , String  endpointSuffix ) {
227+         final  boolean  hasSasToken  = Strings .hasText (sasToken );
228+         final  boolean  hasKey  = Strings .hasText (key );
229+         if  (hasSasToken  == false  && hasKey  == false ) {
230+             throw  new  SettingsException ("Neither a secret key nor a shared access token was set." );
231+         }
232+         if  (hasSasToken  && hasKey ) {
233+             throw  new  SettingsException ("Both a secret as well as a shared access token were set." );
234+         }
222235        final  StringBuilder  connectionStringBuilder  = new  StringBuilder ();
223-         connectionStringBuilder .append ("DefaultEndpointsProtocol=https" )
224-                 .append (";AccountName=" )
225-                 .append (account )
226-                 .append (";AccountKey=" )
227-                 .append (key );
236+         connectionStringBuilder .append ("DefaultEndpointsProtocol=https" ).append (";AccountName=" ).append (account );
237+         if  (hasKey ) {
238+             connectionStringBuilder .append (";AccountKey=" ).append (key );
239+         } else  {
240+             connectionStringBuilder .append (";SharedAccessSignature=" ).append (sasToken );
241+         }
228242        if  (Strings .hasText (endpointSuffix )) {
229243            connectionStringBuilder .append (";EndpointSuffix=" ).append (endpointSuffix );
230244        }
@@ -239,7 +253,6 @@ public LocationMode getLocationMode() {
239253    public  String  toString () {
240254        final  StringBuilder  sb  = new  StringBuilder ("AzureStorageSettings{" );
241255        sb .append ("account='" ).append (account ).append ('\'' );
242-         sb .append (", key='" ).append (key ).append ('\'' );
243256        sb .append (", activeByDefault='" ).append (activeByDefault ).append ('\'' );
244257        sb .append (", timeout=" ).append (timeout );
245258        sb .append (", endpointSuffix='" ).append (endpointSuffix ).append ('\'' );
@@ -309,8 +322,9 @@ static Map<String, AzureStorageSettings> loadRegular(Settings settings) {
309322    /** Parse settings for a single client. */ 
310323    static  AzureStorageSettings  getClientSettings (Settings  settings , String  clientName ) {
311324        try  (SecureString  account  = getConfigValue (settings , clientName , ACCOUNT_SETTING );
312-              SecureString  key  = getConfigValue (settings , clientName , KEY_SETTING )) {
313-             return  new  AzureStorageSettings (account .toString (), key .toString (),
325+              SecureString  key  = getConfigValue (settings , clientName , KEY_SETTING );
326+              SecureString  sasToken  = getConfigValue (settings , clientName , SAS_TOKEN_SETTING )) {
327+             return  new  AzureStorageSettings (account .toString (), key .toString (), sasToken .toString (),
314328                getValue (settings , clientName , ENDPOINT_SUFFIX_SETTING ),
315329                getValue (settings , clientName , TIMEOUT_SETTING ),
316330                getValue (settings , clientName , MAX_RETRIES_SETTING ),
@@ -358,8 +372,8 @@ private static AzureStorageSettings getPrimary(List<AzureStorageSettings> settin
358372        } else  if  (settings .size () == 1 ) {
359373            // the only storage settings belong (implicitly) to the default primary storage 
360374            AzureStorageSettings  storage  = settings .get (0 );
361-             return  new  AzureStorageSettings (storage .getName (), storage .getAccount (), storage .getKey (),  storage .getTimeout (),  true ,
362-                 storage .getMaxRetries ());
375+             return  new  AzureStorageSettings (storage .getName (), storage .getAccount (), storage .connectString ,  null ,  storage .getTimeout (),
376+                 true ,  storage .getMaxRetries (),  null ,  LocationMode . PRIMARY_ONLY );
363377        } else  {
364378            AzureStorageSettings  primary  = null ;
365379            for  (AzureStorageSettings  setting  : settings ) {
@@ -398,8 +412,8 @@ public static Map<String, AzureStorageSettings> overrideLocationMode(Map<String,
398412        final  MapBuilder <String , AzureStorageSettings > mapBuilder  = new  MapBuilder <>();
399413        for  (final  Map .Entry <String , AzureStorageSettings > entry  : clientsSettings .entrySet ()) {
400414            final  AzureStorageSettings  azureSettings  = new  AzureStorageSettings (entry .getValue ().name , entry .getValue ().account ,
401-                      entry .getValue ().key , entry .getValue ().endpointSuffix , entry .getValue ().timeout ,  entry . getValue (). activeByDefault ,
402-                      entry .getValue ().maxRetries , entry .getValue ().proxy , locationMode );
415+                 entry .getValue ().connectString , entry .getValue ().endpointSuffix , entry .getValue ().timeout ,
416+                 entry . getValue (). activeByDefault ,  entry .getValue ().maxRetries , entry .getValue ().proxy , locationMode );
403417            mapBuilder .put (entry .getKey (), azureSettings );
404418        }
405419        return  mapBuilder .immutableMap ();
0 commit comments