From e5232ff7bbcea711203d46d0aa456f7d2e7ea9a9 Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Wed, 11 Sep 2024 15:00:04 +0200 Subject: [PATCH 01/10] [upload] ad option to supply the access token as a cli argument --- upload/upload.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/upload/upload.go b/upload/upload.go index d9973c8c..0a09ac7b 100644 --- a/upload/upload.go +++ b/upload/upload.go @@ -63,6 +63,8 @@ var pubKeyPath = Args.String("encrypt-with-key", "", "Only unencrypted data should be provided when this flag is set.", ) +var accessToken = Args.String("accessToken", "", "Accesstoken to the inbox service. (optional, if it is set in the config file)") + // Function uploadFiles uploads the files in the input list to the s3 bucket func uploadFiles(files, outFiles []string, targetDir string, config *helpers.Config) error { // check also here in case sth went wrong with input files @@ -291,6 +293,10 @@ func Upload(args []string) error { return err } + if *accessToken != "" { + config.AccessToken = *accessToken + } + err = helpers.CheckTokenExpiration(config.AccessToken) if err != nil { return err From 0a548e2de67c4f6f772f7497c0e10b57f91ea97b Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Wed, 11 Sep 2024 15:01:41 +0200 Subject: [PATCH 02/10] [tests][upload] Supply the access token as a cli variable --- upload/upload_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/upload/upload_test.go b/upload/upload_test.go index 330bd0d5..835798ad 100644 --- a/upload/upload_test.go +++ b/upload/upload_test.go @@ -312,6 +312,13 @@ func (suite *TestSuite) TestFunctionality() { newArgs = []string{"upload", "-config", configPath.Name(), "--encrypt-with-key", "somekey", testfile.Name()} assert.EqualError(suite.T(), Upload(newArgs), "aborting") + // Supplying an accesstoken as a parameter overrules the one in the config file + newArgs = []string{"upload", "-accessToken", "BadToken", "-config", configPath.Name(), testfile.Name()} + assert.EqualError(suite.T(), Upload(newArgs), "could not parse token, reason: token contains an invalid number of segments") + + newArgs = []string{"upload", "-accessToken", suite.accessToken, "-config", configPath.Name(), testfile.Name()} + assert.NoError(suite.T(), Upload(newArgs)) + // Remove hash files created by Encrypt if err := os.Remove("checksum_encrypted.md5"); err != nil { log.Panic(err) From 8d9682e78a1125d4877a5b477558d363d7605aa0 Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Wed, 11 Sep 2024 15:02:40 +0200 Subject: [PATCH 03/10] [tests][upload] reset the access token variable before each test starts --- upload/upload_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/upload/upload_test.go b/upload/upload_test.go index 835798ad..829b2127 100644 --- a/upload/upload_test.go +++ b/upload/upload_test.go @@ -33,6 +33,7 @@ func TestConfigTestSuite(t *testing.T) { } func (suite *TestSuite) SetupTest() { + *accessToken = "" suite.accessToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleXN0b3JlLUNIQU5HRS1NRSJ9.eyJqdGkiOiJWTWpfNjhhcEMxR2FJbXRZdFExQ0ciLCJzdWIiOiJkdW1teSIsImlzcyI6Imh0dHA6Ly9vaWRjOjkwOTAiLCJpYXQiOjE3MDc3NjMyODksImV4cCI6MTg2NTU0NzkxOSwic2NvcGUiOiJvcGVuaWQgZ2E0Z2hfcGFzc3BvcnRfdjEgcHJvZmlsZSBlbWFpbCIsImF1ZCI6IlhDNTZFTDExeHgifQ.ZFfIAOGeM2I5cvqr1qJV74qU65appYjpNJVWevGHjGA5Xk_qoRMFJXmG6AiQnYdMKnJ58sYGNjWgs2_RGyw5NyM3-pgP7EKHdWU4PrDOU84Kosg4IPMSFxbBRAEjR5X04YX_CLYW2MFk_OyM9TIln522_JBVT_jA5WTTHSmBRHntVArYYHvQdF-oFRiqL8JXWlsUBh3tqQ33sZdqd9g64YhTk9a5lEC42gn5Hg9Hm_qvkl5orzEqIg7x9z5706IBE4Zypco5ohrAKsEbA8EKbEBb0jigGgCslQNde2owUyKIkvZYmxHA78X5xpymMp9K--PgbkyMS9GtA-YwOHPs-w" } From 00b9d66533df3482bffb687865397972a92c3e27 Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 08:29:00 +0200 Subject: [PATCH 04/10] [upload] optionally supply accesstoken from ENV --- upload/upload.go | 9 ++++++--- upload/upload_test.go | 11 +++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/upload/upload.go b/upload/upload.go index 0a09ac7b..631f28ea 100644 --- a/upload/upload.go +++ b/upload/upload.go @@ -25,7 +25,7 @@ import ( // Usage text that will be displayed as command line help text when using the // `help upload` command var Usage = ` -USAGE: %s upload -config (--encrypt-with-key ) (--force-overwrite) (--force-unencrypted) (-r) [file(s) | folder(s)] (-targetDir ) +USAGE: %s upload -config (-accessToken ) (--encrypt-with-key ) (--force-overwrite) (--force-unencrypted) (-r) [file(s) | folder(s)] (-targetDir ) upload: Uploads files to the Sensitive Data Archive (SDA). @@ -63,7 +63,7 @@ var pubKeyPath = Args.String("encrypt-with-key", "", "Only unencrypted data should be provided when this flag is set.", ) -var accessToken = Args.String("accessToken", "", "Accesstoken to the inbox service. (optional, if it is set in the config file)") +var accessToken = Args.String("accessToken", "", "Access token to the inbox service.\n(optional, if it is set in the config file or exported as the ENV `ACCESSTOKEN`)") // Function uploadFiles uploads the files in the input list to the s3 bucket func uploadFiles(files, outFiles []string, targetDir string, config *helpers.Config) error { @@ -293,7 +293,10 @@ func Upload(args []string) error { return err } - if *accessToken != "" { + switch { + case os.Getenv("ACCESSTOKEN") != "" && *accessToken == "": + config.AccessToken = os.Getenv("ACCESSTOKEN") + case *accessToken != "": config.AccessToken = *accessToken } diff --git a/upload/upload_test.go b/upload/upload_test.go index 829b2127..8286697b 100644 --- a/upload/upload_test.go +++ b/upload/upload_test.go @@ -33,6 +33,7 @@ func TestConfigTestSuite(t *testing.T) { } func (suite *TestSuite) SetupTest() { + os.Setenv("ACCESSTOKEN", "") *accessToken = "" suite.accessToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleXN0b3JlLUNIQU5HRS1NRSJ9.eyJqdGkiOiJWTWpfNjhhcEMxR2FJbXRZdFExQ0ciLCJzdWIiOiJkdW1teSIsImlzcyI6Imh0dHA6Ly9vaWRjOjkwOTAiLCJpYXQiOjE3MDc3NjMyODksImV4cCI6MTg2NTU0NzkxOSwic2NvcGUiOiJvcGVuaWQgZ2E0Z2hfcGFzc3BvcnRfdjEgcHJvZmlsZSBlbWFpbCIsImF1ZCI6IlhDNTZFTDExeHgifQ.ZFfIAOGeM2I5cvqr1qJV74qU65appYjpNJVWevGHjGA5Xk_qoRMFJXmG6AiQnYdMKnJ58sYGNjWgs2_RGyw5NyM3-pgP7EKHdWU4PrDOU84Kosg4IPMSFxbBRAEjR5X04YX_CLYW2MFk_OyM9TIln522_JBVT_jA5WTTHSmBRHntVArYYHvQdF-oFRiqL8JXWlsUBh3tqQ33sZdqd9g64YhTk9a5lEC42gn5Hg9Hm_qvkl5orzEqIg7x9z5706IBE4Zypco5ohrAKsEbA8EKbEBb0jigGgCslQNde2owUyKIkvZYmxHA78X5xpymMp9K--PgbkyMS9GtA-YwOHPs-w" } @@ -313,6 +314,16 @@ func (suite *TestSuite) TestFunctionality() { newArgs = []string{"upload", "-config", configPath.Name(), "--encrypt-with-key", "somekey", testfile.Name()} assert.EqualError(suite.T(), Upload(newArgs), "aborting") + os.Setenv("ACCESSTOKEN", "BadToken") + // Supplying an accesstoken as a ENV overrules the one in the config file + newArgs = []string{"upload", "-config", configPath.Name(), testfile.Name()} + assert.EqualError(suite.T(), Upload(newArgs), "could not parse token, reason: token contains an invalid number of segments") + + suite.SetupTest() + os.Setenv("ACCESSTOKEN", suite.accessToken) + newArgs = []string{"upload", "-config", configPath.Name(), testfile.Name()} + assert.NoError(suite.T(), Upload(newArgs)) + // Supplying an accesstoken as a parameter overrules the one in the config file newArgs = []string{"upload", "-accessToken", "BadToken", "-config", configPath.Name(), testfile.Name()} assert.EqualError(suite.T(), Upload(newArgs), "could not parse token, reason: token contains an invalid number of segments") From df25627381edb62b9e465cb842980750987cb9bf Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 08:35:35 +0200 Subject: [PATCH 05/10] [upload_test] config file with no access_token entry --- upload/upload_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/upload/upload_test.go b/upload/upload_test.go index 8286697b..2ac0296a 100644 --- a/upload/upload_test.go +++ b/upload/upload_test.go @@ -314,6 +314,28 @@ func (suite *TestSuite) TestFunctionality() { newArgs = []string{"upload", "-config", configPath.Name(), "--encrypt-with-key", "somekey", testfile.Name()} assert.EqualError(suite.T(), Upload(newArgs), "aborting") + // config file without an access_token + var confFileNoToken = fmt.Sprintf(` + host_base = %[1]s + encoding = UTF-8 + host_bucket = %[1]s + multipart_chunk_size_mb = 50 + secret_key = dummy + access_key = dummy + use_https = False + check_ssl_certificate = False + check_ssl_hostname = False + socket_timeout = 30 + human_readable_sizes = True + guess_mime_type = True + encrypt = False + `, strings.TrimPrefix(ts.URL, "http://")) + + err = os.WriteFile(configPath.Name(), []byte(confFileNoToken), 0600) + if err != nil { + suite.FailNow("failed to write temp config file, %v", err) + } + os.Setenv("ACCESSTOKEN", "BadToken") // Supplying an accesstoken as a ENV overrules the one in the config file newArgs = []string{"upload", "-config", configPath.Name(), testfile.Name()} From bda43e2e6e6a04ece7e93b8ba9c5924ffc3f1d50 Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 08:36:00 +0200 Subject: [PATCH 06/10] [helpers] accesstoken is now optional in the config file --- helpers/helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/helpers.go b/helpers/helpers.go index 5f2151e4..d63dd73e 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -263,7 +263,7 @@ func LoadConfigFile(path string) (*Config, error) { return nil, err } - if config.AccessKey == "" || config.AccessToken == "" { + if config.AccessKey == "" { return nil, errors.New("failed to find credentials in configuration file") } From 522c406f23fecad21c7536c7b356933f6faa1fd1 Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 09:11:05 +0200 Subject: [PATCH 07/10] Cleanup go.mod file --- go.mod | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 84a9cc7f..efc68cbd 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,10 @@ go 1.22.3 require ( github.com/aws/aws-sdk-go v1.55.5 + github.com/dustin/go-humanize v1.0.1 + github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 + github.com/johannesboyne/gofakes3 v0.0.0-20220627085814-c3ac35da23b2 github.com/manifoldco/promptui v0.9.0 github.com/neicnordic/crypt4gh v1.12.0 github.com/sirupsen/logrus v1.9.3 @@ -17,9 +21,9 @@ require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -32,10 +36,3 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -require ( - github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible - github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 - github.com/johannesboyne/gofakes3 v0.0.0-20220627085814-c3ac35da23b2 -) From b7900ce1a56be2fa10417a8c672fd5f6cf168652 Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 09:32:25 +0200 Subject: [PATCH 08/10] Ignore stupid linter --- .github/workflows/golint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golint.yaml b/.github/workflows/golint.yaml index bf3a6ade..6a94c863 100644 --- a/.github/workflows/golint.yaml +++ b/.github/workflows/golint.yaml @@ -20,4 +20,4 @@ jobs: - name: Run golangci-lint uses: golangci/golangci-lint-action@v6.1.0 with: - args: -E bodyclose,gocritic,gofmt,gosec,govet,nestif,nlreturn,revive,rowserrcheck --exclude G401,G501,G107,G307 + args: -E bodyclose,gocritic,gofmt,gosec,govet,nestif,nlreturn,revive,rowserrcheck --exclude G401,G501,G107,G307,G115 From 3be91089d08fa8df7784ca9b078e79e13a1ee17c Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 14:31:45 +0200 Subject: [PATCH 09/10] [upload] Return error if no access token is supplied --- upload/upload.go | 2 ++ upload/upload_test.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/upload/upload.go b/upload/upload.go index 631f28ea..5f465d12 100644 --- a/upload/upload.go +++ b/upload/upload.go @@ -294,6 +294,8 @@ func Upload(args []string) error { } switch { + case os.Getenv("ACCESSTOKEN") == "" && *accessToken == "" && config.AccessToken == "": + return errors.New("no access token supplied") case os.Getenv("ACCESSTOKEN") != "" && *accessToken == "": config.AccessToken = os.Getenv("ACCESSTOKEN") case *accessToken != "": diff --git a/upload/upload_test.go b/upload/upload_test.go index 2ac0296a..f5b6f175 100644 --- a/upload/upload_test.go +++ b/upload/upload_test.go @@ -336,6 +336,10 @@ func (suite *TestSuite) TestFunctionality() { suite.FailNow("failed to write temp config file, %v", err) } + // Check that an access token is supplied + newArgs = []string{"upload", "-config", configPath.Name(), testfile.Name()} + assert.EqualError(suite.T(), Upload(newArgs), "no access token supplied") + os.Setenv("ACCESSTOKEN", "BadToken") // Supplying an accesstoken as a ENV overrules the one in the config file newArgs = []string{"upload", "-config", configPath.Name(), testfile.Name()} From c4d86c30a880dec05ae3f9804b86c4fbba01973a Mon Sep 17 00:00:00 2001 From: Joakim Bygdell Date: Thu, 12 Sep 2024 14:38:11 +0200 Subject: [PATCH 10/10] Update Readme.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 6a562cce..fbb997f9 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,14 @@ Follow the dialogue to get authenticated and then click on `Download inbox s3cmd Alternatively, you can download the configuration file using the [login command](#Login). +The access token used to authenticate to the inbox can be supplied in 3 different ways; in the config file, as an ENV `ACCESSTOKEN` or on the command line `-accessToken ` as part of the upload command. + +The Priority order for the access token is: + +1. Using the `-accessToken` flag +2. From the ENV `ACCESSTOKEN` +3. In the config file + ### Upload file(s) Now that the configuration file is downloaded, the file(s) can be uploaded to the archive using the binary file created in the first step of this guide. To upload a specific file, use the following command: