77581269e52f8b8ae231d0d69ff0bbaed9b3ec58
[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         secList, 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         // Creating an anonymous struct to store the returned list of data
142         var retStruct = struct {
143                 SecretNames []string `json:"secretnames"`
144         }{
145                 secList,
146         }
147
148         jdata, err := json.Marshal(retStruct)
149         if err != nil {
150                 smslogger.WriteError(err.Error())
151                 http.Error(w, err.Error(), http.StatusInternalServerError)
152                 return
153         }
154
155         w.Header().Set("Content-Type", "application/json")
156         w.Write(jdata)
157 }
158
159 // deleteSecretHandler handles deleting a secret by given domain name and secret name
160 func (h handler) deleteSecretHandler(w http.ResponseWriter, r *http.Request) {
161         vars := mux.Vars(r)
162         domName := vars["domName"]
163         secName := vars["secretName"]
164
165         err := h.secretBackend.DeleteSecret(domName, secName)
166         if err != nil {
167                 smslogger.WriteError(err.Error())
168                 http.Error(w, err.Error(), http.StatusInternalServerError)
169                 return
170         }
171
172         w.WriteHeader(http.StatusNoContent)
173 }
174
175 // struct that tracks various status items for SMS and backend
176 type backendStatus struct {
177         Seal bool `json:"sealstatus"`
178 }
179
180 // statusHandler returns information related to SMS and SMS backend services
181 func (h handler) statusHandler(w http.ResponseWriter, r *http.Request) {
182         s, err := h.secretBackend.GetStatus()
183         if err != nil {
184                 smslogger.WriteError(err.Error())
185                 http.Error(w, err.Error(), http.StatusInternalServerError)
186                 return
187         }
188
189         status := backendStatus{Seal: s}
190         jdata, err := json.Marshal(status)
191         if err != nil {
192                 smslogger.WriteError(err.Error())
193                 http.Error(w, err.Error(), http.StatusInternalServerError)
194                 return
195         }
196
197         w.Header().Set("Content-Type", "application/json")
198         w.Write(jdata)
199 }
200
201 // loginHandler handles login via password and username
202 func (h handler) loginHandler(w http.ResponseWriter, r *http.Request) {
203
204 }
205
206 // unsealHandler is a pass through that sends requests from quorum client
207 // to the backend.
208 func (h handler) unsealHandler(w http.ResponseWriter, r *http.Request) {
209         // Get shards to be used for unseal
210         type unsealStruct struct {
211                 UnsealShard string `json:"unsealshard"`
212         }
213
214         var inp unsealStruct
215         decoder := json.NewDecoder(r.Body)
216         decoder.DisallowUnknownFields()
217         err := decoder.Decode(&inp)
218         if err != nil {
219                 smslogger.WriteError(err.Error())
220                 http.Error(w, "Bad input JSON", http.StatusBadRequest)
221                 return
222         }
223
224         err = h.secretBackend.Unseal(inp.UnsealShard)
225         if err != nil {
226                 smslogger.WriteError(err.Error())
227                 http.Error(w, err.Error(), http.StatusInternalServerError)
228                 return
229         }
230 }
231
232 // CreateRouter returns an http.Handler for the registered URLs
233 // Takes an interface implementation as input
234 func CreateRouter(b smsbackend.SecretBackend) http.Handler {
235         h := handler{secretBackend: b}
236
237         // Create a new mux to handle URL endpoints
238         router := mux.NewRouter()
239
240         router.HandleFunc("/v1/sms/login", h.loginHandler).Methods("POST")
241
242         // Initialization APIs which will be used by quorum client
243         // to unseal and to provide root token to sms service
244         router.HandleFunc("/v1/sms/status", h.statusHandler).Methods("GET")
245         router.HandleFunc("/v1/sms/unseal", h.unsealHandler).Methods("POST")
246
247         router.HandleFunc("/v1/sms/domain", h.createSecretDomainHandler).Methods("POST")
248         router.HandleFunc("/v1/sms/domain/{domName}", h.deleteSecretDomainHandler).Methods("DELETE")
249
250         router.HandleFunc("/v1/sms/domain/{domName}/secret", h.createSecretHandler).Methods("POST")
251         router.HandleFunc("/v1/sms/domain/{domName}/secret", h.listSecretHandler).Methods("GET")
252         router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.getSecretHandler).Methods("GET")
253         router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.deleteSecretHandler).Methods("DELETE")
254
255         return router
256 }