-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add a SecretProvider that can be used for Docker Secrets #171
Add a SecretProvider that can be used for Docker Secrets #171
Conversation
A new preview package for You can pull it locally via the CLI: PM> Install-Package Arcus.Security.All -Version 20200827.0.0-PR-171 -Source https://www.myget.org/F/arcus/api/v3/index.json |
@stijnmoreels Do you want to pick this review up? Looks good from a first glance, only thing I'm not sure about is the naming indeed. I'm more on the DockerSecrets front as it's more straight forward for what it's built as per the docs but can also see why you'd not want to do it 🤔 |
Yes, of course, will do it first thing monday (or some today if I got the time), though if that's OK. I'll assign myself. |
src/Arcus.Security.Providers.KeyPerFile/Arcus.Security.Providers.KeyPerFile.csproj
Outdated
Show resolved
Hide resolved
src/Arcus.Security.Providers.KeyPerFile/KeyPerFileSecretProvider.cs
Outdated
Show resolved
Hide resolved
src/Arcus.Security.Providers.KeyPerFile/KeyPerFileSecretProvider.cs
Outdated
Show resolved
Hide resolved
{ | ||
Guard.NotNull(configurationSource, nameof(configurationSource)); | ||
_provider = new KeyPerFileConfigurationProvider(configurationSource); | ||
_provider.Load(); |
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.
Reason why this is called inside the constructor and not in the extension? Because it allows you to make sure that the configuration provider was loaded?
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 makes sure that if I instantiate an instance, the secrets are loaded as well.
It might make sense to move it outside the ctor, but then users will to call the Load method themselves. I can change that if you want
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 ok for me! But does this mean it will not reflect changes to the file later on?
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 UserSecrets is different in that way. It's begin called there before the ctor. Seems like they both should have the same setup but not sure which one.
Not sure also if it should be the responsibility of the secret provider that the configuration was loaded. 🤔 If this could be checked or so... Also, with 'reloading' this should maybe looked further into.
Should we call .Reload
upon ICachedSecretProvider.InvalidateSecretAsync
?
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.
Well, the ´Load´ method is part of the KeyPerFileConfigurationProvider whereas the parameter of the ctor is a configuration source.
I could change that we're injecting a configurationprovider instead of a configuration source though.
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 do you mean ? Call load when the first secret is retrieved ?
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.
Yes or will it work automatically with ConfigurationProvider? Or does that depend on the IConfiguration of the user? Sorry I'm lost here I think.
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.
Calling Load
on the provider loads all files that are present in the configured directory, and creates 'secrets' from them. So, if you create the secret provider, all secrets will be loaded only once.
In contrast of the KeyVaultSecretProvider
which requests the secret every time from KeyVault itself (when no caching is configured), this provider retrieves the secrets only once.
This can be changed offcourse, but then we should not rely on the KeyPerFile
configuration provider which is now used internally, but implement this functionality ourselves. In that case, we would need to load the correct file, read and return its contents on every call to 'GetSecretAsync'.
Question is, is this necessary ? When using docker and docker secrets, the secrets are mounted as files inside the container. When the secret changes, I guess that this also means that the container needs to be restarted ?
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.
@tomkerkhove what is your view on this ?
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.
Question is, is this necessary ? When using docker and docker secrets, the secrets are mounted as files inside the container. When the secret changes, I guess that this also means that the container needs to be restarted ?
That is not the case actually, often hot-swapping of configs are done without restarting the container.
Maybe odd question, but what if we call Load now and then to refresh things?
src/Arcus.Security.Providers.KeyPerFile/KeyPerFileSecretProvider.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com>
src/Arcus.Security.Providers.KeyPerFile/KeyPerFileSecretProvider.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com>
A new preview package for You can pull it locally via the CLI: PM> Install-Package Arcus.Security.All -Version 20200828.0.0-PR-171 -Source https://www.myget.org/F/arcus/api/v3/index.json |
src/Arcus.Security.Providers.KeyPerFile/SecretStoreBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/Arcus.Security.Providers.KeyPerFile/SecretStoreBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/Arcus.Security.Providers.KeyPerFile/SecretStoreBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/Arcus.Security.Providers.KeyPerFile/SecretStoreBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
{ | ||
public static class SecretStoreBuilderExtensions | ||
{ | ||
public static SecretStoreBuilder AddKeyPerFile(this SecretStoreBuilder builder, string directoryPath, bool optional = true) |
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.
Should we use the optional
here? It was supposed to be used (I think) to return null
instead of throwing, but because we use the secret store, this feature is resulting in the same result bc the secret store will eventuall throw if the secret was not found in any of the registered providers.
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.
If optional is set to false, an exception will be thrown when the directory-path (where the secrets are located inside the container) doesn't exist.
If set to true, no exception will be thrown at that point, however, an exception will be thrown later (which says that the secret could not be found). However, if we have multiple secretstores configured, the secret might as well be found by another secret provider ....
Don't know what the best approach is here, therefore I've just taken over the functionality that exists in the 'KeyPerFile' config provider.
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.
If it's just for the file then I would use false internally because otherwise there is a "setup issue", but I might be too extreme?
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.
Yes, I agree with @tomkerkhove , our other providers are also throwing on 'setup' things and if we would want to have such an optional functionality, I think we should look into it on a broader level and how we can use it for every provider. So, for now, maybe set it on false
and we can maybe look at it in an issue later.
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've changed and pushed this, but would like to do some additional testing.
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.
No problem, let us know when you are ready!
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've changed this, but now this means that if you specify a non-existing directory, the container will fail to start. That is a good example of failing fast but I don't know if you really want that.
What if you have a program which has multiple secret providers configured. In some cases, your program might not be running in a container and needs to retrieve secrets from another location. In that case, you still need to have that directory present.
src/Arcus.Security.Tests.Integration/KeyPerFile/SecretStoreBuilderExtensionTests.cs
Outdated
Show resolved
Hide resolved
src/Arcus.Security.Tests.Integration/KeyPerFile/SecretStoreBuilderExtensionTests.cs
Outdated
Show resolved
Hide resolved
Thanks @fgheysels for the implementation, clearly specified docs and tests! Very clear, and it shows that you try to follow the Arcus standards. Thanks for this! |
…Provider.cs Co-authored-by: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com>
Make sure that a seccret exists when verifying what happens if a non existing secret is retrieved
…gheysels/arcus.security into frgh/feature/149_dockersecrets
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.
When my last comments are resolved, I think this is OK. Thanks for keeping up with this and the complete and correct addition! Much appriciated!
Co-authored-by: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com>
I see there are some failing tests; I can have a look at it tonight |
Should be fixed now. |
A new preview package for You can pull it locally via the CLI: PM> Install-Package Arcus.Security.All -Version 20201015.0.0-PR-171 -Source https://www.myget.org/F/arcus/api/v3/index.json |
Are there any issues left, or are we good to go ? |
I think not (as for my part, I guess). Let's see if @tomkerkhove has any remaining remarks. |
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.
LGTM, just a few remarks for the docs
Co-authored-by: Tom Kerkhove <kerkhove.tom@gmail.com>
Co-authored-by: Tom Kerkhove <kerkhove.tom@gmail.com>
Co-authored-by: Tom Kerkhove <kerkhove.tom@gmail.com>
A new preview package for You can pull it locally via the CLI: PM> Install-Package Arcus.Security.All -Version 20201016.0.0-PR-171 -Source https://www.myget.org/F/arcus/api/v3/index.json |
When using Docker Swarm & Docker secrets, secrets are mounted into the docker container as files.
This KeyPerFile secret provider (which is based on the KeyPerFile configuration provider) allows easy access to those secrets.
(Maybe the secretprovider should be renamed to DockerSecrets ? I've choosen KeyPerFile since it is based on that package ... )
This is related to #149