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
Updated to use common Azure auth logic #972
Conversation
@msfussell @yaron2 FYI |
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.
Overall is on a good path. I would ask to keep backwards compatibility and also keep support for the existing (although non-recommended) authentication via secret key and connection strings. This can be handy for local development and also to give existing apps some room to migrate.
Thanks for the first round of reviews. I'll continue iterating on this. Understood on maintaining support for the "legacy" out, agree it should be preserved. |
Could move task list to issue, and separate PR as small as possible, it would help track and review. |
@daixiang0 I think this would make sense. I could trim down this PR to only what's implemented today (a few things need to be updated/fixed, I'll get to that soon - just need to find some time :) ). The other component updates could be moved to a separate issue, and we could open a PR for each. |
thanks for your contributions! please fix the conflict. |
@ItalyPaleAle I think this contribution is great and exactly what we need. I like that you centralized and standardized the Azure Auth. Also, I approve of the KV related changes (I was working on those independently myself). |
- Currently implemented on secretstores/azure/keyvault and state/azure/blobstorage - Supports Azure AD via service principal (client credentials, client certificate, MSI) - based on the previous authorizer for AKV - Allows using other Azure clouds (China, Germany, etc) - For Blob Storage state, supports using custom endpoints (like emulators like Azurite)
@artursouza feel free to review this now. I think this is in a state where we can merge it. Right now this only updates behaviors for State Store from Azure Storage and Secret Store with Keyvault. It does however generally put the common Azure Auth logic in place. We can in subsequent PRs switch the other Azure components to use this logic. This change here is also fully backwards compatible. I introduced new Environment variables as alternatives to the old |
It's important to make sure this is backward compatible. I'm happy with this change. |
Workflow is running now. |
@yaron2 I'm taking one more pass to review this PR and also the following changes. Working synchronously with @berndverst as I'm writing this. We should be done soon. |
Given that the various settings are specified as metadata in the component YAMLs we decided to name them in a more YAML standard way with camelcase. The naming is still derived from the naming in the other Azure SDKs, but is camelcase with an |
@yaron2 we're done. The last changes include:
I think this is ready for review at this point. Some notes:
|
authentication/azure/storage.go
Outdated
} | ||
var tokenRefresher azblob.TokenRefresher = func(credential azblob.TokenCredential) time.Duration { | ||
log.Debug("Refreshing Azure Storage auth token") | ||
fmt.Println("Refreshing Azure Storage auth token") |
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.
I just noticed there are 2 log statements here. Perhaps only one of the two should be kept (or neither). Same on lines 53-54. Not sure what the standard for logging in Dapr is, maybe you could decide how to fix this please?
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.
We shouldn't use fmt.Println
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.
I already removed it before I saw your comment @yaron2 :)
@artursouza @yaron2 can you please take a look and review? :) |
Codecov Report
@@ Coverage Diff @@
## master #972 +/- ##
==========================================
+ Coverage 34.53% 34.65% +0.12%
==========================================
Files 132 132
Lines 10870 10907 +37
==========================================
+ Hits 3754 3780 +26
- Misses 6736 6740 +4
- Partials 380 387 +7
Continue to review full report at Codecov.
|
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.
Just a comment on a test that might affect backwards compatibility.
@@ -50,13 +50,11 @@ func TestGetBlobStorageMetaData(t *testing.T) { | |||
t.Run("All parameters passed and parsed", func(t *testing.T) { | |||
m := make(map[string]string) | |||
m["accountName"] = "acc" | |||
m["accountKey"] = "key" |
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.
Why key
is not parsed anymore?
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.
The accountKey
property doesn't exist anymore in the object (see line 59 deleted in the test below).
Instead, the shared key is read in the method that returns the azblob.Credential
object:
accountKey, ok := metadata[storageAccountKeyKey] |
dapr#972 accidentally introduced a backwards-incompatible change with a feature added in 1.3. Before, it was possible to specify an Azure environment for the AKV secret store by passing a FQDN as "vaultName" property that included the suffix for the Azure environment. dapr#972 introduced a better way to handle this (using the "azureEnvironment" metadata property), but accidentally broke the behavior added in 1.3 This patch restores full compatibility with 1.3. Although that behavior should be considered deprecated and thus discouraged (and it will be removed from docs), it will still be supported.
* Restored backwards compatibility with 1.3 #972 accidentally introduced a backwards-incompatible change with a feature added in 1.3. Before, it was possible to specify an Azure environment for the AKV secret store by passing a FQDN as "vaultName" property that included the suffix for the Azure environment. #972 introduced a better way to handle this (using the "azureEnvironment" metadata property), but accidentally broke the behavior added in 1.3 This patch restores full compatibility with 1.3. Although that behavior should be considered deprecated and thus discouraged (and it will be removed from docs), it will still be supported. * Lint
* Restored backwards compatibility with 1.3 dapr#972 accidentally introduced a backwards-incompatible change with a feature added in 1.3. Before, it was possible to specify an Azure environment for the AKV secret store by passing a FQDN as "vaultName" property that included the suffix for the Azure environment. dapr#972 introduced a better way to handle this (using the "azureEnvironment" metadata property), but accidentally broke the behavior added in 1.3 This patch restores full compatibility with 1.3. Although that behavior should be considered deprecated and thus discouraged (and it will be removed from docs), it will still be supported. * Lint
* Restored backwards compatibility with 1.3 #972 accidentally introduced a backwards-incompatible change with a feature added in 1.3. Before, it was possible to specify an Azure environment for the AKV secret store by passing a FQDN as "vaultName" property that included the suffix for the Azure environment. #972 introduced a better way to handle this (using the "azureEnvironment" metadata property), but accidentally broke the behavior added in 1.3 This patch restores full compatibility with 1.3. Although that behavior should be considered deprecated and thus discouraged (and it will be removed from docs), it will still be supported. * Lint Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com>
* Common Azure auth logic - Currently implemented on secretstores/azure/keyvault and state/azure/blobstorage - Supports Azure AD via service principal (client credentials, client certificate, MSI) - based on the previous authorizer for AKV - Allows using other Azure clouds (China, Germany, etc) - For Blob Storage state, supports using custom endpoints (like emulators like Azurite) * Add environment variable aliases * Address linter warnings * another lint thing * Fixed typo in method description * Updated metadata key names so they're more consistent * Fix test * Some more linter things Co-authored-by: Bernd Verst <me@bernd.dev> Co-authored-by: Yaron Schneider <yaronsc@microsoft.com> Co-authored-by: Bernd Verst <berndverst@users.noreply.github.com>
* Restored backwards compatibility with 1.3 dapr#972 accidentally introduced a backwards-incompatible change with a feature added in 1.3. Before, it was possible to specify an Azure environment for the AKV secret store by passing a FQDN as "vaultName" property that included the suffix for the Azure environment. dapr#972 introduced a better way to handle this (using the "azureEnvironment" metadata property), but accidentally broke the behavior added in 1.3 This patch restores full compatibility with 1.3. Although that behavior should be considered deprecated and thus discouraged (and it will be removed from docs), it will still be supported. * Lint
TLDR
This PR fixes #970 and it generally tries to improve the authentication logic for (eventually) all Azure services, making it consistent and allowing Azure AD + RBAC wherever possible. Using Azure AD allows greater security and simplified management, such as via MSI. In the process, this PR also adds support for sovereign Azure clouds (Gov, China, etc).
Description
Currently, Dapr authenticates with Azure services primarily via "shared keys". For example, for Azure Storage it uses the "account key", which is not recommended as it's harder to manage the access token securely and it's less auditable. Quoting from the Azure Storage documentation:
This PR adds support for authenticating with Azure services through Azure AD (eventually, supporting all those who support this). This enables authentication via Azure AD "service principals", including client credentials (using a client secret), client certificate credentials (using a client certificate), and MSI. It then enables authorization via Azure RBAC, which can be fine-tuned by admins for better access control.
While I was implementing this, I also enabled the usage of other Azure clouds where possible (Azure China, Azure Gov, etc). For Azure Storage, the goal is to be able to support emulators too for simpler local development (like Azurite).
The code is partly based on the authorizer file that already existed for Azure Key Vault; I have expanded it to support Azure Storage and other services, and I have made it possible to support sovereign clouds.
Example
Example of using
state.azure.blobstorage
using client credentials:Naming consistency
The new authorizer uses key names
spn*
to be consistent with what the Azure Key Vault authorizer was doing before.Within Dapr, other modules (such as
bindings/azure/eventgrid
) usetenantId
,clientId
, andclientSecret
. We should likely standardize on one style (I personally have a preference for the Event Grid's one, omittingspn
because that's an Azure-specific name that is unclear in the OAuth world). For backwards-compatibility, the "deprecated" names can be kept as aliases (such asspnClientId
->clientId
)Work status
The PR is not complete yet. I am opening it as a draft for a review of the underlying authorization logic, and I will complete the support for the remaining modules then (unless someone wants to help :) )
Here's the list of work that's been done and still to do:
bindings/azure/blobstorage
- Uses keysstate/azure/cosmosdb
bindings/azure/eventgrid
- Currently supports client credentials auth but with its own logicbindings/azure/eventhubs
- Uses keysbindings/azure/servicebusqueues
- Uses "connection strings"bindings/azure/signalr
- Uses "connection strings"bindings/azure/storagequeues
- Uses keyspubsub/azure/eventhubs
- Uses keyspubsub/azure/servicebus
- Uses "connection strings"secretstores/azure/keyvault
state/azure/blobstorage
state/azure/cosmosdb
state/azure/tablestorage
- Uses keys