diff --git a/Makefile b/Makefile index 42141538..0830fd35 100644 --- a/Makefile +++ b/Makefile @@ -32,3 +32,4 @@ build-server: build-client: TAG=${TAG} hack/build-client.sh + diff --git a/cmd/clientv2/main.go b/cmd/clientv2/main.go deleted file mode 100644 index d6ea30d0..00000000 --- a/cmd/clientv2/main.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. -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 ( - "bufio" - "context" - "encoding/base64" - "flag" - "fmt" - "log" - "os" - "strings" - - pb "k8s.io/kms/apis/v2" - "sigs.k8s.io/aws-encryption-provider/pkg/connection" -) - -var ( - addr = flag.String("listen", "/tmp/awsencryptionprovider.sock", "GRPC listen address") -) - -func main() { - flag.Parse() - - conn, err := connection.New(*addr) - if err != nil { - log.Fatalf("Failed to initialize client: %v", err) - } - defer conn.Close() - - client := pb.NewKeyManagementServiceClient(conn) - - fmt.Println("Welcome to GRPC Client") - fmt.Println("----------------------") - - ctx := context.Background() - - vReq := &pb.StatusRequest{} - vRes, err := client.Status(ctx, vReq) - if err != nil { - log.Fatalf("Failed to get version: %v", err) - } - - fmt.Println("Connected to GRPC Server", vRes.Version, vRes.Healthz, vRes.KeyId) - - reader := bufio.NewReader(os.Stdin) - fmt.Print("encrypt \ndecrypt \n") - for { - fmt.Print("->") - text, _ := reader.ReadString('\n') - text = strings.Replace(text, "\n", "", -1) - - splits := strings.SplitN(text, " ", 2) - - switch splits[0] { - case "encrypt": - eReq := &pb.EncryptRequest{Plaintext: []byte(splits[1])} - res, err := client.Encrypt(ctx, eReq) - if err != nil { - log.Fatalf("Failed to encrypt: %v", err) - } - fmt.Println(base64.StdEncoding.EncodeToString(res.Ciphertext)) - fmt.Println("KeyId is: ", res.KeyId) - case "decrypt": - b, err := base64.StdEncoding.DecodeString(splits[1]) - if err != nil { - log.Fatalf("Failed to decode: %v", err) - } - dReq := &pb.DecryptRequest{Ciphertext: b} - res, err := client.Decrypt(ctx, dReq) - if err != nil { - log.Fatalf("Failed to encrypt: %v", err) - } - fmt.Println(string(res.Plaintext)) - } - } -} diff --git a/cmd/server/main.go b/cmd/server/main.go index c36efebb..6733a67a 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -84,8 +84,6 @@ func main() { s := server.New() p := plugin.New(*key, c, *encryptionCtx) p.Register(s.Server) - p2 := plugin.NewV2(*key, c, *encryptionCtx) - p2.Register(s.Server) go func() { http.Handle(*healthzPath, healthz.NewHandler(p)) http.Handle(*livezPath, livez.NewHandler(p)) diff --git a/go.mod b/go.mod index 1d2a478b..66ec32f9 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( go.uber.org/zap v1.19.0 golang.org/x/time v0.3.0 google.golang.org/grpc v1.59.0 - k8s.io/kms v0.28.1 + k8s.io/kms v0.28.0 ) require ( diff --git a/go.sum b/go.sum index 425a5187..799d06de 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aws/aws-sdk-go v1.44.145 h1:KMVRrIyjBsNz3xGPuHIRnhIuKlb5h3Ii5e5jbi3cgnc= github.com/aws/aws-sdk-go v1.44.145/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -48,6 +49,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -56,6 +58,11 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -63,7 +70,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -105,6 +115,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -119,6 +130,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -131,8 +143,10 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -203,6 +217,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -215,6 +230,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= @@ -229,6 +245,7 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= @@ -306,6 +323,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -437,7 +455,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -507,6 +524,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.55.0-dev h1:b3WG8LoyS+X/C5ZbIWsJGjt8Hhqq0wUVX8+rPF/BHZo= +google.golang.org/grpc v1.55.0-dev/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -527,7 +546,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -536,11 +554,9 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -549,8 +565,10 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/kms v0.28.1 h1:QLNTIc0k7Yebkt9yobj9Y9qBoRCMB4dq+pFCxVXVBnY= -k8s.io/kms v0.28.1/go.mod h1:I2TwA8oerDRInHWWBOqSUzv1EJDC1+55FQKYkxaPxh0= +k8s.io/kms v0.27.0-alpha.3 h1:HhHp6WvmqHc9sMlyG1WFO+w3Q6nlpntf2bgJmONm/qE= +k8s.io/kms v0.27.0-alpha.3/go.mod h1:M1hyFQ5Ar0OLsO3h6wmDLgZ6AnjLRA2atl3iARZTnL0= +k8s.io/kms v0.28.0 h1:BwJhU9qPcJhHLUcQjtelOSjYti+1/caJLr+4jHbKzTA= +k8s.io/kms v0.28.0/go.mod h1:CNU792ls92v2Ye7Vn1jn+xLqYtUSezDZNVu6PLbJyrU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/healthz/healthz.go b/pkg/healthz/healthz.go index a48a8acf..0adc16c3 100644 --- a/pkg/healthz/healthz.go +++ b/pkg/healthz/healthz.go @@ -10,12 +10,12 @@ import ( ) // NewHandler returns a new healthz handler. -func NewHandler(p *plugin.V1Plugin) http.Handler { +func NewHandler(p *plugin.Plugin) http.Handler { return &handler{p: p} } type handler struct { - p *plugin.V1Plugin + p *plugin.Plugin } func (hd *handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/kmsplugin/kms.go b/pkg/kmsplugin/kms.go deleted file mode 100644 index 0dfd55b9..00000000 --- a/pkg/kmsplugin/kms.go +++ /dev/null @@ -1,126 +0,0 @@ -package kmsplugin - -import ( - "errors" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/request" - awsreq "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/kms" - "go.uber.org/zap" -) - -type KMSErrorType int - -const ( - KMSErrorTypeNil = KMSErrorType(iota) - KMSErrorTypeUserInduced - KMSErrorTypeThrottled - KMSErrorTypeOther -) - -func (t KMSErrorType) String() string { - switch t { - case KMSErrorTypeNil: - return "" - case KMSErrorTypeUserInduced: - return "user-induced" - case KMSErrorTypeThrottled: - return "throttled" - case KMSErrorTypeOther: - return "other" - default: - return "" - } -} - -// ParseError parses error codes from KMS -// ref. https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html -// ref. https://docs.aws.amazon.com/sdk-for-go/api/service/kms/ -func ParseError(err error) (errorType KMSErrorType) { - if err == nil { - return KMSErrorTypeNil - } - - uerr := errors.Unwrap(err) - if uerr == nil { - // in case the error was not wrapped, - // preserve the original error type - uerr = err - } - - ev, ok := uerr.(awserr.Error) - if !ok { - return KMSErrorTypeOther - } - - zap.L().Debug("parsed error", zap.String("code", ev.Code()), zap.String("message", ev.Message())) - if request.IsErrorThrottle(uerr) { - return KMSErrorTypeThrottled - } - switch ev.Code() { - // CMK is disabled or pending deletion - case kms.ErrCodeDisabledException, - kms.ErrCodeInvalidStateException: - return KMSErrorTypeUserInduced - - // CMK does not exist, or grant is not valid - case kms.ErrCodeKeyUnavailableException, - kms.ErrCodeInvalidArnException, - kms.ErrCodeInvalidGrantIdException, - kms.ErrCodeInvalidGrantTokenException: - return KMSErrorTypeUserInduced - - // ref. https://docs.aws.amazon.com/kms/latest/developerguide/requests-per-second.html - case kms.ErrCodeLimitExceededException: - return KMSErrorTypeThrottled - - // AWS SDK Go for KMS does not "yet" define specific error code for a case where a customer specifies the deleted key - // "AccessDeniedException" error code may be returned when (1) CMK does not exist (not pending delete), - // or (2) corresponding IAM role is not allowed to access the key. - // Thus we only want to mark "AccessDeniedException" as user-induced for the case (1). - // e.g., "AccessDeniedException: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access." - // KMS service may change the error message, so we do the string match. - case "AccessDeniedException": - if strings.Contains(ev.Message(), "customer master key that does not exist") || - strings.Contains(ev.Message(), "does not exist in this region") { - return KMSErrorTypeUserInduced - } - } - - return KMSErrorTypeOther -} - -const ( - StatusSuccess = "success" - StatusFailure = "failure" - StatusFailureThrottle = "failure-throttle" - OperationEncrypt = "encrypt" - OperationDecrypt = "decrypt" -) - -// StorageVersion is a prefix used for versioning encrypted content -const StorageVersion = "1" - -// TODO: make configurable -const ( - DefaultHealthCheckPeriod = 30 * time.Second - DefaultErrcBufSize = 100 -) - -func GetMillisecondsSince(startTime time.Time) float64 { - return time.Since(startTime).Seconds() * 1000 -} - -func GetStatusLabel(err error) string { - switch { - case err == nil: - return StatusSuccess - case awsreq.IsErrorThrottle(err): - return StatusFailureThrottle - default: - return StatusFailure - } -} diff --git a/pkg/livez/livez.go b/pkg/livez/livez.go index a06dc547..e4e9d357 100644 --- a/pkg/livez/livez.go +++ b/pkg/livez/livez.go @@ -10,12 +10,12 @@ import ( ) // NewHandler returns a new livez handler. -func NewHandler(p *plugin.V1Plugin) http.Handler { +func NewHandler(p *plugin.Plugin) http.Handler { return &handler{p: p} } type handler struct { - p *plugin.V1Plugin + p *plugin.Plugin } func (hd *handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/plugin/metrics.go b/pkg/plugin/metrics.go index 91ab6cee..8cfcaf2b 100644 --- a/pkg/plugin/metrics.go +++ b/pkg/plugin/metrics.go @@ -9,8 +9,6 @@ func init() { func registerPrometheusMetrics() { prometheus.MustRegister(kmsOperationCounter) prometheus.MustRegister(kmsLatencyMetric) - prometheus.MustRegister(kmsOperationCounterV2) - prometheus.MustRegister(kmsLatencyMetricV2) } var ( @@ -38,29 +36,4 @@ var ( "operation", }, ) - - kmsOperationCounterV2 = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "aws_encryption_provider_kmsv2_operations_total", - Help: "total aws encryption provider kms v2 operations", - }, - []string{ - "key_arn", - "status", - "operation", - }, - ) - - kmsLatencyMetricV2 = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "aws_encryption_provider_kmsv2_operation_latency_ms", - Help: "Response latency in milliseconds for aws encryption provider kms v2 operation ", - Buckets: prometheus.ExponentialBuckets(2, 2, 14), - }, - []string{ - "key_arn", - "status", - "operation", - }, - ) ) diff --git a/pkg/plugin/metrics_test.go b/pkg/plugin/metrics_test.go index 6ca3b6ac..bf81f05d 100644 --- a/pkg/plugin/metrics_test.go +++ b/pkg/plugin/metrics_test.go @@ -18,7 +18,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "go.uber.org/zap" pb "k8s.io/kms/apis/v1beta1" - pb2 "k8s.io/kms/apis/v2" "sigs.k8s.io/aws-encryption-provider/pkg/cloud" "sigs.k8s.io/aws-encryption-provider/pkg/server" ) @@ -108,89 +107,3 @@ func TestMetrics(t *testing.T) { }) } } - -// TestMetricsV2 tests /metrics handler. -func TestMetricsV2(t *testing.T) { - zap.ReplaceGlobals(zap.NewExample()) - - tt := []struct { - key string - encryptErr error - expects string - }{ - { - key: "test-key", - encryptErr: errors.New("fail"), - expects: `aws_encryption_provider_kmsv2_operations_total{key_arn="test-key",operation="encrypt",status="failure"} 1`, - }, - { - key: "test-key-throttle", - encryptErr: awserr.New("RequestLimitExceeded", "test", errors.New("fail")), - expects: `aws_encryption_provider_kmsv2_operations_total{key_arn="test-key-throttle",operation="encrypt",status="failure-throttle"} 1`, - }, - } - for i, entry := range tt { - t.Run(entry.key, func(t *testing.T) { - addr := filepath.Join(os.TempDir(), fmt.Sprintf("metrics%x", rand.Int63())) - defer os.RemoveAll(addr) - - c := &cloud.KMSMock{} - c.SetEncryptResp("test", entry.encryptErr) - - p := NewV2(entry.key, c, nil) - - ready, errc := make(chan struct{}), make(chan error) - s := server.New() - (*p).Register(s.Server) - defer func() { - s.Server.Stop() - if err := <-errc; err != nil { - t.Fatalf("unexpected gRPC server stop error %v", err) - } - }() - go func() { - close(ready) - errc <- s.ListenAndServe(addr) - }() - - // wait enough for unix socket to be open - time.Sleep(time.Second) - select { - case <-ready: - case <-time.After(2 * time.Second): - t.Fatal("took too long to start gRPC server") - } - - mux := http.NewServeMux() - mux.Handle("/metrics", promhttp.Handler()) - - ts := httptest.NewServer(mux) - defer ts.Close() - - u := ts.URL + "/metrics" - - _, err := p.Encrypt(context.Background(), &pb2.EncryptRequest{Plaintext: []byte("hello")}) - if err != nil { - if entry.encryptErr == nil { - t.Fatal(err) - } - if !strings.Contains(err.Error(), entry.encryptErr.Error()) { - t.Fatalf("#%d: unexpected error %v", i, err) - } - } - - resp, err := http.Get(u) - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - d, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(string(d), entry.expects) { - t.Fatalf("#%d: expected %q, got\n\n%s\n\n", i, entry.expects, string(d)) - } - }) - } -} diff --git a/pkg/plugin/plugin.go b/pkg/plugin/plugin.go index d198431c..d256a01e 100644 --- a/pkg/plugin/plugin.go +++ b/pkg/plugin/plugin.go @@ -15,24 +15,121 @@ package plugin import ( "context" + "errors" "fmt" + "strings" "sync" "time" "github.com/aws/aws-sdk-go/aws" + //nolint + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + awsreq "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/kms/kmsiface" "go.uber.org/zap" "google.golang.org/grpc" pb "k8s.io/kms/apis/v1beta1" - "sigs.k8s.io/aws-encryption-provider/pkg/kmsplugin" "sigs.k8s.io/aws-encryption-provider/pkg/version" ) -var _ pb.KeyManagementServiceServer = &V1Plugin{} +type KMSErrorType int + +const ( + KMSErrorTypeNil = KMSErrorType(iota) + KMSErrorTypeUserInduced + KMSErrorTypeThrottled + KMSErrorTypeOther +) + +func (t KMSErrorType) String() string { + switch t { + case KMSErrorTypeNil: + return "" + case KMSErrorTypeUserInduced: + return "user-induced" + case KMSErrorTypeThrottled: + return "throttled" + case KMSErrorTypeOther: + return "other" + default: + return "" + } +} + +// ParseError parses error codes from KMS +// ref. https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html +// ref. https://docs.aws.amazon.com/sdk-for-go/api/service/kms/ +func ParseError(err error) (errorType KMSErrorType) { + if err == nil { + return KMSErrorTypeNil + } + + uerr := errors.Unwrap(err) + if uerr == nil { + // in case the error was not wrapped, + // preserve the original error type + uerr = err + } + + ev, ok := uerr.(awserr.Error) + if !ok { + return KMSErrorTypeOther + } + + zap.L().Debug("parsed error", zap.String("code", ev.Code()), zap.String("message", ev.Message())) + if request.IsErrorThrottle(uerr) { + return KMSErrorTypeThrottled + } + switch ev.Code() { + // CMK is disabled or pending deletion + case kms.ErrCodeDisabledException, + kms.ErrCodeInvalidStateException: + return KMSErrorTypeUserInduced + + // CMK does not exist, or grant is not valid + case kms.ErrCodeKeyUnavailableException, + kms.ErrCodeInvalidArnException, + kms.ErrCodeInvalidGrantIdException, + kms.ErrCodeInvalidGrantTokenException: + return KMSErrorTypeUserInduced + + // ref. https://docs.aws.amazon.com/kms/latest/developerguide/requests-per-second.html + case kms.ErrCodeLimitExceededException: + return KMSErrorTypeThrottled + + // AWS SDK Go for KMS does not "yet" define specific error code for a case where a customer specifies the deleted key + // "AccessDeniedException" error code may be returned when (1) CMK does not exist (not pending delete), + // or (2) corresponding IAM role is not allowed to access the key. + // Thus we only want to mark "AccessDeniedException" as user-induced for the case (1). + // e.g., "AccessDeniedException: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access." + // KMS service may change the error message, so we do the string match. + case "AccessDeniedException": + if strings.Contains(ev.Message(), "customer master key that does not exist") || + strings.Contains(ev.Message(), "does not exist in this region") { + return KMSErrorTypeUserInduced + } + } + + return KMSErrorTypeOther +} + +const ( + statusSuccess = "success" + statusFailure = "failure" + statusFailureThrottle = "failure-throttle" + operationEncrypt = "encrypt" + operationDecrypt = "decrypt" +) + +// StorageVersion is a prefix used for versioning encrypted content +const StorageVersion = "1" + +var _ pb.KeyManagementServiceServer = &Plugin{} // Plugin implements the KeyManagementServiceServer -type V1Plugin struct { +type Plugin struct { svc kmsiface.KMSAPI keyID string encryptionCtx map[string]*string @@ -54,8 +151,8 @@ const ( defaultErrcBufSize = 100 ) -// New returns a new *V1Plugin -func New(key string, svc kmsiface.KMSAPI, encryptionCtx map[string]string) *V1Plugin { +// New returns a new *Plugin +func New(key string, svc kmsiface.KMSAPI, encryptionCtx map[string]string) *Plugin { return newPlugin( key, svc, @@ -71,8 +168,8 @@ func newPlugin( encryptionCtx map[string]string, checkPeriod time.Duration, errcBuf int, -) *V1Plugin { - p := &V1Plugin{ +) *Plugin { + p := &Plugin{ svc: svc, keyID: key, healthCheckPeriod: checkPeriod, @@ -91,7 +188,7 @@ func newPlugin( return p } -func (p *V1Plugin) startCheckHealth() { +func (p *Plugin) startCheckHealth() { zap.L().Info("starting health check routine", zap.String("period", p.healthCheckPeriod.String())) for { select { @@ -105,14 +202,14 @@ func (p *V1Plugin) startCheckHealth() { } } -func (p *V1Plugin) stopCheckHealth() { +func (p *Plugin) stopCheckHealth() { p.healthCheckStopcCloseOnce.Do(func() { close(p.healthCheckStopc) <-p.healthCheckClosed }) } -func (p *V1Plugin) isRecentlyChecked() (bool, error) { +func (p *Plugin) isRecentlyChecked() (bool, error) { p.lastMu.RLock() err, ts := p.lastErr, p.lastTs never, latest := err == nil && ts.IsZero(), time.Since(ts) < p.healthCheckPeriod @@ -120,7 +217,7 @@ func (p *V1Plugin) isRecentlyChecked() (bool, error) { return !never && latest, err } -func (p *V1Plugin) recordErr(err error) { +func (p *Plugin) recordErr(err error) { p.lastMu.Lock() p.lastErr, p.lastTs = err, time.Now() p.lastMu.Unlock() @@ -129,7 +226,7 @@ func (p *V1Plugin) recordErr(err error) { // Health checks KMS API availability. // // The goal is to: -// 1. not incur extra KMS API call if V1Plugin "Encrypt" method has already +// 1. not incur extra KMS API call if plugin "Encrypt" method has already // 2. return latest health status (cached KMS status must reflect the current) // // The error is sent via channel and consumed by goroutine. @@ -141,7 +238,7 @@ func (p *V1Plugin) recordErr(err error) { // 1. there was never a health check done // 2. there was no health check done for the last "healthCheckPeriod" // (only use the cached error if the error is from recent API call) -func (p *V1Plugin) Health() error { +func (p *Plugin) Health() error { recent, err := p.isRecentlyChecked() if !recent { _, err = p.Encrypt(context.Background(), &pb.EncryptRequest{Plain: []byte("foo")}) @@ -162,15 +259,15 @@ func (p *V1Plugin) Health() error { // Live checks the liveness of KMS API. // If the error is user-induced (e.g., revoke CMK), the function returns NO error. // If the error is due to KMS availability, the function returns the error. -func (p *V1Plugin) Live() error { - if err := p.Health(); err != nil && kmsplugin.ParseError(err) != kmsplugin.KMSErrorTypeUserInduced { +func (p *Plugin) Live() error { + if err := p.Health(); err != nil && ParseError(err) != KMSErrorTypeUserInduced { return err } return nil } -// Version returns the V1Plugin server version -func (p *V1Plugin) Version(ctx context.Context, request *pb.VersionRequest) (*pb.VersionResponse, error) { +// Version returns the plugin server version +func (p *Plugin) Version(ctx context.Context, request *pb.VersionRequest) (*pb.VersionResponse, error) { return &pb.VersionResponse{ Version: version.APIVersion, RuntimeName: version.Runtime, @@ -179,7 +276,7 @@ func (p *V1Plugin) Version(ctx context.Context, request *pb.VersionRequest) (*pb } // Encrypt executes the encryption operation using AWS KMS -func (p *V1Plugin) Encrypt(ctx context.Context, request *pb.EncryptRequest) (*pb.EncryptResponse, error) { +func (p *Plugin) Encrypt(ctx context.Context, request *pb.EncryptRequest) (*pb.EncryptResponse, error) { zap.L().Debug("starting encrypt operation") startTime := time.Now() @@ -198,25 +295,25 @@ func (p *V1Plugin) Encrypt(ctx context.Context, request *pb.EncryptRequest) (*pb case p.healthCheckErrc <- err: default: } - zap.L().Error("request to encrypt failed", zap.String("error-type", kmsplugin.ParseError(err).String()), zap.Error(err)) - failLabel := kmsplugin.GetStatusLabel(err) - kmsLatencyMetric.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationEncrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounter.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationEncrypt).Inc() + zap.L().Error("request to encrypt failed", zap.String("error-type", ParseError(err).String()), zap.Error(err)) + failLabel := getStatusLabel(err) + kmsLatencyMetric.WithLabelValues(p.keyID, failLabel, operationEncrypt).Observe(getMillisecondsSince(startTime)) + kmsOperationCounter.WithLabelValues(p.keyID, failLabel, operationEncrypt).Inc() return nil, fmt.Errorf("failed to encrypt %w", err) } zap.L().Debug("encrypt operation successful") - kmsLatencyMetric.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationEncrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounter.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationEncrypt).Inc() - return &pb.EncryptResponse{Cipher: append([]byte(kmsplugin.StorageVersion), result.CiphertextBlob...)}, nil + kmsLatencyMetric.WithLabelValues(p.keyID, statusSuccess, operationEncrypt).Observe(getMillisecondsSince(startTime)) + kmsOperationCounter.WithLabelValues(p.keyID, statusSuccess, operationEncrypt).Inc() + return &pb.EncryptResponse{Cipher: append([]byte(StorageVersion), result.CiphertextBlob...)}, nil } // Decrypt executes the decrypt operation using AWS KMS -func (p *V1Plugin) Decrypt(ctx context.Context, request *pb.DecryptRequest) (*pb.DecryptResponse, error) { +func (p *Plugin) Decrypt(ctx context.Context, request *pb.DecryptRequest) (*pb.DecryptResponse, error) { zap.L().Debug("starting decrypt operation") startTime := time.Now() - if string(request.Cipher[0]) == kmsplugin.StorageVersion { + if string(request.Cipher[0]) == StorageVersion { request.Cipher = request.Cipher[1:] } input := &kms.DecryptInput{ @@ -233,22 +330,22 @@ func (p *V1Plugin) Decrypt(ctx context.Context, request *pb.DecryptRequest) (*pb case p.healthCheckErrc <- err: default: } - zap.L().Error("request to decrypt failed", zap.String("error-type", kmsplugin.ParseError(err).String()), zap.Error(err)) - failLabel := kmsplugin.GetStatusLabel(err) - kmsLatencyMetric.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationDecrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounter.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationDecrypt).Inc() + zap.L().Error("request to decrypt failed", zap.String("error-type", ParseError(err).String()), zap.Error(err)) + failLabel := getStatusLabel(err) + kmsLatencyMetric.WithLabelValues(p.keyID, failLabel, operationDecrypt).Observe(getMillisecondsSince(startTime)) + kmsOperationCounter.WithLabelValues(p.keyID, failLabel, operationDecrypt).Inc() return nil, fmt.Errorf("failed to decrypt %w", err) } zap.L().Debug("decrypt operation successful") - kmsLatencyMetric.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationDecrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounter.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationDecrypt).Inc() + kmsLatencyMetric.WithLabelValues(p.keyID, statusSuccess, operationDecrypt).Observe(getMillisecondsSince(startTime)) + kmsOperationCounter.WithLabelValues(p.keyID, statusSuccess, operationDecrypt).Inc() return &pb.DecryptResponse{Plain: result.Plaintext}, nil } -// Register registers the V1Plugin with the grpc server -func (p *V1Plugin) Register(s *grpc.Server) { - zap.L().Info("registering the kmsplugin plugin with grpc server") +// Register registers the plugin with the grpc server +func (p *Plugin) Register(s *grpc.Server) { + zap.L().Info("registering the kms plugin with grpc server") pb.RegisterKeyManagementServiceServer(s, p) } @@ -270,3 +367,18 @@ func WaitForReady(client pb.KeyManagementServiceClient, duration time.Duration) func NewClient(conn *grpc.ClientConn) pb.KeyManagementServiceClient { return pb.NewKeyManagementServiceClient(conn) } + +func getMillisecondsSince(startTime time.Time) float64 { + return time.Since(startTime).Seconds() * 1000 +} + +func getStatusLabel(err error) string { + switch { + case err == nil: + return statusSuccess + case awsreq.IsErrorThrottle(err): + return statusFailureThrottle + default: + return statusFailure + } +} diff --git a/pkg/plugin/plugin_test.go b/pkg/plugin/plugin_test.go index 7bea27ce..3c96cb81 100644 --- a/pkg/plugin/plugin_test.go +++ b/pkg/plugin/plugin_test.go @@ -27,7 +27,6 @@ import ( "go.uber.org/zap" pb "k8s.io/kms/apis/v1beta1" "sigs.k8s.io/aws-encryption-provider/pkg/cloud" - "sigs.k8s.io/aws-encryption-provider/pkg/kmsplugin" ) var ( @@ -43,7 +42,7 @@ func TestEncrypt(t *testing.T) { ctx map[string]string output string err error - errType kmsplugin.KMSErrorType + errType KMSErrorType healthErr bool checkErr bool }{ @@ -52,7 +51,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: encryptedMessage, err: nil, - errType: kmsplugin.KMSErrorTypeNil, + errType: KMSErrorTypeNil, healthErr: false, checkErr: false, }, @@ -61,7 +60,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: errorMessage, - errType: kmsplugin.KMSErrorTypeOther, + errType: KMSErrorTypeOther, healthErr: true, checkErr: true, }, @@ -70,7 +69,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New("RequestLimitExceeded", "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeThrottled, + errType: KMSErrorTypeThrottled, healthErr: true, checkErr: true, }, @@ -79,7 +78,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New(kms.ErrCodeInternalException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeOther, + errType: KMSErrorTypeOther, healthErr: true, checkErr: true, }, @@ -88,7 +87,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New(kms.ErrCodeLimitExceededException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeThrottled, + errType: KMSErrorTypeThrottled, healthErr: true, checkErr: true, }, @@ -97,7 +96,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New("AccessDeniedException", "The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, + errType: KMSErrorTypeUserInduced, healthErr: true, checkErr: false, }, @@ -106,7 +105,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New("AccessDeniedException", "Some other error message", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeOther, + errType: KMSErrorTypeOther, healthErr: true, checkErr: true, }, @@ -115,7 +114,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New(kms.ErrCodeDisabledException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, + errType: KMSErrorTypeUserInduced, healthErr: true, checkErr: false, }, @@ -124,7 +123,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New(kms.ErrCodeInvalidStateException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, + errType: KMSErrorTypeUserInduced, healthErr: true, checkErr: false, }, @@ -133,7 +132,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New(kms.ErrCodeInvalidGrantIdException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, + errType: KMSErrorTypeUserInduced, healthErr: true, checkErr: false, }, @@ -142,7 +141,7 @@ func TestEncrypt(t *testing.T) { ctx: nil, output: "", err: awserr.New(kms.ErrCodeInvalidGrantTokenException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, + errType: KMSErrorTypeUserInduced, healthErr: true, checkErr: false, }, @@ -151,7 +150,7 @@ func TestEncrypt(t *testing.T) { ctx: make(map[string]string), output: encryptedMessage, err: nil, - errType: kmsplugin.KMSErrorTypeNil, + errType: KMSErrorTypeNil, healthErr: false, checkErr: false, }, @@ -160,7 +159,7 @@ func TestEncrypt(t *testing.T) { ctx: map[string]string{"a": "b"}, output: "", err: errors.New("invalid context"), - errType: kmsplugin.KMSErrorTypeOther, + errType: KMSErrorTypeOther, healthErr: true, checkErr: true, }, @@ -188,11 +187,11 @@ func TestEncrypt(t *testing.T) { t.Fatalf("#%d: returned unexpected error: %v", idx, err) } - if tc.err == nil && string(eRes.Cipher) != kmsplugin.StorageVersion+tc.output { - t.Fatalf("#%d: expected %s, but got %s", idx, kmsplugin.StorageVersion+tc.output, string(eRes.Cipher)) + if tc.err == nil && string(eRes.Cipher) != StorageVersion+tc.output { + t.Fatalf("#%d: expected %s, but got %s", idx, StorageVersion+tc.output, string(eRes.Cipher)) } - et := kmsplugin.ParseError(tc.err) + et := ParseError(tc.err) if !reflect.DeepEqual(tc.errType, et) { t.Fatalf("#%d: expected error type %s, got %s", idx, tc.errType, et) } diff --git a/pkg/plugin/plugin_v2.go b/pkg/plugin/plugin_v2.go deleted file mode 100644 index 90a02f6e..00000000 --- a/pkg/plugin/plugin_v2.go +++ /dev/null @@ -1,254 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. -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 plugin - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/aws/aws-sdk-go/aws" - - "github.com/aws/aws-sdk-go/service/kms" - "github.com/aws/aws-sdk-go/service/kms/kmsiface" - "go.uber.org/zap" - "google.golang.org/grpc" - pb "k8s.io/kms/apis/v2" - "sigs.k8s.io/aws-encryption-provider/pkg/kmsplugin" -) - -var _ pb.KeyManagementServiceServer = &V2Plugin{} - -// Plugin implements the KeyManagementServiceServer -type V2Plugin struct { - svc kmsiface.KMSAPI - keyID string - encryptionCtx map[string]*string - - lastMu sync.RWMutex - lastErr error - lastTs time.Time - - healthCheckPeriod time.Duration - healthCheckErrc chan error - healthCheckStopcCloseOnce *sync.Once - healthCheckStopc chan struct{} - healthCheckClosed chan struct{} -} - -// New returns a new *V2Plugin -func NewV2(key string, svc kmsiface.KMSAPI, encryptionCtx map[string]string) *V2Plugin { - return newPluginV2( - key, - svc, - encryptionCtx, - kmsplugin.DefaultHealthCheckPeriod, - kmsplugin.DefaultErrcBufSize, - ) -} - -func newPluginV2( - key string, - svc kmsiface.KMSAPI, - encryptionCtx map[string]string, - checkPeriod time.Duration, - errcBuf int, -) *V2Plugin { - p := &V2Plugin{ - svc: svc, - keyID: key, - healthCheckPeriod: checkPeriod, - healthCheckErrc: make(chan error, errcBuf), - healthCheckStopcCloseOnce: new(sync.Once), - healthCheckStopc: make(chan struct{}), - healthCheckClosed: make(chan struct{}), - } - if len(encryptionCtx) > 0 { - p.encryptionCtx = make(map[string]*string) - } - for k, v := range encryptionCtx { - p.encryptionCtx[k] = aws.String(v) - } - go p.startCheckHealth() - return p -} - -func (p *V2Plugin) startCheckHealth() { - zap.L().Info("starting health check routine", zap.String("period", p.healthCheckPeriod.String())) - for { - select { - case <-p.healthCheckStopc: - zap.L().Warn("exiting health check routine") - p.healthCheckClosed <- struct{}{} - return - case err := <-p.healthCheckErrc: - p.recordErr(err) - } - } -} - -func (p *V2Plugin) stopCheckHealth() { - p.healthCheckStopcCloseOnce.Do(func() { - close(p.healthCheckStopc) - <-p.healthCheckClosed - }) -} - -func (p *V2Plugin) isRecentlyChecked() (bool, error) { - p.lastMu.RLock() - err, ts := p.lastErr, p.lastTs - never, latest := err == nil && ts.IsZero(), time.Since(ts) < p.healthCheckPeriod - p.lastMu.RUnlock() - return !never && latest, err -} - -func (p *V2Plugin) recordErr(err error) { - p.lastMu.Lock() - p.lastErr, p.lastTs = err, time.Now() - p.lastMu.Unlock() -} - -// Health checks KMS API availability. -// -// The goal is to: -// 1. not incur extra KMS API call if V2Plugin "Encrypt" method has already -// 2. return latest health status (cached KMS status must reflect the current) -// -// The error is sent via channel and consumed by goroutine. -// The error channel may be full and block, when there are too many failures. -// The error channel may be empty and block, when there's no failure. -// To handle those two cases, keep track latest health check timestamps. -// -// Call KMS "Encrypt" API call iff: -// 1. there was never a health check done -// 2. there was no health check done for the last "healthCheckPeriod" -// (only use the cached error if the error is from recent API call) -func (p *V2Plugin) Health() error { - recent, err := p.isRecentlyChecked() - if !recent { - _, err = p.Encrypt(context.Background(), &pb.EncryptRequest{Plaintext: []byte("foo")}) - p.recordErr(err) - if err != nil { - zap.L().Warn("health check failed", zap.Error(err)) - } - return err - } - if err != nil { - zap.L().Warn("health check failed", zap.Error(err)) - } else { - zap.L().Debug("health check success") - } - return err -} - -// Live checks the liveness of KMS API. -// If the error is user-induced (e.g., revoke CMK), the function returns NO error. -// If the error is due to KMS availability, the function returns the error. -func (p *V2Plugin) Live() error { - if err := p.Health(); err != nil && kmsplugin.ParseError(err) != kmsplugin.KMSErrorTypeUserInduced { - return err - } - return nil -} - -// Status returns the V2Plugin server status -func (p *V2Plugin) Status(ctx context.Context, request *pb.StatusRequest) (*pb.StatusResponse, error) { - status := "ok" - if p.Health() != nil { - status = "err" - } - return &pb.StatusResponse{ - Version: "v2beta1", - Healthz: status, - KeyId: p.keyID, - }, nil -} - -// Encrypt executes the encryption operation using AWS KMS -func (p *V2Plugin) Encrypt(ctx context.Context, request *pb.EncryptRequest) (*pb.EncryptResponse, error) { - zap.L().Debug("starting encrypt operation") - - startTime := time.Now() - input := &kms.EncryptInput{ - Plaintext: request.Plaintext, - KeyId: aws.String(p.keyID), - } - if len(p.encryptionCtx) > 0 { - zap.L().Debug("configuring encryption context", zap.String("ctx", fmt.Sprintf("%v", p.encryptionCtx))) - input.EncryptionContext = p.encryptionCtx - } - - result, err := p.svc.Encrypt(input) - if err != nil { - select { - case p.healthCheckErrc <- err: - default: - } - zap.L().Error("request to encrypt failed", zap.String("error-type", kmsplugin.ParseError(err).String()), zap.Error(err)) - failLabel := kmsplugin.GetStatusLabel(err) - kmsLatencyMetricV2.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationEncrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounterV2.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationEncrypt).Inc() - return nil, fmt.Errorf("failed to encrypt %w", err) - } - - zap.L().Debug("encrypt operation successful") - kmsLatencyMetricV2.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationEncrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounterV2.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationEncrypt).Inc() - return &pb.EncryptResponse{ - Ciphertext: append([]byte(kmsplugin.StorageVersion), result.CiphertextBlob...), - KeyId: p.keyID, - }, nil -} - -// Decrypt executes the decrypt operation using AWS KMS -func (p *V2Plugin) Decrypt(ctx context.Context, request *pb.DecryptRequest) (*pb.DecryptResponse, error) { - zap.L().Debug("starting decrypt operation") - - startTime := time.Now() - if string(request.Ciphertext[0]) == kmsplugin.StorageVersion { - request.Ciphertext = request.Ciphertext[1:] - } - input := &kms.DecryptInput{ - CiphertextBlob: request.Ciphertext, - } - if len(p.encryptionCtx) > 0 { - zap.L().Debug("configuring encryption context", zap.String("ctx", fmt.Sprintf("%v", p.encryptionCtx))) - input.EncryptionContext = p.encryptionCtx - } - - result, err := p.svc.Decrypt(input) - if err != nil { - select { - case p.healthCheckErrc <- err: - default: - } - zap.L().Error("request to decrypt failed", zap.String("error-type", kmsplugin.ParseError(err).String()), zap.Error(err)) - failLabel := kmsplugin.GetStatusLabel(err) - kmsLatencyMetricV2.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationDecrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounterV2.WithLabelValues(p.keyID, failLabel, kmsplugin.OperationDecrypt).Inc() - return nil, fmt.Errorf("failed to decrypt %w", err) - } - - zap.L().Debug("decrypt operation successful") - kmsLatencyMetricV2.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationDecrypt).Observe(kmsplugin.GetMillisecondsSince(startTime)) - kmsOperationCounterV2.WithLabelValues(p.keyID, kmsplugin.StatusSuccess, kmsplugin.OperationDecrypt).Inc() - return &pb.DecryptResponse{Plaintext: result.Plaintext}, nil -} - -// Register registers the V2Plugin with the grpc server -func (p *V2Plugin) Register(s *grpc.Server) { - zap.L().Info("registering the kmsplugin plugin with grpc server") - pb.RegisterKeyManagementServiceServer(s, p) -} diff --git a/pkg/plugin/plugin_v2_test.go b/pkg/plugin/plugin_v2_test.go deleted file mode 100644 index 133df40e..00000000 --- a/pkg/plugin/plugin_v2_test.go +++ /dev/null @@ -1,352 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. -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 plugin - -import ( - "context" - "errors" - "reflect" - "strings" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/kms" - "go.uber.org/zap" - pb "k8s.io/kms/apis/v2" - "sigs.k8s.io/aws-encryption-provider/pkg/cloud" - "sigs.k8s.io/aws-encryption-provider/pkg/kmsplugin" -) - -func TestEncryptV2(t *testing.T) { - tt := []struct { - input string - ctx map[string]string - output string - err error - errType kmsplugin.KMSErrorType - healthErr bool - checkErr bool - }{ - { - input: plainMessage, - ctx: nil, - output: encryptedMessage, - err: nil, - errType: kmsplugin.KMSErrorTypeNil, - healthErr: false, - checkErr: false, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: errorMessage, - errType: kmsplugin.KMSErrorTypeOther, - healthErr: true, - checkErr: true, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New("RequestLimitExceeded", "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeThrottled, - healthErr: true, - checkErr: true, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New(kms.ErrCodeInternalException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeOther, - healthErr: true, - checkErr: true, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New(kms.ErrCodeLimitExceededException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeThrottled, - healthErr: true, - checkErr: true, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New("AccessDeniedException", "The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, - healthErr: true, - checkErr: false, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New("AccessDeniedException", "Some other error message", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeOther, - healthErr: true, - checkErr: true, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New(kms.ErrCodeDisabledException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, - healthErr: true, - checkErr: false, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New(kms.ErrCodeInvalidStateException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, - healthErr: true, - checkErr: false, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New(kms.ErrCodeInvalidGrantIdException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, - healthErr: true, - checkErr: false, - }, - { - input: plainMessage, - ctx: nil, - output: "", - err: awserr.New(kms.ErrCodeInvalidGrantTokenException, "test", errors.New("fail")), - errType: kmsplugin.KMSErrorTypeUserInduced, - healthErr: true, - checkErr: false, - }, - { - input: plainMessage, - ctx: make(map[string]string), - output: encryptedMessage, - err: nil, - errType: kmsplugin.KMSErrorTypeNil, - healthErr: false, - checkErr: false, - }, - { - input: encryptedMessage, - ctx: map[string]string{"a": "b"}, - output: "", - err: errors.New("invalid context"), - errType: kmsplugin.KMSErrorTypeOther, - healthErr: true, - checkErr: true, - }, - } - - c := &cloud.KMSMock{} - ctx := context.Background() - - for idx, tc := range tt { - func() { - c.SetEncryptResp(tc.output, tc.err) - p := NewV2(key, c, nil) - defer func() { - p.stopCheckHealth() - }() - - eReq := &pb.EncryptRequest{Plaintext: []byte(tc.input)} - eRes, err := p.Encrypt(ctx, eReq) - - if tc.err != nil && err == nil { - t.Fatalf("#%d: failed to return expected error %v", idx, tc.err) - } - - if tc.err == nil && err != nil { - t.Fatalf("#%d: returned unexpected error: %v", idx, err) - } - - if tc.err == nil && string(eRes.Ciphertext) != kmsplugin.StorageVersion+tc.output { - t.Fatalf("#%d: expected %s, but got %s", idx, kmsplugin.StorageVersion+tc.output, string(eRes.Ciphertext)) - } - - et := kmsplugin.ParseError(tc.err) - if !reflect.DeepEqual(tc.errType, et) { - t.Fatalf("#%d: expected error type %s, got %s", idx, tc.errType, et) - } - - herr := p.Health() - if tc.healthErr && herr == nil { - t.Fatalf("#%d: expected health error, but got nil", idx) - } - if !tc.healthErr && herr != nil { - t.Fatalf("#%d: unexpected health error, got %v", idx, herr) - } - - cerr := p.Live() - if tc.checkErr && cerr == nil { - t.Fatalf("#%d: expected check error, but got nil", idx) - } - if !tc.checkErr && cerr != nil { - t.Fatalf("#%d: unexpected check error, got %v", idx, cerr) - } - }() - } -} -func TestDecryptV2(t *testing.T) { - tt := []struct { - input string - ctx map[string]string - output string - err error - }{ - { - input: encryptedMessage, - ctx: nil, - output: plainMessage, - err: nil, - }, - { - input: encryptedMessage, - ctx: nil, - output: "", - err: errorMessage, - }, - { - input: encryptedMessage, - ctx: map[string]string{"a": "b"}, - output: "", - err: errors.New("invalid context"), - }, - } - - c := &cloud.KMSMock{} - ctx := context.Background() - - for _, tc := range tt { - func() { - c.SetDecryptResp(tc.output, tc.err) - p := NewV2(key, c, tc.ctx) - defer func() { - p.stopCheckHealth() - }() - - dReq := &pb.DecryptRequest{Ciphertext: []byte(tc.input)} - dRes, err := p.Decrypt(ctx, dReq) - - if tc.err != nil && err == nil { - t.Fatalf("Failed to return expected error %v", tc.err) - } - - if tc.err == nil && err != nil { - t.Fatalf("Returned unexpected error: %v", err) - } - - if tc.err == nil && string(dRes.Plaintext) != tc.output { - t.Fatalf("Expected %s, but got %s", tc.output, string(dRes.Plaintext)) - } - }() - } -} - -func TestHealthV2(t *testing.T) { - zap.ReplaceGlobals(zap.NewExample()) - - tt := []struct { - encryptErr error - decryptErr error - }{ - { - encryptErr: nil, - decryptErr: nil, - }, - { - encryptErr: errors.New("encrypt fail"), - decryptErr: errors.New("decrypt fail"), - }, - } - for idx, entry := range tt { - c := &cloud.KMSMock{} - - p := NewV2(key, c, nil) - defer func() { - p.stopCheckHealth() - }() - - c.SetEncryptResp("foo", entry.encryptErr) - c.SetDecryptResp("foo", entry.decryptErr) - - _, encErr := p.Encrypt(context.Background(), &pb.EncryptRequest{Plaintext: []byte("foo")}) - if entry.encryptErr == nil && encErr != nil { - t.Fatalf("#%d: unexpected error from Encrypt %v", idx, encErr) - } - herr1 := p.Health() - if entry.encryptErr == nil { - if herr1 != nil { - t.Fatalf("#%d: unexpected error from Health %v", idx, herr1) - } - } else if !strings.HasSuffix(encErr.Error(), entry.encryptErr.Error()) { - t.Fatalf("#%d: unexpected error from Health %v", idx, herr1) - } - - _, decErr := p.Decrypt(context.Background(), &pb.DecryptRequest{Ciphertext: []byte("foo")}) - if entry.decryptErr == nil && decErr != nil { - t.Fatalf("#%d: unexpected error from Encrypt %v", idx, decErr) - } - herr2 := p.Health() - if entry.decryptErr == nil { - if herr2 != nil { - t.Fatalf("#%d: unexpected error from Health %v", idx, herr2) - } - } else if !strings.HasSuffix(decErr.Error(), entry.decryptErr.Error()) { - t.Fatalf("#%d: unexpected error from Health %v", idx, herr2) - } - } -} - -// TestHealthManyRequests sends many requests to fill up the error channel, -// and ensures following encrypt/decrypt operation do not block. -func TestHealthManyRequestsV2(t *testing.T) { - zap.ReplaceGlobals(zap.NewExample()) - - c := &cloud.KMSMock{} - - p := newPluginV2(key, c, nil, defaultHealthCheckPeriod, 0) - defer func() { - p.stopCheckHealth() - }() - - c.SetEncryptResp("foo", errors.New("fail")) - for i := 0; i < 10; i++ { - errc := make(chan error) - go func() { - _, err := p.Encrypt( - context.Background(), - &pb.EncryptRequest{Plaintext: []byte("foo")}, - ) - errc <- err - }() - select { - case <-time.After(time.Second): - t.Fatalf("#%d: Encrypt took longer than it should", i) - case err := <-errc: - if !strings.HasSuffix(err.Error(), "fail") { - t.Fatalf("#%d: unexpected errro %v", i, err) - } - } - } -} diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 90214e66..45ee885a 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -23,7 +23,6 @@ import ( pb "k8s.io/kms/apis/v1beta1" "sigs.k8s.io/aws-encryption-provider/pkg/cloud" "sigs.k8s.io/aws-encryption-provider/pkg/connection" - "sigs.k8s.io/aws-encryption-provider/pkg/kmsplugin" "sigs.k8s.io/aws-encryption-provider/pkg/plugin" "sigs.k8s.io/aws-encryption-provider/pkg/server" ) @@ -109,8 +108,8 @@ func TestEncrypt(t *testing.T) { t.Fatalf("Returned unexpected error: %v", err) } - if tc.err == nil && string(eRes.Cipher) != kmsplugin.StorageVersion+tc.output { - t.Fatalf("Expected %s, but got %s", kmsplugin.StorageVersion+tc.output, string(eRes.Cipher)) + if tc.err == nil && string(eRes.Cipher) != plugin.StorageVersion+tc.output { + t.Fatalf("Expected %s, but got %s", plugin.StorageVersion+tc.output, string(eRes.Cipher)) } }