-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandlers.go
109 lines (99 loc) · 3.05 KB
/
handlers.go
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
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/gomodule/redigo/redis"
"github.com/google/uuid"
"github.com/gorilla/mux"
)
const OtsPrefix string = "ots:"
type SecretsPayload struct {
Message string `json:"message,omitempty"`
Password string `json:"password"`
}
// pingRedis verifies a successful connection with redis
func pingRedis(c redis.Conn) error {
_, err := redis.String(c.Do("PING"))
return err
}
// Ready handles the GET /ready API that returns the state of the
// service based on the connectivity with the REDIS database
func Ready(w http.ResponseWriter, r *http.Request) {
log.Printf("Received a request from %+v to check the readiness of the API server...", r.Host)
conn := pool.Get()
defer conn.Close()
if err := pingRedis(conn); err != nil {
w.WriteHeader(http.StatusBadGateway)
fmt.Fprint(w, `{"isReady": false}`)
} else {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, `{"isReady": true}`)
}
}
// CreateSecret handles the POST /secrets API that creates a new
// one-time secret and returns the secret UUID
func CreateSecret(w http.ResponseWriter, r *http.Request) {
log.Printf("Received a request from %+v to create a new secret...", r.Host)
secretID, err := uuid.NewRandom()
if err != nil {
log.Fatal(err)
}
decoder := json.NewDecoder(r.Body)
var payload SecretsPayload
err = decoder.Decode(&payload)
if err != nil {
log.Fatal(err)
}
conn := pool.Get()
defer conn.Close()
ciphertext := encrypt(payload.Message, payload.Password)
_, err = conn.Do("SET", OtsPrefix+secretID.String(), ciphertext)
if err != nil {
log.Fatal(err)
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, `{"uuid": `+secretID.String()+`}`)
}
// ReadSecret handles the GET /secrets/{secretId} API handler. It accepts
// the secret ID and the password associated with it and returns the secret
func ReadSecret(w http.ResponseWriter, r *http.Request) {
log.Printf("Received a request from %+v to read a secret...", r.Host)
params := mux.Vars(r)
secretID := params["secretID"]
decoder := json.NewDecoder(r.Body)
var payload SecretsPayload
err := decoder.Decode(&payload)
if err != nil {
log.Fatal(err)
}
conn := pool.Get()
defer conn.Close()
reply, err := conn.Do("GET", OtsPrefix+secretID)
if err != nil || reply == nil {
w.WriteHeader(http.StatusInternalServerError)
errMsg := `{"error": "Could not fetch the secret ` + secretID + `"}`
fmt.Fprint(w, errMsg)
log.Println(errMsg)
return
}
plaintext, err := decrypt(string(reply.([]byte)), payload.Password)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
errMsg := `{"error": "Could not fetch the secret ` + secretID + `"}`
fmt.Fprint(w, errMsg)
log.Printf("SecretID: %s. Error: %+v", secretID, err)
return
}
_, err = conn.Do("DEL", OtsPrefix+secretID)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
errMsg := `{"error": "Could not fetch the secret ` + secretID + `"}`
fmt.Fprint(w, errMsg)
log.Printf("SecretID: %s. Error: %+v", secretID, err)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, `{"message": "`+plaintext+`"}`)
}