Skip to content

Commit

Permalink
Feature/external checks (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
kostas-kou authored Feb 15, 2023
2 parents 402bb43 + 25e8add commit a7d478b
Show file tree
Hide file tree
Showing 13 changed files with 571 additions and 73 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,20 @@ The following configuration is required to run the service
| Variable | Description | Example |
| ------------ | :----------: | ------: |
| crypt4ghKey | Path to public key | `../sda_crypt4gh.pub` |
| egaUsername | The username for the EGA external service | `some_ega_username` |
| egaPassword | The password for the EGA external service | `some_ega_password` |
| egaURL | The url for the EGA external service | `https://ega.url` |
| expirationDays | Token validity duration in days | 14 |
| iss | JWT issuer | `https://issuer.example.com` |
| jwtKey | Path to private key | `../my_key.pub` |
| suprUsername | The username for the SUPR external service | `some_supr_username` |
| suprPassword | The password for the SUPR external service | `some_supr_password` |
| suprURL | The url for the SUPR external service | `https://supr.url` |
| s3url | The URL to the s3Inbox | `s3.example.com` |
| uppmaxUsername | Username for token requester | `some_username` |
| uppmaxPassword | Password for token requester | `some_password` |


## How to deploy
To deploy the service without using vault (e.g. using minikube) in the `lega` namespace, build and push the image using
```sh
Expand Down
2 changes: 1 addition & 1 deletion charts/uppmax-integration/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.2.1
version: 0.3.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
Expand Down
29 changes: 27 additions & 2 deletions charts/uppmax-integration/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,21 @@ spec:
env:
- name: GLOBAL_CRYPT4GHKEY
value: /secrets/{{ .Values.global.crypt4ghKey }}
- name: GLOBAL_EGAUSER
- name: GLOBAL_EGAUSERNAME
valueFrom:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: egaUser
key: egaUsername
- name: GLOBAL_EGAPASSWORD
valueFrom:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: egaPassword
- name: GLOBAL_EGAURL
valueFrom:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: egaURL
- name: GLOBAL_EXPIRATIONDAYS
value: {{ .Values.global.expirationDays | quote }}
- name: GLOBAL_ISS
Expand All @@ -62,6 +72,21 @@ spec:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: uppmaxPassword
- name: GLOBAL_SUPRUSERNAME
valueFrom:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: suprUsername
- name: GLOBAL_SUPRPASSWORD
valueFrom:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: suprPassword
- name: GLOBAL_SUPRURL
valueFrom:
secretKeyRef:
name: {{ include "uppmax-integration.name" . }}-secret
key: suprURL
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
Expand Down
7 changes: 6 additions & 1 deletion charts/uppmax-integration/templates/secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ type: Opaque
stringData:
uppmaxUsername: {{ .Values.global.uppmaxUsername | quote }}
uppmaxPassword: {{ .Values.global.uppmaxPassword | quote }}
egaUser: {{ .Values.global.egaUser | quote }}
egaUsername: {{ .Values.global.ega.username | quote }}
egaPassword: {{ .Values.global.ega.password | quote }}
egaURL: {{ .Values.global.ega.URL | quote }}
suprUsername: {{ .Values.global.supr.username | quote }}
suprPassword: {{ .Values.global.supr.password | quote }}
suprURL: {{ .Values.global.supr.URL | quote }}
crypt4ghKey: {{ .Values.global.crypt4ghKey }}

11 changes: 9 additions & 2 deletions charts/uppmax-integration/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ global:
uppmaxPassword: ""
s3url: ""
expirationDays: "25"
egaUser: ""
ega:
username: ""
password: ""
URL: ""
supr:
username: ""
password: ""
URL: ""
crypt4ghKey: ""
tls:
enabled: false
Expand All @@ -26,7 +33,7 @@ image:
repository: harbor.nbis.se/uppmax/integration
pullPolicy: Always
# Overrides the image tag whose default is the chart appVersion.
tag: "latest"
tag: "0.1.1"

imagePullSecrets: []
nameOverride: ""
Expand Down
4 changes: 3 additions & 1 deletion compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ services:
environment:
- LOG_LEVEL=debug
- GLOBAL_CRYPT4GHKEY=/keys/c4gh.sec.pem
- [email protected]
- GLOBAL_EGAUSER=sda
- GLOBAL_EGAPASSWORD=pass
- GLOBAL_EGAURL=http://ega.dev
- GLOBAL_EXPIRATIONDAYS=14
- GLOBAL_ISS=https://login.sda.dev
- GLOBAL_JWTKEY=/keys/jwt.key
Expand Down
7 changes: 6 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
global:
crypt4ghKey: ""
egaUser: ""
egaUsername: ""
egaPassword: ""
egaURL: ""
expirationDays: 14
iss: ""
jwtKey: ""
suprUsername: ""
suprPassword: ""
suprURL: ""
s3url: ""
uppmaxUsername: ""
uppmaxPassword: ""
Expand Down
27 changes: 20 additions & 7 deletions helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,23 @@ var Config Conf
type Conf struct {
Crypt4ghKeyPath string
Crypt4ghKey string
EgaUser string
EgaUsername string
EgaPassword string
EgaURL string
ExpirationDays int
Iss string
JwtKeyPath string
JwtParsedKey *ecdsa.PrivateKey
S3URL string
Username string
Password string
SuprUsername string
SuprPassword string
SuprURL string
}

// NewConf reads the configuration from the config.yaml file
func NewConf(conf *Conf) (err error) {
func NewConf(conf *Conf) error {
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.AutomaticEnv()
Expand All @@ -63,7 +68,8 @@ func NewConf(conf *Conf) (err error) {
}

requiredConfVars := []string{
"global.iss", "global.crypt4ghKey", "global.uppmaxUsername", "global.uppmaxPassword", "global.s3url", "global.egaUser", "global.jwtKey",
"global.iss", "global.crypt4ghKey", "global.uppmaxUsername", "global.uppmaxPassword", "global.s3url", "global.jwtKey",
"global.suprUsername", "global.suprPassword", "global.suprUrl", "global.egaUsername", "global.egaPassword", "global.egaUrl",
}

for _, s := range requiredConfVars {
Expand Down Expand Up @@ -95,18 +101,25 @@ func NewConf(conf *Conf) (err error) {
conf.Username = viper.GetString("global.uppmaxUsername")
conf.Password = viper.GetString("global.uppmaxPassword")
conf.S3URL = viper.GetString("global.s3url")
conf.EgaUser = viper.GetString("global.egaUser")
conf.EgaUsername = viper.GetString("global.egaUsername")
conf.EgaPassword = viper.GetString("global.egaPassword")
conf.EgaURL = viper.GetString("global.egaURL")
conf.Crypt4ghKeyPath = viper.GetString("global.crypt4ghKey")
conf.SuprPassword = viper.GetString("global.suprPassword")
conf.SuprURL = viper.GetString("global.suprURL")
conf.SuprUsername = viper.GetString("global.suprUsername")

if !viper.IsSet("global.expirationDays") {
conf.ExpirationDays = 14
} else {
conf.ExpirationDays = viper.GetInt("global.expirationDays")
}
conf.JwtParsedKey, err = parsePrivateECKey(conf.JwtKeyPath)
JwtParsedKey, err := parsePrivateECKey(conf.JwtKeyPath)
if err != nil {
return fmt.Errorf("could not parse ec key: %v", err)
}
conf.JwtParsedKey = JwtParsedKey

// Parse crypt4gh key and store it as base64 encoded
keyBytes, err := os.ReadFile(conf.Crypt4ghKeyPath)
if err != nil {
Expand All @@ -124,10 +137,10 @@ type errorStruct struct {
}

// CreateErrorResponse returns a JSON structure containing the error passed in the function
func CreateErrorResponse(errorMessage string) (errorBytes []byte) {
func CreateErrorResponse(errorMessage string) []byte {
currentError := errorStruct{}
currentError.ErrorStruct.Message = errorMessage
errorBytes, _ = json.Marshal(currentError)
errorBytes, _ := json.Marshal(currentError)

return errorBytes
}
Expand Down
27 changes: 18 additions & 9 deletions helpers/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,19 @@ func (suite *TestSuite) TestCreateErrorResponse() {

func (suite *TestSuite) TestNewConf() {
confData := `global:
crypt4ghKey: ` + suite.Crypt4ghKeyPath + `
egaUsername: "some-user"
egaPassword: "some-pass"
egaURL: "http://ega.dev"
expirationDays: 14
iss: "https://some.url"
jwtKey: "` + suite.PrivateKeyPath + `"
suprUsername: "some-user"
suprPassword: "some-pass"
suprURL: "http://supr.dev"
s3url: "some.s3.url"
uppmaxUsername: "user"
uppmaxPassword: "password"
s3url: "some.s3.url"
expirationDays: 14
egaUser: "some-user"
crypt4ghKey: "` + suite.Crypt4ghKeyPath + `"
`
configName := "config.yaml"
err := os.WriteFile(configName, []byte(confData), 0600)
Expand Down Expand Up @@ -95,14 +99,19 @@ func (suite *TestSuite) TestNewConfMissingValue() {

func (suite *TestSuite) TestNewConfMissingKey() {
confData := `global:
crypt4ghKey: "` + suite.Crypt4ghKeyPath + `"
egaUsername: "some-user"
egaPassword: "some-pass"
egaURL: "http://ega.dev"
expirationDays: 14
iss: "https://some.url"
jwtKey: "some/path"
suprUsername: "some-user"
suprPassword: "some-pass"
suprURL: "http://supr.dev"
s3url: "some.s3.url"
uppmaxUsername: "user"
uppmaxPassword: "password"
s3url: "some.s3.url"
expirationDays: 14
egaUser: "some-user"
crypt4ghKey: "` + suite.Crypt4ghKeyPath + `"
`
configName := "config.yaml"
err := os.WriteFile(configName, []byte(confData), 0600)
Expand Down
94 changes: 94 additions & 0 deletions token/ega.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package token

import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"

"github.com/NBISweden/sda-uppmax-integration/helpers"
log "github.com/sirupsen/logrus"
)

type EgaHeader struct {
APIVersion string `json:"apiVersion"`
Code int `json:"code"`
Service string `json:"service"`
DeveloperMessage string `json:"developerMessage"`
UserMessage string `json:"userMessage"`
ErrorCode int `json:"errorCode"`
DocLink string `json:"docLink"`
}

type EgaUserResult struct {
Username string `json:"username"`
SSHPublicKey string `json:"sshPublicKey"`
PasswordHash string `json:"passwordHash"`
UID int `json:"uid"`
Gecos string `json:"gecos"`
}

type EgaResponse struct {
NumTotalResults int `json:"numTotalResults"`
ResultType string `json:"resultType"`
Result []EgaUserResult `json:"result"`
}

type EgaReply struct {
Header EgaHeader `json:"header"`
Response EgaResponse `json:"response"`
}

// verifyEGABoxAccount checks that a given `username` is a valid EGA account, and
// returns error if the user does not exist.
func verifyEGABoxAccount(username string) error {

egaUser := helpers.Config.EgaUsername
egaPass := helpers.Config.EgaPassword
egaURL := helpers.Config.EgaURL

url := fmt.Sprintf("%v/%v?idType=username", egaURL, username)

client := &http.Client{
Timeout: 5 * time.Second,
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {

return err
}
req.SetBasicAuth(egaUser, egaPass)
resp, err := client.Do(req)
if err != nil {

return err
}

if resp.StatusCode != 200 {

message, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
defer resp.Body.Close()

return fmt.Errorf("got %v from EGA", message)
}

var reply EgaReply
err = json.NewDecoder(resp.Body).Decode(&reply)
if err != nil {

return err
}

defer resp.Body.Close()
log.Debugf("reply: %v", reply)
if len(reply.Response.Result) == 0 {

return nil
}

return nil
}
Loading

0 comments on commit a7d478b

Please sign in to comment.