...
1 package main
2
3 import (
4 "context"
5 "encoding/json"
6 "flag"
7 "fmt"
8 "io"
9 "net/http"
10 "sync"
11 "time"
12
13 "github.com/letsencrypt/boulder/akamai"
14 "github.com/letsencrypt/boulder/cmd"
15 )
16
17 func main() {
18 listenAddr := flag.String("listen", "localhost:6789", "Address to listen on")
19 secret := flag.String("secret", "", "Akamai client secret")
20 flag.Parse()
21
22 v3Purges := [][]string{}
23 mu := sync.Mutex{}
24
25 http.HandleFunc("/debug/get-purges", func(w http.ResponseWriter, r *http.Request) {
26 mu.Lock()
27 defer mu.Unlock()
28 body, err := json.Marshal(struct {
29 V3 [][]string
30 }{V3: v3Purges})
31 if err != nil {
32 w.WriteHeader(http.StatusInternalServerError)
33 return
34 }
35 w.Write(body)
36 })
37
38 http.HandleFunc("/debug/reset-purges", func(w http.ResponseWriter, r *http.Request) {
39 mu.Lock()
40 defer mu.Unlock()
41 v3Purges = [][]string{}
42 w.WriteHeader(http.StatusOK)
43 })
44
45 http.HandleFunc("/ccu/", func(w http.ResponseWriter, r *http.Request) {
46 if r.Method != http.MethodPost {
47 w.WriteHeader(http.StatusMethodNotAllowed)
48 fmt.Println("Wrong method:", r.Method)
49 return
50 }
51 mu.Lock()
52 defer mu.Unlock()
53 var purgeRequest struct {
54 Objects []string `json:"objects"`
55 }
56 body, err := io.ReadAll(r.Body)
57 if err != nil {
58 w.WriteHeader(http.StatusBadRequest)
59 fmt.Println("Can't read body:", err)
60 return
61 }
62 if err = akamai.CheckSignature(*secret, "http://"+*listenAddr, r, body); err != nil {
63 w.WriteHeader(http.StatusUnauthorized)
64 fmt.Println("Bad signature:", err)
65 return
66 }
67 if err = json.Unmarshal(body, &purgeRequest); err != nil {
68 w.WriteHeader(http.StatusBadRequest)
69 fmt.Println("Can't unmarshal:", err)
70 return
71 }
72 if len(purgeRequest.Objects) == 0 {
73 w.WriteHeader(http.StatusBadRequest)
74 fmt.Println("Bad parameters:", purgeRequest)
75 return
76 }
77 v3Purges = append(v3Purges, purgeRequest.Objects)
78
79 respObj := struct {
80 PurgeID string
81 HTTPStatus int
82 EstimatedSeconds int
83 }{
84 PurgeID: "welcome-to-the-purge",
85 HTTPStatus: http.StatusCreated,
86 EstimatedSeconds: 153,
87 }
88 w.WriteHeader(http.StatusCreated)
89 resp, err := json.Marshal(respObj)
90 if err != nil {
91 return
92 }
93 w.Write(resp)
94 })
95
96 s := http.Server{
97 ReadTimeout: 30 * time.Second,
98 Addr: *listenAddr,
99 }
100
101 go func() {
102 err := s.ListenAndServe()
103 if err != nil && err != http.ErrServerClosed {
104 cmd.FailOnError(err, "Running TLS server")
105 }
106 }()
107
108 defer func() {
109 ctx, cancel := context.WithTimeout(context.Background(), time.Second)
110 defer cancel()
111 _ = s.Shutdown(ctx)
112 }()
113
114 cmd.WaitForSignal()
115 }
116
View as plain text