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)
40 if smslogger.CheckError(err, "CreateSecretDomainHandler") != nil {
41 http.Error(w, err.Error(), http.StatusBadRequest)
45 dom, err := h.secretBackend.CreateSecretDomain(d.Name)
46 if smslogger.CheckError(err, "CreateSecretDomainHandler") != nil {
47 http.Error(w, err.Error(), http.StatusInternalServerError)
51 w.Header().Set("Content-Type", "application/json")
52 w.WriteHeader(http.StatusCreated)
53 err = json.NewEncoder(w).Encode(dom)
54 if smslogger.CheckError(err, "CreateSecretDomainHandler") != nil {
55 http.Error(w, err.Error(), http.StatusInternalServerError)
60 // deleteSecretDomainHandler deletes a secret domain with the name provided
61 func (h handler) deleteSecretDomainHandler(w http.ResponseWriter, r *http.Request) {
63 domName := vars["domName"]
65 err := h.secretBackend.DeleteSecretDomain(domName)
66 if smslogger.CheckError(err, "DeleteSecretDomainHandler") != nil {
67 http.Error(w, err.Error(), http.StatusInternalServerError)
71 w.WriteHeader(http.StatusNoContent)
74 // createSecretHandler handles creation of secrets on a given domain name
75 func (h handler) createSecretHandler(w http.ResponseWriter, r *http.Request) {
76 // Get domain name from URL
78 domName := vars["domName"]
80 // Get secrets to be stored from body
81 var b smsbackend.Secret
82 err := json.NewDecoder(r.Body).Decode(&b)
83 if smslogger.CheckError(err, "CreateSecretHandler") != nil {
84 http.Error(w, err.Error(), http.StatusBadRequest)
88 err = h.secretBackend.CreateSecret(domName, b)
89 if smslogger.CheckError(err, "CreateSecretHandler") != nil {
90 http.Error(w, err.Error(), http.StatusInternalServerError)
94 w.WriteHeader(http.StatusCreated)
97 // getSecretHandler handles reading a secret by given domain name and secret name
98 func (h handler) getSecretHandler(w http.ResponseWriter, r *http.Request) {
100 domName := vars["domName"]
101 secName := vars["secretName"]
103 sec, err := h.secretBackend.GetSecret(domName, secName)
104 if smslogger.CheckError(err, "GetSecretHandler") != nil {
105 http.Error(w, err.Error(), http.StatusInternalServerError)
109 w.Header().Set("Content-Type", "application/json")
110 err = json.NewEncoder(w).Encode(sec)
111 if smslogger.CheckError(err, "GetSecretHandler") != nil {
112 http.Error(w, err.Error(), http.StatusInternalServerError)
117 // listSecretHandler handles listing all secrets under a particular domain name
118 func (h handler) listSecretHandler(w http.ResponseWriter, r *http.Request) {
120 domName := vars["domName"]
122 secList, err := h.secretBackend.ListSecret(domName)
123 if smslogger.CheckError(err, "ListSecretHandler") != nil {
124 http.Error(w, err.Error(), http.StatusInternalServerError)
128 // Creating an anonymous struct to store the returned list of data
129 var retStruct = struct {
130 SecretNames []string `json:"secretnames"`
135 w.Header().Set("Content-Type", "application/json")
136 err = json.NewEncoder(w).Encode(retStruct)
137 if smslogger.CheckError(err, "ListSecretHandler") != nil {
138 http.Error(w, err.Error(), http.StatusInternalServerError)
143 // deleteSecretHandler handles deleting a secret by given domain name and secret name
144 func (h handler) deleteSecretHandler(w http.ResponseWriter, r *http.Request) {
146 domName := vars["domName"]
147 secName := vars["secretName"]
149 err := h.secretBackend.DeleteSecret(domName, secName)
150 if smslogger.CheckError(err, "DeleteSecretHandler") != nil {
151 http.Error(w, err.Error(), http.StatusInternalServerError)
155 w.WriteHeader(http.StatusNoContent)
158 // statusHandler returns information related to SMS and SMS backend services
159 func (h handler) statusHandler(w http.ResponseWriter, r *http.Request) {
160 s, err := h.secretBackend.GetStatus()
161 if smslogger.CheckError(err, "StatusHandler") != nil {
162 http.Error(w, err.Error(), http.StatusInternalServerError)
167 Seal bool `json:"sealstatus"`
172 w.Header().Set("Content-Type", "application/json")
173 err = json.NewEncoder(w).Encode(status)
174 if smslogger.CheckError(err, "StatusHandler") != nil {
175 http.Error(w, err.Error(), http.StatusInternalServerError)
180 // loginHandler handles login via password and username
181 func (h handler) loginHandler(w http.ResponseWriter, r *http.Request) {
185 // unsealHandler is a pass through that sends requests from quorum client
187 func (h handler) unsealHandler(w http.ResponseWriter, r *http.Request) {
188 // Get shards to be used for unseal
189 type unsealStruct struct {
190 UnsealShard string `json:"unsealshard"`
194 decoder := json.NewDecoder(r.Body)
195 decoder.DisallowUnknownFields()
196 err := decoder.Decode(&inp)
197 if smslogger.CheckError(err, "UnsealHandler") != nil {
198 http.Error(w, "Bad input JSON", http.StatusBadRequest)
202 err = h.secretBackend.Unseal(inp.UnsealShard)
203 if smslogger.CheckError(err, "UnsealHandler") != nil {
204 http.Error(w, err.Error(), http.StatusInternalServerError)
209 // registerHandler allows the quorum clients to register with SMS
210 // with their PGP public keys that are then used by sms for backend
212 func (h handler) registerHandler(w http.ResponseWriter, r *http.Request) {
213 // Get shards to be used for unseal
214 type registerStruct struct {
215 PGPKey string `json:"pgpkey"`
216 QuorumID string `json:"quorumid"`
219 var inp registerStruct
220 decoder := json.NewDecoder(r.Body)
221 decoder.DisallowUnknownFields()
222 err := decoder.Decode(&inp)
223 if smslogger.CheckError(err, "RegisterHandler") != nil {
224 http.Error(w, "Bad input JSON", http.StatusBadRequest)
228 sh, err := h.secretBackend.RegisterQuorum(inp.PGPKey)
229 if smslogger.CheckError(err, "RegisterHandler") != nil {
230 http.Error(w, err.Error(), http.StatusInternalServerError)
234 // Creating a struct for return data
236 Shard string `json:"shard"`
241 w.Header().Set("Content-Type", "application/json")
242 err = json.NewEncoder(w).Encode(shStruct)
243 if smslogger.CheckError(err, "RegisterHandler") != nil {
244 http.Error(w, err.Error(), http.StatusInternalServerError)
249 // CreateRouter returns an http.Handler for the registered URLs
250 // Takes an interface implementation as input
251 func CreateRouter(b smsbackend.SecretBackend) http.Handler {
252 h := handler{secretBackend: b}
254 // Create a new mux to handle URL endpoints
255 router := mux.NewRouter()
257 router.HandleFunc("/v1/sms/login", h.loginHandler).Methods("POST")
259 // Initialization APIs which will be used by quorum client
260 // to unseal and to provide root token to sms service
261 router.HandleFunc("/v1/sms/quorum/status", h.statusHandler).Methods("GET")
262 router.HandleFunc("/v1/sms/quorum/unseal", h.unsealHandler).Methods("POST")
263 router.HandleFunc("/v1/sms/quorum/register", h.registerHandler).Methods("POST")
265 router.HandleFunc("/v1/sms/domain", h.createSecretDomainHandler).Methods("POST")
266 router.HandleFunc("/v1/sms/domain/{domName}", h.deleteSecretDomainHandler).Methods("DELETE")
268 router.HandleFunc("/v1/sms/domain/{domName}/secret", h.createSecretHandler).Methods("POST")
269 router.HandleFunc("/v1/sms/domain/{domName}/secret", h.listSecretHandler).Methods("GET")
270 router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.getSecretHandler).Methods("GET")
271 router.HandleFunc("/v1/sms/domain/{domName}/secret/{secretName}", h.deleteSecretHandler).Methods("DELETE")