-
Notifications
You must be signed in to change notification settings - Fork 7
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
Configurable s3 endpoint for download #1163
base: main
Are you sure you want to change the base?
Configurable s3 endpoint for download #1163
Conversation
d5fc9f1
to
d9c8803
Compare
d9c8803
to
73baacd
Compare
9f68afa
to
d4e2439
Compare
32a1128
to
058887a
Compare
402b10a
to
8a9b000
Compare
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.
Crypt4gh config already exists, there is not need to add another one since the app will only need one.
Either reuse the existing one or move everything up under the app
sub heading.
@@ -194,7 +194,7 @@ echo "expected file found" | |||
# Test file can be decrypted | |||
## test also the files endpoint | |||
|
|||
C4GH_PASSPHRASE=$(grep -F passphrase config.yaml | sed -e 's/.* //' -e 's/"//g') | |||
C4GH_PASSPHRASE=$(grep -F passphrase config.yaml | tail -1 | sed -e 's/.* //' -e 's/"//g') |
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.
C4GH_PASSPHRASE=$(grep -F passphrase config.yaml | tail -1 | sed -e 's/.* //' -e 's/"//g') | |
C4GH_PASSPHRASE=$(grep -F passphrase config.yaml | sed -e 's/.* //' -e 's/"//g') |
Shouldn't be needed since the config file only will have one cryptgh config block
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 you want to extract a specific entry using yq
is the simplest solution.
yq '.app.c4gh.passphrase' config.yaml
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.
changed all similar to using yq
sda-download/.github/integration/tests/s3notls/52_check_endpoint.sh
Outdated
Show resolved
Hide resolved
I unresolved the initial the conversations that I set as resolved (these are answered) so that @jbygdell can take a look and resolve. According to how we decided to do things on our last meeting about PRs. |
dataset="https://doi.example/ty009.sfrrss/600.45asasga" | ||
file="dummy_data" | ||
clientkey=$(base64 -w0 client.pub.pem) | ||
bad_token=token2=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJyZXF1ZXN0ZXJAZGVtby5vcmciLCJhdWQiOlsiYXVkMiIsImF1ZDMiXSwiYXpwIjoiYXpwIiwic2NvcGUiOiJvcGVuaWQiLCJpc3MiOiJodHRwczovL2RlbW8uZXhhbXBsZSIsImV4cCI6OTk5OTk5OTk5OSwiaWF0IjoxNTYxNjIxOTEzLCJqdGkiOiI2YWQ3YWE0Mi0zZTljLTQ4MzMtYmQxNi03NjVjYjgwYzIxMDIifQ.ncUyjNytxqS9bqLnsbjv6D839PnHVw-anQS4bFpAs20 |
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 bit confusing for providing a bad_token
at the first glance.
sda-download/.github/integration/tests/common/90_check_s3_errors.sh
Outdated
Show resolved
Hide resolved
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.
Looks like good and thorough work..!
I left some questions, but otherwise I think it looks good!
and do a small refactoring
- add serveDecrypted object variable - repurpose obsolete c4gh secret logic - update README
if they are run more than once
to increase success rate of date comparison
Co-authored-by: Nanjiang Shu <[email protected]>
516c1ae
to
1dfc725
Compare
I believe I have addressed all relevant comments and suggest we leave the renaming of variables for a refinement issue, especially since these are suggestions over changes made in the 1st round in response to 1st round renaming suggestions for the same variables. |
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 tested this manually, and the s3
endpoint seems to work as expected ⭐ . However, the files
endpoint is not supported when the service is in encrypted mode, the answer is always downloading unencrypted data is not supported
. Maybe that's intended..? The docs says you can provide the header Public-Key
, but I cannot get that to work. I also tried the Client-Public-Key
header.
If this behavior is intended (or if someone can point out what I'm doing wrong), I will approve :)
Good point @MalinAhlberg, just tried the same thing that you describe with the latest version from main and the behavior is the same. So the current behavior is at least consistent. Not sure All in all, we need to discuss about this with the team. |
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.
Looks good!
- name: APP_C4GH_PRIVATEKEYPATH | ||
value: {{ template "c4ghPath" . }}/{{ .Values.global.download.serveDecrypted.c4ghKeyFile }} | ||
- name: APP_C4GH_PASSPHRASE |
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.
- name: APP_C4GH_PRIVATEKEYPATH | |
value: {{ template "c4ghPath" . }}/{{ .Values.global.download.serveDecrypted.c4ghKeyFile }} | |
- name: APP_C4GH_PASSPHRASE | |
- name: C4GH_TRANSIENTPRIVATEKEYPATH | |
value: {{ template "c4ghPath" . }}/{{ .Values.global.download.serveDecrypted.c4ghKeyFile }} | |
- name: C4GH_TRANSIENTPASSPHRASE |
keyPath := viper.GetString("app.c4gh.privateKeyPath") | ||
passphrase := viper.GetString("app.c4gh.passphrase") |
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.
keyPath := viper.GetString("app.c4gh.privateKeyPath") | |
passphrase := viper.GetString("app.c4gh.passphrase") | |
keyPath := viper.GetString("c4gh.transientKeyPath") | |
passphrase := viper.GetString("c4gh.transientPassphrase") |
if viper.GetString("app.c4gh.privateKeyPath") != "" { | ||
|
||
if !viper.IsSet("app.c4gh.passphrase") { | ||
return errors.New("app.c4gh.passphrase is not set") | ||
} | ||
|
||
c.App.Crypt4GHPrivateKey, c.App.Crypt4GHPublicKeyB64, err = GetC4GHKeys() | ||
if err != nil { | ||
return err | ||
} |
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 viper.GetString("app.c4gh.privateKeyPath") != "" { | |
if !viper.IsSet("app.c4gh.passphrase") { | |
return errors.New("app.c4gh.passphrase is not set") | |
} | |
c.App.Crypt4GHPrivateKey, c.App.Crypt4GHPublicKeyB64, err = GetC4GHKeys() | |
if err != nil { | |
return err | |
} | |
if viper.GetString("c4gh.transientKeyPath") != "" { | |
if !viper.IsSet("c4gh.transientPassphrase") { | |
return errors.New("c4gh.transientPassphrase is not set") | |
} | |
c.C4GH.PrivateKey, c.C4GH.PublicKeyB64, err = GetC4GHKeys() | |
if err != nil { | |
return err | |
} |
If this is done something like this, we wont end up with to much of a conflict when we merge download int the rest of sda. transient
might not be the best prefix but as long as it is clear it should be fine.
tl;dr;
Create an entry in the Map
struct for the C4GH keypair and remove it from the AppConfig
entry above. Since the AppConfig
holds the server config, something that will be shared by all our APIs in the sda folder (curently there are some duplicaitons that needs to be removed there.)
viper.Set("app.c4gh.PrivateKeyPath", privateKeyFile.Name()) | ||
viper.Set("app.c4gh.passphrase", "password") |
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.
viper.Set("app.c4gh.PrivateKeyPath", privateKeyFile.Name()) | |
viper.Set("app.c4gh.passphrase", "password") | |
viper.Set("c4gh.transientKeyPath", privateKeyFile.Name()) | |
viper.Set("c4gh.transientPassphrase", "password") |
publicKey, err := base64.StdEncoding.DecodeString(c.App.Crypt4GHPublicKeyB64) | ||
assert.Nilf(suite.T(), err, "Incorrect public c4gh key generated (error in base64 encoding)") | ||
_, err = keys.ReadPublicKey(bytes.NewReader(publicKey)) | ||
assert.Nilf(suite.T(), err, "Incorrect public c4gh key generated (bad key)") | ||
|
||
// Check false c4gh key | ||
viper.Set("app.c4gh.privateKeyPath", "some/nonexistent.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.
viper.Set("app.c4gh.privateKeyPath", "some/nonexistent.key") | |
viper.Set("c4gh.transientKeyPath", "some/nonexistent.key") |
viper.Set("app.c4gh.privateKeyPath", privateKeyFilePath) | ||
viper.Set("app.c4gh.passphrase", "password") | ||
config.Config.App.Crypt4GHPrivateKey, config.Config.App.Crypt4GHPublicKeyB64, err = config.GetC4GHKeys() |
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.
viper.Set("app.c4gh.privateKeyPath", privateKeyFilePath) | |
viper.Set("app.c4gh.passphrase", "password") | |
config.Config.App.Crypt4GHPrivateKey, config.Config.App.Crypt4GHPublicKeyB64, err = config.GetC4GHKeys() | |
viper.Set("c4gh.transientKeyPath", privateKeyFilePath) | |
viper.Set("c4gh.transientPassphrase", "password") | |
config.Config.C4GH.PrivateKey, config.Config.C4GH.PublicKeyB64, err = config.GetC4GHKeys() |
originalServeUnencryptedDataTrigger := config.Config.App.Crypt4GHPublicKeyB64 | ||
originalC4ghPrivateKeyFilepath := config.Config.App.Crypt4GHPrivateKey |
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.
originalServeUnencryptedDataTrigger := config.Config.App.Crypt4GHPublicKeyB64 | |
originalC4ghPrivateKeyFilepath := config.Config.App.Crypt4GHPrivateKey | |
originalServeUnencryptedDataTrigger := config.Config.C4GH.PublicKeyB64 | |
originalC4ghPrivateKeyFilepath := config.Config.C4GH.PrivateKey |
originalServeUnencryptedDataTrigger := config.Config.App.Crypt4GHPublicKeyB64 | ||
config.Config.App.Crypt4GHPublicKeyB64 = "" |
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.
originalServeUnencryptedDataTrigger := config.Config.App.Crypt4GHPublicKeyB64 | |
config.Config.App.Crypt4GHPublicKeyB64 = "" | |
originalServeUnencryptedDataTrigger := config.Config.C4GH.PublicKeyB64 | |
config.Config.C4GH.PublicKeyB64 = "" |
@@ -329,7 +330,7 @@ func Download(c *gin.Context) { | |||
ListBuckets(c) | |||
|
|||
case c.Param("filename") != "": | |||
if strings.HasPrefix(c.Request.URL.Path, "/s3-encrypted") { | |||
if config.Config.App.Crypt4GHPublicKeyB64 == "" { |
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 config.Config.App.Crypt4GHPublicKeyB64 == "" { | |
if config.Config.C4GH.PublicKeyB64 == "" { |
// when Crypt4GHPublicKeyB64 is not set or empty, but this is not the case for calls to /files endpoint. | ||
// So we need this check. | ||
|
||
if c.Param("type") != "encrypted" && config.Config.App.Crypt4GHPublicKeyB64 == "" { |
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 c.Param("type") != "encrypted" && config.Config.App.Crypt4GHPublicKeyB64 == "" { | |
if c.Param("type") != "encrypted" && config.Config.CGH.PublicKeyB64 == "" { |
Related issue(s) and PR(s)
This PR closes #750.
Description
With this PR
download
can either be deployed as serving either unencrypted or encrypted files. TheserveUnencryptedData
boolean is removed as well as the logic fordownload
to always generate an internal c4gh key-pair (that would allow the service to serve unencrypted files in caseserveUnencryptedData=true
).Main changes:
download
can now be configured to only serve unencrypted files if a filepath to a c4gh private key file is provided. Internally, the code checks the validity of the provided key by using the supplied passphrase to retrieve the corresponding c4gh public key. The service will not start if this procedure fails and the service will serve unencrypted data only if the retrieved public key is non-empty. This ensures that there can be no misconfiguration by e.g. providing malfunctioning keys etc. For example, the crypt4gh library and thereforereencrypt
will use any string provided to it and encrypt a file but with this mechanism we avoid such a scary scenario.download
will serve only encrypted files. This is the default behavior.Other changes include:
download
listening at different ports, one serving encrypted and the other serving unencrypted filesHow to test
Integration tests pass.