-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathmain.go
More file actions
134 lines (111 loc) · 5.02 KB
/
main.go
File metadata and controls
134 lines (111 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"time"
"github.com/ClusterLabs/hawk-apiserver/api"
"github.com/ClusterLabs/hawk-apiserver/internal"
"github.com/ClusterLabs/hawk-apiserver/server"
logrus "github.com/sirupsen/logrus"
)
const hawkRubySock = "/usr/share/hawk/tmp/hawk.sock"
type rubyAuthResp struct {
OK bool `json:"ok"`
User string `json:"user"`
}
/*
hawk-apiserver doesn't do auth right now (but will do it in later versions)
instead, it asks the hawk (RoR) if it's authenticated
each time inside /cib/live/primitives/{primitive-id}/edit page.
Thought it's stressfull, but it happens only in one page right now (as of 18.12.2025)
and in future, Go should do all the auth routines. (#TODO)
*/
func authViaRuby(r *http.Request) (ok bool, user string, err error) {
tr := &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
d := net.Dialer{Timeout: 2 * time.Second}
return d.DialContext(ctx, "unix", hawkRubySock)
},
}
client := &http.Client{
Transport: tr,
Timeout: 3 * time.Second,
}
// URL host is dummy; DialContext ignores it and uses the unix socket.
req, err := http.NewRequestWithContext(r.Context(), http.MethodGet, "http://localhost/internal/auth", nil)
if err != nil {
return false, "", err
}
// Forward cookies from the *incoming* browser request to Ruby.
if ck := r.Header.Get("Cookie"); ck != "" {
req.Header.Set("Cookie", ck)
}
resp, err := client.Do(req)
if err != nil {
return false, "", err
}
defer resp.Body.Close()
var out rubyAuthResp
if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
return false, "", err
}
return out.OK, out.User, nil
}
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ok, user, err := authViaRuby(r)
if err != nil {
log.Printf("[auth] ruby auth error: %v", err)
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
if !ok {
log.Printf("[auth] ruby auth: forbidden")
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
// (Optional) log who Ruby thinks it is
_ = user
next.ServeHTTP(w, r)
}
}
// the released version of the binary. Generated via makefile or buildsystem
var version = "was not built correctly"
func main() {
// initialize configuration, which handle the different routes
config := internal.InitConfig(version)
routehandler := internal.NewRouteHandler(&config)
api.Routehandler = routehandler
// binds to pacemaker-go and serve CIB async info
routehandler.Cib.Start()
logrus.Infof("Listening to https://%s:%d\n", config.Listen, config.Port)
mux := http.NewServeMux()
mux.HandleFunc("/api/cib/create-primitive/", authMiddleware(api.CreatePrimitiveHandler))
mux.HandleFunc("/api/cib/update-primitive/", authMiddleware(api.UpdatePrimitiveHandler)) // Can't find where it was used (let's not remove it though)
mux.HandleFunc("/api/cib/rename-primitive/", authMiddleware(api.RenamePrimitiveHandler))
mux.HandleFunc("/api/cib/delete-primitive/", authMiddleware(api.DeletePrimitiveHandler))
mux.HandleFunc("/api/data-interface/fetch-cluster-details", authMiddleware(api.FetchClusterDetails))
mux.HandleFunc("/api/data-interface/fetch-resource-classes", authMiddleware(api.FetchResourceClasses))
mux.HandleFunc("/api/data-interface/fetch-resource-providers", authMiddleware(api.FetchResourceProviders))
mux.HandleFunc("/api/data-interface/fetch-resource-types", authMiddleware(api.FetchResourceTypes))
mux.HandleFunc("/api/data-interface/fetch-resource-params", authMiddleware(api.FetchResourceParams))
mux.HandleFunc("/api/data-interface/submit-resource-params", authMiddleware(api.SubmitResourceParams))
mux.HandleFunc("/api/data-interface/fetch-resource-meta-attributes", authMiddleware(api.FetchResourceMetaAttributes))
mux.HandleFunc("/api/data-interface/submit-resource-meta-attributes", authMiddleware(api.SubmitResourceMetaAttributes))
mux.HandleFunc("/api/data-interface/fetch-resource-operations", authMiddleware(api.FetchResourceOperations))
mux.HandleFunc("/api/data-interface/submit-resource-operations", authMiddleware(api.SubmitResourceOperations))
mux.HandleFunc("/api/data-interface/resource-operation/fetch-attributes", authMiddleware(api.FetchResourceOperationAttributes))
mux.HandleFunc("/api/data-interface/resource-operation/submit-attributes", authMiddleware(api.SubmitResourceOperationAttributes))
// Register BOTH /cib/live/primitives and /cib/live/primitives/ to avoid a conflicts with Ruby
mux.HandleFunc("/cib/live/primitives", authMiddleware(api.ResourceEditHandler))
mux.HandleFunc("/cib/live/primitives/", authMiddleware(api.ResourceEditHandler))
mux.Handle("/", routehandler) // routehandler is a fallback
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
//TODO: this function should return errors
// an https server with a reverse proxy. http is redirected to https
server.ListenAndServeWithRedirect(fmt.Sprintf("%s:%d", config.Listen, config.Port), mux, config.Cert, config.Key)
}