diff options
-rw-r--r-- | LICENSE.txt | 18 | ||||
-rw-r--r-- | sms-service/doc/api_swagger.yaml (renamed from sms-service/doc/swagger.yaml) | 0 | ||||
-rw-r--r-- | sms-service/src/sms/backend/backend.go | 50 | ||||
-rw-r--r-- | sms-service/src/sms/backend/vault.go | 95 | ||||
-rw-r--r-- | sms-service/src/sms/backend/vault/vault.go | 56 | ||||
-rw-r--r-- | sms-service/src/sms/config/config.go | 9 | ||||
-rw-r--r-- | sms-service/src/sms/handler/handler.go | 105 | ||||
-rw-r--r-- | sms-service/src/sms/sms.go | 13 |
8 files changed, 233 insertions, 113 deletions
diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..5f63bb7 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,18 @@ + + ============LICENSE_START========================================== + =================================================================== + Copyright © 2018 Intel Corp, Inc + All rights reserved. + =================================================================== + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END============================================ diff --git a/sms-service/doc/swagger.yaml b/sms-service/doc/api_swagger.yaml index c1fb634..c1fb634 100644 --- a/sms-service/doc/swagger.yaml +++ b/sms-service/doc/api_swagger.yaml diff --git a/sms-service/src/sms/backend/backend.go b/sms-service/src/sms/backend/backend.go index ceb28a4..5611f37 100644 --- a/sms-service/src/sms/backend/backend.go +++ b/sms-service/src/sms/backend/backend.go @@ -16,30 +16,50 @@ package backend -import ( - vaultwrap "sms/backend/vault" -) - -// SecretDomain struct that will be passed around between http handler -// and code that interfaces with vault +// SecretDomain is where Secrets are stored. +// A single domain can have any number of secrets type SecretDomain struct { - ID int - Name string - MountPoint string + UUID string `json:"uuid"` + Name string `json:"name"` +} + +// SecretKeyValue is building block for a Secret +type SecretKeyValue struct { + Key string `json:"name"` + Value string `json:"value"` +} + +// Secret is the struct that defines the structure of a secret +// A single Secret can have any number of SecretKeyValue pairs +type Secret struct { + Name string `json:"name"` + Values []SecretKeyValue `json:"values"` } // SecretBackend interface that will be implemented for various secret backends type SecretBackend interface { - Init() + Init() error + + GetStatus() (bool, error) + GetSecretDomain(name string) (SecretDomain, error) + GetSecret(dom string, sec string) (Secret, error) - GetStatus() bool + CreateSecretDomain(name string) (SecretDomain, error) + CreateSecret(dom string, sec Secret) (Secret, error) + + DeleteSecretDomain(name string) error + DeleteSecret(dom string, name string) error } // InitSecretBackend returns an interface implementation -func InitSecretBackend() SecretBackend { - backendImpl := &vaultwrap.Vault{} - backendImpl.Init() - return backendImpl +func InitSecretBackend() (SecretBackend, error) { + backendImpl := &Vault{} + err := backendImpl.Init() + if err != nil { + return nil, err + } + + return backendImpl, nil } // LoginBackend Interface that will be implemented for various login backends diff --git a/sms-service/src/sms/backend/vault.go b/sms-service/src/sms/backend/vault.go new file mode 100644 index 0000000..f3e2ac1 --- /dev/null +++ b/sms-service/src/sms/backend/vault.go @@ -0,0 +1,95 @@ +/* + * Copyright 2018 Intel Corporation, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package backend + +import ( + vaultapi "github.com/hashicorp/vault/api" + + smsconfig "sms/config" +) + +// Vault is the main Struct used in Backend to initialize the struct +type Vault struct { + vaultClient *vaultapi.Client +} + +// Init will initialize the vault connection +// TODO: Check to see if we need to wait for vault to be running +func (v *Vault) Init() error { + vaultCFG := vaultapi.DefaultConfig() + vaultCFG.Address = smsconfig.SMSConfig.VaultAddress + + client, err := vaultapi.NewClient(vaultCFG) + if err != nil { + return err + } + + v.vaultClient = client + return nil +} + +// GetStatus returns the current seal status of vault +func (v *Vault) GetStatus() (bool, error) { + sys := v.vaultClient.Sys() + sealStatus, err := sys.SealStatus() + if err != nil { + return false, err + } + + return sealStatus.Sealed, nil +} + +// GetSecretDomain returns any information related to the secretDomain +// More information can be added in the future with updates to the struct +func (v *Vault) GetSecretDomain(name string) (SecretDomain, error) { + + return SecretDomain{}, nil +} + +// GetSecret returns a secret mounted on a particular domain name +// The secret itself is referenced via its name which translates to +// a mount path in vault +func (v *Vault) GetSecret(dom string, sec string) (Secret, error) { + + return Secret{}, nil +} + +// CreateSecretDomain mounts the kv backend on a path with the given name +func (v *Vault) CreateSecretDomain(name string) (SecretDomain, error) { + + return SecretDomain{}, nil +} + +// CreateSecret creates a secret mounted on a particular domain name +// The secret itself is mounted on a path specified by name +func (v *Vault) CreateSecret(dom string, sec Secret) (Secret, error) { + + return Secret{}, nil +} + +// DeleteSecretDomain deletes a secret domain which translates to +// an unmount operation on the given path in Vault +func (v *Vault) DeleteSecretDomain(name string) error { + + return nil +} + +// DeleteSecret deletes a secret mounted on the path provided +func (v *Vault) DeleteSecret(dom string, name string) error { + + return nil +} diff --git a/sms-service/src/sms/backend/vault/vault.go b/sms-service/src/sms/backend/vault/vault.go deleted file mode 100644 index 37cb19a..0000000 --- a/sms-service/src/sms/backend/vault/vault.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2018 Intel Corporation, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package vault - -import ( - "fmt" - "log" - - vaultapi "github.com/hashicorp/vault/api" - smsConfig "sms/config" -) - -// Vault is the main Struct used in Backend to initialize the struct -type Vault struct { - vaultClient *vaultapi.Client -} - -// Init will initialize the vault connection -// TODO: Check to see if we need to wait for vault to be running -func (v *Vault) Init() { - vaultCFG := vaultapi.DefaultConfig() - vaultCFG.Address = smsConfig.SMSConfig.VaultAddress - - client, err := vaultapi.NewClient(vaultCFG) - if err != nil { - log.Fatal(err) - } - - v.vaultClient = client -} - -// GetStatus returns the current seal status of vault -func (v *Vault) GetStatus() bool { - sys := v.vaultClient.Sys() - fmt.Println(v.vaultClient.Address()) - sealStatus, err := sys.SealStatus() - if err != nil { - log.Fatal(err) - } - - return sealStatus.Sealed -} diff --git a/sms-service/src/sms/config/config.go b/sms-service/src/sms/config/config.go index d958e15..e1c1b86 100644 --- a/sms-service/src/sms/config/config.go +++ b/sms-service/src/sms/config/config.go @@ -18,7 +18,6 @@ package config import ( "encoding/json" - "log" "os" ) @@ -34,19 +33,19 @@ type SMSConfiguration struct { var SMSConfig *SMSConfiguration // ReadConfigFile reads the specified smsConfig file to setup some env variables -func ReadConfigFile(file string) *SMSConfiguration { +func ReadConfigFile(file string) (*SMSConfiguration, error) { if SMSConfig == nil { f, err := os.Open(file) if err != nil { - log.Fatalf("Unable to find file %s", file) + return nil, err } decoder := json.NewDecoder(f) err = decoder.Decode(&SMSConfig) if err != nil { - log.Fatal(err) + return nil, err } } - return SMSConfig + return SMSConfig, nil } diff --git a/sms-service/src/sms/handler/handler.go b/sms-service/src/sms/handler/handler.go index 79b8618..1b9b869 100644 --- a/sms-service/src/sms/handler/handler.go +++ b/sms-service/src/sms/handler/handler.go @@ -18,51 +18,79 @@ package handler import ( "encoding/json" + "github.com/gorilla/mux" "net/http" "sms/backend" - - "github.com/gorilla/mux" ) -type secretDomainJSON struct { - name string +type handler struct { + secretBackend backend.SecretBackend + loginBackend backend.LoginBackend } -type secretKeyValue struct { - name string - value string -} +// createSecretDomainHandler creates a secret domain with a name provided +func (h handler) createSecretDomainHandler(w http.ResponseWriter, r *http.Request) { + var d backend.SecretDomain -type secretJSON struct { - name string - values []secretKeyValue + err := json.NewDecoder(r.Body).Decode(&d) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + h.secretBackend.CreateSecretDomain(d.Name) } -type handler struct { - secretBackend backend.SecretBackend - loginBackend backend.LoginBackend +// getSecretDomainHandler returns list of secret domains +func (h handler) getSecretDomainHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + domName := vars["domName"] + + h.secretBackend.GetSecretDomain(domName) + //encode data into json and return } -// GetSecretDomainHandler returns list of secret domains -func (h handler) GetSecretDomainHandler(w http.ResponseWriter, r *http.Request) { +// deleteSecretDomainHandler deletes a secret domain with the name provided +func (h handler) deleteSecretDomainHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + domName := vars["domName"] + h.secretBackend.DeleteSecretDomain(domName) } -// CreateSecretDomainHandler creates a secret domain with a name provided -func (h handler) CreateSecretDomainHandler(w http.ResponseWriter, r *http.Request) { - var d secretDomainJSON +// createSecretHandler handles creation of secrets on a given domain name +func (h handler) createSecretHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + domName := vars["domName"] - err := json.NewDecoder(r.Body).Decode(&d) + var b backend.Secret + err := json.NewDecoder(r.Body).Decode(&b) if err != nil { http.Error(w, err.Error(), 400) return } + + h.secretBackend.CreateSecret(domName, b) +} + +// getSecretHandler handles reading a secret by given domain name and secret name +func (h handler) getSecretHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + domName := vars["domName"] + secName := vars["secretName"] + + h.secretBackend.GetSecret(domName, secName) + //encode and return response } -// DeleteSecretDomainHandler deletes a secret domain with the ID provided -func (h handler) DeleteSecretDomainHandler(w http.ResponseWriter, r *http.Request) { +// deleteSecretHandler handles deleting a secret by given domain name and secret name +func (h handler) deleteSecretHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + domName := vars["domName"] + secName := vars["secretName"] + h.secretBackend.DeleteSecret(domName, secName) } // struct that tracks various status items for SMS and backend @@ -70,19 +98,24 @@ type status struct { Seal bool `json:"sealstatus"` } -// StatusHandler returns information related to SMS and SMS backend services -func (h handler) StatusHandler(w http.ResponseWriter, r *http.Request) { - s := h.secretBackend.GetStatus() +// statusHandler returns information related to SMS and SMS backend services +func (h handler) statusHandler(w http.ResponseWriter, r *http.Request) { + s, err := h.secretBackend.GetStatus() + if err != nil { + http.Error(w, err.Error(), 500) + return + } + status := status{Seal: s} - err := json.NewEncoder(w).Encode(status) + err = json.NewEncoder(w).Encode(status) if err != nil { - http.Error(w, err.Error(), 400) + http.Error(w, err.Error(), 500) return } } -// LoginHandler handles login via password and username -func (h handler) LoginHandler(w http.ResponseWriter, r *http.Request) { +// loginHandler handles login via password and username +func (h handler) loginHandler(w http.ResponseWriter, r *http.Request) { } @@ -93,13 +126,17 @@ func CreateRouter(b backend.SecretBackend) http.Handler { // Create a new mux to handle URL endpoints router := mux.NewRouter() - router.HandleFunc("/v1/sms/login", h.LoginHandler).Methods("POST") + router.HandleFunc("/v1/sms/login", h.loginHandler).Methods("POST") + + router.HandleFunc("/v1/sms/status", h.statusHandler).Methods("GET") - router.HandleFunc("/v1/sms/status", h.StatusHandler).Methods("GET") + router.HandleFunc("/v1/sms/domain", h.createSecretDomainHandler).Methods("POST") + router.HandleFunc("/v1/sms/domain/{domName}", h.getSecretDomainHandler).Methods("GET") + router.HandleFunc("/v1/sms/domain/{domName}", h.deleteSecretDomainHandler).Methods("DELETE") - router.HandleFunc("/v1/sms/domain", h.GetSecretDomainHandler).Methods("GET") - router.HandleFunc("/v1/sms/domain", h.CreateSecretDomainHandler).Methods("POST") - router.HandleFunc("/v1/sms/domain/{domName}", h.DeleteSecretDomainHandler).Methods("DELETE") + router.HandleFunc("v1/sms/domain/{domainName}/secret", h.createSecretHandler).Methods("POST") + router.HandleFunc("v1/sms/domain/{domainName}/secret/{secretName}", h.getSecretHandler).Methods("GET") + router.HandleFunc("v1/sms/domain/{domainName}/secret/{secretName}", h.deleteSecretHandler).Methods("DELETE") return router } diff --git a/sms-service/src/sms/sms.go b/sms-service/src/sms/sms.go index 8fdf399..98b2824 100644 --- a/sms-service/src/sms/sms.go +++ b/sms-service/src/sms/sms.go @@ -28,9 +28,16 @@ import ( func main() { // Read Configuration File - smsConf := smsconfig.ReadConfigFile("smsconfig.json") + smsConf, err := smsconfig.ReadConfigFile("smsconfig.json") + if err != nil { + log.Fatal(err) + } + + backendImpl, err := smsbackend.InitSecretBackend() + if err != nil { + log.Fatal(err) + } - backendImpl := smsbackend.InitSecretBackend() httpRouter := smshandler.CreateRouter(backendImpl) // TODO: Use CA certificate from AAF @@ -42,6 +49,6 @@ func main() { TLSConfig: tlsConfig, } - err := httpServer.ListenAndServeTLS(smsConf.ServerCert, smsConf.ServerKey) + err = httpServer.ListenAndServeTLS(smsConf.ServerCert, smsConf.ServerKey) log.Fatal(err) } |