Skip to content

Commit

Permalink
Feature/compose (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
norling authored Feb 1, 2023
2 parents 6d4eea9 + b789cc3 commit 402bb43
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sda-uppmax-integration
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,19 @@ curl --location --request POST '<base_url>:8080/token' \
"projectid": "<projectid>"
}'
```
where `<basic_auth_from_creds>` is the base64 encoded string `username:password`.

The `token` endpoint requires basic auth and the allowed credentials can be defined in the configuration file `config.yaml`.

ex.
```bash
$ curl --location --request POST 'localhost:8080/token' \
--header "Authorization: Basic $(printf 'uppmax:uppmax' | base64)" \
--header 'Content-Type: application/json' \
--data-raw '{"swamid": "[email protected]", "projectid": "sda001"}'
```
can be used in the docker compose development environment.

## Endpoint Response

The `token` endpoint returns the following structure, if the user is authorised to access the `<projectid>` requested:
Expand Down
37 changes: 37 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
services:
keymaker:
image: golang:alpine3.16
volumes:
- keys:/keys
command:
- "/bin/sh"
- "-c"
- if [ ! -f "/keys/c4gh.sec.pem" ]; then git --help >/dev/null 2>&1; [[ "$$?" != "0" ]] && apk add git;
[ ! -d "crypt4gh" ] && git clone https://github.com/neicnordic/crypt4gh.git;
cd crypt4gh;
[ ! -f "crypt4gh" ] && go build .;
./crypt4gh generate -n c4gh -p 'pass' && mv *.pem /keys/; fi;
[ ! -f /keys/jwt.key ] && apk add openssl && openssl ecparam -name prime256v1 -genkey -noout -out /keys/jwt.key && chmod 644 /keys/jwt.key || true
uppmax-integration:
build:
context: .
depends_on:
keymaker:
condition: service_completed_successfully
environment:
- LOG_LEVEL=debug
- GLOBAL_CRYPT4GHKEY=/keys/c4gh.sec.pem
- [email protected]
- GLOBAL_EXPIRATIONDAYS=14
- GLOBAL_ISS=https://login.sda.dev
- GLOBAL_JWTKEY=/keys/jwt.key
- GLOBAL_S3URL=inbox.sda.dev
- GLOBAL_UPPMAXUSERNAME=uppmax
- GLOBAL_UPPMAXPASSWORD=uppmax
volumes:
- keys:/keys
ports:
- 8080:8080

volumes:
keys:
4 changes: 4 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ global:
s3url: ""
uppmaxUsername: ""
uppmaxPassword: ""

log:
format: text
level: debug
24 changes: 21 additions & 3 deletions helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,28 @@ func NewConf(conf *Conf) (err error) {

for _, s := range requiredConfVars {
if !viper.IsSet(s) || viper.GetString(s) == "" {
return fmt.Errorf("Required configuration field %s not set", s)
return fmt.Errorf("required configuration field %s not set", s)
}
}

if viper.IsSet("log.format") {
if viper.GetString("log.format") == "json" {
log.SetFormatter(&log.JSONFormatter{})
log.Info("The logs format is set to JSON")
}
}

if viper.IsSet("log.level") {
stringLevel := viper.GetString("log.level")
intLevel, err := log.ParseLevel(stringLevel)
if err != nil {
log.Printf("Log level '%s' not supported, setting to 'trace'", stringLevel)
intLevel = log.TraceLevel
}
log.SetLevel(intLevel)
log.Printf("Setting log level to '%s'", stringLevel)
}

conf.Iss = viper.GetString("global.iss")
conf.JwtKeyPath = viper.GetString("global.jwtKey")
conf.Username = viper.GetString("global.uppmaxUsername")
Expand All @@ -87,12 +105,12 @@ func NewConf(conf *Conf) (err error) {
}
conf.JwtParsedKey, err = parsePrivateECKey(conf.JwtKeyPath)
if err != nil {
return fmt.Errorf("Could not parse ec key")
return fmt.Errorf("could not parse ec key: %v", err)
}
// Parse crypt4gh key and store it as base64 encoded
keyBytes, err := os.ReadFile(conf.Crypt4ghKeyPath)
if err != nil {
return fmt.Errorf("Could not parse crypt4gh public key")
return fmt.Errorf("could not parse crypt4gh public key: %v", err)
}
conf.Crypt4ghKey = b64.StdEncoding.EncodeToString([]byte(keyBytes))

Expand Down
4 changes: 2 additions & 2 deletions helpers/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (suite *TestSuite) TestNewConfMissingValue() {
}

err = NewConf(&Config)
assert.EqualError(suite.T(), err, "Required configuration field global.iss not set")
assert.EqualError(suite.T(), err, "required configuration field global.iss not set")

defer os.Remove(configName)
}
Expand All @@ -111,7 +111,7 @@ func (suite *TestSuite) TestNewConfMissingKey() {
}

err = NewConf(&Config)
assert.EqualError(suite.T(), err, "Could not parse ec key")
assert.EqualError(suite.T(), err, "could not parse ec key: open some/path: no such file or directory")

defer os.Remove(configName)
}
Expand Down
6 changes: 4 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@ func main() {
log.Fatal(err)
}

servicePort := 8080

http.HandleFunc("/token", helpers.BasicAuth(token.GetToken))
http.HandleFunc("/ping", ping)

server := &http.Server{
Addr: ":8000",
Addr: fmt.Sprintf(":%v", servicePort),
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 30 * time.Second,
ReadHeaderTimeout: 30 * time.Second,
}

fmt.Println("Starting server at port 8080")
log.Infof("Starting server at port %v", servicePort)
log.Fatal(server.ListenAndServe())

}
8 changes: 4 additions & 4 deletions token/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ func readRequestBody(body io.ReadCloser) (tokenRequest tokenRequest, err error)
if err != nil {
log.Print("Error reading request body: ", err)

return tokenRequest, fmt.Errorf("Error reading request body")
return tokenRequest, fmt.Errorf("error reading request body")
}
defer body.Close()

err = json.Unmarshal(reqBody, &tokenRequest)
if err != nil {
log.Print("Error unmarshaling: ", err)

return tokenRequest, fmt.Errorf("Error unmarshaling data")
return tokenRequest, fmt.Errorf("error unmarshaling data")
}

if tokenRequest.ProjectID == "" || tokenRequest.Swamid == "" {
return tokenRequest, fmt.Errorf("Incomplete incoming data")
return tokenRequest, fmt.Errorf("incomplete incoming data")
}

return tokenRequest, nil
Expand Down Expand Up @@ -107,7 +107,7 @@ func createResponse(tokenRequest tokenRequest, username string) (tokenResponse t

tokenResponse.S3Config, tokenResponse.Expiration, err = createS3Config(username)
if err != nil {
return tokenResponse, fmt.Errorf("Error creating S3 configuration")
return tokenResponse, fmt.Errorf("error creating S3 configuration")
}

return tokenResponse, err
Expand Down
4 changes: 2 additions & 2 deletions token/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (suite *TestSuite) TestNewConf() {

_, err = readRequestBody(r)

assert.EqualError(suite.T(), err, "Error unmarshaling data")
assert.EqualError(suite.T(), err, "error unmarshaling data")

r = io.NopCloser(strings.NewReader(`{
"swami": "<swamid>",
Expand All @@ -75,7 +75,7 @@ func (suite *TestSuite) TestNewConf() {

_, err = readRequestBody(r)

assert.EqualError(suite.T(), err, "Incomplete incoming data")
assert.EqualError(suite.T(), err, "incomplete incoming data")
}

func (suite *TestSuite) TestCreateECToken() {
Expand Down

0 comments on commit 402bb43

Please sign in to comment.