aboutsummaryrefslogtreecommitdiff
path: root/pkg/server
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus@rgdd.se>2023-12-31 09:39:25 +0100
committerRasmus Dahlberg <rasmus@rgdd.se>2024-01-07 20:22:23 +0100
commite18d36ebae30536c77c61cd5da123991e0ca1629 (patch)
treebf4880c0019a6009ab1b671e23ef4a1a4a5e8e08 /pkg/server
parent54d980afcbd6f0011d6a162e0003587d26a3e311 (diff)
Add drafty prototype
Diffstat (limited to 'pkg/server')
-rw-r--r--pkg/server/handler.go32
-rw-r--r--pkg/server/messages.go23
-rw-r--r--pkg/server/nodes.go53
-rw-r--r--pkg/server/server.go133
4 files changed, 0 insertions, 241 deletions
diff --git a/pkg/server/handler.go b/pkg/server/handler.go
deleted file mode 100644
index 6d17af7..0000000
--- a/pkg/server/handler.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package server
-
-import (
- "fmt"
- "net/http"
-)
-
-// handler implements the http.Handler interface
-type handler struct {
- method string
- endpoint string
- callback func(w http.ResponseWriter, r *http.Request) (int, string)
-}
-
-func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
- w.Header().Set("Cache-Control", "no-cache")
- if r.Method != h.method {
- http.Error(w, "Invalid HTTP method, expected "+h.method, http.StatusMethodNotAllowed)
- return
- }
- code, text := h.callback(w, r)
- if code != http.StatusOK {
- http.Error(w, text, code)
- return
- }
- fmt.Fprintf(w, fmt.Sprintf("%s\n", text))
-}
-
-func (h handler) register(mux *http.ServeMux) {
- mux.Handle("/"+h.endpoint, h)
-}
diff --git a/pkg/server/messages.go b/pkg/server/messages.go
deleted file mode 100644
index a6ea243..0000000
--- a/pkg/server/messages.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package server
-
-import (
- "fmt"
- "time"
-)
-
-type MessageNodeSubmission struct {
- SerialNumber string
- NotBefore time.Time
- DomainNames []string
- PEMChain []byte
-}
-
-type ErrorUnauthorizedDomainName struct {
- PEMChain []byte
- Node Node
- Err error
-}
-
-func (e ErrorUnauthorizedDomainName) Error() string {
- return fmt.Sprintf("%v", e.Err)
-}
diff --git a/pkg/server/nodes.go b/pkg/server/nodes.go
deleted file mode 100644
index 164c06f..0000000
--- a/pkg/server/nodes.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package server
-
-import (
- "crypto/x509"
- "fmt"
- "net/http"
-)
-
-// Node is an identified system that can request certificates
-type Node struct {
- Name string `json:"name"` // Artbirary node name for authentication
- Secret string `json:"secret"` // Arbitrary node secret for authentication
- Domains []string `json:"issues"` // Exact-match domain names that are allowed
-}
-
-func (node *Node) authenticate(r *http.Request) error {
- user, password, ok := r.BasicAuth()
- if !ok {
- return fmt.Errorf("no http basic auth credentials")
- }
- if user != node.Name || password != node.Secret {
- return fmt.Errorf("invalid http basic auth credentials")
- }
- return nil
-}
-
-func (node *Node) check(crt x509.Certificate) error {
- for _, san := range crt.DNSNames {
- ok := false
- for _, domain := range node.Domains {
- if domain == san {
- ok = true
- break
- }
- }
- if !ok {
- return fmt.Errorf("%s: not authorized to issue certificates for %s", node.Name, san)
- }
- }
- return nil
-}
-
-// Nodes is a list of nodes that can request certificates
-type Nodes []Node
-
-func (nodes *Nodes) authenticate(r *http.Request) (Node, error) {
- for _, node := range (*nodes)[:] {
- if err := node.authenticate(r); err == nil {
- return node, nil
- }
- }
- return Node{}, fmt.Errorf("no valid HTTP basic auth credentials")
-}
diff --git a/pkg/server/server.go b/pkg/server/server.go
deleted file mode 100644
index 06eb258..0000000
--- a/pkg/server/server.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package server
-
-import (
- "context"
- "fmt"
- "io"
- "net"
- "net/http"
- "time"
-
- "rgdd.se/silent-ct/internal/x509util"
-)
-
-const (
- EndpointAddChain = "add-chain"
- EndpointGetStatus = "get-status"
-
- DefaultNetwork = "tcp"
- DefaultAddress = "localhost:2009"
- DefaultConfigFile = "/home/rgdd/.config/silent-ct/config.json" // FIXME
-)
-
-type Config struct {
- Network string // tcp or unix
- Address string // hostname[:port] or path to a unix socket
- Nodes Nodes // Which nodes are trusted to issue what certificates
-}
-
-type Server struct {
- Config
-
- eventCh chan MessageNodeSubmission
- errorCh chan error
-}
-
-func New(cfg Config) (Server, error) {
- if cfg.Network == "" {
- cfg.Network = DefaultNetwork
- }
- if cfg.Address == "" {
- cfg.Network = DefaultAddress
- }
- return Server{Config: cfg}, nil
-}
-
-func (srv *Server) Run(ctx context.Context, submitCh chan MessageNodeSubmission, errorCh chan error) error {
- srv.eventCh = submitCh
- srv.errorCh = errorCh
- mux := http.NewServeMux()
- for _, handler := range srv.handlers() {
- handler.register(mux)
- }
-
- listener, err := net.Listen(srv.Network, srv.Address)
- if err != nil {
- return fmt.Errorf("listen: %v", err)
- }
- defer listener.Close()
-
- s := http.Server{Handler: mux}
- exitCh := make(chan error, 1)
- defer close(exitCh)
- go func() {
- exitCh <- s.Serve(listener)
- }()
-
- select {
- case err := <-exitCh:
- if err != nil && err != http.ErrServerClosed {
- return fmt.Errorf("serve: %v", err)
- }
- case <-ctx.Done():
- tctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
- defer cancel()
- if err := s.Shutdown(tctx); err != nil {
- return fmt.Errorf("shutdown: %v", err)
- }
- }
- return nil
-}
-
-func (srv *Server) handlers() []handler {
- return []handler{
- handler{
- method: http.MethodGet,
- endpoint: EndpointGetStatus,
- callback: func(w http.ResponseWriter, r *http.Request) (int, string) { return srv.getStatus(w, r) },
- },
- handler{
- method: http.MethodPost,
- endpoint: EndpointAddChain,
- callback: func(w http.ResponseWriter, r *http.Request) (int, string) { return srv.addChain(w, r) },
- },
- }
-}
-
-func (srv *Server) getStatus(w http.ResponseWriter, r *http.Request) (int, string) {
- return http.StatusOK, "OK"
-}
-
-func (srv *Server) addChain(w http.ResponseWriter, r *http.Request) (int, string) {
- node, err := srv.Nodes.authenticate(r)
- if err != nil {
- return http.StatusForbidden, "Invalid HTTP Basic Auth credentials"
- }
-
- b, err := io.ReadAll(r.Body)
- if err != nil {
- return http.StatusBadRequest, "Read HTTP POST body failed"
- }
- defer r.Body.Close()
-
- chain, err := x509util.ParseChain(b)
- if err != nil {
- return http.StatusBadRequest, "Malformed HTTP POST body"
- }
- if err := node.check(chain[0]); err != nil {
- srv.errorCh <- ErrorUnauthorizedDomainName{
- PEMChain: b,
- Node: node,
- Err: err,
- }
- } else {
- srv.eventCh <- MessageNodeSubmission{
- SerialNumber: chain[0].SerialNumber.String(),
- NotBefore: chain[0].NotBefore,
- DomainNames: chain[0].DNSNames,
- PEMChain: b,
- }
- }
-
- return http.StatusOK, "OK"
-}