2021-09-09 09:20:45 +00:00
package api
import (
"bytes"
"fmt"
"io/ioutil"
"path"
"text/template"
"srs.epita.fr/fic-server/admin/pki"
"srs.epita.fr/fic-server/libfic"
"github.com/julienschmidt/httprouter"
)
var OidcSecret = ""
func init ( ) {
router . POST ( "/api/password" , apiHandler (
func ( httprouter . Params , [ ] byte ) ( interface { } , error ) {
if passwd , err := fic . GeneratePassword ( ) ; err != nil {
return nil , err
} else {
return map [ string ] string { "password" : passwd } , nil
}
} ) )
router . GET ( "/api/teams/:tid/password" , apiHandler ( teamHandler (
2021-11-22 14:35:07 +00:00
func ( team * fic . Team , _ [ ] byte ) ( interface { } , error ) {
2021-09-09 09:20:45 +00:00
return team . Password , nil
} ) ) )
router . POST ( "/api/teams/:tid/password" , apiHandler ( teamHandler (
2021-11-22 14:35:07 +00:00
func ( team * fic . Team , _ [ ] byte ) ( interface { } , error ) {
2021-09-09 09:20:45 +00:00
if passwd , err := fic . GeneratePassword ( ) ; err != nil {
return nil , err
} else {
team . Password = & passwd
return team . Update ( )
}
} ) ) )
router . GET ( "/api/dex.yaml" , apiHandler (
func ( httprouter . Params , [ ] byte ) ( interface { } , error ) {
return genDexConfig ( )
} ) )
router . POST ( "/api/dex.yaml" , apiHandler (
func ( httprouter . Params , [ ] byte ) ( interface { } , error ) {
if dexcfg , err := genDexConfig ( ) ; err != nil {
return nil , err
} else if err := ioutil . WriteFile ( path . Join ( pki . PKIDir , "shared" , "dex-config.yaml" ) , [ ] byte ( dexcfg ) , 0644 ) ; err != nil {
return nil , err
} else {
return true , nil
}
} ) )
router . GET ( "/api/dex-password.tpl" , apiHandler (
func ( httprouter . Params , [ ] byte ) ( interface { } , error ) {
return genDexPasswordTpl ( )
} ) )
router . POST ( "/api/dex-password.tpl" , apiHandler (
func ( httprouter . Params , [ ] byte ) ( interface { } , error ) {
if dexcfg , err := genDexPasswordTpl ( ) ; err != nil {
return nil , err
} else if err := ioutil . WriteFile ( path . Join ( pki . PKIDir , "shared" , "dex-password.tpl" ) , [ ] byte ( dexcfg ) , 0644 ) ; err != nil {
return nil , err
} else {
return true , nil
}
} ) )
}
const dexcfgtpl = ` issuer : https : //fic.srs.epita.fr
storage :
type : sqlite3
config :
file : / var / dex / dex . db
web :
http : 0.0 .0 .0 : 5556
frontend :
issuer : Challenge forensic
logoURL : img / fic . png
dir : / srv / dex / web /
oauth2 :
skipApprovalScreen : true
staticClients :
{ { range $ c := . Clients } }
- id : { { $ c . Id } }
name : { { $ c . Name } }
redirectURIs : [ { { range $ u := $ c . RedirectURIs } } ' { { $ u } } ' { { end } } ]
secret : { { $ c . Secret } }
{ { end } }
enablePasswordDB : true
staticPasswords :
{ { range $ t := . Teams } }
- email : "team{{ printf " % 02 d " $t.Id }}"
hash : "{{with $t }}{{ .HashedPassword }}{{end}}"
{ { end } }
`
const dexpasswdtpl = ` { { "{{" } } template "header.html" . { { "}}" } }
< div class = "theme-panel" >
< h2 class = "theme-heading" >
Bienvenue au challenge Forensic & nbsp ; !
< / h2 >
< form method = "post" action = "{{ " { { " }} .PostURL {{ " } } " }}" >
< div class = "theme-form-row" >
< div class = "theme-form-label" >
< label for = "userid" > Votre équipe < / label >
< / div >
< select tabindex = "1" required id = "login" name = "login" class = "theme-form-input" autofocus >
{ { range $ t := . Teams } } < option value = "team{{ printf " % 02 d " $t.Id }}" > { { $ t . Name } } < / option >
{ { end } } < / select >
< / div >
< div class = "theme-form-row" >
< div class = "theme-form-label" >
< label for = "password" > Mot de passe < / label >
< / div >
< input tabindex = "2" required id = "password" name = "password" type = "password" class = "theme-form-input" placeholder = "mot de passe" { { "{{" } } if . Invalid { { "}}" } } autofocus { { "{{" } } end { { "}}" } } / >
< / div >
{ { "{{" } } if . Invalid { { "}}" } }
< div id = "login-error" class = "dex-error-box" >
Identifiants incorrects .
< / div >
{ { "{{" } } end { { "}}" } }
< button tabindex = "3" id = "submit-login" type = "submit" class = "dex-btn theme-btn--primary" > C ' est parti & nbsp ; ! < / button >
< / form >
{ { "{{" } } if . BackLink { { "}}" } }
< div class = "theme-link-back" >
< a class = "dex-subtle-text" href = "{{ " { { " }} .BackLink {{ " } } " }}" > Sélectionner une autre méthode d ' authentification . < / a >
< / div >
{ { "{{" } } end { { "}}" } }
< / div >
{ { "{{" } } template "footer.html" . { { "}}" } }
`
type dexConfigClient struct {
Id string
Name string
RedirectURIs [ ] string
Secret string
}
type dexConfig struct {
Clients [ ] dexConfigClient
2021-11-22 14:35:07 +00:00
Teams [ ] * fic . Team
2021-09-09 09:20:45 +00:00
}
func genDexConfig ( ) ( [ ] byte , error ) {
if teams , err := fic . GetTeams ( ) ; err != nil {
return nil , err
} else if OidcSecret == "" {
return nil , fmt . Errorf ( "Unable to generate dex configuration: OIDC Secret not defined. Please define FICOIDC_SECRET in your environment." )
} else {
b := bytes . NewBufferString ( "" )
if dexTmpl , err := template . New ( "dexcfg" ) . Parse ( dexcfgtpl ) ; err != nil {
return nil , fmt . Errorf ( "Cannot create template: %w" , err )
} else if err = dexTmpl . Execute ( b , dexConfig {
Clients : [ ] dexConfigClient {
dexConfigClient {
Id : "epita-challenge" ,
Name : "Challenge Forensic" ,
RedirectURIs : [ ] string { "https://fic.srs.epita.fr/challenge_access/auth" } ,
Secret : OidcSecret ,
} ,
} ,
Teams : teams ,
} ) ; err != nil {
return nil , fmt . Errorf ( "An error occurs during template execution: %w" , err )
} else {
return b . Bytes ( ) , nil
}
}
}
func genDexPasswordTpl ( ) ( [ ] byte , error ) {
if teams , err := fic . GetTeams ( ) ; err != nil {
return nil , err
} else {
b := bytes . NewBufferString ( "" )
if dexTmpl , err := template . New ( "dexpasswd" ) . Parse ( dexpasswdtpl ) ; err != nil {
return nil , fmt . Errorf ( "Cannot create template: %w" , err )
} else if err = dexTmpl . Execute ( b , dexConfig {
Teams : teams ,
} ) ; err != nil {
return nil , fmt . Errorf ( "An error occurs during template execution: %w" , err )
} else {
return b . Bytes ( ) , nil
}
}
}