2 * Copyright 2018 Intel Corporation, Inc
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 "github.com/gorilla/mux"
24 smsbackend "sms/backend"
28 // handler stores two interface implementations that implement
29 // the backend functionality
31 secretBackend smsbackend.SecretBackend
32 loginBackend smsbackend.LoginBackend
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
39 err := json.NewDecoder(r.Body).Decode(&d)
41 smslogger.WriteError(err.Error())
42 http.Error(w, err.Error(), http.StatusBadRequest)
46 dom, err := h.secretBackend.CreateSecretDomain(d.Name)
48 smslogger.WriteError(err.Error())
49 http.Error(w, err.Error(), http.StatusInternalServerError)
53 w.Header().Set("Content-Type", "application/json")
54 w.WriteHeader(http.StatusCreated)
55 err = json.NewEncoder(w).Encode(dom)
57 smslogger.WriteError(err.Error())
58 http.Error(w, err.Error(), http.StatusInternalServerError)
63 // deleteSecretDomainHandler deletes a secret domain with the name provided
64 func (h handler) deleteSecretDomainHandler(w http.ResponseWriter, r *http.Request) {
66 domName := vars["domName"]
68 err := h.secretBackend.DeleteSecretDomain(domName)
70 smslogger.WriteError(err.Error())
71 http.Error(w, err.Error(), http.StatusInternalServerError)
75 w.WriteHeader(http.StatusNoContent)
78 // createSecretHandler handles creation of secrets on a given domain name
79 func (h handler) createSecretHandler(w http.ResponseWriter, r *http.Request) {
80 // Get domain name from URL
82 domName := vars["domName"]
84 // Get secrets to be stored from body
85 var b smsbackend.Secret
86 err := json.NewDecoder(r.Body).Decode(&b)
88 smslogger.WriteError(err.Error())
89 http.Error(w, err.Error(), http.StatusBadRequest)
93 err = h.secretBackend.CreateSecret(domName, b)
95 smslogger.WriteError(err.Error())
96 http.Error(w, err.Error(), http.StatusInternalServerError)
100 w.WriteHeader(http.StatusCreated)
103 // getSecretHandler handles reading a secret by given domain name and secret name
104 func (h handler) getSecretHandler(w http.ResponseWriter, r *http.Request) {
106 domName := vars["domName"]
107 secName := vars["secretName"]
109 sec, err := h.secretBackend.GetSecret(domName, secName)
111 smslogger.WriteError(err.Error())
112 http.Error(w, err.Error(), http.StatusInternalServerError)
116 w.Header().Set("Content-Type", "application/json")
117 err = json.NewEncoder(w).Encode(sec)
119 smslogger.WriteError(err.Error())
120 http.Error(w, err.Error(), http.StatusInternalServerError)
125 // listSecretHandler handles listing all secrets under a particular domain name
126 func (h handler) listSecretHandler(w http.ResponseWriter, r *http.Request) {
128 domName := vars["domName"]
130 secList, err := h.secretBackend.ListSecret(domName)
132 smslogger.WriteError(err.Error())
133 http.Error(w, err.Error(), http.StatusInternalServerError)
137 // Creating an anonymous struct to store the returned list of data
138 var retStruct = struct {
139 SecretNames []string `json:"secretnames"`
144 w.Header().Set("Content-Type", "application/json")
145 err = json.NewEncoder(w).Encode(retStruct)
147 smslogger.WriteError(err.Error())
148 http.Error(w, err.Error(), http.StatusInternalServerError)
153 // deleteSecretHandler handles deleting a secret by given domain name and secret name
154 func (h handler) deleteSecretHandler(w http.ResponseWriter, r *http.Request) {
156 domName := vars["domName"]
157 secName := vars["secretName"]
159 err := h.secretBackend.DeleteSecret(domName, secName)
161 smslogger.WriteError(err.Error())
162 http.Error(w, err.Error(), http.StatusInternalServerError)
166 w.WriteHeader(http.StatusNoContent)
169 // statusHandler returns information related to SMS and SMS backend services
170 func (h handler) statusHandler(w http.ResponseWriter, r *http.Request) {
171 s, err := h.secretBackend.GetStatus()
173 smslogger.WriteError(err.Error())
174 http.Error(w, err.Error(), http.StatusInternalServerError)
179 Seal bool `json:"sealstatus"`
184 w.Header().Set("Content-Type", "application/json")
185 err = json.NewEncoder(w).Encode(status)
187 smslogger.WriteError(err.Error())
188 http.Error(w, err.Error(), http.StatusInternalServerError)
193 // loginHandler handles login via password and username
194 func (h handler) loginHandler(w http.ResponseWriter, r *http.Request) {
198 // unsealHandler is a pass through that sends requests from quorum client
200 func (h handler) unsealHandler(w http.ResponseWriter, r *http.Request) {
201 // Get shards to be used for unseal
202 type unsealStruct struct {
203 UnsealShard string `json:"unsealshard"`
207 decoder := json.NewDecoder(r.Body)
208 decoder.DisallowUnknownFields()
209 err := decoder.Decode(&inp)
211 smslogger.WriteError(err.Error())
212 http.Error(w, "Bad input JSON", http.StatusBadRequest)
216 err = h.secretBackend.Unseal(inp.UnsealShard)
218 smslogger.WriteError(err.Error())
219 http.Error(w, err.Error(), http.StatusInternalServerError)
224 // registerHandler allows the quorum clients to register with SMS
225 // with their PGP public keys that are then used by sms for backend
227 func (h handler) registerHandler(w http.ResponseWriter, r *http.Request) {
228 // Get shards to be used for unseal
229 type registerStruct struct {
230 PGPKey string `json:"pgpkey"`
231 QuorumID string `json:"quorumid"`
234 smslogger.WriteInfo("Entering registerHandler")
236 var inp registerStruct
237 decoder := json.NewDecoder(r.Body)
238 decoder.DisallowUnknownFields()
239 err := decoder.Decode(&inp)
241 smslogger.WriteError(err.Error())
242 http.Error(w, "Bad input JSON", http.StatusBadRequest)
246 sh, err := h.secretBackend.RegisterQuorum(inp.PGPKey)
248 smslogger.WriteError(err.Error())
249 http.Error(w, err.Error(), http.StatusInternalServerError)
253 // Creating a struct for return data
255 Shard string `json:"shard"`
260 w.Header().Set("Content-Type", "application/json")
261 err = json.NewEncoder(w).Encode(shStruct)
263 smslogger.WriteError("Unable to encode response: " + err.Error())
264 http.Error(w, err.Error(), http.StatusInternalServerError)
269 // CreateRouter returns an http.Handler for the registered URLs
270 // Takes an interface implementation as input
271 func CreateRouter(b smsbackend.SecretBackend) http.Handler {
272 h := handler{secretBackend: b}
274 // Create a new mux to handle URL endpoints
275 router := mux.NewRouter()
277 router.HandleFunc("/v1/sms/login", h.loginHandler).Methods("POST")
279 // Initialization APIs which will be used by quorum client
280 // to unseal and to provide root token to sms service
281 router.HandleFunc("/v1/sms/quorum/status", h.statusHandler).Methods("GET")
282 router.HandleFunc("/v1/sms/quorum/unseal", h.unsealHandler).Methods("POST")
283 router.HandleFunc("/v1/sms/quorum/register", h.registerHandler).Methods("POST")
285 router.HandleFunc("/v1/sms/domain", h.createSecretDomainHandler).Methods("POST")
286 router.HandleFunc("/v1/sms/domain/{domName}", h.deleteSecretDomainHandler).Methods("DELETE")
288 router.HandleFunc("/v1/sms/domain/{domName}/secret", h.createSecretHandler).Methods("POST")
289 router.HandleFunc("/v1/sms/domain/{domName}/secret", h.listSecretHandler).Methods("GET")
290 router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.getSecretHandler).Methods("GET")
291 router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.deleteSecretHandler).Methods("DELETE")