4456806f87209bf4964f9273ca8af97ee2693ea0
[aaf/sms.git] / sms-service / src / sms / handler / handler.go
1 /*
2  * Copyright 2018 Intel Corporation, Inc
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package handler
18
19 import (
20         "encoding/json"
21         "github.com/gorilla/mux"
22         "net/http"
23
24         smsbackend "sms/backend"
25         smslogger "sms/log"
26 )
27
28 // handler stores two interface implementations that implement
29 // the backend functionality
30 type handler struct {
31         secretBackend smsbackend.SecretBackend
32         loginBackend  smsbackend.LoginBackend
33 }
34
35 // createSecretDomainHandler creates a secret domain with a name provided
36 func (h handler) createSecretDomainHandler(w http.ResponseWriter, r *http.Request) {
37         var d smsbackend.SecretDomain
38
39         err := json.NewDecoder(r.Body).Decode(&d)
40         if err != nil {
41                 smslogger.WriteError(err.Error())
42                 http.Error(w, err.Error(), http.StatusBadRequest)
43                 return
44         }
45
46         dom, err := h.secretBackend.CreateSecretDomain(d.Name)
47         if err != nil {
48                 smslogger.WriteError(err.Error())
49                 http.Error(w, err.Error(), http.StatusInternalServerError)
50                 return
51         }
52
53         jdata, err := json.Marshal(dom)
54         if err != nil {
55                 smslogger.WriteError(err.Error())
56                 http.Error(w, err.Error(), http.StatusInternalServerError)
57                 return
58         }
59
60         w.Header().Set("Content-Type", "application/json")
61         w.WriteHeader(http.StatusCreated)
62         w.Write(jdata)
63 }
64
65 // deleteSecretDomainHandler deletes a secret domain with the name provided
66 func (h handler) deleteSecretDomainHandler(w http.ResponseWriter, r *http.Request) {
67         vars := mux.Vars(r)
68         domName := vars["domName"]
69
70         err := h.secretBackend.DeleteSecretDomain(domName)
71         if err != nil {
72                 smslogger.WriteError(err.Error())
73                 http.Error(w, err.Error(), http.StatusInternalServerError)
74                 return
75         }
76
77         w.WriteHeader(http.StatusNoContent)
78 }
79
80 // createSecretHandler handles creation of secrets on a given domain name
81 func (h handler) createSecretHandler(w http.ResponseWriter, r *http.Request) {
82         // Get domain name from URL
83         vars := mux.Vars(r)
84         domName := vars["domName"]
85
86         // Get secrets to be stored from body
87         var b smsbackend.Secret
88         err := json.NewDecoder(r.Body).Decode(&b)
89         if err != nil {
90                 smslogger.WriteError(err.Error())
91                 http.Error(w, err.Error(), http.StatusBadRequest)
92                 return
93         }
94
95         err = h.secretBackend.CreateSecret(domName, b)
96         if err != nil {
97                 smslogger.WriteError(err.Error())
98                 http.Error(w, err.Error(), http.StatusInternalServerError)
99                 return
100         }
101
102         w.WriteHeader(http.StatusCreated)
103 }
104
105 // getSecretHandler handles reading a secret by given domain name and secret name
106 func (h handler) getSecretHandler(w http.ResponseWriter, r *http.Request) {
107         vars := mux.Vars(r)
108         domName := vars["domName"]
109         secName := vars["secretName"]
110
111         sec, err := h.secretBackend.GetSecret(domName, secName)
112         if err != nil {
113                 smslogger.WriteError(err.Error())
114                 http.Error(w, err.Error(), http.StatusInternalServerError)
115                 return
116         }
117
118         jdata, err := json.Marshal(sec)
119         if err != nil {
120                 smslogger.WriteError(err.Error())
121                 http.Error(w, err.Error(), http.StatusInternalServerError)
122                 return
123         }
124
125         w.Header().Set("Content-Type", "application/json")
126         w.Write(jdata)
127 }
128
129 // listSecretHandler handles listing all secrets under a particular domain name
130 func (h handler) listSecretHandler(w http.ResponseWriter, r *http.Request) {
131         vars := mux.Vars(r)
132         domName := vars["domName"]
133
134         sec, err := h.secretBackend.ListSecret(domName)
135         if err != nil {
136                 smslogger.WriteError(err.Error())
137                 http.Error(w, err.Error(), http.StatusInternalServerError)
138                 return
139         }
140
141         jdata, err := json.Marshal(sec)
142         if err != nil {
143                 smslogger.WriteError(err.Error())
144                 http.Error(w, err.Error(), http.StatusInternalServerError)
145                 return
146         }
147
148         w.Header().Set("Content-Type", "application/json")
149         w.Write(jdata)
150 }
151
152 // deleteSecretHandler handles deleting a secret by given domain name and secret name
153 func (h handler) deleteSecretHandler(w http.ResponseWriter, r *http.Request) {
154         vars := mux.Vars(r)
155         domName := vars["domName"]
156         secName := vars["secretName"]
157
158         err := h.secretBackend.DeleteSecret(domName, secName)
159         if err != nil {
160                 smslogger.WriteError(err.Error())
161                 http.Error(w, err.Error(), http.StatusInternalServerError)
162                 return
163         }
164 }
165
166 // struct that tracks various status items for SMS and backend
167 type backendStatus struct {
168         Seal bool `json:"sealstatus"`
169 }
170
171 // statusHandler returns information related to SMS and SMS backend services
172 func (h handler) statusHandler(w http.ResponseWriter, r *http.Request) {
173         s, err := h.secretBackend.GetStatus()
174         if err != nil {
175                 smslogger.WriteError(err.Error())
176                 http.Error(w, err.Error(), http.StatusInternalServerError)
177                 return
178         }
179
180         status := backendStatus{Seal: s}
181         jdata, err := json.Marshal(status)
182         if err != nil {
183                 smslogger.WriteError(err.Error())
184                 http.Error(w, err.Error(), http.StatusInternalServerError)
185                 return
186         }
187
188         w.Header().Set("Content-Type", "application/json")
189         w.Write(jdata)
190 }
191
192 // loginHandler handles login via password and username
193 func (h handler) loginHandler(w http.ResponseWriter, r *http.Request) {
194
195 }
196
197 // unsealHandler is a pass through that sends requests from quorum client
198 // to the backend.
199 func (h handler) unsealHandler(w http.ResponseWriter, r *http.Request) {
200         // Get shards to be used for unseal
201         type unsealStruct struct {
202                 UnsealShard string `json:"unsealshard"`
203         }
204
205         var inp unsealStruct
206         decoder := json.NewDecoder(r.Body)
207         decoder.DisallowUnknownFields()
208         err := decoder.Decode(&inp)
209         if err != nil {
210                 smslogger.WriteError(err.Error())
211                 http.Error(w, "Bad input JSON", http.StatusBadRequest)
212                 return
213         }
214
215         err = h.secretBackend.Unseal(inp.UnsealShard)
216         if err != nil {
217                 smslogger.WriteError(err.Error())
218                 http.Error(w, err.Error(), http.StatusInternalServerError)
219                 return
220         }
221 }
222
223 // CreateRouter returns an http.Handler for the registered URLs
224 // Takes an interface implementation as input
225 func CreateRouter(b smsbackend.SecretBackend) http.Handler {
226         h := handler{secretBackend: b}
227
228         // Create a new mux to handle URL endpoints
229         router := mux.NewRouter()
230
231         router.HandleFunc("/v1/sms/login", h.loginHandler).Methods("POST")
232
233         // Initialization APIs which will be used by quorum client
234         // to unseal and to provide root token to sms service
235         router.HandleFunc("/v1/sms/status", h.statusHandler).Methods("GET")
236         router.HandleFunc("/v1/sms/unseal", h.unsealHandler).Methods("POST")
237
238         router.HandleFunc("/v1/sms/domain", h.createSecretDomainHandler).Methods("POST")
239         router.HandleFunc("/v1/sms/domain/{domName}", h.deleteSecretDomainHandler).Methods("DELETE")
240
241         router.HandleFunc("/v1/sms/domain/{domName}/secret", h.createSecretHandler).Methods("POST")
242         router.HandleFunc("/v1/sms/domain/{domName}/secret", h.listSecretHandler).Methods("GET")
243         router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.getSecretHandler).Methods("GET")
244         router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.deleteSecretHandler).Methods("DELETE")
245
246         return router
247 }