-
Notifications
You must be signed in to change notification settings - Fork 849
Azure Storage Accounts PoLP (Principle of least privilege) Approach #2284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
ea4b5e5
9d5c501
fa8a0d1
5665fdc
52f519c
a1c64a0
9b949cb
1a6324c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -31,21 +31,26 @@ public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context | |||||
| { | ||||||
| try | ||||||
| { | ||||||
| // Note: BlobServiceClient.GetPropertiesAsync() cannot be used with only the role assignment | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, this comment should not be removed. |
||||||
| // "Storage Blob Data Contributor," so BlobServiceClient.GetBlobContainersAsync() is used instead to probe service health. | ||||||
| // However, BlobContainerClient.GetPropertiesAsync() does have sufficient permissions. | ||||||
| await _blobServiceClient | ||||||
| .GetBlobContainersAsync(cancellationToken: cancellationToken) | ||||||
| .AsPages(pageSizeHint: 1) | ||||||
| .GetAsyncEnumerator(cancellationToken) | ||||||
| .MoveNextAsync() | ||||||
| .ConfigureAwait(false); | ||||||
|
|
||||||
| if (!string.IsNullOrEmpty(_options.ContainerName)) | ||||||
| { | ||||||
| // Note: PoLP (Principle of least privilege) | ||||||
| // This can be used having at least the role assignment "Storage Blob Data Reader" at container level or at least "Storage Blob Data Reader" at storage account level. | ||||||
| // See <see href="https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app?tabs=dotnet#configure-permissions-for-access-to-blob-and-queue-data">Configure permissions for access to blob and queue data</see> | ||||||
|
||||||
| // See <see href="https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app?tabs=dotnet#configure-permissions-for-access-to-blob-and-queue-data">Configure permissions for access to blob and queue data</see> | |
| // See https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app?tabs=dotnet#configure-permissions-for-access-to-blob-and-queue-data |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
| // See <see href="https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app?tabs=dotnet#configure-permissions-for-access-to-blob-and-queue-data">Configure permissions for access to blob and queue data</see> | |
| // See https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app?tabs=dotnet#configure-permissions-for-access-to-blob-and-queue-data |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,21 +31,26 @@ public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context | |
| { | ||
| try | ||
| { | ||
| // Note: QueueServiceClient.GetPropertiesAsync() cannot be used with only the role assignment | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
| // "Storage Queue Data Contributor," so QueueServiceClient.GetQueuesAsync() is used instead to probe service health. | ||
| // However, QueueClient.GetPropertiesAsync() does have sufficient permissions. | ||
| await _queueServiceClient | ||
| .GetQueuesAsync(cancellationToken: cancellationToken) | ||
| .AsPages(pageSizeHint: 1) | ||
| .GetAsyncEnumerator(cancellationToken) | ||
| .MoveNextAsync() | ||
| .ConfigureAwait(false); | ||
|
|
||
| if (!string.IsNullOrEmpty(_options.QueueName)) | ||
| { | ||
| // Note: PoLP (Principle of least privilege) | ||
| // This can be used having at least the role assignment "Storage Queue Data Reader" at container level or at least "Storage Queue Data Reader" at storage account level. | ||
| // See <see href="https://learn.microsoft.com/en-us/rest/api/storageservices/get-queue-metadata#authorization">Configure permissions for access to queue data</see> | ||
| var queueClient = _queueServiceClient.GetQueueClient(_options.QueueName); | ||
| await queueClient.GetPropertiesAsync(cancellationToken).ConfigureAwait(false); | ||
| } | ||
| else | ||
| { | ||
| // Note: PoLP (Principle of least privilege) | ||
| // This can be used having at least "Storage Queue Data Reader" at storage account level. | ||
| // See <see href="https://learn.microsoft.com/en-us/rest/api/storageservices/get-queue-metadata#authorization">Configure permissions for access to queue data</see> | ||
| await _queueServiceClient | ||
| .GetQueuesAsync(cancellationToken: cancellationToken) | ||
| .AsPages(pageSizeHint: 1) | ||
| .GetAsyncEnumerator(cancellationToken) | ||
| .MoveNextAsync() | ||
| .ConfigureAwait(false); | ||
| } | ||
|
|
||
| return HealthCheckResult.Healthy(); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |||||||||||||||||||||||||||||||||||||||||
| using Azure; | ||||||||||||||||||||||||||||||||||||||||||
| using Azure.Data.Tables; | ||||||||||||||||||||||||||||||||||||||||||
| using Azure.Data.Tables.Models; | ||||||||||||||||||||||||||||||||||||||||||
| using Microsoft.AspNetCore.Mvc.RazorPages; | ||||||||||||||||||||||||||||||||||||||||||
| using NSubstitute; | ||||||||||||||||||||||||||||||||||||||||||
| using NSubstitute.ExceptionExtensions; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -55,36 +56,26 @@ public async Task return_healthy_when_only_checking_healthy_service() | |||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| [Fact] | ||||||||||||||||||||||||||||||||||||||||||
| public async Task return_healthy_when_checking_healthy_service_and_table() | ||||||||||||||||||||||||||||||||||||||||||
| public async Task return_healthy_when_checking_healthy_service_table() | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
| public async Task return_healthy_when_checking_healthy_service_table() | |
| public async Task return_healthy_when_checking_healthy_table() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to other reviewers: we already have a test that is testing the code path where _tableServiceClient is being used:
Lines 36 to 55 in f587a63
| public async Task return_healthy_when_only_checking_healthy_service() | |
| { | |
| using var tokenSource = new CancellationTokenSource(); | |
| _tableServiceClient | |
| .QueryAsync(filter: "false", cancellationToken: tokenSource.Token) | |
| .Returns(AsyncPageable<TableItem>.FromPages(Array.Empty<Page<TableItem>>())); | |
| var actual = await _healthCheck.CheckHealthAsync(_context, tokenSource.Token); | |
| _tableServiceClient | |
| .Received(1) | |
| .QueryAsync(filter: "false", cancellationToken: tokenSource.Token); | |
| _tableClient | |
| .DidNotReceiveWithAnyArgs() | |
| .QueryAsync<TableEntity>(default(string), default, default, default); | |
| actual.Status.ShouldBe(HealthStatus.Healthy); | |
| } |
(this change looks like we test only 1 out of 2, but we keep testing both)
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
queue? did you mean "table"?
| public async Task return_unhealthy_when_checking_unhealthy_service_queue() | |
| public async Task return_unhealthy_when_checking_unhealthy_table() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a valuable comment and it should be moved rather than deleted.