Skip to content

Commit

Permalink
Merge pull request #208 from neicnordic/200-provide-info-for-cli-login
Browse files Browse the repository at this point in the history
Provide endpoint with info for sda-cli login
  • Loading branch information
pahatz authored Dec 19, 2023
2 parents ecbd588 + 56a8453 commit 333e14b
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 5 deletions.
1 change: 0 additions & 1 deletion .github/integration/scripts/charts/dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ C4GHPASSPHRASE="$(random-string)"
export C4GHPASSPHRASE
crypt4gh generate -n c4gh -p "$C4GHPASSPHRASE"
kubectl create secret generic c4gh --from-file="c4gh.sec.pem" --from-file="c4gh.pub.pem" --from-literal=passphrase="${C4GHPASSPHRASE}"

# secret for the OIDC keypair
openssl ecparam -name prime256v1 -genkey -noout -out "jwt.key"
openssl ec -in "jwt.key" -pubout -out "jwt.pub"
Expand Down
2 changes: 1 addition & 1 deletion .github/integration/scripts/charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ global:
secretName: c4gh
keyFile: c4gh.sec.pem
publicFile: c4gh.pub.pem
passphrase: PLACEHOLDER_VALUE
passphrase: PLACEHOLDER_VALUE
db:
host: "postgres-sda-db"
user: "postgres"
Expand Down
2 changes: 1 addition & 1 deletion charts/sda-svc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Parameter | Description | Default
`global.cega.password` | Password for the EGA user authentication service. |`""`
`global.c4gh.keyFile` | Private C4GH key. |`c4gh.key`
`global.c4gh.passphrase` | Passphrase for the private C4GH key. |`""`
`global.c4gh.publicFile` | Public key corresponding to the private key, neeeded for tests. |`""`
`global.c4gh.publicFile` | Public key corresponding to the private key, provided in /info endpoint. |`""`
`global.db.host` | Hostname for the database. |`""`
`global.db.name` | Database to connect to. |`lega`
`global.db.passIngest` | Password used for `data in` services. |`""`
Expand Down
15 changes: 15 additions & 0 deletions charts/sda-svc/templates/auth-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ spec:
{{- end }}
- name: RESIGNJWT
value: {{ .Values.global.auth.resignJwt | quote }}
- name: PUBLICFILE
value: "{{ template "c4ghPath" . }}/{{ .Values.global.c4gh.publicFile }}"
{{- if .Values.global.tls.enabled}}
- name: SERVER_CERT
value: {{ template "tlsPath" . }}/tls.crt
Expand Down Expand Up @@ -184,6 +186,10 @@ spec:
- name: jwt
mountPath: {{ template "jwtPath" . }}
{{- end }}
{{- if not .Values.global.vaultSecrets }}
- name: c4gh
mountPath: {{ template "c4ghPath" . }}
{{- end }}
volumes:
{{- if and (.Values.global.auth.resignJwt) (not .Values.global.vaultSecrets) }}
- name: jwt
Expand All @@ -196,6 +202,15 @@ spec:
- key: {{ required "The name of the JWT signing key is needed" .Values.global.auth.jwtKey }}
path: {{ .Values.global.auth.jwtKey }}
{{- end }}
{{- if not .Values.global.vaultSecrets }}
- name: c4gh
secret:
defaultMode: 0440
secretName: {{ required "A secret for the C4GH public key is needed" .Values.global.c4gh.secretName }}
items:
- key: {{ required "The C4GH public key is needed" .Values.global.c4gh.publicFile }}
path: {{ .Values.global.c4gh.publicFile }}
{{- end }}
{{- if and (not .Values.global.pkiService) .Values.global.tls.enabled }}
- name: tls
projected:
Expand Down
8 changes: 6 additions & 2 deletions sda-auth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Config struct {
ResignJwt bool
InfoURL string
InfoText string
PublicFile string
}

