From 3fd9374e539f8c43fa25f6731d2701e6ac0f693c Mon Sep 17 00:00:00 2001 From: three Date: Mon, 9 Dec 2019 13:00:49 +0800 Subject: [PATCH 1/9] SCB-1563: Support for encrypting values proxy service --- cmd/kieserver/main.go | 3 + examples/dev/kie-conf.yaml | 5 +- server/config/config.go | 5 + server/config/config_test.go | 4 +- server/config/struct.go | 7 +- server/crypto/crypto.go | 44 ++++++ server/crypto/crypto_test.go | 47 +++++++ server/crypto/init.go | 22 +++ server/crypto/noop.go | 48 +++++++ server/resource/v1/history_resource_test.go | 6 +- server/service/crypto_service.go | 146 ++++++++++++++++++++ server/service/mongo/session/session.go | 3 +- 12 files changed, 335 insertions(+), 5 deletions(-) create mode 100644 server/crypto/crypto.go create mode 100644 server/crypto/crypto_test.go create mode 100644 server/crypto/init.go create mode 100644 server/crypto/noop.go create mode 100644 server/service/crypto_service.go diff --git a/cmd/kieserver/main.go b/cmd/kieserver/main.go index e0b65fbd..2fffec79 100644 --- a/cmd/kieserver/main.go +++ b/cmd/kieserver/main.go @@ -101,6 +101,9 @@ func main() { if err := service.DBInit(); err != nil { openlogging.Fatal(err.Error()) } + if err := service.CryptoInit(); err != nil { + openlogging.Fatal(err.Error()) + } if err := chassis.Run(); err != nil { openlogging.Fatal("service exit: " + err.Error()) } diff --git a/examples/dev/kie-conf.yaml b/examples/dev/kie-conf.yaml index c9633fa8..ca8a75a0 100644 --- a/examples/dev/kie-conf.yaml +++ b/examples/dev/kie-conf.yaml @@ -5,4 +5,7 @@ db: poolSize: 10 timeout: 5m sslEnabled: false - rootCAFile: /opt/kie/ca.crt \ No newline at end of file + rootCAFile: /opt/kie/ca.crt + +crypto: + name: noop \ No newline at end of file diff --git a/server/config/config.go b/server/config/config.go index de573d04..194ec48c 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -42,3 +42,8 @@ func Init(file string) error { func GetDB() DB { return Configurations.DB } + +//GetCrypto return crypto configs +func GetCrypto() Crypto { + return Configurations.Crypto +} diff --git a/server/config/config_test.go b/server/config/config_test.go index 75ca3aea..0f8f9ef8 100644 --- a/server/config/config_test.go +++ b/server/config/config_test.go @@ -37,7 +37,8 @@ db: ssl: false sslCA: sslCert: - +crypto: + name: noop `) defer os.Remove("test.yaml") f1, err := os.Create("test.yaml") @@ -48,4 +49,5 @@ db: assert.NoError(t, err) assert.Equal(t, 10, config.GetDB().PoolSize) assert.Equal(t, "mongodb://admin:123@127.0.0.1:27017/kie", config.GetDB().URI) + assert.Equal(t, "noop", config.GetCrypto().Name) } diff --git a/server/config/struct.go b/server/config/struct.go index d3ad4dad..9f775438 100644 --- a/server/config/struct.go +++ b/server/config/struct.go @@ -19,7 +19,8 @@ package config //Config is yaml file struct type Config struct { - DB DB `yaml:"db"` + DB DB `yaml:"db"` + Crypto Crypto `yaml:"crypto"` } //DB is yaml file struct to set mongodb config @@ -30,3 +31,7 @@ type DB struct { RootCA string `yaml:"rootCAFile"` Timeout string `yaml:"timeout"` } + +type Crypto struct { + Name string `yaml:"name"` +} diff --git a/server/crypto/crypto.go b/server/crypto/crypto.go new file mode 100644 index 00000000..55db5e0c --- /dev/null +++ b/server/crypto/crypto.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 crypto + +//Cipher interface declares two function for encryption and decryption +//See https://github.com/go-chassis/foundation/blob/master/security/cipher.go +type Cipher interface { + Encrypt(src string) (string, error) + + Decrypt(src string) (string, error) +} + +var ciphers map[string]Cipher + +func Register(name string, c Cipher) { + if ciphers == nil { + ciphers = make(map[string]Cipher) + } + ciphers[name] = c +} + +func Lookup(name string) Cipher { + cipher, ok := ciphers[name] + if !ok { + return &namedNoop{Name: name} + } + + return cipher +} diff --git a/server/crypto/crypto_test.go b/server/crypto/crypto_test.go new file mode 100644 index 00000000..99f9bbaf --- /dev/null +++ b/server/crypto/crypto_test.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 crypto + +import ( + "reflect" + "testing" +) + +func TestLookup(t *testing.T) { + type args struct { + name string + value string + } + tests := []struct { + name string + args args + want string + }{ + {"noop", args{"noop", "123"}, "123"}, + {"namedNoop", args{"not_implemented", "123"}, "123"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotCipher := Lookup(tt.args.name); + expect, _ := gotCipher.Encrypt(tt.args.value) + if !reflect.DeepEqual(expect, tt.want) { + t.Errorf("Lookup() = %v, want %v", expect, tt.want) + } + }) + } +} diff --git a/server/crypto/init.go b/server/crypto/init.go new file mode 100644 index 00000000..c1008f27 --- /dev/null +++ b/server/crypto/init.go @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 crypto + +func init() { + Register("noop", &Noop{}) +} diff --git a/server/crypto/noop.go b/server/crypto/noop.go new file mode 100644 index 00000000..13e118ad --- /dev/null +++ b/server/crypto/noop.go @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 crypto + +import ( + "fmt" + "github.com/go-mesh/openlogging" +) + +type Noop struct { +} + +func (*Noop) Encrypt(src string) (string, error) { + return src, nil +} + +func (*Noop) Decrypt(src string) (string, error) { + return src, nil +} + +type namedNoop struct { + Name string +} + +func (nn *namedNoop) Encrypt(src string) (string, error) { + openlogging.Warn(fmt.Sprintf("security name [%s] not implemented.", nn.Name)) + return src, nil +} + +func (nn *namedNoop) Decrypt(src string) (string, error) { + openlogging.Warn(fmt.Sprintf("security name [%s] not implemented.", nn.Name)) + return src, nil +} \ No newline at end of file diff --git a/server/resource/v1/history_resource_test.go b/server/resource/v1/history_resource_test.go index c4316148..26617802 100644 --- a/server/resource/v1/history_resource_test.go +++ b/server/resource/v1/history_resource_test.go @@ -61,7 +61,11 @@ var _ = Describe("v1 history resource", func() { Domain: "default", Project: "test", } - kv, _ = service.KVService.CreateOrUpdate(context.Background(), kv) + kv, err = service.KVService.CreateOrUpdate(context.Background(), kv) + It("should not return err or nil", func() { + Expect(err).Should(BeNil()) + }) + path := fmt.Sprintf("/v1/%s/kie/revision/%s", "test", kv.LabelID) r, _ := http.NewRequest("GET", path, nil) revision := &v1.HistoryResource{} diff --git a/server/service/crypto_service.go b/server/service/crypto_service.go new file mode 100644 index 00000000..799f59b7 --- /dev/null +++ b/server/service/crypto_service.go @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 service + +import ( + "context" + "github.com/apache/servicecomb-kie/pkg/model" + "github.com/apache/servicecomb-kie/server/config" + "github.com/apache/servicecomb-kie/server/crypto" +) + +func CryptoInit() error { + if KVService != nil { + KVService = newCryptoKV(KVService) + } + if HistoryService != nil { + HistoryService = newCryptoHistory(HistoryService) + } + + return nil +} + +func newCryptoHistory(service History) History { + return &cryptoHistory{service: service} +} + +func newCryptoKV(service KV) KV { + return &cryptoKV{service: service} +} + +// lookup Crypto +func lookupCrypto(kv *model.KVDoc) crypto.Cipher { + return crypto.Lookup(config.GetCrypto().Name) +} + +// History service security proxy +type cryptoHistory struct { + service History +} + +func (history *cryptoHistory) GetHistory(ctx context.Context, labelID string, options ...FindOption) ([]*model.LabelRevisionDoc, error) { + res, err := history.service.GetHistory(ctx, labelID, options...) + + cipher := lookupCrypto(nil) + + for i := 0; i < len(res); i++ { + doc := res[i] + for j := 0; j < len(doc.KVs); j++ { + kv := doc.KVs[j] + val, err := cipher.Decrypt(kv.Value) + if err != nil { + return nil, err + } + kv.Value = val + } + } + + return res, err +} + +// KV service security proxy +type cryptoKV struct { + service KV +} + +func (ckv *cryptoKV) CreateOrUpdate(ctx context.Context, kv *model.KVDoc) (*model.KVDoc, error) { + cipher := lookupCrypto(nil) + val, err := cipher.Encrypt(kv.Value) + if err != nil { + return nil, err + } + kv.Value = val + + res, err := ckv.service.CreateOrUpdate(ctx, kv) + if res == nil { + return res, err + } + + val, err = cipher.Decrypt(kv.Value) + if err != nil { + return nil, err + } + kv.Value = val + + return res, err +} + +func (ckv *cryptoKV) List(ctx context.Context, domain, project, key string, labels map[string]string, limit, offset int) (*model.KVResponse, error) { + res, err := ckv.service.List(ctx, domain, project, key, labels, limit, offset) + cipher := lookupCrypto(nil) + if res == nil { + return res, err + } + + for j := 0; j < len(res.Data); j++ { + kv := res.Data[j] + val, err := cipher.Decrypt(kv.Value) + if err != nil { + return nil, err + } + kv.Value = val + } + + return res, err +} + +func (ckv *cryptoKV) Delete(kvID string, labelID string, domain, project string) error { + return ckv.Delete(kvID, labelID, domain, project) +} + +func (ckv *cryptoKV) FindKV(ctx context.Context, domain, project string, options ...FindOption) ([]*model.KVResponse, error) { + res, err := ckv.service.FindKV(ctx, domain, project, options...) + cipher := lookupCrypto(nil) + if res == nil { + return res, err + } + + for i := 0; i < len(res); i++ { + doc := res[i] + for j := 0; j < len(doc.Data); j++ { + kv := doc.Data[j] + val, err := cipher.Decrypt(kv.Value) + if err != nil { + return nil, err + } + kv.Value = val + } + } + + return res, err +} diff --git a/server/service/mongo/session/session.go b/server/service/mongo/session/session.go index 1eb43e23..17f15cff 100644 --- a/server/service/mongo/session/session.go +++ b/server/service/mongo/session/session.go @@ -88,7 +88,8 @@ func Init() error { RegisterEncoder(reflect.TypeOf(model.KVDoc{}), sc). RegisterEncoder(reflect.TypeOf(model.LabelRevisionDoc{}), sc). Build() - clientOps := []*options.ClientOptions{options.Client().ApplyURI(config.GetDB().URI)} + opt := options.Client().ApplyURI(config.GetDB().URI).SetRegistry(reg) + clientOps := []*options.ClientOptions{opt} if config.GetDB().SSLEnabled { if config.GetDB().RootCA == "" { err = ErrRootCAMissing From a0208f73bb17d5e4210ce4da57f3d0818cce4166 Mon Sep 17 00:00:00 2001 From: three Date: Mon, 9 Dec 2019 18:19:22 +0800 Subject: [PATCH 2/9] SCB-1563: Optimize &namednoop{} object creation --- server/crypto/crypto.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/crypto/crypto.go b/server/crypto/crypto.go index 55db5e0c..cf50e6ec 100644 --- a/server/crypto/crypto.go +++ b/server/crypto/crypto.go @@ -37,7 +37,8 @@ func Register(name string, c Cipher) { func Lookup(name string) Cipher { cipher, ok := ciphers[name] if !ok { - return &namedNoop{Name: name} + cipher = &namedNoop{Name: name} + ciphers[name] = cipher } return cipher From d3b4fca175900e898fa115645727ef6a702cb19f Mon Sep 17 00:00:00 2001 From: three Date: Mon, 9 Dec 2019 18:47:07 +0800 Subject: [PATCH 3/9] SCB-1563: add unit test --- server/resource/v1/history_resource_test.go | 5 +++++ server/resource/v1/kv_resource_test.go | 5 +++++ server/service/crypto_service.go | 3 +++ 3 files changed, 13 insertions(+) diff --git a/server/resource/v1/history_resource_test.go b/server/resource/v1/history_resource_test.go index 26617802..f0cb9e95 100644 --- a/server/resource/v1/history_resource_test.go +++ b/server/resource/v1/history_resource_test.go @@ -43,6 +43,7 @@ var _ = Describe("v1 history resource", func() { config.Configurations = &config.Config{ DB: config.DB{}, + Crypto: config.Crypto{}, } Describe("get history revisions", func() { @@ -51,6 +52,10 @@ var _ = Describe("v1 history resource", func() { It("should not return err", func() { Expect(err).Should(BeNil()) }) + err = service.CryptoInit() + It("should not return err", func() { + Expect(err).Should(BeNil()) + }) Context("valid param", func() { kv := &model.KVDoc{ Key: "test", diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go index 5fe878b1..580185b1 100644 --- a/server/resource/v1/kv_resource_test.go +++ b/server/resource/v1/kv_resource_test.go @@ -43,12 +43,17 @@ var _ = Describe("v1 kv resource", func() { //for UT config.Configurations = &config.Config{ DB: config.DB{}, + Crypto: config.Crypto{Name:"not_implemented"}, } config.Configurations.DB.URI = "mongodb://kie:123@127.0.0.1:27017" err := service.DBInit() if err != nil { panic(err) } + err = service.CryptoInit() + if err != nil { + panic(err) + } Describe("put kv", func() { Context("valid param", func() { kv := &model.KVDoc{ diff --git a/server/service/crypto_service.go b/server/service/crypto_service.go index 799f59b7..69a466e4 100644 --- a/server/service/crypto_service.go +++ b/server/service/crypto_service.go @@ -25,6 +25,9 @@ import ( ) func CryptoInit() error { + if config.GetCrypto().Name == "" { + return nil + } if KVService != nil { KVService = newCryptoKV(KVService) } From 75b2d9120deb1b13cbf80d1106ab37534de108ea Mon Sep 17 00:00:00 2001 From: three Date: Mon, 9 Dec 2019 21:30:29 +0800 Subject: [PATCH 4/9] SCB-1563: code format --- server/crypto/crypto_test.go | 6 +++--- server/crypto/noop.go | 2 +- server/resource/v1/history_resource_test.go | 2 +- server/resource/v1/kv_resource_test.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/server/crypto/crypto_test.go b/server/crypto/crypto_test.go index 99f9bbaf..310b6e30 100644 --- a/server/crypto/crypto_test.go +++ b/server/crypto/crypto_test.go @@ -24,7 +24,7 @@ import ( func TestLookup(t *testing.T) { type args struct { - name string + name string value string } tests := []struct { @@ -37,9 +37,9 @@ func TestLookup(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotCipher := Lookup(tt.args.name); + gotCipher := Lookup(tt.args.name) expect, _ := gotCipher.Encrypt(tt.args.value) - if !reflect.DeepEqual(expect, tt.want) { + if !reflect.DeepEqual(expect, tt.want) { t.Errorf("Lookup() = %v, want %v", expect, tt.want) } }) diff --git a/server/crypto/noop.go b/server/crypto/noop.go index 13e118ad..f20c6065 100644 --- a/server/crypto/noop.go +++ b/server/crypto/noop.go @@ -45,4 +45,4 @@ func (nn *namedNoop) Encrypt(src string) (string, error) { func (nn *namedNoop) Decrypt(src string) (string, error) { openlogging.Warn(fmt.Sprintf("security name [%s] not implemented.", nn.Name)) return src, nil -} \ No newline at end of file +} diff --git a/server/resource/v1/history_resource_test.go b/server/resource/v1/history_resource_test.go index f0cb9e95..5c7efdc3 100644 --- a/server/resource/v1/history_resource_test.go +++ b/server/resource/v1/history_resource_test.go @@ -42,7 +42,7 @@ import ( var _ = Describe("v1 history resource", func() { config.Configurations = &config.Config{ - DB: config.DB{}, + DB: config.DB{}, Crypto: config.Crypto{}, } diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go index 580185b1..09ed3f5e 100644 --- a/server/resource/v1/kv_resource_test.go +++ b/server/resource/v1/kv_resource_test.go @@ -42,8 +42,8 @@ import ( var _ = Describe("v1 kv resource", func() { //for UT config.Configurations = &config.Config{ - DB: config.DB{}, - Crypto: config.Crypto{Name:"not_implemented"}, + DB: config.DB{}, + Crypto: config.Crypto{Name: "not_implemented"}, } config.Configurations.DB.URI = "mongodb://kie:123@127.0.0.1:27017" err := service.DBInit() From 8c234e11ba2eaf11d68fb2460b06f248ad5a0d6b Mon Sep 17 00:00:00 2001 From: three Date: Mon, 9 Dec 2019 22:41:55 +0800 Subject: [PATCH 5/9] SCB-1563: fixed GoLint warnings --- server/config/struct.go | 1 + server/crypto/crypto.go | 3 ++- server/crypto/noop.go | 3 +++ server/resource/v1/kv_resource.go | 2 +- server/service/crypto_service.go | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/server/config/struct.go b/server/config/struct.go index 9f775438..e660e076 100644 --- a/server/config/struct.go +++ b/server/config/struct.go @@ -32,6 +32,7 @@ type DB struct { Timeout string `yaml:"timeout"` } +// Crypto is yaml file struct to set crypto config type Crypto struct { Name string `yaml:"name"` } diff --git a/server/crypto/crypto.go b/server/crypto/crypto.go index cf50e6ec..ff62e3ec 100644 --- a/server/crypto/crypto.go +++ b/server/crypto/crypto.go @@ -27,13 +27,14 @@ type Cipher interface { var ciphers map[string]Cipher +// Register is register crypto func Register(name string, c Cipher) { if ciphers == nil { ciphers = make(map[string]Cipher) } ciphers[name] = c } - +// Lookup is lookup crypto func Lookup(name string) Cipher { cipher, ok := ciphers[name] if !ok { diff --git a/server/crypto/noop.go b/server/crypto/noop.go index f20c6065..ab318e37 100644 --- a/server/crypto/noop.go +++ b/server/crypto/noop.go @@ -22,13 +22,16 @@ import ( "github.com/go-mesh/openlogging" ) +// Noop is none implement type Noop struct { } +// Encrypt implement func (*Noop) Encrypt(src string) (string, error) { return src, nil } +// Decrypt implement func (*Noop) Decrypt(src string) (string, error) { return src, nil } diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go index b8e20104..dba600ea 100644 --- a/server/resource/v1/kv_resource.go +++ b/server/resource/v1/kv_resource.go @@ -120,7 +120,7 @@ func (r *KVResource) List(rctx *restful.Context) { return } var limit int64 = 20 - var offset int64 = 0 + var offset int64 labels := make(map[string]string, 0) var err error for k, v := range rctx.ReadRequest().URL.Query() { diff --git a/server/service/crypto_service.go b/server/service/crypto_service.go index 69a466e4..9e9e0362 100644 --- a/server/service/crypto_service.go +++ b/server/service/crypto_service.go @@ -24,6 +24,7 @@ import ( "github.com/apache/servicecomb-kie/server/crypto" ) +// CryptoInit init crypto config func CryptoInit() error { if config.GetCrypto().Name == "" { return nil From bf0c31f5e5543b9ddfe82283a21538769fdaf773 Mon Sep 17 00:00:00 2001 From: three Date: Tue, 10 Dec 2019 10:57:33 +0800 Subject: [PATCH 6/9] SCB-1563: code format --- server/crypto/crypto.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/crypto/crypto.go b/server/crypto/crypto.go index ff62e3ec..f591bd2e 100644 --- a/server/crypto/crypto.go +++ b/server/crypto/crypto.go @@ -34,6 +34,7 @@ func Register(name string, c Cipher) { } ciphers[name] = c } + // Lookup is lookup crypto func Lookup(name string) Cipher { cipher, ok := ciphers[name] From 5de352382c4b048f488b638d455cad09fddd2f97 Mon Sep 17 00:00:00 2001 From: three Date: Wed, 11 Dec 2019 10:51:52 +0800 Subject: [PATCH 7/9] SCB-1563: fixed bug for code review --- cmd/kieserver/main.go | 3 +- examples/dev/kie-conf.yaml | 2 +- server/{crypto/crypto.go => cipher/cipher.go} | 38 +++++++++++++------ .../crypto_test.go => cipher/cipher_test.go} | 2 +- server/{crypto => cipher}/init.go | 2 +- server/{crypto => cipher}/noop.go | 2 +- .../crypto_service.go => cipher/service.go} | 38 ++++++------------- server/config/config.go | 4 +- server/config/config_test.go | 2 +- server/config/struct.go | 6 +-- server/resource/v1/history_resource_test.go | 5 ++- server/resource/v1/kv_resource_test.go | 5 ++- 12 files changed, 56 insertions(+), 53 deletions(-) rename server/{crypto/crypto.go => cipher/cipher.go} (62%) rename server/{crypto/crypto_test.go => cipher/cipher_test.go} (98%) rename server/{crypto => cipher}/init.go (98%) rename server/{crypto => cipher}/noop.go (98%) rename server/{service/crypto_service.go => cipher/service.go} (81%) diff --git a/cmd/kieserver/main.go b/cmd/kieserver/main.go index 2fffec79..b906bbee 100644 --- a/cmd/kieserver/main.go +++ b/cmd/kieserver/main.go @@ -18,6 +18,7 @@ package main import ( + "github.com/apache/servicecomb-kie/server/cipher" "github.com/apache/servicecomb-kie/server/service" "os" @@ -101,7 +102,7 @@ func main() { if err := service.DBInit(); err != nil { openlogging.Fatal(err.Error()) } - if err := service.CryptoInit(); err != nil { + if err := cipher.Init(); err != nil { openlogging.Fatal(err.Error()) } if err := chassis.Run(); err != nil { diff --git a/examples/dev/kie-conf.yaml b/examples/dev/kie-conf.yaml index ca8a75a0..959096a0 100644 --- a/examples/dev/kie-conf.yaml +++ b/examples/dev/kie-conf.yaml @@ -7,5 +7,5 @@ db: sslEnabled: false rootCAFile: /opt/kie/ca.crt -crypto: +cipher: name: noop \ No newline at end of file diff --git a/server/crypto/crypto.go b/server/cipher/cipher.go similarity index 62% rename from server/crypto/crypto.go rename to server/cipher/cipher.go index f591bd2e..22efe0f4 100644 --- a/server/crypto/crypto.go +++ b/server/cipher/cipher.go @@ -15,28 +15,27 @@ * limitations under the License. */ -package crypto +package cipher -//Cipher interface declares two function for encryption and decryption -//See https://github.com/go-chassis/foundation/blob/master/security/cipher.go -type Cipher interface { - Encrypt(src string) (string, error) - - Decrypt(src string) (string, error) -} +import ( + "github.com/apache/servicecomb-kie/server/config" + "github.com/apache/servicecomb-kie/server/service" + "github.com/go-chassis/foundation/security" +) -var ciphers map[string]Cipher +//See https://github.com/go-chassis/foundation/blob/master/security/cipher.go +var ciphers map[string]security.Cipher // Register is register crypto -func Register(name string, c Cipher) { +func Register(name string, c security.Cipher) { if ciphers == nil { - ciphers = make(map[string]Cipher) + ciphers = make(map[string]security.Cipher) } ciphers[name] = c } // Lookup is lookup crypto -func Lookup(name string) Cipher { +func Lookup(name string) security.Cipher { cipher, ok := ciphers[name] if !ok { cipher = &namedNoop{Name: name} @@ -45,3 +44,18 @@ func Lookup(name string) Cipher { return cipher } + +// Init init crypto config +func Init() error { + if config.GetCrypto().Name == "" { + return nil + } + if service.KVService != nil { + service.KVService = newCipherKV(service.KVService) + } + if service.HistoryService != nil { + service.HistoryService = newCipherHistory(service.HistoryService) + } + + return nil +} diff --git a/server/crypto/crypto_test.go b/server/cipher/cipher_test.go similarity index 98% rename from server/crypto/crypto_test.go rename to server/cipher/cipher_test.go index 310b6e30..7e720229 100644 --- a/server/crypto/crypto_test.go +++ b/server/cipher/cipher_test.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package crypto +package cipher import ( "reflect" diff --git a/server/crypto/init.go b/server/cipher/init.go similarity index 98% rename from server/crypto/init.go rename to server/cipher/init.go index c1008f27..74da9a2e 100644 --- a/server/crypto/init.go +++ b/server/cipher/init.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package crypto +package cipher func init() { Register("noop", &Noop{}) diff --git a/server/crypto/noop.go b/server/cipher/noop.go similarity index 98% rename from server/crypto/noop.go rename to server/cipher/noop.go index ab318e37..451d9de4 100644 --- a/server/crypto/noop.go +++ b/server/cipher/noop.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package crypto +package cipher import ( "fmt" diff --git a/server/service/crypto_service.go b/server/cipher/service.go similarity index 81% rename from server/service/crypto_service.go rename to server/cipher/service.go index 9e9e0362..e014a201 100644 --- a/server/service/crypto_service.go +++ b/server/cipher/service.go @@ -15,49 +15,35 @@ * limitations under the License. */ -package service +package cipher import ( "context" "github.com/apache/servicecomb-kie/pkg/model" "github.com/apache/servicecomb-kie/server/config" - "github.com/apache/servicecomb-kie/server/crypto" + "github.com/apache/servicecomb-kie/server/service" + "github.com/go-chassis/foundation/security" ) -// CryptoInit init crypto config -func CryptoInit() error { - if config.GetCrypto().Name == "" { - return nil - } - if KVService != nil { - KVService = newCryptoKV(KVService) - } - if HistoryService != nil { - HistoryService = newCryptoHistory(HistoryService) - } - - return nil -} - -func newCryptoHistory(service History) History { +func newCipherHistory(service service.History) service.History { return &cryptoHistory{service: service} } -func newCryptoKV(service KV) KV { +func newCipherKV(service service.KV) service.KV { return &cryptoKV{service: service} } -// lookup Crypto -func lookupCrypto(kv *model.KVDoc) crypto.Cipher { - return crypto.Lookup(config.GetCrypto().Name) +// lookup Cipher +func lookupCrypto(unused *model.KVDoc) security.Cipher { + return Lookup(config.GetCrypto().Name) } // History service security proxy type cryptoHistory struct { - service History + service service.History } -func (history *cryptoHistory) GetHistory(ctx context.Context, labelID string, options ...FindOption) ([]*model.LabelRevisionDoc, error) { +func (history *cryptoHistory) GetHistory(ctx context.Context, labelID string, options ...service.FindOption) ([]*model.LabelRevisionDoc, error) { res, err := history.service.GetHistory(ctx, labelID, options...) cipher := lookupCrypto(nil) @@ -79,7 +65,7 @@ func (history *cryptoHistory) GetHistory(ctx context.Context, labelID string, op // KV service security proxy type cryptoKV struct { - service KV + service service.KV } func (ckv *cryptoKV) CreateOrUpdate(ctx context.Context, kv *model.KVDoc) (*model.KVDoc, error) { @@ -127,7 +113,7 @@ func (ckv *cryptoKV) Delete(kvID string, labelID string, domain, project string) return ckv.Delete(kvID, labelID, domain, project) } -func (ckv *cryptoKV) FindKV(ctx context.Context, domain, project string, options ...FindOption) ([]*model.KVResponse, error) { +func (ckv *cryptoKV) FindKV(ctx context.Context, domain, project string, options ...service.FindOption) ([]*model.KVResponse, error) { res, err := ckv.service.FindKV(ctx, domain, project, options...) cipher := lookupCrypto(nil) if res == nil { diff --git a/server/config/config.go b/server/config/config.go index 194ec48c..7be31975 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -44,6 +44,6 @@ func GetDB() DB { } //GetCrypto return crypto configs -func GetCrypto() Crypto { - return Configurations.Crypto +func GetCrypto() Cipher { + return Configurations.Cipher } diff --git a/server/config/config_test.go b/server/config/config_test.go index 0f8f9ef8..6e0a4d45 100644 --- a/server/config/config_test.go +++ b/server/config/config_test.go @@ -37,7 +37,7 @@ db: ssl: false sslCA: sslCert: -crypto: +cipher: name: noop `) defer os.Remove("test.yaml") diff --git a/server/config/struct.go b/server/config/struct.go index e660e076..a4a0beb1 100644 --- a/server/config/struct.go +++ b/server/config/struct.go @@ -20,7 +20,7 @@ package config //Config is yaml file struct type Config struct { DB DB `yaml:"db"` - Crypto Crypto `yaml:"crypto"` + Cipher Cipher `yaml:"cipher"` } //DB is yaml file struct to set mongodb config @@ -32,7 +32,7 @@ type DB struct { Timeout string `yaml:"timeout"` } -// Crypto is yaml file struct to set crypto config -type Crypto struct { +// Cipher is yaml file struct to set crypto config +type Cipher struct { Name string `yaml:"name"` } diff --git a/server/resource/v1/history_resource_test.go b/server/resource/v1/history_resource_test.go index 5c7efdc3..bf2b6af8 100644 --- a/server/resource/v1/history_resource_test.go +++ b/server/resource/v1/history_resource_test.go @@ -19,6 +19,7 @@ package v1_test import ( "context" "encoding/json" + "github.com/apache/servicecomb-kie/server/cipher" "github.com/apache/servicecomb-kie/server/service" "io/ioutil" @@ -43,7 +44,7 @@ var _ = Describe("v1 history resource", func() { config.Configurations = &config.Config{ DB: config.DB{}, - Crypto: config.Crypto{}, + Cipher: config.Cipher{}, } Describe("get history revisions", func() { @@ -52,7 +53,7 @@ var _ = Describe("v1 history resource", func() { It("should not return err", func() { Expect(err).Should(BeNil()) }) - err = service.CryptoInit() + err = cipher.Init() It("should not return err", func() { Expect(err).Should(BeNil()) }) diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go index 09ed3f5e..75eb1229 100644 --- a/server/resource/v1/kv_resource_test.go +++ b/server/resource/v1/kv_resource_test.go @@ -20,6 +20,7 @@ package v1_test import ( "bytes" "encoding/json" + "github.com/apache/servicecomb-kie/server/cipher" "github.com/apache/servicecomb-kie/server/service" "io/ioutil" "log" @@ -43,14 +44,14 @@ var _ = Describe("v1 kv resource", func() { //for UT config.Configurations = &config.Config{ DB: config.DB{}, - Crypto: config.Crypto{Name: "not_implemented"}, + Cipher: config.Cipher{Name: "not_implemented"}, } config.Configurations.DB.URI = "mongodb://kie:123@127.0.0.1:27017" err := service.DBInit() if err != nil { panic(err) } - err = service.CryptoInit() + err = cipher.Init() if err != nil { panic(err) } From 8d5b918bbb043c7fb8b9d5cc2a31da33e9ed8735 Mon Sep 17 00:00:00 2001 From: three Date: Tue, 17 Dec 2019 16:03:32 +0800 Subject: [PATCH 8/9] SCB-1563: add unit test --- server/cipher/cipher_test.go | 31 ++++++++ server/cipher/noop_test.go | 141 +++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 server/cipher/noop_test.go diff --git a/server/cipher/cipher_test.go b/server/cipher/cipher_test.go index 7e720229..1d412ef8 100644 --- a/server/cipher/cipher_test.go +++ b/server/cipher/cipher_test.go @@ -42,6 +42,37 @@ func TestLookup(t *testing.T) { if !reflect.DeepEqual(expect, tt.want) { t.Errorf("Lookup() = %v, want %v", expect, tt.want) } + + expect, _ = gotCipher.Decrypt(tt.args.value) + if !reflect.DeepEqual(expect, tt.want) { + t.Errorf("Lookup() = %v, want %v", expect, tt.want) + } }) } } + +type testCipher struct {} + +func (*testCipher) Encrypt(src string) (string, error) { + panic("implement me") +} + +func (*testCipher) Decrypt(src string) (string, error) { + panic("implement me") +} + +func TestRegister(t *testing.T) { + test := &testCipher{} + noop2 := &namedNoop{} + Register("test", test) + Register("noop2", noop2) + + act := Lookup("test") + if !reflect.DeepEqual(test, act) { + t.Errorf("Register() = %v, want %v", test, act) + } + act = Lookup("noop2") + if !reflect.DeepEqual(noop2, act) { + t.Errorf("Register() = %v, want %v", noop2, act) + } +} diff --git a/server/cipher/noop_test.go b/server/cipher/noop_test.go new file mode 100644 index 00000000..97f168b7 --- /dev/null +++ b/server/cipher/noop_test.go @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 cipher + +import "testing" + +func TestNoop_Encrypt(t *testing.T) { + type args struct { + src string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + {"empty", args{""}, "", false}, + {"123", args{"123"}, "123", false}, + {"nil", args{}, "", false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + n := &Noop{} + got, err := n.Encrypt(tt.args.src) + if (err != nil) != tt.wantErr { + t.Errorf("Noop.Encrypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Noop.Encrypt() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNoop_Decrypt(t *testing.T) { + type args struct { + src string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + {"empty", args{""}, "", false}, + {"123", args{"123"}, "123", false}, + {"nil", args{}, "", false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + n := &Noop{} + got, err := n.Decrypt(tt.args.src) + if (err != nil) != tt.wantErr { + t.Errorf("Noop.Decrypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Noop.Decrypt() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_namedNoop_Encrypt(t *testing.T) { + type args struct { + src string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + {"empty", args{""}, "", false}, + {"123", args{"123"}, "123", false}, + {"nil", args{}, "", false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + nn := &namedNoop{ + Name: "any", + } + got, err := nn.Encrypt(tt.args.src) + if (err != nil) != tt.wantErr { + t.Errorf("namedNoop.Encrypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("namedNoop.Encrypt() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_namedNoop_Decrypt(t *testing.T) { + + type args struct { + src string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + {"empty", args{""}, "", false}, + {"123", args{"123"}, "123", false}, + {"nil", args{}, "", false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + nn := &namedNoop{ + Name: "any", + } + got, err := nn.Decrypt(tt.args.src) + if (err != nil) != tt.wantErr { + t.Errorf("namedNoop.Decrypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("namedNoop.Decrypt() = %v, want %v", got, tt.want) + } + }) + } +} From e2218b08d06114b972f60de85a8508a666124095 Mon Sep 17 00:00:00 2001 From: three Date: Tue, 17 Dec 2019 16:37:08 +0800 Subject: [PATCH 9/9] SCB-1563: code format --- server/cipher/cipher_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/cipher/cipher_test.go b/server/cipher/cipher_test.go index 1d412ef8..f75ce808 100644 --- a/server/cipher/cipher_test.go +++ b/server/cipher/cipher_test.go @@ -51,14 +51,14 @@ func TestLookup(t *testing.T) { } } -type testCipher struct {} +type testCipher struct{} func (*testCipher) Encrypt(src string) (string, error) { - panic("implement me") + return src, nil } func (*testCipher) Decrypt(src string) (string, error) { - panic("implement me") + return src, nil } func TestRegister(t *testing.T) {