110 lines
2.4 KiB
Go
110 lines
2.4 KiB
Go
package registrar
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/google/uuid"
|
|
svc "go.fixergrid.net/servicedemon/pkg/registrar/internal/services"
|
|
)
|
|
|
|
const (
|
|
REGISTRATION_TOPIC = "net.fixergrid.events.app.admission"
|
|
)
|
|
|
|
var validApprover string = "Nautilus Admins"
|
|
|
|
type Registrar struct {
|
|
svc.Publisher
|
|
repo svc.AppRepo
|
|
log internalLog
|
|
}
|
|
|
|
func WithLogger(l logger) RegistrarOpt {
|
|
return func(r *Registrar) {
|
|
r.log = internalLog{l}
|
|
}
|
|
}
|
|
|
|
type RegistrarOpt func(*Registrar)
|
|
|
|
func NewRegistrar(publisher svc.Publisher, repo svc.AppRepo, options ...RegistrarOpt) Registrar {
|
|
r := Registrar{
|
|
Publisher: publisher,
|
|
repo: repo,
|
|
}
|
|
for _, opt := range options {
|
|
opt(&r)
|
|
}
|
|
return r
|
|
}
|
|
|
|
func (r Registrar) HandleRegistration(resp http.ResponseWriter, req *http.Request) {
|
|
cert := req.TLS.PeerCertificates[0]
|
|
|
|
name := cert.DNSNames[0]
|
|
if r.repo.IsRegistered(name) {
|
|
resp.WriteHeader(http.StatusOK)
|
|
resp.Write([]byte(`{"status": "registered"}`))
|
|
} else {
|
|
id := r.repo.StartAppRegistration(name)
|
|
event := map[string]string{
|
|
"id": id.String(),
|
|
"name": name,
|
|
"type": "ApplicationRegistrationSubmitted",
|
|
}
|
|
|
|
r.sendEvent(REGISTRATION_TOPIC, event)
|
|
|
|
resp.WriteHeader(http.StatusCreated)
|
|
fmt.Fprintf(resp, `{"status": "pending_approval"}`)
|
|
}
|
|
}
|
|
|
|
func (r Registrar) HandleApproval(resp http.ResponseWriter, req *http.Request) {
|
|
headers := resp.Header()
|
|
headers.Set("content-type", "application/json")
|
|
|
|
in := req.URL.Path
|
|
cert := req.TLS.PeerCertificates[0]
|
|
OUs := cert.Subject.OrganizationalUnit
|
|
|
|
var ou string
|
|
if len(OUs) == 1 {
|
|
ou = OUs[0]
|
|
} else {
|
|
fmt.Fprintf(resp, `{"errors": ["missing OU"]}`)
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if ou != validApprover {
|
|
fmt.Fprintf(resp, `{"errors": ["approval forbidden"]}`)
|
|
resp.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
appID := uuid.MustParse(in)
|
|
|
|
event := map[string]string{
|
|
"id": appID.String(),
|
|
"approver": ou,
|
|
"type": "ApplicationRegistrationApproved",
|
|
}
|
|
r.sendEvent(APPROVAL_TOPIC, event)
|
|
resp.WriteHeader(http.StatusOK)
|
|
fmt.Fprintf(resp, `{"status": "registered"}`)
|
|
}
|
|
|
|
func (r Registrar) sendEvent(topic string, event map[string]string) error {
|
|
b, err := json.Marshal(event)
|
|
if err != nil {
|
|
return fmt.Errorf("registrar: sendEvent: failed to marshal: %w", err)
|
|
}
|
|
|
|
r.log.Printf("sending event: %s", event)
|
|
r.Publish(topic, string(b))
|
|
return nil
|
|
}
|