// NewConfig initializes and parses the config file and/or environment using
Expand Down Expand Up @@ -94,6 +95,7 @@ func (c *Config) readConfig() error {
c.JwtIssuer = viper.GetString("jwtIssuer")
c.InfoURL = viper.GetString("infoUrl")
c.InfoText = viper.GetString("infoText")
c.PublicFile = viper.GetString("publicFile")

viper.SetDefault("ResignJwt", true)
c.ResignJwt = viper.GetBool("resignJwt")
Expand Down Expand Up @@ -172,8 +174,10 @@ func (c *Config) readConfig() error {
log.Printf("Setting log level to '%s'", stringLevel)
}

if viper.GetString("s3Inbox") == "" {
return fmt.Errorf("%s not set", "s3Inbox")
for _, s := range []string{"s3Inbox", "publicFile"} {
if viper.GetString(s) == "" {
return fmt.Errorf("%s not set", s)
}
}

// no need to check the variables for JWT generation if we won't use it
Expand Down
1 change: 1 addition & 0 deletions sda-auth/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ jwtSignatureAlg: "ES256"
resignJwt: true
infoText: "About Federated EGA"
infoUrl: "https://ega-archive.org/about/projects-and-funders/federated-ega/"
publicFile: "/keys/c4gh.pub.pem"
5 changes: 5 additions & 0 deletions sda-auth/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type ConfigTests struct {
ResignJwt bool
InfoURL string
InfoText string
PublicFile string
}

func TestConfigTestSuite(t *testing.T) {
Expand Down Expand Up @@ -89,6 +90,7 @@ func (suite *ConfigTests) SetupTest() {
suite.ResignJwt = true
suite.InfoURL = "https://test.info"
suite.InfoText = "About LEGA"
suite.PublicFile = "public.pem"

// Write config to temp config file
configYaml, err := yaml.Marshal(Config{
Expand All @@ -102,6 +104,7 @@ func (suite *ConfigTests) SetupTest() {
ResignJwt: suite.ResignJwt,
InfoURL: suite.InfoURL,
InfoText: suite.InfoText,
PublicFile: suite.PublicFile,
})
if err != nil {
log.Errorf("Error marshalling config yaml: %v", err)
Expand Down Expand Up @@ -186,6 +189,7 @@ func (suite *ConfigTests) TestConfig() {

os.Setenv("INFOTEXT", fmt.Sprintf("env_%v", suite.InfoText))
os.Setenv("INFOURL", fmt.Sprintf("env_%v", suite.InfoURL))
os.Setenv("PUBLICFILE", fmt.Sprintf("env_%v", suite.PublicFile))

// re-read the config
config, err = NewConfig()
Expand All @@ -212,6 +216,7 @@ func (suite *ConfigTests) TestConfig() {

assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.InfoText), config.InfoText, "Project info text misread from environment variable")
assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.InfoURL), config.InfoURL, "Project info text misread from environment variable")
assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.PublicFile), config.PublicFile, "Public file misread from environment variable")

// Check missing private key
os.Setenv("JWTPRIVATEKEY", "nonexistent-key-file")
Expand Down
14 changes: 14 additions & 0 deletions sda-auth/dev-server/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ services:
- CEGA_USERS_USER=dummy
ports:
- 8443:8443
keygen:
image: golang:alpine3.16
container_name: keygen
command:
- "/bin/sh"
- "-c"
- if [ ! -f "/out/c4gh.sec.pem" ]; then wget -qO- "https://github.com/neicnordic/crypt4gh/releases/latest/download/crypt4gh_linux_x86_64.tar.gz" | tar zxf -;
./crypt4gh generate -n c4gh -p privatekeypass && mv *.pem /out/; fi
volumes:
- /tmp:/out
auth:
container_name: auth
build:
Expand All @@ -55,6 +65,8 @@ services:
condition: service_healthy
cega:
condition: service_started
keygen:
condition: service_completed_successfully
environment:
- ELIXIR_ID=XC56EL11xx
- ELIXIR_PROVIDER=http://oidc:9090
Expand All @@ -73,9 +85,11 @@ services:
- JWTSIGNATUREALG=ES256
- INFOTEXT=About Federated EGA
- INFOURL=https://ega-archive.org/about/projects-and-funders/federated-ega/
- PUBLICFILE=/c4gh.pub.pem
volumes:
- ../keys:/keys
- ../:/sda-auth
- /tmp/c4gh.pub.pem:/c4gh.pub.pem
image: sda-auth
ports:
- 8080:8080
Expand Down
3 changes: 3 additions & 0 deletions sda-auth/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/iris-contrib/middleware/cors v0.0.0-20230311205048-b568fe9b470f
github.com/kataras/iris/v12 v12.2.7
github.com/lestrrat/go-jwx v0.9.1
github.com/neicnordic/crypt4gh v1.7.6
github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.18.2
Expand All @@ -20,6 +21,7 @@ require (
)

require (
filippo.io/edwards25519 v1.0.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
Expand All @@ -28,6 +30,7 @@ require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
Expand Down
7 changes: 7 additions & 0 deletions sda-auth/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
Expand All @@ -21,6 +23,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU=
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a/go.mod h1:Bw9BbhOJVNR+t0jCqx2GC6zv0TGBsShs56Y3gfSCvl0=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
Expand Down Expand Up @@ -96,6 +100,8 @@ github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/neicnordic/crypt4gh v1.7.6 h1:Vqcb8Yb950oaBBJFepDK1oLeu9rZzpywYWVHLmO0oI8=
github.com/neicnordic/crypt4gh v1.7.6/go.mod h1:rqmVXsprDFBRRLJkm1cK9kLETBPGEZmft9lHD/V40wk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282 h1:TQMyrpijtkFyXpNI3rY5hsZQZw+paiH+BfAlsb81HBY=
Expand Down Expand Up @@ -202,6 +208,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
45 changes: 45 additions & 0 deletions sda-auth/info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"os"
"path/filepath"

"github.com/kataras/iris/v12"
"github.com/neicnordic/crypt4gh/keys"
log "github.com/sirupsen/logrus"
)

type Info struct {
ClientID string `json:"client_id"`
OidcURI string `json:"oidc_uri"`
PublicKey string `json:"public_key"`
InboxURI string `json:"inbox_uri"`
}

// Reads the public key file and returns the public key
func readPublicKeyFile(filename string) (key *[32]byte, err error) {
log.Info("Reading Public key file")
file, err := os.Open(filepath.Clean(filename))
if err != nil {
return nil, err
}
defer file.Close()
publicKey, err := keys.ReadPublicKey(file)
if err != nil {
return nil, err
}

return &publicKey, err
}

// getInfo returns information needed by the client to authenticate
func (auth AuthHandler) getInfo(ctx iris.Context) {
info := Info{ClientID: auth.OAuth2Config.ClientID, OidcURI: auth.Config.Elixir.Provider, PublicKey: auth.pubKey, InboxURI: auth.Config.S3Inbox}

err := ctx.JSON(info)
if err != nil {
log.Error("Failure to get Info ", err)

return
}
}
12 changes: 12 additions & 0 deletions sda-auth/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/hex"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -35,6 +36,7 @@ type AuthHandler struct {
OIDCProvider *oidc.Provider
htmlDir string
staticDir string
pubKey string
}

func (auth AuthHandler) getInboxConfig(ctx iris.Context, authType string) {
Expand Down Expand Up @@ -380,6 +382,7 @@ func main() {
OIDCProvider: provider,
htmlDir: "./frontend/templates",
staticDir: "./frontend/static",
pubKey: "",
}

// Initialise web server
Expand Down Expand Up @@ -417,6 +420,15 @@ func main() {
app.Get("/elixir/login", authHandler.getElixirLogin)
app.Get("/elixir/cors_login", authHandler.getElixirCORSLogin)

publicKey, err := readPublicKeyFile(authHandler.Config.PublicFile)
if err != nil {
log.Fatalf("Failed to get public key: %s", err.Error())
}
authHandler.pubKey = hex.EncodeToString(publicKey[:])

// Endpoint for client login info
app.Get("/info", authHandler.getInfo)

app.UseGlobal(globalHeaders)

if config.Server.Cert != "" && config.Server.Key != "" {
Expand Down

0 comments on commit 333e14b

Please sign in to comment.