diff --git a/.github/integration/scripts/charts/values.yaml b/.github/integration/scripts/charts/values.yaml index 26f5897e1..9b2303a08 100644 --- a/.github/integration/scripts/charts/values.yaml +++ b/.github/integration/scripts/charts/values.yaml @@ -33,6 +33,7 @@ global: jwtAlg: ES256 jwtKey: jwt.key jwtPub: jwt.pub + jwtTTL: 168 resignJwt: true broker: durable: true diff --git a/.github/integration/sda/config.yaml b/.github/integration/sda/config.yaml index 0d49e0abd..f9a61cb34 100644 --- a/.github/integration/sda/config.yaml +++ b/.github/integration/sda/config.yaml @@ -22,6 +22,7 @@ auth: issuer: "https://auth:8888" privateKey: /shared/keys/jwt.key signatureAlg: ES256 + tokenTTL: 168 publicFile: "/shared/c4gh.pub.pem" resignJwt: s3Inbox: "http://inbox:8000" diff --git a/charts/sda-svc/Chart.yaml b/charts/sda-svc/Chart.yaml index d139ab4e8..46692b14a 100644 --- a/charts/sda-svc/Chart.yaml +++ b/charts/sda-svc/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: sda-svc -version: 0.26.7 +version: 0.27.0 appVersion: v0.3.87 kubeVersion: '>= 1.26.0' description: Components for Sensitive Data Archive (SDA) installation diff --git a/charts/sda-svc/README.md b/charts/sda-svc/README.md index 292a38991..f20c4ec25 100644 --- a/charts/sda-svc/README.md +++ b/charts/sda-svc/README.md @@ -79,6 +79,7 @@ Parameter | Description | Default `global.auth.jwtAlg` | Key type to sign the JWT, available options are RS265 & ES256, Must match the key type |`"ES256"` `global.auth.jwtKey` | Private key used to sign the JWT. |`""` `global.auth.jwtPub` | Public key ues to verify the JWT. |`""` +`global.auth.jwtTTL` | TTL of the resigned token (hours). |`168` `global.auth.resignJWT` | Resign the LS-AAI JWTs. |`true` `global.auth.useTLS` | Run a TLS secured server. |`true` `global.auth.corsOrigins` | Domain name allowed for cross-domain requests. |`""` diff --git a/charts/sda-svc/templates/auth-deploy.yaml b/charts/sda-svc/templates/auth-deploy.yaml index 1cce414b7..1d722b422 100644 --- a/charts/sda-svc/templates/auth-deploy.yaml +++ b/charts/sda-svc/templates/auth-deploy.yaml @@ -128,6 +128,8 @@ spec: value: "{{ template "jwtPath" . }}/{{ .Values.global.auth.jwtKey }}" - name: AUTH_JWT_SIGNATUREALG value: {{ .Values.global.auth.jwtAlg }} + - name: AUTH_JWT_TOKENTTL + value: {{ .Values.global.auth.jwtTTL | quote }} {{- end }} - name: AUTH_PUBLICFILE value: "{{ template "c4ghPath" . }}/{{ .Values.global.c4gh.publicFile }}" diff --git a/charts/sda-svc/values.yaml b/charts/sda-svc/values.yaml index 9ccce2a95..214749c88 100644 --- a/charts/sda-svc/values.yaml +++ b/charts/sda-svc/values.yaml @@ -147,6 +147,8 @@ global: jwtKey: # @param jwtPub, name of the public signing key jwtPub: + # @param jwtTTL, TTL of the resigned token (hours) + jwtTTL: 168 # @param resignJwt, if true (or empty) the jwt will be resigned with the jwtKey resignJwt: false # @param corsOrigins, domain name of allowed origin for cross-domain requests diff --git a/sda/cmd/auth/auth.md b/sda/cmd/auth/auth.md index 44bc4b366..838a8f154 100644 --- a/sda/cmd/auth/auth.md +++ b/sda/cmd/auth/auth.md @@ -25,6 +25,7 @@ The following settings can be configured for deploying the service, either by us | `AUTH_JWT_ISSUER` | Issuer of JWT tokens | `http://auth:8080` | | `AUTH_JWT_PRIVATEKEY` | Path to private key for signing the JWT token | `keys/sign-jwt.key` | | `AUTH_JWT_SIGNATUREALG` | Algorithm used to sign the JWT token. ES256 (ECDSA) or RS256 (RSA) are supported | `ES256` | +| `AUTH_JWT_TOKENTTL` | TTL of the resigned token in hours | `168` | | `AUTH_RESIGNJWT` | Set to `false` to serve the raw OIDC JWT, i.e. without re-signing it | `""` | | `AUTH_S3INBOX` | S3 inbox host | `http://s3.example.com` | | `LOG_LEVEL` | Log level | `info` | diff --git a/sda/cmd/auth/main.go b/sda/cmd/auth/main.go index 679fbe376..4eec912c7 100644 --- a/sda/cmd/auth/main.go +++ b/sda/cmd/auth/main.go @@ -142,7 +142,7 @@ func (auth AuthHandler) postEGA(ctx iris.Context) { if ok { log.WithFields(log.Fields{"authType": "cega", "user": username}).Info("Valid password entered by user") claims := map[string]interface{}{ - jwt.ExpirationKey: time.Now().UTC().Add(200 * time.Hour), + jwt.ExpirationKey: time.Now().UTC().Add(time.Duration(auth.Config.JwtTTL) * time.Hour), jwt.IssuedAtKey: time.Now().UTC(), jwt.IssuerKey: auth.Config.JwtIssuer, jwt.SubjectKey: username, diff --git a/sda/internal/config/config.go b/sda/internal/config/config.go index 83cdd025a..75324fdf7 100644 --- a/sda/internal/config/config.go +++ b/sda/internal/config/config.go @@ -117,6 +117,7 @@ type AuthConf struct { JwtIssuer string JwtPrivateKey string JwtSignatureAlg string + JwtTTL int Server ServerConfig S3Inbox string ResignJwt bool @@ -228,7 +229,7 @@ func NewConfig(app string) (*Config, error) { } if viper.GetBool("auth.resignJwt") { - requiredConfVars = append(requiredConfVars, []string{"auth.jwt.issuer", "auth.jwt.privateKey", "auth.jwt.signatureAlg"}...) + requiredConfVars = append(requiredConfVars, []string{"auth.jwt.issuer", "auth.jwt.privateKey", "auth.jwt.signatureAlg", "auth.jwt.tokenTTL"}...) } case "ingest": requiredConfVars = []string{ @@ -494,6 +495,7 @@ func NewConfig(app string) (*Config, error) { c.Auth.JwtPrivateKey = viper.GetString("auth.jwt.privateKey") c.Auth.JwtSignatureAlg = viper.GetString("auth.jwt.signatureAlg") c.Auth.JwtIssuer = viper.GetString("auth.jwt.issuer") + c.Auth.JwtTTL = viper.GetInt("auth.jwt.tokenTTL") if _, err := os.Stat(c.Auth.JwtPrivateKey); err != nil { return nil, err diff --git a/sda/internal/config/config_test.go b/sda/internal/config/config_test.go index 253f68db5..59d06c599 100644 --- a/sda/internal/config/config_test.go +++ b/sda/internal/config/config_test.go @@ -414,6 +414,7 @@ func (suite *ConfigTestSuite) TestConfigAuth_CEGA() { viper.Set("auth.jwt.Issuer", "http://auth:8080") viper.Set("auth.Jwt.privateKey", "nonexistent-key-file") viper.Set("auth.Jwt.signatureAlg", "ES256") + viper.Set("auth.Jwt.tokenTTL", 168) _, err = NewConfig("auth") assert.ErrorContains(suite.T(), err, "no such file or directory") @@ -421,6 +422,7 @@ func (suite *ConfigTestSuite) TestConfigAuth_CEGA() { viper.Set("auth.Jwt.privateKey", ECPath+"/ec") c, err := NewConfig("auth") assert.Equal(suite.T(), c.Auth.JwtPrivateKey, fmt.Sprintf("%s/ec", ECPath)) + assert.Equal(suite.T(), c.Auth.JwtTTL, 168) assert.NoError(suite.T(), err, "unexpected failure") }