This repository has been archived on 2024-03-03. You can view files and clone it, but cannot push or open issues or pull requests.
adlin/token-validator/domain.go

312 lines
9.7 KiB
Go
Raw Normal View History

2019-03-13 23:05:45 +00:00
package main
import (
"encoding/json"
2019-03-14 07:51:40 +00:00
"errors"
"fmt"
"log"
"os"
"os/exec"
"strconv"
"strings"
2019-03-13 23:05:45 +00:00
"github.com/julienschmidt/httprouter"
)
const (
AssociatedDomainSuffix = "adlin2020.p0m.fr"
DelegatedDomainSuffix = "srs.p0m.fr"
)
2019-03-13 23:05:45 +00:00
func init() {
2019-03-14 07:51:40 +00:00
router.GET("/api/adomains/", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.GetAssociatedDomains(), nil
}))
router.POST("/api/adomains/", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return true, student.AddAssociatedDomains()
}))
router.GET("/api/adomains/:dn", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.GetAssociatedDomain(ps.ByName("dn"))
}))
2019-03-13 23:05:45 +00:00
router.GET("/api/ddomains/", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return []string{student.MyDelegatedDomain()}, nil
}))
router.GET("/api/ddomains/:dn/", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.getRRDelegatedDomain(ps.ByName("dn"), "")
}))
router.GET("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.getRRDelegatedDomain(ps.ByName("dn"), "NS")
}))
router.POST("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry
if err := json.Unmarshal(body, &ue); err != nil {
return nil, err
}
return true, student.UpdateNSDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values[0])
}))
router.DELETE("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "NS")
}))
router.GET("/api/ddomains/:dn/GLUE", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.getRRDelegatedDomain(ps.ByName("dn"), "AAAA")
}))
router.POST("/api/ddomains/:dn/AAAA", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry
if err := json.Unmarshal(body, &ue); err != nil {
return nil, err
}
return true, student.UpdateGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values[0])
}))
router.POST("/api/ddomains/:dn/GLUE", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry
if err := json.Unmarshal(body, &ue); err != nil {
return nil, err
}
return true, student.UpdateGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values[0])
}))
router.DELETE("/api/ddomains/:dn/AAAA", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "AAAA")
}))
router.GET("/api/ddomains/:dn/DS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.getRRDelegatedDomain(ps.ByName("dn"), "DS")
2019-03-13 23:05:45 +00:00
}))
router.POST("/api/ddomains/:dn/DS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry
if err := json.Unmarshal(body, &ue); err != nil {
return nil, err
}
return true, student.UpdateDSDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values)
}))
router.DELETE("/api/ddomains/:dn/DS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "DS")
2019-03-13 23:05:45 +00:00
}))
}
2019-03-14 07:51:40 +00:00
type Entry struct {
Domain string `json:"domain"`
TTL uint64 `json:"ttl"`
RR string `json:"rr"`
Values []string `json:"values"`
}
func runKnotc(args ...string) (out []byte, err error) {
cmd := exec.Command("knotc", args...)
cmd.Env = append(os.Environ(),
"LD_PRELOAD=/usr/lib/gcc/armv5tel-softfloat-linux-gnueabi/8.2.0/libgcc_s.so.1",
)
return cmd.CombinedOutput()
}
func parseKnotZoneRead(args ...string) (rr []Entry, err error) {
var out []byte
args = append([]string{"zone-read"}, args...)
out, err = runKnotc(args...)
for _, line := range strings.Split(string(out), "\n") {
cols := strings.Fields(line)
if len(cols) >= 5 {
var ttl uint64
ttl, err = strconv.ParseUint(cols[2], 10, 64)
if err != nil {
return
}
rr = append(rr, Entry{cols[1], ttl, cols[3], cols[4:]})
}
}
return
}
func (student Student) myAssociatedDomain() (string) {
2019-03-15 12:03:21 +00:00
return fmt.Sprintf("%s.%s.", strings.Replace(student.Login, "_", "-", -1), AssociatedDomainSuffix)
2019-03-14 07:51:40 +00:00
}
func (student Student) GetAssociatedDomains() (ds []string) {
studentDomain := student.myAssociatedDomain()
if _, err := parseKnotZoneRead(AssociatedDomainSuffix, studentDomain); err == nil {
2019-03-14 07:51:40 +00:00
ds = append(ds, studentDomain)
}
return
}
func (student Student) GetAssociatedDomain(dn string) (rrs []Entry, err error) {
domains := student.GetAssociatedDomains()
found := false
for _, d := range domains {
if d == dn {
found = true
}
}
if !found {
err = errors.New(fmt.Sprintf("Unable to find domain %q.", dn))
}
rrs, err = parseKnotZoneRead(AssociatedDomainSuffix, dn)
2019-03-14 07:51:40 +00:00
return
}
func (student Student) AddAssociatedDomains() (err error) {
for _, d := range []string{student.myAssociatedDomain()} {
for _, cmd := range [][]string{
[]string{"zone-begin", AssociatedDomainSuffix},
[]string{"zone-set", AssociatedDomainSuffix, d, "900", "A", "82.64.31.248"},
[]string{"zone-set", AssociatedDomainSuffix, d, "900", "AAAA", studentIP(student.Id) + "1"},
[]string{"zone-commit", AssociatedDomainSuffix},
2019-03-14 07:51:40 +00:00
} {
var out []byte
out, err = runKnotc(cmd...)
if err != nil {
err = errors.New(fmt.Sprintf("An error occurs on command '%s': %s", strings.Join(cmd, " "), err.Error()))
log.Println(string(out))
runKnotc("zone-abort", AssociatedDomainSuffix)
2019-03-14 07:51:40 +00:00
return
}
}
}
return
}
func (student Student) MyDelegatedDomain() (string) {
2019-03-15 12:03:21 +00:00
return fmt.Sprintf("%s.%s.", strings.Replace(student.Login, "_", "-", -1), DelegatedDomainSuffix)
}
2019-03-13 23:05:45 +00:00
func (student Student) getRRDelegatedDomain(dn string, rr string) (rrs []Entry, err error) {
domains := []string{student.MyDelegatedDomain()}
found := false
for _, d := range domains {
if d == dn {
found = true
}
}
if !found {
err = errors.New(fmt.Sprintf("Unable to find domain %q.", dn))
}
rrs, err = parseKnotZoneRead(DelegatedDomainSuffix, dn, rr)
return
2019-03-13 23:05:45 +00:00
}
func (student Student) UpdateNSDelegatedDomain(dn string, ttl uint64, ns string) (err error) {
for _, d := range []string{student.MyDelegatedDomain()} {
for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix},
[]string{"zone-unset", DelegatedDomainSuffix, d, "NS"},
[]string{"zone-set", DelegatedDomainSuffix, d, fmt.Sprintf("%d", ttl), "NS", ns},
[]string{"zone-commit", DelegatedDomainSuffix},
} {
var out []byte
out, err = runKnotc(cmd...)
if err != nil && cmd[0] != "zone-unset" {
err = errors.New(fmt.Sprintf("An error occurs on command '%s': %s", strings.Join(cmd, " "), err.Error()))
log.Println(string(out))
runKnotc("zone-abort", DelegatedDomainSuffix)
return
}
}
}
2019-03-13 23:05:45 +00:00
return
}
func (student Student) UpdateGLUEDelegatedDomain(dn string, ttl uint64, aaaa string) (err error) {
domains := []string{student.MyDelegatedDomain()}
found := false
for _, d := range domains {
if strings.HasSuffix(dn, d) {
found = true
}
}
if !found {
err = errors.New(fmt.Sprintf("Unable to find domain %q in your whitelist.", dn))
return
}
for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix},
[]string{"zone-unset", DelegatedDomainSuffix, student.MyDelegatedDomain(), "AAAA"},
[]string{"zone-unset", DelegatedDomainSuffix, dn, "AAAA"},
[]string{"zone-set", DelegatedDomainSuffix, dn, fmt.Sprintf("%d", ttl), "AAAA", aaaa},
[]string{"zone-commit", DelegatedDomainSuffix},
} {
var out []byte
out, err = runKnotc(cmd...)
if err != nil && cmd[0] != "zone-unset" {
err = errors.New(fmt.Sprintf("An error occurs on command '%s': %s", strings.Join(cmd, " "), err.Error()))
log.Println(string(out))
runKnotc("zone-abort", DelegatedDomainSuffix)
return
}
}
return
}
func (student Student) UpdateDSDelegatedDomain(dn string, ttl uint64, ds []string) (err error) {
for _, d := range []string{student.MyDelegatedDomain()} {
for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix},
[]string{"zone-unset", DelegatedDomainSuffix, d, "DS"},
[]string{"zone-set", DelegatedDomainSuffix, d, fmt.Sprintf("%d", ttl), "DS", strings.Join(ds, " ")},
[]string{"zone-commit", DelegatedDomainSuffix},
} {
var out []byte
out, err = runKnotc(cmd...)
if err != nil && cmd[0] != "zone-unset" {
err = errors.New(fmt.Sprintf("An error occurs on command '%s': %s", strings.Join(cmd, " "), err.Error()))
log.Println(string(out))
runKnotc("zone-abort", DelegatedDomainSuffix)
return
}
}
}
return
}
func (student Student) DeleteRRDelegatedDomain(dn string, rr string) (err error) {
domains := []string{student.MyDelegatedDomain()}
found := false
for _, d := range domains {
if strings.HasSuffix(dn, d) {
found = true
}
}
if !found {
err = errors.New(fmt.Sprintf("Unable to find domain %q in your whitelist.", dn))
return
}
for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix},
[]string{"zone-unset", DelegatedDomainSuffix, dn, rr},
[]string{"zone-commit", DelegatedDomainSuffix},
} {
var out []byte
out, err = runKnotc(cmd...)
if err != nil {
err = errors.New(fmt.Sprintf("An error occurs on command '%s': %s", strings.Join(cmd, " "), err.Error()))
log.Println(string(out))
runKnotc("zone-abort", DelegatedDomainSuffix)
return
}
}
2019-03-13 23:05:45 +00:00
return
}