[ISSUE-67869881] address comments, add test cases
diff --git a/accessEntity/data.go b/accessEntity/data.go
index bb53fea..4634f61 100644
--- a/accessEntity/data.go
+++ b/accessEntity/data.go
@@ -16,7 +16,6 @@
import (
"database/sql"
"fmt"
- "github.com/apid/apid-core/cipher"
"github.com/apid/apid-core/util"
"github.com/apid/apidApiMetadata/common"
"strings"
@@ -96,9 +95,7 @@
if err != nil || !email.Valid {
return "", err
}
- // decryption
- ret, err := d.CipherManager.TryDecryptBase64(email.String, org)
- return ret, err
+ return email.String, err
}
func (d *DbManager) GetComNames(id string, idType string) ([]string, error) {
@@ -287,6 +284,10 @@
appCredentials, err = d.getAppCredentialByAppId(priVal, org)
}
+ if err != nil {
+ return
+ }
+
var plaintext string
for i := range appCredentials {
if plaintext, err = d.CipherManager.TryDecryptBase64(appCredentials[i].ConsumerSecret, org); err != nil {
@@ -309,15 +310,6 @@
case IdentifierDeveloperId:
developers, err = d.getDeveloperById(priVal, org)
}
-
- var plaintext string
- for i := range developers {
- if plaintext, err = d.CipherManager.TryDecryptBase64(developers[i].Email, org); err != nil {
- return
- }
- developers[i].Email = plaintext
- }
-
return
}
@@ -369,17 +361,12 @@
appQuery = selectAppByNameAndDeveloperId(
"?",
selectDeveloperByEmail(
- "?, ?",
+ "?",
"id",
),
"id",
)
- var encrypted string
- encrypted, err = d.CipherManager.EncryptBase64(devEmail, org, cipher.ModeEcb, cipher.PaddingPKCS5)
- if err != nil {
- return
- }
- args = append(args, devEmail, encrypted)
+ args = append(args, devEmail)
case devId != "":
appQuery = selectAppByNameAndDeveloperId(
"?",
@@ -438,17 +425,12 @@
query = selectAppByNameAndDeveloperId(
"?",
selectDeveloperByEmail(
- "?, ?",
+ "?",
"id",
),
cols...,
)
- var encrypted string
- encrypted, err = d.CipherManager.EncryptBase64(devEmail, org, cipher.ModeEcb, cipher.PaddingPKCS5)
- if err != nil {
- return
- }
- args = append(args, devEmail, encrypted)
+ args = append(args, devEmail)
case devId != "":
query = selectAppByNameAndDeveloperId(
"?",
@@ -610,16 +592,11 @@
func (d *DbManager) getDeveloperByEmail(email, org string) (developers []common.Developer, err error) {
cols := []string{"*"}
query := selectDeveloperByEmail(
- "?, ?",
+ "?",
cols...,
) + " AND dev.tenant_id IN " + sql_select_tenant_org
//log.Debugf("getDeveloperByEmail: %v", query)
- var encrypted string
- encrypted, err = d.CipherManager.EncryptBase64(email, org, cipher.ModeEcb, cipher.PaddingPKCS5)
- if err != nil {
- return
- }
- err = d.GetDb().QueryStructs(&developers, query, email, encrypted, org)
+ err = d.GetDb().QueryStructs(&developers, query, email, org)
return
}
diff --git a/accessEntity/data_test.sql b/accessEntity/data_test.sql
index 16aa13f..7f01503 100644
--- a/accessEntity/data_test.sql
+++ b/accessEntity/data_test.sql
@@ -36,9 +36,9 @@
CREATE TABLE kms_company_developer (tenant_id text,company_id text,developer_id text,roles text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (tenant_id,company_id,developer_id));
INSERT INTO "kms_company_developer" VALUES('515211e9','a94f75e2-69b0-44af-8776-155df7c7d22e','590f33bf-f05c-48c1-bb93-183759bd9ee1','admin','2017-11-02 16:00:16.287+00:00','haoming@apid.git','2017-11-02 16:00:16.287+00:00','haoming@apid.git','515211e9');
CREATE TABLE kms_developer (id text,tenant_id text,username text,first_name text,last_name text,password text,email text,status text,encrypted_password text,salt text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
-INSERT INTO "kms_developer" VALUES('e41f04e8-9d3f-470a-8bfd-c7939945896c','515211e9','haoming','haoming','zhang','','encrypted:bar@google.com','ACTIVE','','','2017-08-16 22:39:46.669+00:00','foo@google.com','2017-08-16 22:39:46.669+00:00','foo@google.com','515211e9');
-INSERT INTO "kms_developer" VALUES('47d862db-884f-4b8e-9649-fe6d0be1a739','515211e9','qwe','qwe','qwe','','encrypted:barfoo@google.com','ACTIVE','','','2017-10-12 19:12:48.306+00:00','haoming@apid.git','2017-10-12 19:12:48.306+00:00','haoming@apid.git','515211e9');
-INSERT INTO "kms_developer" VALUES('590f33bf-f05c-48c1-bb93-183759bd9ee1','515211e9','remoteproxy','remote','proxy','','encrypted:fooo@google.com','ACTIVE','','','2017-09-20 23:03:52.327+00:00','haoming@apid.git','2017-09-20 23:03:52.327+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_developer" VALUES('e41f04e8-9d3f-470a-8bfd-c7939945896c','515211e9','haoming','haoming','zhang','','bar@google.com','ACTIVE','','','2017-08-16 22:39:46.669+00:00','foo@google.com','2017-08-16 22:39:46.669+00:00','foo@google.com','515211e9');
+INSERT INTO "kms_developer" VALUES('47d862db-884f-4b8e-9649-fe6d0be1a739','515211e9','qwe','qwe','qwe','','barfoo@google.com','ACTIVE','','','2017-10-12 19:12:48.306+00:00','haoming@apid.git','2017-10-12 19:12:48.306+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_developer" VALUES('590f33bf-f05c-48c1-bb93-183759bd9ee1','515211e9','remoteproxy','remote','proxy','','fooo@google.com','ACTIVE','','','2017-09-20 23:03:52.327+00:00','haoming@apid.git','2017-09-20 23:03:52.327+00:00','haoming@apid.git','515211e9');
CREATE TABLE edgex_apid_cluster (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, last_sequence text DEFAULT '', primary key (id));
INSERT INTO "edgex_apid_cluster" VALUES('950b30f1-8c41-4bf5-94a3-f10c104ff5d4','apid-haomingOrgCluster','','X-sZXhaOymL6VtWnNQqK7uPsFyPvZYq6FFnrc8','2017-08-23 23:31:49.134+00:00','temp@google.com','2017-08-23 23:31:49.134+00:00','temp@google.com','950b30f1-8c41-4bf5-94a3-f10c104ff5d4','');
CREATE TABLE kms_api_product (id text,tenant_id text,name text,display_name text,description text,api_resources text,approval_type text,scopes text,proxies text,environments text,quota text,quota_time_unit text,quota_interval integer,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
@@ -49,9 +49,9 @@
INSERT INTO "kms_api_product" VALUES('db90a25a-15c8-42ad-96c1-63ed9682b5a9','515211e9','apigee-remote-proxy','apigee-remote-proxy','','{/**,/}','AUTO','{""}','{apigee-remote-proxy}','{prod,test}','','',NULL,'2017-09-20 23:05:09.234+00:00','haoming@apid.git','2017-09-20 23:05:09.234+00:00','haoming@apid.git','515211e9');
INSERT INTO "kms_api_product" VALUES('fea8a6d5-8d34-477f-ac82-c397eaec06af','515211e9','testproductsdljnkpt','testproductsdljnkpt','','{/res1}','AUTO','{}','{}','{test}','','',NULL,'2017-11-02 16:00:15.608+00:00','haoming@apid.git','2017-11-02 16:00:18.125+00:00','haoming@apid.git','515211e9');
CREATE TABLE kms_app_credential (id text,tenant_id text,consumer_secret text,app_id text,method_type text,status text,issued_at blob,expires_at blob,app_status text,scopes text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
-INSERT INTO "kms_app_credential" VALUES('abcd','515211e9','secret1','408ad853-3fa0-402f-90ee-103de98d71a5','','APPROVED','2017-08-18 22:13:18.35+00:00','','','{}','2017-08-18 22:13:18.35+00:00','-NA-','2017-08-18 22:13:18.352+00:00','-NA-','515211e9');
-INSERT INTO "kms_app_credential" VALUES('dcba','515211e9','secret2','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','APPROVED','2017-09-20 23:05:59.148+00:00','','','{}','2017-09-20 23:05:59.148+00:00','-NA-','2017-09-20 23:05:59.151+00:00','-NA-','515211e9');
-INSERT INTO "kms_app_credential" VALUES('wxyz','515211e9','secret3','35608afe-2715-4064-bb4d-3cbb4e82c474','','APPROVED','2017-11-02 16:00:16.512+00:00','','','{}','2017-11-02 16:00:16.512+00:00','-NA-','2017-11-02 16:00:16.514+00:00','-NA-','515211e9');
+INSERT INTO "kms_app_credential" VALUES('abcd','515211e9','encrypted:secret1','408ad853-3fa0-402f-90ee-103de98d71a5','','APPROVED','2017-08-18 22:13:18.35+00:00','','','{}','2017-08-18 22:13:18.35+00:00','-NA-','2017-08-18 22:13:18.352+00:00','-NA-','515211e9');
+INSERT INTO "kms_app_credential" VALUES('dcba','515211e9','encrypted:secret2','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','APPROVED','2017-09-20 23:05:59.148+00:00','','','{}','2017-09-20 23:05:59.148+00:00','-NA-','2017-09-20 23:05:59.151+00:00','-NA-','515211e9');
+INSERT INTO "kms_app_credential" VALUES('wxyz','515211e9','encrypted:secret3','35608afe-2715-4064-bb4d-3cbb4e82c474','','APPROVED','2017-11-02 16:00:16.512+00:00','','','{}','2017-11-02 16:00:16.512+00:00','-NA-','2017-11-02 16:00:16.514+00:00','-NA-','515211e9');
CREATE TABLE kms_app_credential_apiproduct_mapper (tenant_id text,appcred_id text,app_id text,apiprdt_id text,status text,_change_selector text, primary key (tenant_id,appcred_id,app_id,apiprdt_id));
INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','abcd','408ad853-3fa0-402f-90ee-103de98d71a5','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','APPROVED','515211e9');
INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','dcba','ae053aee-f12d-4591-84ef-2e6ae0d4205d','db90a25a-15c8-42ad-96c1-63ed9682b5a9','APPROVED','515211e9');
diff --git a/common/cipher.go b/common/cipher.go
index 6e88d33..5e727a2 100644
--- a/common/cipher.go
+++ b/common/cipher.go
@@ -27,7 +27,7 @@
"time"
)
-const RegEncrypted = `^\{[0-9A-Za-z]+/[0-9A-Za-z]+/[0-9A-Za-z]+\}.`
+const regEncrypted = `^\{[0-9A-Za-z]+/[0-9A-Za-z]+/[0-9A-Za-z]+\}.`
const retrieveEncryptKeyPath = "/encryptionkey"
const EncryptAes = "AES"
@@ -44,12 +44,11 @@
)
const errorCodeNoKey = "organizations.EncryptionKeyDoesNotExist"
-var RegexpEncrypted = regexp.MustCompile(RegEncrypted)
+var RegexpEncrypted = regexp.MustCompile(regEncrypted)
func CreateCipherManager(client *http.Client, serverUrlBase string) *KmsCipherManager {
return &KmsCipherManager{
serverUrlBase: serverUrlBase,
- key: make(map[string][]byte),
aes: make(map[string]*cipher.AesCipher),
mutex: &sync.RWMutex{},
client: client,
@@ -60,8 +59,6 @@
type KmsCipherManager struct {
serverUrlBase string
- // org-level key map {organization: key}
- key map[string][]byte
// org-level AesCipher map {organization: AesCipher}
aes map[string]*cipher.AesCipher
mutex *sync.RWMutex
@@ -91,7 +88,6 @@
return
case <-ticker.C:
if err := c.retrieveKey(org); err != nil {
-
log.Error(err)
} else {
return
@@ -103,14 +99,14 @@
func (c *KmsCipherManager) retrieveKey(org string) error {
var key []byte
req, err := http.NewRequest(http.MethodGet, c.serverUrlBase+retrieveEncryptKeyPath, nil)
+ if err != nil {
+ return fmt.Errorf("failed to create retrieving key request for org=%s : %v", org, err)
+ }
pars := req.URL.Query()
pars[parameterOrganization] = []string{org}
req.URL.RawQuery = pars.Encode()
req.Header.Set("Authorization", "Bearer "+services.Config().GetString(configBearerToken))
log.Debugf("Retrieving key: %s", req.URL.String())
- if err != nil {
- return fmt.Errorf("failed to create retrieving key request for org=%s : %v", org, err)
- }
res, err := c.client.Do(req)
if err != nil {
return fmt.Errorf("failed to retrieve key for org=%s : %v", org, err)
@@ -131,7 +127,6 @@
}
if res.StatusCode != http.StatusOK {
- err = fmt.Errorf("failed to retrieve key for org [%v] with status: %v", org, res.Status)
return fmt.Errorf("failed to retrieve key for org [%v] with status: %v", org, res.Status)
}
@@ -151,7 +146,6 @@
return fmt.Errorf("CreateAesCipher error for org [%v] when CreateAesCipher: %v", org, err)
}
c.mutex.Lock()
- c.key[org] = key
c.aes[org] = a
c.mutex.Unlock()
return nil
@@ -228,48 +222,47 @@
return
}
-// TODO: make sure this regex has no false positive for all possible inputs
func IsEncrypted(input string) (encrypted bool) {
return RegexpEncrypted.Match([]byte(input))
}
func GetCiphertext(input string) (ciphertext string, mode cipher.Mode, padding cipher.Padding, err error) {
- l := strings.SplitN(input, "}", 2)
- if len(l) != 2 {
+ list := strings.SplitN(input, "}", 2)
+ if len(list) != 2 {
err = fmt.Errorf("invalid input for GetCiphertext: %v", input)
return
}
- ciphertext = l[1]
- l = strings.Split(strings.TrimLeft(l[0], "{"), "/")
- if len(l) != 3 {
+ ciphertext = list[1]
+ list = strings.Split(strings.TrimLeft(list[0], "{"), "/")
+ if len(list) != 3 {
err = fmt.Errorf("invalid input for GetCiphertext: %v", input)
return
}
// encryption algorithm
- if l[0] != EncryptAes {
- err = fmt.Errorf("unsupported algorithm for GetCiphertext: %v", l[0])
+ if list[0] != EncryptAes {
+ err = fmt.Errorf("unsupported algorithm for GetCiphertext: %v", list[0])
return
}
// mode
- mode = cipher.Mode(l[1])
+ mode = cipher.Mode(list[1])
// padding
- padding = cipher.Padding(l[2])
+ padding = cipher.Padding(list[2])
return
}
-type ErrorRes struct {
+type KeyErrorResponse struct {
Code string
Message string
}
-func parseErrorResponse(res *http.Response) (*ErrorRes, error) {
- contentType := res.Header.Get("Content-Type")
+func parseErrorResponse(res *http.Response) (*KeyErrorResponse, error) {
+ contentType := res.Header.Get(headerContentType)
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
- ret := &ErrorRes{}
+ ret := &KeyErrorResponse{}
if contentType == typeJson {
return ret, json.Unmarshal(body, ret)
} else if contentType == typeXml {
diff --git a/common/cipher_test.go b/common/cipher_test.go
index 4ff12b9..62162ad 100644
--- a/common/cipher_test.go
+++ b/common/cipher_test.go
@@ -40,7 +40,6 @@
BeforeEach(func() {
testCipherMan = CreateCipherManager(nil, "")
// set key locally
- testCipherMan.key[testOrg] = key
var err error
testCipherMan.aes[testOrg], err = cipher.CreateAesCipher(key)
Expect(err).Should(Succeed())
@@ -66,6 +65,8 @@
// set key server
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer GinkgoRecover()
+ Expect(r.URL.Path).Should(Equal(retrieveEncryptKeyPath))
+ Expect(r.URL.Query().Get(parameterOrganization)).Should(Equal(testOrg))
Expect(w.Write([]byte(base64.StdEncoding.EncodeToString(key)))).Should(Equal(24))
}))
time.Sleep(100 * time.Millisecond)
@@ -84,5 +85,39 @@
It("Decryption", func() {
Expect(testCipherMan.TryDecryptBase64(cipher64, testOrg)).Should(Equal(plaingtext))
})
+
+ It("Retrieve Key", func() {
+ testCipherMan.AddOrgs([]string{testOrg})
+ for {
+ time.Sleep(100 * time.Millisecond)
+ testCipherMan.mutex.RLock()
+ aesCipher := testCipherMan.aes[testOrg]
+ testCipherMan.mutex.RUnlock()
+ if aesCipher != nil {
+ //close server to make sure key was retrieved by "AddOrgs"
+ server.Close()
+ Expect(testCipherMan.EncryptBase64(plaingtext, testOrg, cipher.ModeEcb, cipher.PaddingPKCS5)).
+ Should(Equal(cipher64))
+ return
+ }
+ }
+ }, 2)
+ })
+
+ Context("IsEncrypted", func() {
+ It("IsEncrypted", func() {
+ testData := [][]interface{}{
+ {"{AES/ECB/PKCS5Padding}foo", true},
+ {"AES/ECB/PKCS5Padding}foo", false},
+ {"{AES/ECB/PKCS5Paddingfoo", false},
+ {"{AES/ECB/}foo", false},
+ {"{AES/PKCS5Padding}foo", false},
+ {"{AES//PKCS5Padding}foo", false},
+ {"foo", false},
+ }
+ for i := range testData {
+ Expect(IsEncrypted(testData[i][0].(string))).Should(Equal(testData[i][1]))
+ }
+ })
})
})
diff --git a/verifyApiKey/data.go b/verifyApiKey/data.go
index c2169bb..a5d3708 100644
--- a/verifyApiKey/data.go
+++ b/verifyApiKey/data.go
@@ -68,17 +68,11 @@
return errors.New("InvalidApiKey")
}
- email, err := dbc.CipherManager.TryDecryptBase64(dataWrapper.tempDeveloperDetails.Email,
- dataWrapper.verifyApiKeyRequest.OrganizationName)
- if err != nil {
- return err
- }
secret, err := dbc.CipherManager.TryDecryptBase64(dataWrapper.verifyApiKeySuccessResponse.ClientId.ClientSecret,
dataWrapper.verifyApiKeyRequest.OrganizationName)
if err != nil {
return err
}
- dataWrapper.tempDeveloperDetails.Email = email
dataWrapper.verifyApiKeySuccessResponse.ClientId.ClientSecret = secret
if dataWrapper.verifyApiKeySuccessResponse.App.CallbackUrl != "" {