-
Notifications
You must be signed in to change notification settings - Fork 7
feat/secretstore #42
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
base: main
Are you sure you want to change the base?
feat/secretstore #42
Conversation
Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com>
Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com>
samples/LocalEnvSecretStoreSample/LocalEnvSecretStoreSample.csproj
Outdated
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreGetResponse.cs
Outdated
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreBulkGetResponse.cs
Show resolved
Hide resolved
|
|
||
| public sealed record SecretStoreBulkGetResponse | ||
| { | ||
| //public IReadOnlyDictionary<string, Dictionary<string, string>> responseData = new Dictionary<string, Dictionary<string, string>>(); |
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.
IReadOnlyDictionary<string, IReadonlyDictionary<string, string>> would be the most raw way to expose the bulk data, but I'm not sure if that'd be the best way, as it doesn't easily allow for changes to the API in the future. (E.g. suppose the bulk request returns both values and other metadata for each individual secret). It'd probably be better to expose something like IReadOnlyDictionary<string, GetSecretResponse> Data (which is actually closer to the .proto definition anyway).
I think it's fine to try to simplify some of the .proto APIs where it makes sense (e.g. where it contains unnecessary layers), but we also want to walk that fine line of being true to the .proto as well so that the .NET APIs are still conceptually similar to the other SDKs.
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 think we can use the SecretResponse() constructor from the proto defintion.
src/Dapr.PluggableComponents/Components/SecretStores/ISecretStore.cs
Outdated
Show resolved
Hide resolved
| /// <param name="request">Properties related to the secret to be retrieved.</param> | ||
| /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> | ||
| /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous operation, resulting in the retrieved secret, if any.</returns> | ||
| Task<SecretStoreGetResponse?> GetAsync(SecretStoreGetRequest request, CancellationToken cancellationToken = default); |
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.
What's the Dapr semantics for getting a secret key that doesn't exist? Is that an error or should a "does not exist" value be returned? In the case of state stores, we return null in that case.
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.
in case of env secret store we return empty value like {somsecret: ""}. I think it can depend on specific implementation.
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreGetRequest.cs
Outdated
Show resolved
Hide resolved
|
|
||
| <ItemGroup> | ||
| <Protobuf Include="@(Protos->'$(ProtosComponentsDir)/%(Identity)')" ProtoRoot="$(ProtosRootDir)" GrpcServices="Client,Server" /> | ||
| <Protobuf Include="@(Protos->'$(ProtosComponentsDir)/%(Identity)')" ProtoRoot="$(ProtosRootDir)" GrpcServices="Client,Server" /> |
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.
Not sure what happened here...
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 think the XML editor is getting too aggressive about escaping characters; -> is what it should be.
Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com>
Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com>
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreBulkGetResponse.cs
Outdated
Show resolved
Hide resolved
| { | ||
| public IReadOnlyDictionary<string, string> Data = new Dictionary<string, string>(); | ||
|
|
||
| internal static BulkGetSecretResponse ToBulkGetResponse(SecretStoreBulkGetResponse? response) |
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.
Remove the nullability (?) from the response argument? We would always expect the implementation to give us one, right?
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreGetResponse.cs
Outdated
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreGetResponse.cs
Outdated
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStores/SecretStoreBulkGetResponse.cs
Outdated
Show resolved
Hide resolved
| <PropertyGroup> | ||
| <ProtosVersion>v1</ProtosVersion> | ||
| <ProtosTag>v1.11.0</ProtosTag> | ||
| <ProtosTag>master</ProtosTag> |
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'll want to defer committing this PR until (at least) a v1.12.0 tag exists in dapr/dapr, as we don't want builds picking up whatever happens to be in the master branch at the time.
samples/LocalEnvSecretStoreSample/LocalEnvSecretStoreSample.csproj
Outdated
Show resolved
Hide resolved
| data = ""; | ||
| } | ||
| Dictionary<string, string> resp = new Dictionary<string, string>(); | ||
| resp.Add(request.SecretName, data); |
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.
C# allows Add() methods to be inlined:
var resp = new Dictionary<string, string>
{
{ request.SecretName, data }
}| } | ||
| Dictionary<string, string> resp = new Dictionary<string, string>(); | ||
| resp.Add(request.SecretName, data); | ||
| response = new SecretStoreGetResponse |
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.
Nit: var response = new SecretStoreGetResponse allows you to eliminate the nullable response created above.
| this.logger.LogInformation("Get request for secret {key}", request.SecretName); | ||
|
|
||
| SecretStoreGetResponse? response = null; | ||
| string data = Environment.GetEnvironmentVariable(request.SecretName); |
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.
Nit: should be string? data = ...?
I'd expect a build warning about nullability otherwise (as GetEnvironmentVariable() returns string?).
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.
GetEnvironmentVariable returns string when environment variable is not found or set.
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.
GetEnvironmentVariable() returns string? (a potentially null string). An alternative would be:
string data = Environment.GetEnvironmentVariable() ?? String.Empty;...which assigns "" only if the return value is null.
| Dictionary<string, string> resp = new Dictionary<string, string>(); | ||
| foreach (string key in Environment.GetEnvironmentVariables().Keys) | ||
| { | ||
| resp.Add(key, Environment.GetEnvironmentVariable(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.
GetEnvironmentVariables() returns a dictionary of both names and values; there shouldn't be a reason to later call GetEnvironmentVariable() for each variable name.
| /// <param name="request">Properties related to the secret to be retrieved.</param> | ||
| /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> | ||
| /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous operation, resulting in the retrieved secret, if any.</returns> | ||
| Task<SecretStoreGetResponse> GetAsync(SecretStoreGetRequest request, CancellationToken cancellationToken = default); |
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.
It might be good to add <remarks> that describe the expected behavior for secrets that don't exist as well as differences between stores that support multiple values per secret and those that don't.
philliphoff
left a comment
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.
Generally on the right track. There's a question for how to represent bulk secret responses, and it'd be helpful to include unit tests for the new components and data types. (I just committed a change that switches tests to NSubstitute from Moq, so be sure to merge in the main branch.)
Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com>
| foreach (var sec in item.Value.Data) | ||
| { | ||
| secretResp.Secrets.Add(sec.Key, sec.Value); | ||
| grpcResponse.Data.Add(sec.Key, secretResp); |
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 should only happen once, right, outside the foreach and for the item.Key key?
|
|
||
| // NOTE: in case of not found, you should not return any error. | ||
|
|
||
| if (response != null) |
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.
response should be non-null (by nullability contract). While the implementor could still technically return null at runtime, I'd say that's their problem and not something to explicitly account for.
|
|
||
| // NOTE: in case of not found, you should not return any error. | ||
|
|
||
| if (response != null) |
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.
response should be non-null (by nullability contract). While the implementor could still technically return null at runtime, I'd say that's their problem and not something to explicitly account for.
|
@pravinpushkar With 1.12 now out the door, we should be able to pick this PR back up, right? |
@philliphoff Yes, I will plan to complete this in coming weeks. |
1d62a95 to
8be3241
Compare
Signed-off-by: Phillip Hoff <phillip@orst.edu>
Signed-off-by: Phillip Hoff <phillip@orst.edu>
WhitWaldo
left a comment
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.
Several changes. Mostly around naming consistency questions, a potentially unnecessary type and some assignment/nullability nits.
samples/LocalEnvSecretStoreSample/Services/LocalEnvSecretStore.cs
Outdated
Show resolved
Hide resolved
samples/LocalEnvSecretStoreSample/Services/LocalEnvSecretStore.cs
Outdated
Show resolved
Hide resolved
samples/LocalEnvSecretStoreSample/Services/LocalEnvSecretStore.cs
Outdated
Show resolved
Hide resolved
samples/LocalEnvSecretStoreSample/Services/LocalEnvSecretStore.cs
Outdated
Show resolved
Hide resolved
samples/LocalEnvSecretStoreSample/Services/LocalEnvSecretStore.cs
Outdated
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStore/SecretStoreBulkGetRequest.cs
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStore/SecretStoreBulkGetResponse.cs
Show resolved
Hide resolved
src/Dapr.PluggableComponents/Components/SecretStore/SecretStoreResponse.cs
Outdated
Show resolved
Hide resolved
Signed-off-by: Phillip Hoff <phillip@orst.edu>
Signed-off-by: Phillip Hoff <phillip@orst.edu>
|
@philliphoff Good to merge? |
Description
Please explain the changes you've made
Issue reference
We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.
Please reference the issue this PR will close: #43
Checklist
Please make sure you've completed the relevant tasks for this PR, out of the following list: