From 53b6f4630af634272ed60d582f9bb29205c6ff17 Mon Sep 17 00:00:00 2001 From: Kiran Date: Mon, 5 Feb 2018 14:04:32 -0800 Subject: [PATCH] Initial Project Structure Includes a directory stucture for all the current components The implemented code establishes a mTLS connection to client and serves a GET status request Other requests and handlers will come in future patches Issue-ID: AAF-102 Change-Id: Ib3bca066586d23330b10550f83772ab11aacabc7 Signed-off-by: Kiran --- .gitreview | 4 + sms-cli/.keep | 0 sms-client/.keep | 0 sms-gui/.keep | 0 sms-service/.gitignore | 4 + sms-service/doc/swagger.yaml | 588 +++++++++++++++++++++++++++++ sms-service/src/sms/Gopkg.lock | 134 +++++++ sms-service/src/sms/Gopkg.toml | 29 ++ sms-service/src/sms/auth/auth.go | 51 +++ sms-service/src/sms/backend/backend.go | 47 +++ sms-service/src/sms/backend/vault/vault.go | 56 +++ sms-service/src/sms/config/config.go | 52 +++ sms-service/src/sms/handler/handler.go | 105 ++++++ sms-service/src/sms/sms.go | 47 +++ sms-service/src/sms/smsconfig.json | 7 + 15 files changed, 1124 insertions(+) create mode 100644 .gitreview create mode 100644 sms-cli/.keep create mode 100644 sms-client/.keep create mode 100644 sms-gui/.keep create mode 100644 sms-service/.gitignore create mode 100644 sms-service/doc/swagger.yaml create mode 100644 sms-service/src/sms/Gopkg.lock create mode 100644 sms-service/src/sms/Gopkg.toml create mode 100644 sms-service/src/sms/auth/auth.go create mode 100644 sms-service/src/sms/backend/backend.go create mode 100644 sms-service/src/sms/backend/vault/vault.go create mode 100644 sms-service/src/sms/config/config.go create mode 100644 sms-service/src/sms/handler/handler.go create mode 100644 sms-service/src/sms/sms.go create mode 100644 sms-service/src/sms/smsconfig.json diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..651dace --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=gerrit.onap.org +port=29418 +project=aaf/sms.git diff --git a/sms-cli/.keep b/sms-cli/.keep new file mode 100644 index 0000000..e69de29 diff --git a/sms-client/.keep b/sms-client/.keep new file mode 100644 index 0000000..e69de29 diff --git a/sms-gui/.keep b/sms-gui/.keep new file mode 100644 index 0000000..e69de29 diff --git a/sms-service/.gitignore b/sms-service/.gitignore new file mode 100644 index 0000000..e98d43b --- /dev/null +++ b/sms-service/.gitignore @@ -0,0 +1,4 @@ +pkg/ +src/sms/.vscode/ +src/sms/vendor/ +src/sms/test/ diff --git a/sms-service/doc/swagger.yaml b/sms-service/doc/swagger.yaml new file mode 100644 index 0000000..c1fb634 --- /dev/null +++ b/sms-service/doc/swagger.yaml @@ -0,0 +1,588 @@ +swagger: "2.0" +info: + description: "This is a service that provides secret management facilities" + version: "1.0.0" + title: "Secret Management Service" + contact: + email: "kiran.k.kamineni@intel.com" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" +host: "aaf.onap.org:8000" +basePath: "/v1/sms/" +tags: +- name: "domain" + description: "Operations related to Secret Domains" + externalDocs: + description: "Find out more" + url: "http://swagger.io" +- name: "secret" + description: "Operations related to Secrets" +schemes: +- "https" +paths: + /domain: + post: + tags: + - "domain" + summary: "Add a new domain" + description: "" + operationId: "addDomain" + consumes: + - "application/json" + produces: + - "application/json" + parameters: + - in: "body" + name: "body" + required: true + schema: + $ref: "#/definitions/Domain" + responses: + 405: + description: "Invalid input" + 200: + description: "Successful Creation" + schema: + $ref: "#/definitions/Domain" + /domain/{domain_name}: + get: + tags: + - "domain" + summary: "Gets domain by name" + description: "Multiple status values can be provided with comma separated strings" + operationId: "findPetsByStatus" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "status" + in: "query" + description: "Status values that need to be considered for filter" + required: true + type: "array" + items: + type: "string" + enum: + - "available" + - "pending" + - "sold" + default: "available" + collectionFormat: "multi" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid status value" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByTags: + get: + tags: + - "pet" + summary: "Finds Pets by tags" + description: "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing." + operationId: "findPetsByTags" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "tags" + in: "query" + description: "Tags to filter by" + required: true + type: "array" + items: + type: "string" + collectionFormat: "multi" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid tag value" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + deprecated: true + /{domainName}/{secretName}: + get: + tags: + - "secret" + summary: "Find Secret by Name" + description: "Returns a single secret" + operationId: "getSecretByName" + produces: + - "application/json" + parameters: + - name: "domainName" + in: "path" + description: "Name of the domain in which to look at" + required: true + type: "string" + - name: "secretName" + in: "path" + description: "Name of the secret which is needed" + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Secret" + 404: + description: "Invalid Path or Path not found" + security: + - api_key: [] + delete: + tags: + - "secret" + summary: "Deletes a Secret" + description: "" + operationId: "deleteSecret" + produces: + - "application/json" + parameters: + - name: "token" + in: "header" + required: true + type: "string" + - name: "secretName" + in: "path" + description: "Name of Secret to Delete" + required: true + type: "string" + - name: "domainName" + in: "path" + description: "Path to the SecretDomain which contains the Secret" + type: "string" + responses: + 204: + description: "Successful Deletion" + 404: + description: "Invalid Path or Path not found" + /pet/{petId}/uploadImage: + post: + tags: + - "pet" + summary: "uploads an image" + description: "" + operationId: "uploadFile" + consumes: + - "multipart/form-data" + produces: + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to update" + required: true + type: "integer" + format: "int64" + - name: "additionalMetadata" + in: "formData" + description: "Additional data to pass to server" + required: false + type: "string" + - name: "file" + in: "formData" + description: "file to upload" + required: false + type: "file" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /store/inventory: + get: + tags: + - "store" + summary: "Returns pet inventories by status" + description: "Returns a map of status codes to quantities" + operationId: "getInventory" + produces: + - "application/json" + parameters: [] + responses: + 200: + description: "successful operation" + schema: + type: "object" + additionalProperties: + type: "integer" + format: "int32" + security: + - api_key: [] + /store/order: + post: + tags: + - "store" + summary: "Place an order for a pet" + description: "" + operationId: "placeOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "order placed for purchasing the pet" + required: true + schema: + $ref: "#/definitions/Order" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid Order" + /store/order/{orderId}: + get: + tags: + - "store" + summary: "Find purchase order by ID" + description: "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions" + operationId: "getOrderById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "orderId" + in: "path" + description: "ID of pet that needs to be fetched" + required: true + type: "integer" + maximum: 10.0 + minimum: 1.0 + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + delete: + tags: + - "store" + summary: "Delete purchase order by ID" + description: "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors" + operationId: "deleteOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "orderId" + in: "path" + description: "ID of the order that needs to be deleted" + required: true + type: "integer" + minimum: 1.0 + format: "int64" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + /user: + post: + tags: + - "user" + summary: "Create user" + description: "This can only be done by the logged in user." + operationId: "createUser" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Created user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithArray: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithArrayInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithList: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithListInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/login: + get: + tags: + - "user" + summary: "Logs user into the system" + description: "" + operationId: "loginUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "query" + description: "The user name for login" + required: true + type: "string" + - name: "password" + in: "query" + description: "The password for login in clear text" + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + type: "string" + headers: + X-Rate-Limit: + type: "integer" + format: "int32" + description: "calls per hour allowed by the user" + X-Expires-After: + type: "string" + format: "date-time" + description: "date in UTC when token expires" + 400: + description: "Invalid username/password supplied" + /user/logout: + get: + tags: + - "user" + summary: "Logs out current logged in user session" + description: "" + operationId: "logoutUser" + produces: + - "application/xml" + - "application/json" + parameters: [] + responses: + default: + description: "successful operation" + /user/{username}: + get: + tags: + - "user" + summary: "Get user by user name" + description: "" + operationId: "getUserByName" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be fetched. Use user1 for testing. " + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/User" + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + put: + tags: + - "user" + summary: "Updated user" + description: "This can only be done by the logged in user." + operationId: "updateUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "name that need to be updated" + required: true + type: "string" + - in: "body" + name: "body" + description: "Updated user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + 400: + description: "Invalid user supplied" + 404: + description: "User not found" + delete: + tags: + - "user" + summary: "Delete user" + description: "This can only be done by the logged in user." + operationId: "deleteUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be deleted" + required: true + type: "string" + responses: + 400: + description: "Invalid username supplied" + 404: + description: "User not found" +securityDefinitions: + petstore_auth: + type: "oauth2" + authorizationUrl: "http://petstore.swagger.io/oauth/dialog" + flow: "implicit" + scopes: + write:pets: "modify pets in your account" + read:pets: "read your pets" + api_key: + type: "apiKey" + name: "api_key" + in: "header" +definitions: + Domain: + type: "object" + properties: + uuid: + type: "string" + description: "Optional value provided by user. If user does not provide, server will auto generate" + name: + type: "string" + description: "Name of the secret domain under which all secrets will be stored" + Secret: + type: "object" + properties: + name: + type: "string" + description: "Name of the secret" + value: + type: "array" + description: "Array of key value pairs that constitute the secret" + items: + type: "object" + properties: + key: + type: "string" + value: + type: "string" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Tag" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + properties: + id: + type: "integer" + format: "int64" + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + xml: + name: "Pet" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" +externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io" \ No newline at end of file diff --git a/sms-service/src/sms/Gopkg.lock b/sms-service/src/sms/Gopkg.lock new file mode 100644 index 0000000..da2fafd --- /dev/null +++ b/sms-service/src/sms/Gopkg.lock @@ -0,0 +1,134 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/fatih/structs" + packages = ["."] + revision = "a720dfa8df582c51dee1b36feabb906bde1588bd" + version = "v1.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + name = "github.com/gorilla/context" + packages = ["."] + revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a" + version = "v1.1" + +[[projects]] + name = "github.com/gorilla/mux" + packages = ["."] + revision = "53c1911da2b537f792e7cafcb446b05ffe33b996" + version = "v1.6.1" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/errwrap" + packages = ["."] + revision = "7554cd9344cec97297fa6649b055a8c98c2a1e55" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/go-cleanhttp" + packages = ["."] + revision = "d5fe4b57a186c716b0e00b8c301cbd9b4182694d" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/go-multierror" + packages = ["."] + revision = "b7773ae218740a7be65057fc60b366a49b538a44" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/go-rootcerts" + packages = ["."] + revision = "6bb64b370b90e7ef1fa532be9e591a81c3493e00" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/hcl" + packages = [ + ".", + "hcl/ast", + "hcl/parser", + "hcl/scanner", + "hcl/strconv", + "hcl/token", + "json/parser", + "json/scanner", + "json/token" + ] + revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8" + +[[projects]] + name = "github.com/hashicorp/vault" + packages = [ + "api", + "helper/compressutil", + "helper/jsonutil", + "helper/parseutil" + ] + revision = "5acd6a21d5a69ab49d0f7c0bf540123a9b2c696d" + version = "v0.9.3" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/go-homedir" + packages = ["."] + revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/mapstructure" + packages = ["."] + revision = "b4575eea38cca1123ec2dc90c26529b5c5acfcff" + +[[projects]] + branch = "master" + name = "github.com/sethgrid/pester" + packages = ["."] + revision = "760f8913c0483b776294e1bee43f1d687527127b" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "http2", + "http2/hpack", + "idna", + "lex/httplex" + ] + revision = "0ed95abb35c445290478a5348a7b38bb154135fd" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] + revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "04ef42d3e34fec943a6bbcbde4a3caea30a3ca59d53faf7c99aa63094bea4e8f" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/sms-service/src/sms/Gopkg.toml b/sms-service/src/sms/Gopkg.toml new file mode 100644 index 0000000..af2ce87 --- /dev/null +++ b/sms-service/src/sms/Gopkg.toml @@ -0,0 +1,29 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/gorilla/mux" + version = "1.6.1" + +[[constraint]] + name = "github.com/hashicorp/vault" + version = "0.9.3" diff --git a/sms-service/src/sms/auth/auth.go b/sms-service/src/sms/auth/auth.go new file mode 100644 index 0000000..690fe62 --- /dev/null +++ b/sms-service/src/sms/auth/auth.go @@ -0,0 +1,51 @@ +/* + * 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 auth + +import ( + "crypto/tls" + "crypto/x509" + "io/ioutil" + "log" +) + +var tlsConfig *tls.Config + +// GetTLSConfig initializes a tlsConfig using the CA's certificate +// This config is then used to enable the server for mutual TLS +func GetTLSConfig(caCertFile string) *tls.Config { + // Initialize tlsConfig once + if tlsConfig == nil { + caCert, err := ioutil.ReadFile(caCertFile) + + if err != nil { + log.Fatal("Error reading CA Certificate") + log.Fatal(err) + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + tlsConfig = &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: caCertPool, + MinVersion: tls.VersionTLS12, + } + tlsConfig.BuildNameToCertificate() + } + return tlsConfig +} diff --git a/sms-service/src/sms/backend/backend.go b/sms-service/src/sms/backend/backend.go new file mode 100644 index 0000000..ceb28a4 --- /dev/null +++ b/sms-service/src/sms/backend/backend.go @@ -0,0 +1,47 @@ +/* + * 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 ( + vaultwrap "sms/backend/vault" +) + +// SecretDomain struct that will be passed around between http handler +// and code that interfaces with vault +type SecretDomain struct { + ID int + Name string + MountPoint string +} + +// SecretBackend interface that will be implemented for various secret backends +type SecretBackend interface { + Init() + + GetStatus() bool +} + +// InitSecretBackend returns an interface implementation +func InitSecretBackend() SecretBackend { + backendImpl := &vaultwrap.Vault{} + backendImpl.Init() + return backendImpl +} + +// LoginBackend Interface that will be implemented for various login backends +type LoginBackend interface { +} diff --git a/sms-service/src/sms/backend/vault/vault.go b/sms-service/src/sms/backend/vault/vault.go new file mode 100644 index 0000000..37cb19a --- /dev/null +++ b/sms-service/src/sms/backend/vault/vault.go @@ -0,0 +1,56 @@ +/* + * 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 new file mode 100644 index 0000000..d958e15 --- /dev/null +++ b/sms-service/src/sms/config/config.go @@ -0,0 +1,52 @@ +/* + * 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 config + +import ( + "encoding/json" + "log" + "os" +) + +type SMSConfiguration struct { + CAFile string `json:"cafile"` + ServerCert string `json:"servercert"` + ServerKey string `json:"serverkey"` + + VaultAddress string `json:"vaultaddress"` +} + +// SMSConfig is the structure that stores the configuration +var SMSConfig *SMSConfiguration + +// ReadConfigFile reads the specified smsConfig file to setup some env variables +func ReadConfigFile(file string) *SMSConfiguration { + if SMSConfig == nil { + f, err := os.Open(file) + if err != nil { + log.Fatalf("Unable to find file %s", file) + } + + decoder := json.NewDecoder(f) + err = decoder.Decode(&SMSConfig) + if err != nil { + log.Fatal(err) + } + } + + return SMSConfig +} diff --git a/sms-service/src/sms/handler/handler.go b/sms-service/src/sms/handler/handler.go new file mode 100644 index 0000000..79b8618 --- /dev/null +++ b/sms-service/src/sms/handler/handler.go @@ -0,0 +1,105 @@ +/* + * 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 handler + +import ( + "encoding/json" + "net/http" + + "sms/backend" + + "github.com/gorilla/mux" +) + +type secretDomainJSON struct { + name string +} + +type secretKeyValue struct { + name string + value string +} + +type secretJSON struct { + name string + values []secretKeyValue +} + +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) { + +} + +// CreateSecretDomainHandler creates a secret domain with a name provided +func (h handler) CreateSecretDomainHandler(w http.ResponseWriter, r *http.Request) { + var d secretDomainJSON + + err := json.NewDecoder(r.Body).Decode(&d) + if err != nil { + http.Error(w, err.Error(), 400) + return + } +} + +// DeleteSecretDomainHandler deletes a secret domain with the ID provided +func (h handler) DeleteSecretDomainHandler(w http.ResponseWriter, r *http.Request) { + +} + +// struct that tracks various status items for SMS and backend +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() + status := status{Seal: s} + err := json.NewEncoder(w).Encode(status) + if err != nil { + http.Error(w, err.Error(), 400) + return + } +} + +// LoginHandler handles login via password and username +func (h handler) LoginHandler(w http.ResponseWriter, r *http.Request) { + +} + +// CreateRouter returns an http.Handler for the registered URLs +func CreateRouter(b backend.SecretBackend) http.Handler { + h := handler{secretBackend: b} + + // Create a new mux to handle URL endpoints + router := mux.NewRouter() + + router.HandleFunc("/v1/sms/login", h.LoginHandler).Methods("POST") + + router.HandleFunc("/v1/sms/status", h.StatusHandler).Methods("GET") + + 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") + + return router +} diff --git a/sms-service/src/sms/sms.go b/sms-service/src/sms/sms.go new file mode 100644 index 0000000..8fdf399 --- /dev/null +++ b/sms-service/src/sms/sms.go @@ -0,0 +1,47 @@ +/* + * 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 main + +import ( + "log" + "net/http" + + smsauth "sms/auth" + smsbackend "sms/backend" + smsconfig "sms/config" + smshandler "sms/handler" +) + +func main() { + // Read Configuration File + smsConf := smsconfig.ReadConfigFile("smsconfig.json") + + backendImpl := smsbackend.InitSecretBackend() + httpRouter := smshandler.CreateRouter(backendImpl) + + // TODO: Use CA certificate from AAF + tlsConfig := smsauth.GetTLSConfig(smsConf.CAFile) + + httpServer := &http.Server{ + Handler: httpRouter, + Addr: ":10443", + TLSConfig: tlsConfig, + } + + err := httpServer.ListenAndServeTLS(smsConf.ServerCert, smsConf.ServerKey) + log.Fatal(err) +} diff --git a/sms-service/src/sms/smsconfig.json b/sms-service/src/sms/smsconfig.json new file mode 100644 index 0000000..ddb89d3 --- /dev/null +++ b/sms-service/src/sms/smsconfig.json @@ -0,0 +1,7 @@ +{ + "cafile": "auth/selfsignedca.pem", + "servercert": "auth/server_cat.cert", + "serverkey": "auth/server.key", + + "vaultaddress": "http://localhost:8200" +} -- 2.16.6