-
Notifications
You must be signed in to change notification settings - Fork 244
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
A secret vault storage with AES encryption using a certificate #56
Conversation
Codecov Report
@@ Coverage Diff @@
## master #56 +/- ##
==========================================
+ Coverage 53.61% 56.27% +2.66%
==========================================
Files 14 16 +2
Lines 1218 1418 +200
==========================================
+ Hits 653 798 +145
- Misses 496 527 +31
- Partials 69 93 +24
Continue to review full report at Codecov.
|
security/vault_test.go
Outdated
} | ||
defer os.Remove(vaultName) | ||
v.Cert = []byte("test") | ||
v.OpenVault() |
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 isn't needed here.
@michelvocks The view of the vault. :) |
security/vault.go
Outdated
} | ||
|
||
// OpenVault decrypts the contents of the vault and fills up a map of data to work with. | ||
func (v *Vault) OpenVault() error { |
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.
Maybe call this LoadVault or GetVaultContent because it feels weird to use it in the handler.
security/vault.go
Outdated
} | ||
|
||
// CloseVault encrypts data passed to the vault in a k/v format and saves it to the vault file. | ||
func (v *Vault) CloseVault() error { |
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 definitely shloud be called SaveVault rather.
handlers/vault.go
Outdated
gaia.Cfg.Logger.Error("error initializing vault", "error", err.Error()) | ||
return c.String(http.StatusInternalServerError, err.Error()) | ||
} | ||
v.Add(s.Key, []byte(s.Value)) |
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'm missing an open here so this is overwriting whatever is in the vault at the moment. Which brings me to rename the functions to make it more apparent how this needs to be used.
I need to write docs for the vault. |
Is the value shown as plain text? 😧 |
@michelvocks for sure. It's for testing purposes only. :) |
@michelvocks masked :) |
…d user. Also fixed the possibility to have an empty vault.
Ah, I need to write docs for 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.
Good Job @Skarlso 🤗 Just a few remarks with things I do not understand 🤣
@@ -29,6 +29,14 @@ const state = { | |||
icon: 'fa-cogs' | |||
}, | |||
component: lazyLoading('settings', 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.
Move vault up so it's over Settings in the menu list. Don't know why, but I'm used to find Settings at the last menu entry 🤗
}, | ||
|
||
changeSecret () { | ||
// pre-validate |
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 make sense to put the validation steps into another method so we can avoid some lines in both changeSecret and addSecret 😄
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.
@michelvocks I suck at Javascript. How do I do that? :D
message: 'Secret has been successful changed.', | ||
type: 'success' | ||
}) | ||
this.selectSecret.newvalue = '' |
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.
you call close
below which sets selectSecret to {}
. Is this still needed?
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.
didn't know that, thanks! :)
message: 'Secret has been successfully added.', | ||
type: 'success' | ||
}) | ||
this.selectSecret.value = 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.
Same here. You call below close
which already sets selectSecret
handlers/vault.go
Outdated
s := new(updateSecret) | ||
err := c.Bind(s) | ||
if err != nil { | ||
gaia.Cfg.Logger.Error("error reading secret", "error", err.Error()) |
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 might get spammy in the logs when a user or another client is bored 😄. To be consistent with all other handlers, I think we should not log here.
handlers/vault.go
Outdated
return c.String(http.StatusInternalServerError, err.Error()) | ||
} | ||
gaia.Cfg.Logger.Info("secret successfully added") | ||
return c.String(http.StatusOK, "secret successfully added") |
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.
To be honest, I'm not really good at HTTP Status codes but this should be Created, right? 😆
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.
Ops, absolutely.
security/vault.go
Outdated
} | ||
|
||
// Setting up certificate key content | ||
c, err := InitCA() |
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.
Don't create the CA here. It will be already created in the main.go file. You should pass this instance via Parameter to NewVault
.
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.
Yeah, but I'm always using NewVault, and Ca won't be something global, and it shouldn't be. A call to init, should just be idempotent, OR... be a singleton which still is a global 🤔 Not sure.
security/vault.go
Outdated
if err != nil { | ||
return nil, err | ||
} | ||
data, err := ioutil.ReadFile(c.caKeyPath) |
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.
You should not access the private variable caKeyPath
here. Use the method GetCACertPath
.
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.
Ops, I mean to do that, huh.
security/vault.go
Outdated
// GetAll returns all keys and values in a copy of the internal data. | ||
func (v *Vault) GetAll() []string { | ||
m := make([]string, 0) | ||
for k := range v.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.
What happens when someone accesses Add
and in the same time GetAll
? Isn't this a race condition?
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, there should be a Read Lock here. :/ Thanks.
security/vault.go
Outdated
|
||
// Vault is a secret storage for data that gaia needs to store encrypted. | ||
type Vault struct { | ||
Path 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.
Is it on purpose that Path and Cert are global available?
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.
You mean exported? Hum, haven't really thought about it, but you are right. They aren't used directly, so they can be private for only internal use. Thanks. :)
handlers/vault.go
Outdated
} | ||
|
||
// UpdateSecret updates a secret using the vault. | ||
func UpdateSecret(c echo.Context) error { |
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 don't like this duplication. I'm going to pull it into SetSecret which updates or Creates.
7c29152
to
0c12482
Compare
README.rst
Outdated
Security | ||
-------- | ||
|
||
See the Documentation located here: |security-docs|. |
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 isn't linking the way I thought it would :D
README.rst
Outdated
@@ -132,6 +132,11 @@ Gaia will compile it and add it to it's store for later execution. | |||
|
|||
Please find a bit more sophisticated example in our `go-example repo`_. | |||
|
|||
Security | |||
-------- |
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 should be =
instead of -
.
README.rst
Outdated
Security | ||
-------- | ||
|
||
See the Documentation located here: |security-docs|. |
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.
`security-docs`_
README.rst
Outdated
.. |sh-pipeline-logs| image:: https://cdn.rawgit.com/michelvocks/6868118d0da06a422e69e453497eb30d/raw/51b4d6cbc3d86b1fe9531250db5456595423d9ec/pipeline_logs.png | ||
:alt: gaia pipeline logs screenshot | ||
:width: 650px | ||
|
||
.. |sh-settings| image:: https://cdn.rawgit.com/michelvocks/6868118d0da06a422e69e453497eb30d/raw/142a2969c4d27d4135ef8f96213bb166009fda1e/settings.png | ||
:alt: gaia settings screenshot | ||
:width: 650px | ||
.. |security-docs| |
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.
.. _`security-docs`: https://github.com/gaia-pipeline/gaia/blob/master/security/README.md
@michelvocks Battle tested the front-end with the Javascript modifications and all worked fine. Thanks for that. :) Also updated the docs, everything should be cool now. Thanks for those fixes. |
@michelvocks A little change... I slept on this and realised that we might want to change the vault's storage medium at some point to a database, or I don't know what. In that case, I created the VaultStorer interface here: https://github.com/gaia-pipeline/gaia/pull/56/files#diff-6d277307688fa8de2b326d79a993e6b4R25 This made me able to mock the vault to a simple |
I think that PR would be better off if this one is already in, since we could immediately utilise the functionality in #48. Which is blocked on the both of them. Also, I would rather start on the parameter stuff once this and #61 are in because they provide facilities and implementation details that could prove useful. Especially the Service Provider. In fact, I kind of want that in first, since it touches everything basically. And if this is in, I can also make the vault part of the service provider. At least that's what I'm thinking @michelvocks. :) |
Good point. Could you please squash your commits? Makes the history a bit cleaner. 🤗 Can you also have a look at the following change? https://github.com/gaia-pipeline/gaia/pull/60/files#diff-1e72a85e5dbe49ee4428eae35d6f1ee6R207 |
It does, yeah. But not that much and I agree with you. I'll do the changes. Also git can squash commits. You can select the squash and merge when merging, but I can do that if you wish ofc. :-) Also, in fact I shloud have been using #8... Lazy me. :-/ |
So, I completely misunderstood this comment, and thought about something completely different. :D yay, me. So as I wrote in Slack, but I'm writing it here too, what's happening with the certificate is, that I'm deriving a 32 bit password from it by base64-ing the content, and chopping it into a aes.BlockSize'd slice. This means that the vault doesn't care what is in there. I'm also applying some padding in case of testing. The IV is generated and then used upon decryption too. It's marshalled into the encrypted data. All in all it should be pretty secure. And it's AES 256 so it should be safe from brute forcing. |
Deals with #51.
TODO