Skip to content

Commit

Permalink
Encrypt fetches pub key from auth (#285)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbygdell authored Dec 19, 2023
2 parents b3e2708 + ddaf140 commit 8cf95d9
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 30 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ You can login to download the configuration file needed for some of the the tool
```bash
./sda-cli login <login_target>
```
where `login_target` is the URL can be the login endpoint for Big Picture (https://login.bp.nbis.se/), Federated EGA (https://login.test.fega.nbis.se/) or Genomic Data Infrastructure (https://login.gdi.nbis.se/)
where `login_target` is the URL to the `sda-auth` service from the [sensitive-data-archive](https://github.com/neicnordic/sensitive-data-archive/) project.

This will open a link for the user where they can go and log in.
After the login is complete, a configuration file will be created in the tool's directory with the name of `.sda-cli-session`
Expand Down
38 changes: 31 additions & 7 deletions encrypt/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"strings"

"github.com/NBISweden/sda-cli/helpers"

"github.com/NBISweden/sda-cli/login"
"github.com/neicnordic/crypt4gh/keys"
"github.com/neicnordic/crypt4gh/streaming"
log "github.com/sirupsen/logrus"
Expand All @@ -26,7 +26,7 @@ import (
// Usage text that will be displayed as command line help text when using the
// `help encrypt` command
var Usage = `
USAGE: %s encrypt -key <public-key-file> (-outdir <dir>) (-continue=true) [file(s)]
USAGE: %s encrypt -key <public-key-file> (-target <target>) (-outdir <dir>) (-continue=true) [file(s)]
encrypt:
Encrypts files according to the crypt4gh standard used in the
Expand Down Expand Up @@ -54,6 +54,8 @@ var outDir = Args.String("outdir", "",

var continueEncrypt = Args.Bool("continue", false, "Do not exit on file errors but skip and continue.")

var target = Args.String("target", "", "Client target for public key.")

var publicKeyFileList []string

func init() {
Expand All @@ -75,14 +77,36 @@ func Encrypt(args []string) error {
return err
}

// no key provided, check for one in the session file
if len(publicKeyFileList) == 0 {
if publicKeyFileList != nil && *target != "" {
return errors.New("only one of -key or -target can be used")
}

sesKey, err := helpers.GetPublicKey()
if *target != "" {
// fetch info endpoint values
log.Println("fetching public key")
info, err := login.GetAuthInfo(*target)
if err != nil {
return err
}
// create pub file
pubKeyFile, err := helpers.CreatePubFile(info.PublicKey, "crypt4gh_key.pub")
if err != nil {
return fmt.Errorf("public key not provided or %v", err)
return err
}
// no key provided, no key in session file, target provided
publicKeyFileList = append(publicKeyFileList, pubKeyFile)
}
// no key provided, no key in session file, no target provided
if publicKeyFileList == nil && *target == "" {
// check for public key in .sda-cli-session file from login
pubKey, err := helpers.GetPublicKeyFromSession()
if err != nil {
return err
}
// key from session file found
if len(publicKeyFileList) == 0 && pubKey != "" {
publicKeyFileList = append(publicKeyFileList, pubKey)
}
publicKeyFileList = append(publicKeyFileList, sesKey)
}

// Each filename is first read into a helper struct (sliced for combatibility with checkFiles)
Expand Down
2 changes: 1 addition & 1 deletion encrypt/encrypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (suite *EncryptTests) TestEncryptFunction() {
// pub key not given
os.Args = []string{"encrypt", suite.fileOk.Name()}
err := Encrypt(os.Args)
assert.EqualError(suite.T(), err, "public key not provided or configuration file (.sda-cli-session) not found")
assert.EqualError(suite.T(), err, "configuration file (.sda-cli-session) not found")

// no such pub key file
msg := "open somekey: no such file or directory"
Expand Down
31 changes: 20 additions & 11 deletions helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,16 @@ func GetAuth(path string) (*Config, error) {
return nil, errors.New("failed to read the configuration file")
}

func GetPublicKey() (string, error) {
// reads the .sda-cli-session file, creates the public key file and returns the name of the file
func GetPublicKeyFromSession() (string, error) {
// Check if the ".sda-cli-session" file exists
if !FileExists(".sda-cli-session") {
return "", errors.New("configuration file (.sda-cli-session) not found")
}

if FileExists(".sda-cli-session") {
file, err := os.Open(".sda-cli-session")
if err != nil {
fmt.Println("could not read file:", file)
}
_, err := os.Open(".sda-cli-session")
if err != nil {
return "", err
}

// Load the configuration file
Expand All @@ -316,13 +315,24 @@ func GetPublicKey() (string, error) {
return "", errors.New("public key not found in the configuration")
}

pubFile, err := CreatePubFile(config.PublicKey, "key-from-oidc.pub.pem")
if err != nil {
return "", err
}

return pubFile, nil

}

// Create public key file
func CreatePubFile(publicKey string, filename string) (string, error) {
// Create a fixed-size array to hold the public key data
var publicKeyData [32]byte
b := []byte(config.PublicKey)
b := []byte(publicKey)
copy(publicKeyData[:], b)

// Open or create a file named "key-from-oidc.pub.pem" in write-only mode with file permissions 0600
pubFile, err := os.OpenFile(filepath.Clean("key-from-oidc.pub.pem"), os.O_WRONLY|os.O_CREATE, 0600)
// Open or create a file in write-only mode with file permissions 0600
pubFile, err := os.OpenFile(filepath.Clean(filename), os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return "", fmt.Errorf("failed to open or create the public key file: %w", err)
}
Expand All @@ -332,15 +342,14 @@ func GetPublicKey() (string, error) {
log.Errorf("Error closing file: %s\n", cerr)
}
}()

// Write the publicKeyData array to the "key-from-oidc.pub.pem" file in Crypt4GHX25519 public key format
err = keys.WriteCrypt4GHX25519PublicKey(pubFile, publicKeyData)
if err != nil {
return "", fmt.Errorf("failed to write the public key data: %w", err)
}

// If everything is successful, return the name of the generated public key file
return "key-from-oidc.pub.pem", nil
return filename, nil
}

// CheckTokenExpiration is used to determine whether the token is expiring in less than a day
Expand Down
21 changes: 18 additions & 3 deletions helpers/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,11 @@ encrypt = False
log.Printf("failed to write temp config file, %v", err)
}

_, err = GetPublicKey()
_, err = GetPublicKeyFromSession()
assert.EqualError(suite.T(), err, "public key not found in the configuration")
}

func (suite *HelperTests) TestGetPublicKey() {
func (suite *HelperTests) TestGetPublicKeyFromSession() {

var confFile = `
access_token = someToken
Expand Down Expand Up @@ -396,7 +396,7 @@ public_key = 27be42445fd9e39c9be39e6b36a55e61e3801fc845f63781a813d3fe9977e17a
log.Printf("failed to write temp config file, %v", err)
}

_, err = GetPublicKey()
_, err = GetPublicKeyFromSession()
assert.NoError(suite.T(), err)

if assert.FileExists(suite.T(), "key-from-oidc.pub.pem") {
Expand All @@ -415,3 +415,18 @@ func (suite *HelperTests) TestInvalidCharacters() {
assert.Equal(suite.T(), fmt.Sprintf("filepath %v contains disallowed characters: %+v", testfilepath, badchar), err.Error())
}
}

func (suite *HelperTests) TestCreatePubFile() {
var pubKeyContent = `339eb2a458fec5e23aa8b57cfcb35f10e7389025816e44d4234f814ed2aeed3f`
var expectedPubKey = `-----BEGIN CRYPT4GH PUBLIC KEY-----
MzM5ZWIyYTQ1OGZlYzVlMjNhYThiNTdjZmNiMzVmMTA=
-----END CRYPT4GH PUBLIC KEY-----
`
_, err := CreatePubFile(pubKeyContent, os.TempDir()+"/test_public_file.pub.pem")
assert.NoError(suite.T(), err)

pubFile, _ := os.ReadFile(os.TempDir() + "/test_public_file.pub.pem")
s := string(pubFile)
assert.Equal(suite.T(), expectedPubKey, s)
defer os.Remove(os.TempDir() + "/test_public_file.pub.pem")
}
7 changes: 2 additions & 5 deletions login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ login:
// the module help
var ArgHelp = `
[login-target]
The login target can be one of the following:
https://login.bp.nbis.se/
https://login.test.fega.nbis.se/
https://login.gdi.nbis.se/`
The login target is the base URL of the service.`

// Args is a flagset that needs to be exported so that it can be written to the
// main program help
Expand Down Expand Up @@ -168,7 +165,7 @@ func NewLogin(args []string) error {
}
err = deviceLogin.Login()
if err != nil {
return fmt.Errorf("Login failed")
return err
}
fmt.Printf("Logged in as %v\n", deviceLogin.UserInfo.Name)

Expand Down
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ func ParseArgs() (string, []string) {

if Help(subcommand) == nil {
os.Exit(0)
} else {
os.Exit(1)
}
os.Exit(1)

}

// The "list" command can have no arguments since it can use the
Expand Down

0 comments on commit 8cf95d9

Please sign in to comment.