admin/pki: use symlink instead of DB to associate certificate to team
This commit is contained in:
parent
73eb04bcf0
commit
156a87abc0
@ -6,10 +6,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
"strconv"
|
||||
|
||||
"srs.epita.fr/fic-server/admin/pki"
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
@ -26,7 +28,21 @@ func init() {
|
||||
}))
|
||||
|
||||
router.GET("/api/teams/:tid/certificates", apiHandler(teamHandler(
|
||||
func(team fic.Team, _ []byte) (interface{}, error) { return fic.GetTeamCertificates(team) })))
|
||||
func(team fic.Team, _ []byte) (interface{}, error) {
|
||||
if serials, err := pki.GetTeamSerials(TeamsDir, team.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
var certs []fic.Certificate
|
||||
for _, serial := range serials {
|
||||
if cert, err := fic.GetCertificate(serial); err == nil {
|
||||
certs = append(certs, cert)
|
||||
} else {
|
||||
log.Println("Unable to get back certificate, whereas an association exists on disk: ", err)
|
||||
}
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
})))
|
||||
|
||||
router.GET("/api/certs/", apiHandler(getCertificates))
|
||||
router.POST("/api/certs/", apiHandler(generateClientCert))
|
||||
@ -128,7 +144,7 @@ func generateClientCert(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
type CertExported struct {
|
||||
Id string `json:"id"`
|
||||
Creation time.Time `json:"creation"`
|
||||
IdTeam *int64 `json:"id_team"`
|
||||
IdTeam *uint64 `json:"id_team"`
|
||||
Revoked *time.Time `json:"revoked"`
|
||||
}
|
||||
|
||||
@ -137,8 +153,17 @@ func getCertificates(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
return nil, err
|
||||
} else {
|
||||
ret := make([]CertExported, 0)
|
||||
for _, c := range certificates {
|
||||
ret = append(ret, CertExported{fmt.Sprintf("%d", c.Id), c.Creation, c.IdTeam, c.Revoked})
|
||||
for _, cert := range certificates {
|
||||
dstLinkPath := path.Join(TeamsDir, pki.GetCertificateAssociation(cert.Id))
|
||||
|
||||
var idTeam *uint64 = nil
|
||||
if lnk, err := os.Readlink(dstLinkPath); err == nil {
|
||||
if tid, err := strconv.ParseUint(lnk, 10, 64); err == nil {
|
||||
idTeam = &tid
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, CertExported{fmt.Sprintf("%d", cert.Id), cert.Creation, idTeam, cert.Revoked})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@ -154,15 +179,7 @@ func updateCertificateAssociation(cert fic.Certificate, body []byte) (interface{
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: This should be read from file system, not in DB:
|
||||
// the relation is made through a symlink, so if it exists, it is suffisant to read the relation
|
||||
// moreover, backend doesn't update the DB at registration, it only creates a symlink
|
||||
cert.IdTeam = uc.Team
|
||||
|
||||
var serial big.Int
|
||||
serial.SetUint64(cert.Id)
|
||||
|
||||
dstLinkPath := path.Join(TeamsDir, fmt.Sprintf("_AUTH_ID_%0X", serial.Bytes()))
|
||||
dstLinkPath := path.Join(TeamsDir, pki.GetCertificateAssociation(cert.Id))
|
||||
|
||||
if uc.Team != nil {
|
||||
srcLinkPath := fmt.Sprintf("%d", *uc.Team)
|
||||
@ -173,9 +190,5 @@ func updateCertificateAssociation(cert fic.Certificate, body []byte) (interface{
|
||||
os.Remove(dstLinkPath)
|
||||
}
|
||||
|
||||
if _, err := cert.Update(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return cert, err
|
||||
}
|
||||
return cert, nil
|
||||
}
|
||||
|
46
admin/pki/team.go
Normal file
46
admin/pki/team.go
Normal file
@ -0,0 +1,46 @@
|
||||
package pki
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GetCertificateAssociation(serial uint64) string {
|
||||
return fmt.Sprintf("_AUTH_ID_%0X", serial)
|
||||
}
|
||||
|
||||
func GetAssociations(dirname string) (assocs []string, err error) {
|
||||
if ds, errr := ioutil.ReadDir(dirname); err != nil {
|
||||
return nil, errr
|
||||
} else {
|
||||
for _, d := range ds {
|
||||
if d.Mode() & os.ModeSymlink == os.ModeSymlink {
|
||||
assocs = append(assocs, d.Name())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func GetTeamSerials(dirname string, id_team int64) (serials []uint64, err error) {
|
||||
// As futher comparaisons will be made with strings, convert it only one time
|
||||
str_tid := fmt.Sprintf("%d", id_team)
|
||||
|
||||
var assocs []string
|
||||
if assocs, err = GetAssociations(dirname); err != nil {
|
||||
return
|
||||
} else {
|
||||
for _, assoc := range assocs {
|
||||
var tid string
|
||||
if tid, err = os.Readlink(path.Join(dirname, assoc)); err == nil && tid == str_tid {
|
||||
if serial, err := strconv.ParseUint(assoc[9:], 16, 64); err == nil {
|
||||
serials = append(serials, serial)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
@ -20,20 +20,19 @@ type Certificate struct {
|
||||
Id uint64 `json:"id,string"`
|
||||
Creation time.Time `json:"creation"`
|
||||
Password string `json:"password"`
|
||||
IdTeam *int64 `json:"id_team"`
|
||||
Revoked *time.Time `json:"revoked"`
|
||||
}
|
||||
|
||||
// GetCertificates returns the list of all generated certificates.
|
||||
func GetCertificates() (certificates []Certificate, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_cert, creation, password, id_team, revoked FROM certificates ORDER BY creation"); err == nil {
|
||||
if rows, err = DBQuery("SELECT id_cert, creation, password, revoked FROM certificates ORDER BY creation"); err == nil {
|
||||
defer rows.Close()
|
||||
|
||||
certificates = make([]Certificate, 0)
|
||||
for rows.Next() {
|
||||
var c Certificate
|
||||
if err = rows.Scan(&c.Id, &c.Creation, &c.Password, &c.IdTeam, &c.Revoked); err != nil {
|
||||
if err = rows.Scan(&c.Id, &c.Creation, &c.Password, &c.Revoked); err != nil {
|
||||
return
|
||||
}
|
||||
certificates = append(certificates, c)
|
||||
@ -44,28 +43,9 @@ func GetCertificates() (certificates []Certificate, err error) {
|
||||
}
|
||||
|
||||
|
||||
// GetTeamCertificates returns all certificates generated for a given Team.
|
||||
func GetTeamCertificates(team Team) (certificates []Certificate, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_cert, creation, password, id_team, revoked FROM certificates WHERE id_team = ? ORDER BY creation", team.Id); err == nil {
|
||||
defer rows.Close()
|
||||
|
||||
certificates = make([]Certificate, 0)
|
||||
for rows.Next() {
|
||||
var c Certificate
|
||||
if err = rows.Scan(&c.Id, &c.Creation, &c.Password, &c.IdTeam, &c.Revoked); err != nil {
|
||||
return
|
||||
}
|
||||
certificates = append(certificates, c)
|
||||
}
|
||||
err = rows.Err()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetCertificate retrieves a certificate from its serial number.
|
||||
func GetCertificate(serial uint64) (c Certificate, err error) {
|
||||
err = DBQueryRow("SELECT id_cert, creation, password, id_team, revoked FROM certificates WHERE id_cert = ?", serial).Scan(&c.Id, &c.Creation, &c.Password, &c.IdTeam, &c.Revoked)
|
||||
err = DBQueryRow("SELECT id_cert, creation, password, revoked FROM certificates WHERE id_cert = ?", serial).Scan(&c.Id, &c.Creation, &c.Password, &c.Revoked)
|
||||
return
|
||||
}
|
||||
|
||||
@ -87,13 +67,13 @@ func RegisterCertificate(serial uint64, password string) (Certificate, error) {
|
||||
if _, err := DBExec("INSERT INTO certificates (id_cert, creation, password) VALUES (?, ?, ?)", serial, now, password); err != nil {
|
||||
return Certificate{}, err
|
||||
} else {
|
||||
return Certificate{serial, now, password, nil, nil}, nil
|
||||
return Certificate{serial, now, password, nil}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (c Certificate) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE certificates SET creation = ?, password = ?, id_team = ?, revoked = ? WHERE id_cert = ?", c.Creation, c.Password, c.IdTeam, c.Revoked, c.Id); err != nil {
|
||||
if res, err := DBExec("UPDATE certificates SET creation = ?, password = ?, revoked = ? WHERE id_cert = ?", c.Creation, c.Password, c.Revoked, c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
|
@ -91,9 +91,7 @@ CREATE TABLE IF NOT EXISTS certificates(
|
||||
id_cert BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
creation TIMESTAMP NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
id_team INTEGER NULL,
|
||||
revoked TIMESTAMP NULL,
|
||||
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||
revoked TIMESTAMP NULL
|
||||
) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin;
|
||||
`); err != nil {
|
||||
return err
|
||||
|
Loading…
x
Reference in New Issue
Block a user