0
# SAS Token Generation - Shared Access Signatures
1
2
The Azure Storage File Share SDK provides functions to generate Shared Access Signatures (SAS) for secure, time-limited access to storage resources without exposing account keys.
3
4
## Import and Core Types
5
6
```python { .api }
7
from azure.storage.fileshare import (
8
generate_account_sas,
9
generate_share_sas,
10
generate_file_sas,
11
ShareSasPermissions,
12
FileSasPermissions,
13
AccountSasPermissions,
14
ResourceTypes,
15
Services
16
)
17
from datetime import datetime, timedelta
18
from typing import Union, Optional, Callable, Any
19
```
20
21
## Account-Level SAS Generation
22
23
```python { .api }
24
def generate_account_sas(
25
account_name: str,
26
account_key: str,
27
resource_types: Union[ResourceTypes, str],
28
permission: Union[AccountSasPermissions, str],
29
expiry: Union[datetime, str],
30
start: Optional[Union[datetime, str]] = None,
31
ip: Optional[str] = None,
32
*,
33
services: Union[Services, str] = Services(fileshare=True),
34
protocol: Optional[str] = None,
35
sts_hook: Optional[Callable[[str], None]] = None,
36
**kwargs: Any
37
) -> str:
38
"""
39
Generates a shared access signature for the file service at account level.
40
41
Parameters:
42
account_name: The storage account name used to generate the SAS
43
account_key: The account key (access key) to generate the SAS
44
resource_types: Specifies resource types accessible with the SAS
45
permission: The permissions associated with the SAS
46
expiry: The time at which the SAS becomes invalid
47
start: The time at which the SAS becomes valid (optional)
48
ip: IP address or range of IP addresses to accept requests from (optional)
49
services: Specifies services the SAS token can be used with (default: fileshare only)
50
protocol: Specifies protocol permitted for requests ("https" or "https,http")
51
sts_hook: Debugging hook for Security Token Service (optional)
52
53
Returns:
54
str: The SAS token string that can be appended to resource URLs
55
56
Example:
57
sas_token = generate_account_sas(
58
account_name="myaccount",
59
account_key="mykey",
60
resource_types=ResourceTypes(service=True, container=True, object=True),
61
permission=AccountSasPermissions(read=True, write=True, list=True),
62
expiry=datetime.utcnow() + timedelta(hours=1)
63
)
64
"""
65
```
66
67
## Share-Level SAS Generation
68
69
```python { .api }
70
def generate_share_sas(
71
account_name: str,
72
share_name: str,
73
account_key: str,
74
permission: Optional[Union[ShareSasPermissions, str]] = None,
75
expiry: Optional[Union[datetime, str]] = None,
76
start: Optional[Union[datetime, str]] = None,
77
policy_id: Optional[str] = None,
78
ip: Optional[str] = None,
79
*,
80
protocol: Optional[str] = None,
81
cache_control: Optional[str] = None,
82
content_disposition: Optional[str] = None,
83
content_encoding: Optional[str] = None,
84
content_language: Optional[str] = None,
85
content_type: Optional[str] = None,
86
sts_hook: Optional[Callable[[str], None]] = None,
87
**kwargs: Any
88
) -> str:
89
"""
90
Generates a shared access signature for a share.
91
92
Parameters:
93
account_name: The storage account name used to generate the SAS
94
share_name: The name of the share
95
account_key: The account key to generate the SAS
96
permission: The permissions associated with the SAS (optional if policy_id provided)
97
expiry: The time at which the SAS becomes invalid (optional if policy_id provided)
98
start: The time at which the SAS becomes valid (optional)
99
policy_id: A unique value that correlates to a stored access policy (optional)
100
ip: IP address or range of IP addresses to accept requests from (optional)
101
protocol: Specifies protocol permitted for requests ("https" or "https,http")
102
cache_control: Response header value for Cache-Control when resource accessed via SAS
103
content_disposition: Response header value for Content-Disposition when accessed via SAS
104
content_encoding: Response header value for Content-Encoding when accessed via SAS
105
content_language: Response header value for Content-Language when accessed via SAS
106
content_type: Response header value for Content-Type when accessed via SAS
107
sts_hook: Debugging hook for Security Token Service (optional)
108
109
Returns:
110
str: The SAS token string that can be appended to share URLs
111
"""
112
```
113
114
## File-Level SAS Generation
115
116
```python { .api }
117
def generate_file_sas(
118
account_name: str,
119
share_name: str,
120
file_path: str,
121
account_key: str,
122
permission: Optional[Union[FileSasPermissions, str]] = None,
123
expiry: Optional[Union[datetime, str]] = None,
124
start: Optional[Union[datetime, str]] = None,
125
policy_id: Optional[str] = None,
126
ip: Optional[str] = None,
127
*,
128
protocol: Optional[str] = None,
129
cache_control: Optional[str] = None,
130
content_disposition: Optional[str] = None,
131
content_encoding: Optional[str] = None,
132
content_language: Optional[str] = None,
133
content_type: Optional[str] = None,
134
sts_hook: Optional[Callable[[str], None]] = None,
135
**kwargs: Any
136
) -> str:
137
"""
138
Generates a shared access signature for a file.
139
140
Parameters:
141
account_name: The storage account name used to generate the SAS
142
share_name: The name of the share containing the file
143
file_path: The path to the file with which to associate the SAS
144
account_key: The account key to generate the SAS
145
permission: The permissions associated with the SAS (optional if policy_id provided)
146
expiry: The time at which the SAS becomes invalid (optional if policy_id provided)
147
start: The time at which the SAS becomes valid (optional)
148
policy_id: A unique value that correlates to a stored access policy (optional)
149
ip: IP address or range of IP addresses to accept requests from (optional)
150
protocol: Specifies protocol permitted for requests ("https" or "https,http")
151
cache_control: Response header value for Cache-Control when resource accessed via SAS
152
content_disposition: Response header value for Content-Disposition when accessed via SAS
153
content_encoding: Response header value for Content-Encoding when accessed via SAS
154
content_language: Response header value for Content-Language when accessed via SAS
155
content_type: Response header value for Content-Type when accessed via SAS
156
sts_hook: Debugging hook for Security Token Service (optional)
157
158
Returns:
159
str: The SAS token string that can be appended to file URLs
160
"""
161
```
162
163
## Permission Classes
164
165
### AccountSasPermissions
166
167
```python { .api }
168
class AccountSasPermissions:
169
def __init__(
170
self,
171
read: bool = False,
172
write: bool = False,
173
delete: bool = False,
174
list: bool = False,
175
add: bool = False,
176
create: bool = False,
177
update: bool = False,
178
process: bool = False
179
) -> None:
180
"""
181
Account-level SAS permissions.
182
183
Parameters:
184
read: Valid for all signed resources types (Service, Container, Object)
185
write: Valid for all signed resources types (Service, Container, Object)
186
delete: Valid for Container and Object resource types
187
list: Valid for Service and Container resource types only
188
add: Valid for Object resource types only (queue messages, table entities, append blobs)
189
create: Valid for Object resource types only (blobs and files)
190
update: Valid for Object resource types only (queue messages and table entities)
191
process: Valid for Object resource types only (queue messages)
192
"""
193
194
@classmethod
195
def from_string(cls, permission: str) -> AccountSasPermissions:
196
"""
197
Create AccountSasPermissions from a string.
198
199
Parameters:
200
permission: Permission string using letters (r=read, w=write, d=delete, l=list, a=add, c=create, u=update, p=process)
201
"""
202
```
203
204
### ShareSasPermissions
205
206
```python { .api }
207
class ShareSasPermissions:
208
def __init__(
209
self,
210
read: bool = False,
211
create: bool = False,
212
write: bool = False,
213
delete: bool = False,
214
list: bool = False
215
) -> None:
216
"""
217
Share-level SAS permissions.
218
219
Parameters:
220
read: Read the content, properties, metadata of any file in the share
221
create: Create a new file in the share, or copy a file to a new file in the share
222
write: Create or write content, properties, metadata. Resize the file
223
delete: Delete any file in the share
224
list: List files and directories in the share
225
"""
226
227
@classmethod
228
def from_string(cls, permission: str) -> ShareSasPermissions:
229
"""
230
Create ShareSasPermissions from a string.
231
232
Parameters:
233
permission: Permission string using letters (r=read, c=create, w=write, d=delete, l=list)
234
"""
235
```
236
237
### FileSasPermissions
238
239
```python { .api }
240
class FileSasPermissions:
241
def __init__(
242
self,
243
read: bool = False,
244
create: bool = False,
245
write: bool = False,
246
delete: bool = False
247
) -> None:
248
"""
249
File-level SAS permissions.
250
251
Parameters:
252
read: Read the content, properties, metadata. Use file as source of copy operation
253
create: Create a new file or copy a file to a new file
254
write: Create or write content, properties, metadata. Resize the file
255
delete: Delete the file
256
"""
257
258
@classmethod
259
def from_string(cls, permission: str) -> FileSasPermissions:
260
"""
261
Create FileSasPermissions from a string.
262
263
Parameters:
264
permission: Permission string using letters (r=read, c=create, w=write, d=delete)
265
"""
266
```
267
268
## Resource Types and Services
269
270
### ResourceTypes
271
272
```python { .api }
273
class ResourceTypes:
274
def __init__(
275
self,
276
service: bool = False,
277
container: bool = False,
278
object: bool = False
279
) -> None:
280
"""
281
Specifies resource types accessible with the account SAS.
282
283
Parameters:
284
service: Access to service-level APIs (Get/Set Service Properties, List Shares)
285
container: Access to container-level APIs (Create/Delete Share, Share Properties, List Directories/Files)
286
object: Access to object-level APIs (Create/Delete/Read/Write File, File Properties)
287
"""
288
289
@classmethod
290
def from_string(cls, resource_types: str) -> ResourceTypes:
291
"""
292
Create ResourceTypes from a string.
293
294
Parameters:
295
resource_types: String using letters (s=service, c=container, o=object)
296
"""
297
```
298
299
### Services
300
301
```python { .api }
302
class Services:
303
def __init__(
304
self,
305
blob: bool = False,
306
queue: bool = False,
307
table: bool = False,
308
fileshare: bool = False
309
) -> None:
310
"""
311
Specifies services accessible with the account SAS.
312
313
Parameters:
314
blob: Valid for Blob service
315
queue: Valid for Queue service
316
table: Valid for Table service
317
fileshare: Valid for File service
318
"""
319
320
@classmethod
321
def from_string(cls, services: str) -> Services:
322
"""
323
Create Services from a string.
324
325
Parameters:
326
services: String using letters (b=blob, q=queue, t=table, f=fileshare)
327
"""
328
```
329
330
## Usage Examples
331
332
### Basic SAS Token Generation
333
334
```python { .api }
335
from azure.storage.fileshare import *
336
from datetime import datetime, timedelta
337
338
# Account credentials
339
account_name = "mystorageaccount"
340
account_key = "myaccountkey"
341
342
# Generate account-level SAS for full file service access
343
account_sas = generate_account_sas(
344
account_name=account_name,
345
account_key=account_key,
346
resource_types=ResourceTypes(service=True, container=True, object=True),
347
permission=AccountSasPermissions(read=True, write=True, list=True, create=True, delete=True),
348
expiry=datetime.utcnow() + timedelta(hours=24), # Valid for 24 hours
349
start=datetime.utcnow() - timedelta(minutes=5), # Valid from 5 minutes ago
350
protocol="https" # HTTPS only
351
)
352
print(f"Account SAS: {account_sas}")
353
354
# Generate share-level SAS for specific share
355
share_sas = generate_share_sas(
356
account_name=account_name,
357
share_name="documents",
358
account_key=account_key,
359
permission=ShareSasPermissions(read=True, list=True),
360
expiry=datetime.utcnow() + timedelta(hours=2) # 2-hour read access
361
)
362
print(f"Share SAS: {share_sas}")
363
364
# Generate file-level SAS for specific file
365
file_sas = generate_file_sas(
366
account_name=account_name,
367
share_name="documents",
368
file_path="reports/monthly_report.pdf",
369
account_key=account_key,
370
permission=FileSasPermissions(read=True),
371
expiry=datetime.utcnow() + timedelta(hours=1), # 1-hour read access
372
content_disposition="attachment; filename=report.pdf" # Force download
373
)
374
print(f"File SAS: {file_sas}")
375
```
376
377
### Using SAS Tokens with Clients
378
379
```python { .api }
380
from azure.storage.fileshare import ShareServiceClient, ShareClient, ShareFileClient
381
382
# Use account SAS with service client
383
service_client = ShareServiceClient(
384
account_url=f"https://{account_name}.file.core.windows.net",
385
credential=account_sas
386
)
387
388
# List shares using account SAS
389
shares = list(service_client.list_shares())
390
print(f"Found {len(shares)} shares")
391
392
# Use share SAS with share client
393
share_client = ShareClient(
394
account_url=f"https://{account_name}.file.core.windows.net",
395
share_name="documents",
396
credential=share_sas
397
)
398
399
# List files using share SAS
400
files = list(share_client.list_directories_and_files())
401
print(f"Found {len(files)} items in share")
402
403
# Use file SAS with file client
404
file_client = ShareFileClient(
405
account_url=f"https://{account_name}.file.core.windows.net",
406
share_name="documents",
407
file_path="reports/monthly_report.pdf",
408
credential=file_sas
409
)
410
411
# Download file using file SAS
412
download_stream = file_client.download_file()
413
content = download_stream.readall()
414
print(f"Downloaded {len(content)} bytes")
415
```
416
417
### Advanced SAS Configuration
418
419
```python { .api }
420
# SAS with IP restrictions
421
restricted_sas = generate_file_sas(
422
account_name=account_name,
423
share_name="sensitive-data",
424
file_path="confidential.txt",
425
account_key=account_key,
426
permission=FileSasPermissions(read=True),
427
expiry=datetime.utcnow() + timedelta(minutes=30),
428
ip="192.168.1.100", # Only allow from specific IP
429
protocol="https" # HTTPS only
430
)
431
432
# SAS with custom response headers
433
download_sas = generate_file_sas(
434
account_name=account_name,
435
share_name="downloads",
436
file_path="software/installer.exe",
437
account_key=account_key,
438
permission=FileSasPermissions(read=True),
439
expiry=datetime.utcnow() + timedelta(hours=6),
440
content_type="application/octet-stream",
441
content_disposition="attachment; filename=installer.exe",
442
cache_control="no-cache"
443
)
444
445
# SAS for temporary upload access
446
upload_sas = generate_share_sas(
447
account_name=account_name,
448
share_name="uploads",
449
account_key=account_key,
450
permission=ShareSasPermissions(create=True, write=True),
451
expiry=datetime.utcnow() + timedelta(hours=1), # 1-hour upload window
452
start=datetime.utcnow() # Valid immediately
453
)
454
455
print(f"Upload SAS: {upload_sas}")
456
```
457
458
### SAS with Stored Access Policies
459
460
```python { .api }
461
from azure.storage.fileshare import AccessPolicy
462
463
# First, create a stored access policy on the share
464
share_client = ShareClient(
465
account_url=f"https://{account_name}.file.core.windows.net",
466
share_name="documents",
467
credential=AzureNamedKeyCredential(account_name, account_key)
468
)
469
470
# Define access policy
471
policy = AccessPolicy(
472
permission=ShareSasPermissions(read=True, list=True),
473
expiry=datetime.utcnow() + timedelta(days=30),
474
start=datetime.utcnow()
475
)
476
477
# Set the access policy on the share
478
share_client.set_share_access_policy({"readonly": policy})
479
480
# Generate SAS using stored access policy (no expiry/permission needed)
481
policy_sas = generate_share_sas(
482
account_name=account_name,
483
share_name="documents",
484
account_key=account_key,
485
policy_id="readonly" # Reference to stored policy
486
)
487
488
# This SAS inherits permissions and expiry from the stored policy
489
print(f"Policy-based SAS: {policy_sas}")
490
491
# Benefits: Can modify policy without regenerating SAS tokens
492
# Update the policy to add write permissions
493
updated_policy = AccessPolicy(
494
permission=ShareSasPermissions(read=True, list=True, write=True),
495
expiry=datetime.utcnow() + timedelta(days=30),
496
start=datetime.utcnow()
497
)
498
499
share_client.set_share_access_policy({"readonly": updated_policy})
500
# Existing SAS tokens now have write permissions too!
501
```
502
503
### SAS for Different Use Cases
504
505
```python { .api }
506
# 1. Read-only access for external users
507
public_read_sas = generate_share_sas(
508
account_name=account_name,
509
share_name="public-documents",
510
account_key=account_key,
511
permission=ShareSasPermissions(read=True, list=True),
512
expiry=datetime.utcnow() + timedelta(days=7) # Week-long access
513
)
514
515
# 2. Temporary upload for file submissions
516
upload_window_sas = generate_share_sas(
517
account_name=account_name,
518
share_name="submissions",
519
account_key=account_key,
520
permission=ShareSasPermissions(create=True, write=True),
521
expiry=datetime.utcnow() + timedelta(hours=2), # 2-hour upload window
522
start=datetime.utcnow()
523
)
524
525
# 3. Backup service access
526
backup_sas = generate_account_sas(
527
account_name=account_name,
528
account_key=account_key,
529
resource_types=ResourceTypes(container=True, object=True),
530
permission=AccountSasPermissions(read=True, list=True),
531
expiry=datetime.utcnow() + timedelta(hours=8), # 8-hour backup window
532
services=Services(fileshare=True)
533
)
534
535
# 4. Monitoring/audit read access
536
audit_sas = generate_account_sas(
537
account_name=account_name,
538
account_key=account_key,
539
resource_types=ResourceTypes(service=True, container=True),
540
permission=AccountSasPermissions(read=True, list=True),
541
expiry=datetime.utcnow() + timedelta(days=1)
542
)
543
```
544
545
### SAS URL Construction and Usage
546
547
```python { .api }
548
# Construct full URLs with SAS tokens
549
base_url = f"https://{account_name}.file.core.windows.net"
550
551
# Share URL with SAS
552
share_url_with_sas = f"{base_url}/documents?{share_sas}"
553
print(f"Share URL: {share_url_with_sas}")
554
555
# File URL with SAS
556
file_url_with_sas = f"{base_url}/documents/reports/monthly_report.pdf?{file_sas}"
557
print(f"File URL: {file_url_with_sas}")
558
559
# Use URLs directly with HTTP clients
560
import requests
561
562
# Download file using direct HTTP request
563
response = requests.get(file_url_with_sas)
564
if response.status_code == 200:
565
with open("downloaded_report.pdf", "wb") as f:
566
f.write(response.content)
567
print("File downloaded successfully")
568
else:
569
print(f"Download failed: {response.status_code}")
570
571
# Upload file using direct HTTP request
572
upload_url = f"{base_url}/uploads/new_file.txt?{upload_sas}"
573
with open("local_file.txt", "rb") as f:
574
response = requests.put(
575
upload_url,
576
data=f,
577
headers={
578
"x-ms-type": "file",
579
"x-ms-content-length": str(os.path.getsize("local_file.txt"))
580
}
581
)
582
583
if response.status_code in [201, 200]:
584
print("File uploaded successfully")
585
else:
586
print(f"Upload failed: {response.status_code}")
587
```
588
589
### SAS Security Best Practices
590
591
```python { .api }
592
# 1. Principle of least privilege - minimal permissions
593
minimal_sas = generate_file_sas(
594
account_name=account_name,
595
share_name="documents",
596
file_path="public/readme.txt",
597
account_key=account_key,
598
permission=FileSasPermissions(read=True), # Only read, no write/delete
599
expiry=datetime.utcnow() + timedelta(hours=1) # Short expiration
600
)
601
602
# 2. HTTPS only for sensitive data
603
secure_sas = generate_file_sas(
604
account_name=account_name,
605
share_name="confidential",
606
file_path="sensitive_data.txt",
607
account_key=account_key,
608
permission=FileSasPermissions(read=True),
609
expiry=datetime.utcnow() + timedelta(minutes=15), # Very short expiration
610
protocol="https", # Force HTTPS
611
ip="203.0.113.0/24" # Restrict to known IP range
612
)
613
614
# 3. Use stored access policies for revocation capability
615
def create_revocable_sas(share_client, policy_name, permissions, duration):
616
"""Create SAS that can be revoked by updating stored policy."""
617
618
# Create policy
619
policy = AccessPolicy(
620
permission=permissions,
621
expiry=datetime.utcnow() + duration,
622
start=datetime.utcnow()
623
)
624
625
# Set policy on share
626
share_client.set_share_access_policy({policy_name: policy})
627
628
# Generate SAS using policy
629
return generate_share_sas(
630
account_name=share_client.account_name,
631
share_name=share_client.share_name,
632
account_key=account_key,
633
policy_id=policy_name
634
)
635
636
# To revoke, just delete the policy
637
def revoke_sas(share_client, policy_name):
638
"""Revoke SAS by removing stored access policy."""
639
share_client.set_share_access_policy({}) # Empty policy removes all
640
641
# 4. Monitor SAS usage (implement logging)
642
def generate_tracked_sas(purpose, **sas_args):
643
"""Generate SAS with usage tracking."""
644
sas_token = generate_file_sas(**sas_args)
645
646
# Log SAS generation
647
print(f"Generated SAS for {purpose}")
648
print(f"Expiry: {sas_args['expiry']}")
649
print(f"Permissions: {sas_args['permission']}")
650
651
return sas_token
652
```
653
654
SAS tokens provide secure, granular access control to Azure File Share resources without exposing storage account keys. Use them to grant time-limited, permission-specific access to external users, applications, or services.