├── .github └── PULL_REQUEST_TEMPLATE.md ├── CONTRIBUTING.md ├── LICENSE ├── OWNERS ├── README.md ├── SECURITY_CONTACTS ├── apis ├── OWNERS ├── v1beta1 │ ├── api.pb.go │ ├── api.proto │ └── v1beta1.go └── v2 │ ├── api.pb.go │ ├── api.proto │ └── v2.go ├── code-of-conduct.md ├── doc.go ├── go.mod ├── go.sum ├── internal └── plugins │ └── _mock │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── go.work │ ├── kms.yaml │ ├── pkcs11 │ └── pkcs11.go │ └── plugin.go └── pkg ├── service ├── grpc_service.go ├── grpc_service_test.go └── interface.go └── util ├── util.go └── util_test.go /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Sorry, we do not accept changes directly against this repository. Please see 2 | CONTRIBUTING.md for information on where and how to contribute instead. 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes. 4 | 5 | This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/kms](https://git.k8s.io/kubernetes/staging/src/k8s.io/kms) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot). 6 | 7 | Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/sig-architecture/staging.md) for more information 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - sig-auth-encryption-at-rest-approvers 5 | reviewers: 6 | - sig-auth-encryption-at-rest-reviewers 7 | labels: 8 | - sig/auth 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KMS 2 | 3 | 4 | 5 | This repository contains the KMS proto APIs. 6 | 7 | See https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/3299-kms-v2-improvements for more details. 8 | 9 | ## Community, discussion, contribution, and support 10 | 11 | KMS a sub-project of [SIG-Auth](https://github.com/kubernetes/community/tree/master/sig-auth). 12 | 13 | You can reach the maintainers of this project at: 14 | 15 | - Slack: [#sig-auth](https://kubernetes.slack.com/messages/sig-auth) 16 | - Mailing List: [kubernetes-sig-auth](https://groups.google.com/forum/#!forum/kubernetes-sig-auth) 17 | 18 | Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). 19 | 20 | ### Code of conduct 21 | 22 | Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). 23 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Committee to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | aramase 14 | enj 15 | ritazh 16 | -------------------------------------------------------------------------------- /apis/OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | # Disable inheritance as this is an api owners file 4 | options: 5 | no_parent_owners: true 6 | approvers: 7 | - api-approvers 8 | reviewers: 9 | - sig-auth-api-reviewers 10 | -------------------------------------------------------------------------------- /apis/v1beta1/api.pb.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 18 | // api.proto is a deprecated file. 19 | 20 | package v1beta1 21 | 22 | import ( 23 | context "context" 24 | fmt "fmt" 25 | proto "github.com/gogo/protobuf/proto" 26 | grpc "google.golang.org/grpc" 27 | codes "google.golang.org/grpc/codes" 28 | status "google.golang.org/grpc/status" 29 | math "math" 30 | ) 31 | 32 | // Reference imports to suppress errors if they are not otherwise used. 33 | var _ = proto.Marshal 34 | var _ = fmt.Errorf 35 | var _ = math.Inf 36 | 37 | // This is a compile-time assertion to ensure that this generated file 38 | // is compatible with the proto package it is being compiled against. 39 | // A compilation error at this line likely means your copy of the 40 | // proto package needs to be updated. 41 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package 42 | 43 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 44 | type VersionRequest struct { 45 | // Version of the KMS plugin API. 46 | Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` 47 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 48 | XXX_unrecognized []byte `json:"-"` 49 | XXX_sizecache int32 `json:"-"` 50 | } 51 | 52 | func (m *VersionRequest) Reset() { *m = VersionRequest{} } 53 | func (m *VersionRequest) String() string { return proto.CompactTextString(m) } 54 | func (*VersionRequest) ProtoMessage() {} 55 | func (*VersionRequest) Descriptor() ([]byte, []int) { 56 | return fileDescriptor_00212fb1f9d3bf1c, []int{0} 57 | } 58 | func (m *VersionRequest) XXX_Unmarshal(b []byte) error { 59 | return xxx_messageInfo_VersionRequest.Unmarshal(m, b) 60 | } 61 | func (m *VersionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 62 | return xxx_messageInfo_VersionRequest.Marshal(b, m, deterministic) 63 | } 64 | func (m *VersionRequest) XXX_Merge(src proto.Message) { 65 | xxx_messageInfo_VersionRequest.Merge(m, src) 66 | } 67 | func (m *VersionRequest) XXX_Size() int { 68 | return xxx_messageInfo_VersionRequest.Size(m) 69 | } 70 | func (m *VersionRequest) XXX_DiscardUnknown() { 71 | xxx_messageInfo_VersionRequest.DiscardUnknown(m) 72 | } 73 | 74 | var xxx_messageInfo_VersionRequest proto.InternalMessageInfo 75 | 76 | func (m *VersionRequest) GetVersion() string { 77 | if m != nil { 78 | return m.Version 79 | } 80 | return "" 81 | } 82 | 83 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 84 | type VersionResponse struct { 85 | // Version of the KMS plugin API. 86 | Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` 87 | // Name of the KMS provider. 88 | RuntimeName string `protobuf:"bytes,2,opt,name=runtime_name,json=runtimeName,proto3" json:"runtime_name,omitempty"` 89 | // Version of the KMS provider. The string must be semver-compatible. 90 | RuntimeVersion string `protobuf:"bytes,3,opt,name=runtime_version,json=runtimeVersion,proto3" json:"runtime_version,omitempty"` 91 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 92 | XXX_unrecognized []byte `json:"-"` 93 | XXX_sizecache int32 `json:"-"` 94 | } 95 | 96 | func (m *VersionResponse) Reset() { *m = VersionResponse{} } 97 | func (m *VersionResponse) String() string { return proto.CompactTextString(m) } 98 | func (*VersionResponse) ProtoMessage() {} 99 | func (*VersionResponse) Descriptor() ([]byte, []int) { 100 | return fileDescriptor_00212fb1f9d3bf1c, []int{1} 101 | } 102 | func (m *VersionResponse) XXX_Unmarshal(b []byte) error { 103 | return xxx_messageInfo_VersionResponse.Unmarshal(m, b) 104 | } 105 | func (m *VersionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 106 | return xxx_messageInfo_VersionResponse.Marshal(b, m, deterministic) 107 | } 108 | func (m *VersionResponse) XXX_Merge(src proto.Message) { 109 | xxx_messageInfo_VersionResponse.Merge(m, src) 110 | } 111 | func (m *VersionResponse) XXX_Size() int { 112 | return xxx_messageInfo_VersionResponse.Size(m) 113 | } 114 | func (m *VersionResponse) XXX_DiscardUnknown() { 115 | xxx_messageInfo_VersionResponse.DiscardUnknown(m) 116 | } 117 | 118 | var xxx_messageInfo_VersionResponse proto.InternalMessageInfo 119 | 120 | func (m *VersionResponse) GetVersion() string { 121 | if m != nil { 122 | return m.Version 123 | } 124 | return "" 125 | } 126 | 127 | func (m *VersionResponse) GetRuntimeName() string { 128 | if m != nil { 129 | return m.RuntimeName 130 | } 131 | return "" 132 | } 133 | 134 | func (m *VersionResponse) GetRuntimeVersion() string { 135 | if m != nil { 136 | return m.RuntimeVersion 137 | } 138 | return "" 139 | } 140 | 141 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 142 | type DecryptRequest struct { 143 | // Version of the KMS plugin API. 144 | Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` 145 | // The data to be decrypted. 146 | Cipher []byte `protobuf:"bytes,2,opt,name=cipher,proto3" json:"cipher,omitempty"` 147 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 148 | XXX_unrecognized []byte `json:"-"` 149 | XXX_sizecache int32 `json:"-"` 150 | } 151 | 152 | func (m *DecryptRequest) Reset() { *m = DecryptRequest{} } 153 | func (m *DecryptRequest) String() string { return proto.CompactTextString(m) } 154 | func (*DecryptRequest) ProtoMessage() {} 155 | func (*DecryptRequest) Descriptor() ([]byte, []int) { 156 | return fileDescriptor_00212fb1f9d3bf1c, []int{2} 157 | } 158 | func (m *DecryptRequest) XXX_Unmarshal(b []byte) error { 159 | return xxx_messageInfo_DecryptRequest.Unmarshal(m, b) 160 | } 161 | func (m *DecryptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 162 | return xxx_messageInfo_DecryptRequest.Marshal(b, m, deterministic) 163 | } 164 | func (m *DecryptRequest) XXX_Merge(src proto.Message) { 165 | xxx_messageInfo_DecryptRequest.Merge(m, src) 166 | } 167 | func (m *DecryptRequest) XXX_Size() int { 168 | return xxx_messageInfo_DecryptRequest.Size(m) 169 | } 170 | func (m *DecryptRequest) XXX_DiscardUnknown() { 171 | xxx_messageInfo_DecryptRequest.DiscardUnknown(m) 172 | } 173 | 174 | var xxx_messageInfo_DecryptRequest proto.InternalMessageInfo 175 | 176 | func (m *DecryptRequest) GetVersion() string { 177 | if m != nil { 178 | return m.Version 179 | } 180 | return "" 181 | } 182 | 183 | func (m *DecryptRequest) GetCipher() []byte { 184 | if m != nil { 185 | return m.Cipher 186 | } 187 | return nil 188 | } 189 | 190 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 191 | type DecryptResponse struct { 192 | // The decrypted data. 193 | Plain []byte `protobuf:"bytes,1,opt,name=plain,proto3" json:"plain,omitempty"` 194 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 195 | XXX_unrecognized []byte `json:"-"` 196 | XXX_sizecache int32 `json:"-"` 197 | } 198 | 199 | func (m *DecryptResponse) Reset() { *m = DecryptResponse{} } 200 | func (m *DecryptResponse) String() string { return proto.CompactTextString(m) } 201 | func (*DecryptResponse) ProtoMessage() {} 202 | func (*DecryptResponse) Descriptor() ([]byte, []int) { 203 | return fileDescriptor_00212fb1f9d3bf1c, []int{3} 204 | } 205 | func (m *DecryptResponse) XXX_Unmarshal(b []byte) error { 206 | return xxx_messageInfo_DecryptResponse.Unmarshal(m, b) 207 | } 208 | func (m *DecryptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 209 | return xxx_messageInfo_DecryptResponse.Marshal(b, m, deterministic) 210 | } 211 | func (m *DecryptResponse) XXX_Merge(src proto.Message) { 212 | xxx_messageInfo_DecryptResponse.Merge(m, src) 213 | } 214 | func (m *DecryptResponse) XXX_Size() int { 215 | return xxx_messageInfo_DecryptResponse.Size(m) 216 | } 217 | func (m *DecryptResponse) XXX_DiscardUnknown() { 218 | xxx_messageInfo_DecryptResponse.DiscardUnknown(m) 219 | } 220 | 221 | var xxx_messageInfo_DecryptResponse proto.InternalMessageInfo 222 | 223 | func (m *DecryptResponse) GetPlain() []byte { 224 | if m != nil { 225 | return m.Plain 226 | } 227 | return nil 228 | } 229 | 230 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 231 | type EncryptRequest struct { 232 | // Version of the KMS plugin API. 233 | Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` 234 | // The data to be encrypted. 235 | Plain []byte `protobuf:"bytes,2,opt,name=plain,proto3" json:"plain,omitempty"` 236 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 237 | XXX_unrecognized []byte `json:"-"` 238 | XXX_sizecache int32 `json:"-"` 239 | } 240 | 241 | func (m *EncryptRequest) Reset() { *m = EncryptRequest{} } 242 | func (m *EncryptRequest) String() string { return proto.CompactTextString(m) } 243 | func (*EncryptRequest) ProtoMessage() {} 244 | func (*EncryptRequest) Descriptor() ([]byte, []int) { 245 | return fileDescriptor_00212fb1f9d3bf1c, []int{4} 246 | } 247 | func (m *EncryptRequest) XXX_Unmarshal(b []byte) error { 248 | return xxx_messageInfo_EncryptRequest.Unmarshal(m, b) 249 | } 250 | func (m *EncryptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 251 | return xxx_messageInfo_EncryptRequest.Marshal(b, m, deterministic) 252 | } 253 | func (m *EncryptRequest) XXX_Merge(src proto.Message) { 254 | xxx_messageInfo_EncryptRequest.Merge(m, src) 255 | } 256 | func (m *EncryptRequest) XXX_Size() int { 257 | return xxx_messageInfo_EncryptRequest.Size(m) 258 | } 259 | func (m *EncryptRequest) XXX_DiscardUnknown() { 260 | xxx_messageInfo_EncryptRequest.DiscardUnknown(m) 261 | } 262 | 263 | var xxx_messageInfo_EncryptRequest proto.InternalMessageInfo 264 | 265 | func (m *EncryptRequest) GetVersion() string { 266 | if m != nil { 267 | return m.Version 268 | } 269 | return "" 270 | } 271 | 272 | func (m *EncryptRequest) GetPlain() []byte { 273 | if m != nil { 274 | return m.Plain 275 | } 276 | return nil 277 | } 278 | 279 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 280 | type EncryptResponse struct { 281 | // The encrypted data. 282 | Cipher []byte `protobuf:"bytes,1,opt,name=cipher,proto3" json:"cipher,omitempty"` 283 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 284 | XXX_unrecognized []byte `json:"-"` 285 | XXX_sizecache int32 `json:"-"` 286 | } 287 | 288 | func (m *EncryptResponse) Reset() { *m = EncryptResponse{} } 289 | func (m *EncryptResponse) String() string { return proto.CompactTextString(m) } 290 | func (*EncryptResponse) ProtoMessage() {} 291 | func (*EncryptResponse) Descriptor() ([]byte, []int) { 292 | return fileDescriptor_00212fb1f9d3bf1c, []int{5} 293 | } 294 | func (m *EncryptResponse) XXX_Unmarshal(b []byte) error { 295 | return xxx_messageInfo_EncryptResponse.Unmarshal(m, b) 296 | } 297 | func (m *EncryptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 298 | return xxx_messageInfo_EncryptResponse.Marshal(b, m, deterministic) 299 | } 300 | func (m *EncryptResponse) XXX_Merge(src proto.Message) { 301 | xxx_messageInfo_EncryptResponse.Merge(m, src) 302 | } 303 | func (m *EncryptResponse) XXX_Size() int { 304 | return xxx_messageInfo_EncryptResponse.Size(m) 305 | } 306 | func (m *EncryptResponse) XXX_DiscardUnknown() { 307 | xxx_messageInfo_EncryptResponse.DiscardUnknown(m) 308 | } 309 | 310 | var xxx_messageInfo_EncryptResponse proto.InternalMessageInfo 311 | 312 | func (m *EncryptResponse) GetCipher() []byte { 313 | if m != nil { 314 | return m.Cipher 315 | } 316 | return nil 317 | } 318 | 319 | func init() { 320 | proto.RegisterType((*VersionRequest)(nil), "v1beta1.VersionRequest") 321 | proto.RegisterType((*VersionResponse)(nil), "v1beta1.VersionResponse") 322 | proto.RegisterType((*DecryptRequest)(nil), "v1beta1.DecryptRequest") 323 | proto.RegisterType((*DecryptResponse)(nil), "v1beta1.DecryptResponse") 324 | proto.RegisterType((*EncryptRequest)(nil), "v1beta1.EncryptRequest") 325 | proto.RegisterType((*EncryptResponse)(nil), "v1beta1.EncryptResponse") 326 | } 327 | 328 | func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } 329 | 330 | var fileDescriptor_00212fb1f9d3bf1c = []byte{ 331 | // 314 bytes of a gzipped FileDescriptorProto 332 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0xcf, 0x4a, 0xf3, 0x40, 333 | 0x10, 0xef, 0xf6, 0xe3, 0x6b, 0xe9, 0x58, 0x12, 0x58, 0x8a, 0x0d, 0xe2, 0x41, 0xf7, 0x52, 0xf5, 334 | 0x90, 0x52, 0xbd, 0x78, 0x12, 0x29, 0x7a, 0x12, 0x3d, 0x44, 0xf0, 0xe0, 0x45, 0xb6, 0x61, 0xd0, 335 | 0xa5, 0x66, 0xb3, 0xee, 0x6e, 0x23, 0x7d, 0x33, 0x9f, 0xc4, 0xe7, 0x11, 0x93, 0x4d, 0xdc, 0x54, 336 | 0x44, 0x8f, 0x33, 0xfb, 0xfb, 0x33, 0xbf, 0x99, 0x85, 0x01, 0x57, 0x22, 0x56, 0x3a, 0xb7, 0x39, 337 | 0xed, 0x17, 0xb3, 0x05, 0x5a, 0x3e, 0x63, 0x47, 0x10, 0xdc, 0xa1, 0x36, 0x22, 0x97, 0x09, 0xbe, 338 | 0xac, 0xd0, 0x58, 0x1a, 0x41, 0xbf, 0xa8, 0x3a, 0x11, 0xd9, 0x23, 0x07, 0x83, 0xa4, 0x2e, 0xd9, 339 | 0x2b, 0x84, 0x0d, 0xd6, 0xa8, 0x5c, 0x1a, 0xfc, 0x19, 0x4c, 0xf7, 0x61, 0xa8, 0x57, 0xd2, 0x8a, 340 | 0x0c, 0x1f, 0x24, 0xcf, 0x30, 0xea, 0x96, 0xcf, 0x5b, 0xae, 0x77, 0xc3, 0x33, 0xa4, 0x13, 0x08, 341 | 0x6b, 0x48, 0x2d, 0xf2, 0xaf, 0x44, 0x05, 0xae, 0xed, 0xdc, 0xd8, 0x1c, 0x82, 0x0b, 0x4c, 0xf5, 342 | 0x5a, 0xd9, 0x5f, 0x87, 0xa4, 0xdb, 0xd0, 0x4b, 0x85, 0x7a, 0x42, 0x5d, 0x3a, 0x0e, 0x13, 0x57, 343 | 0xb1, 0x09, 0x84, 0x8d, 0x86, 0x1b, 0x7e, 0x04, 0xff, 0xd5, 0x33, 0x17, 0x95, 0xc4, 0x30, 0xa9, 344 | 0x0a, 0x76, 0x0e, 0xc1, 0xa5, 0xfc, 0xa3, 0x59, 0xa3, 0xd0, 0xf5, 0x15, 0x0e, 0x21, 0x6c, 0x14, 345 | 0x9c, 0xd5, 0xd7, 0x54, 0xc4, 0x9f, 0xea, 0xf8, 0x9d, 0xc0, 0xe8, 0x0a, 0xd7, 0xd7, 0x5c, 0xf2, 346 | 0x47, 0xcc, 0x50, 0xda, 0x5b, 0xd4, 0x85, 0x48, 0x91, 0x9e, 0x41, 0xdf, 0xa5, 0xa7, 0xe3, 0xd8, 347 | 0x1d, 0x2b, 0x6e, 0x5f, 0x6a, 0x27, 0xfa, 0xfe, 0x50, 0xd9, 0xb1, 0xce, 0x27, 0xdf, 0xc5, 0xf5, 348 | 0xf8, 0xed, 0x25, 0x7a, 0xfc, 0x8d, 0xcd, 0x54, 0x7c, 0x97, 0xc1, 0xe3, 0xb7, 0xf7, 0xe2, 0xf1, 349 | 0x37, 0xe2, 0xb2, 0xce, 0x7c, 0xf7, 0x7e, 0xbc, 0x3c, 0x35, 0xb1, 0xc8, 0xa7, 0xcb, 0xcc, 0x4c, 350 | 0xb9, 0x12, 0x66, 0xea, 0xc0, 0x6f, 0x84, 0x2c, 0x7a, 0xe5, 0x2f, 0x3c, 0xf9, 0x08, 0x00, 0x00, 351 | 0xff, 0xff, 0x18, 0x47, 0x93, 0xb2, 0x92, 0x02, 0x00, 0x00, 352 | } 353 | 354 | // Reference imports to suppress errors if they are not otherwise used. 355 | var _ context.Context 356 | var _ grpc.ClientConn 357 | 358 | // This is a compile-time assertion to ensure that this generated file 359 | // is compatible with the grpc package it is being compiled against. 360 | const _ = grpc.SupportPackageIsVersion4 361 | 362 | // KeyManagementServiceClient is the client API for KeyManagementService service. 363 | // 364 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 365 | type KeyManagementServiceClient interface { 366 | // Version returns the runtime name and runtime version of the KMS provider. 367 | Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) 368 | // Execute decryption operation in KMS provider. 369 | Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) 370 | // Execute encryption operation in KMS provider. 371 | Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) 372 | } 373 | 374 | type keyManagementServiceClient struct { 375 | cc *grpc.ClientConn 376 | } 377 | 378 | func NewKeyManagementServiceClient(cc *grpc.ClientConn) KeyManagementServiceClient { 379 | return &keyManagementServiceClient{cc} 380 | } 381 | 382 | func (c *keyManagementServiceClient) Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) { 383 | out := new(VersionResponse) 384 | err := c.cc.Invoke(ctx, "/v1beta1.KeyManagementService/Version", in, out, opts...) 385 | if err != nil { 386 | return nil, err 387 | } 388 | return out, nil 389 | } 390 | 391 | func (c *keyManagementServiceClient) Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) { 392 | out := new(DecryptResponse) 393 | err := c.cc.Invoke(ctx, "/v1beta1.KeyManagementService/Decrypt", in, out, opts...) 394 | if err != nil { 395 | return nil, err 396 | } 397 | return out, nil 398 | } 399 | 400 | func (c *keyManagementServiceClient) Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) { 401 | out := new(EncryptResponse) 402 | err := c.cc.Invoke(ctx, "/v1beta1.KeyManagementService/Encrypt", in, out, opts...) 403 | if err != nil { 404 | return nil, err 405 | } 406 | return out, nil 407 | } 408 | 409 | // KeyManagementServiceServer is the server API for KeyManagementService service. 410 | type KeyManagementServiceServer interface { 411 | // Version returns the runtime name and runtime version of the KMS provider. 412 | Version(context.Context, *VersionRequest) (*VersionResponse, error) 413 | // Execute decryption operation in KMS provider. 414 | Decrypt(context.Context, *DecryptRequest) (*DecryptResponse, error) 415 | // Execute encryption operation in KMS provider. 416 | Encrypt(context.Context, *EncryptRequest) (*EncryptResponse, error) 417 | } 418 | 419 | // UnimplementedKeyManagementServiceServer can be embedded to have forward compatible implementations. 420 | type UnimplementedKeyManagementServiceServer struct { 421 | } 422 | 423 | func (*UnimplementedKeyManagementServiceServer) Version(ctx context.Context, req *VersionRequest) (*VersionResponse, error) { 424 | return nil, status.Errorf(codes.Unimplemented, "method Version not implemented") 425 | } 426 | func (*UnimplementedKeyManagementServiceServer) Decrypt(ctx context.Context, req *DecryptRequest) (*DecryptResponse, error) { 427 | return nil, status.Errorf(codes.Unimplemented, "method Decrypt not implemented") 428 | } 429 | func (*UnimplementedKeyManagementServiceServer) Encrypt(ctx context.Context, req *EncryptRequest) (*EncryptResponse, error) { 430 | return nil, status.Errorf(codes.Unimplemented, "method Encrypt not implemented") 431 | } 432 | 433 | func RegisterKeyManagementServiceServer(s *grpc.Server, srv KeyManagementServiceServer) { 434 | s.RegisterService(&_KeyManagementService_serviceDesc, srv) 435 | } 436 | 437 | func _KeyManagementService_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 438 | in := new(VersionRequest) 439 | if err := dec(in); err != nil { 440 | return nil, err 441 | } 442 | if interceptor == nil { 443 | return srv.(KeyManagementServiceServer).Version(ctx, in) 444 | } 445 | info := &grpc.UnaryServerInfo{ 446 | Server: srv, 447 | FullMethod: "/v1beta1.KeyManagementService/Version", 448 | } 449 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 450 | return srv.(KeyManagementServiceServer).Version(ctx, req.(*VersionRequest)) 451 | } 452 | return interceptor(ctx, in, info, handler) 453 | } 454 | 455 | func _KeyManagementService_Decrypt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 456 | in := new(DecryptRequest) 457 | if err := dec(in); err != nil { 458 | return nil, err 459 | } 460 | if interceptor == nil { 461 | return srv.(KeyManagementServiceServer).Decrypt(ctx, in) 462 | } 463 | info := &grpc.UnaryServerInfo{ 464 | Server: srv, 465 | FullMethod: "/v1beta1.KeyManagementService/Decrypt", 466 | } 467 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 468 | return srv.(KeyManagementServiceServer).Decrypt(ctx, req.(*DecryptRequest)) 469 | } 470 | return interceptor(ctx, in, info, handler) 471 | } 472 | 473 | func _KeyManagementService_Encrypt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 474 | in := new(EncryptRequest) 475 | if err := dec(in); err != nil { 476 | return nil, err 477 | } 478 | if interceptor == nil { 479 | return srv.(KeyManagementServiceServer).Encrypt(ctx, in) 480 | } 481 | info := &grpc.UnaryServerInfo{ 482 | Server: srv, 483 | FullMethod: "/v1beta1.KeyManagementService/Encrypt", 484 | } 485 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 486 | return srv.(KeyManagementServiceServer).Encrypt(ctx, req.(*EncryptRequest)) 487 | } 488 | return interceptor(ctx, in, info, handler) 489 | } 490 | 491 | var _KeyManagementService_serviceDesc = grpc.ServiceDesc{ 492 | ServiceName: "v1beta1.KeyManagementService", 493 | HandlerType: (*KeyManagementServiceServer)(nil), 494 | Methods: []grpc.MethodDesc{ 495 | { 496 | MethodName: "Version", 497 | Handler: _KeyManagementService_Version_Handler, 498 | }, 499 | { 500 | MethodName: "Decrypt", 501 | Handler: _KeyManagementService_Decrypt_Handler, 502 | }, 503 | { 504 | MethodName: "Encrypt", 505 | Handler: _KeyManagementService_Encrypt_Handler, 506 | }, 507 | }, 508 | Streams: []grpc.StreamDesc{}, 509 | Metadata: "api.proto", 510 | } 511 | -------------------------------------------------------------------------------- /apis/v1beta1/api.proto: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // To regenerate api.pb.go run `hack/update-codegen.sh protobindings` 18 | syntax = "proto3"; 19 | 20 | package v1beta1; 21 | option go_package = "k8s.io/kms/apis/v1beta1"; 22 | option deprecated = true; 23 | 24 | // This service defines the public APIs for remote KMS provider. 25 | service KeyManagementService { 26 | // Version returns the runtime name and runtime version of the KMS provider. 27 | rpc Version(VersionRequest) returns (VersionResponse) {} 28 | 29 | // Execute decryption operation in KMS provider. 30 | rpc Decrypt(DecryptRequest) returns (DecryptResponse) {} 31 | // Execute encryption operation in KMS provider. 32 | rpc Encrypt(EncryptRequest) returns (EncryptResponse) {} 33 | } 34 | 35 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 36 | message VersionRequest { 37 | // Version of the KMS plugin API. 38 | string version = 1; 39 | } 40 | 41 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 42 | message VersionResponse { 43 | // Version of the KMS plugin API. 44 | string version = 1; 45 | // Name of the KMS provider. 46 | string runtime_name = 2; 47 | // Version of the KMS provider. The string must be semver-compatible. 48 | string runtime_version = 3; 49 | } 50 | 51 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 52 | message DecryptRequest { 53 | // Version of the KMS plugin API. 54 | string version = 1; 55 | // The data to be decrypted. 56 | bytes cipher = 2; 57 | } 58 | 59 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 60 | message DecryptResponse { 61 | // The decrypted data. 62 | bytes plain = 1; 63 | } 64 | 65 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 66 | message EncryptRequest { 67 | // Version of the KMS plugin API. 68 | string version = 1; 69 | // The data to be encrypted. 70 | bytes plain = 2; 71 | } 72 | 73 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 74 | message EncryptResponse { 75 | // The encrypted data. 76 | bytes cipher = 1; 77 | } 78 | -------------------------------------------------------------------------------- /apis/v1beta1/v1beta1.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains definition of kms-plugin's gRPC service. 18 | // Deprecated: KMSv1 is deprecated in v1.28 and will only receive security updates going forward. Use KMSv2 instead. 19 | package v1beta1 20 | 21 | // IsVersionCheckMethod determines whether the supplied method is a version check against kms-plugin. 22 | func IsVersionCheckMethod(method string) bool { 23 | return method == "/v1beta1.KeyManagementService/Version" 24 | } 25 | -------------------------------------------------------------------------------- /apis/v2/api.pb.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 18 | // source: api.proto 19 | 20 | package v2 21 | 22 | import ( 23 | context "context" 24 | fmt "fmt" 25 | proto "github.com/gogo/protobuf/proto" 26 | grpc "google.golang.org/grpc" 27 | codes "google.golang.org/grpc/codes" 28 | status "google.golang.org/grpc/status" 29 | math "math" 30 | ) 31 | 32 | // Reference imports to suppress errors if they are not otherwise used. 33 | var _ = proto.Marshal 34 | var _ = fmt.Errorf 35 | var _ = math.Inf 36 | 37 | // This is a compile-time assertion to ensure that this generated file 38 | // is compatible with the proto package it is being compiled against. 39 | // A compilation error at this line likely means your copy of the 40 | // proto package needs to be updated. 41 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package 42 | 43 | type StatusRequest struct { 44 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 45 | XXX_unrecognized []byte `json:"-"` 46 | XXX_sizecache int32 `json:"-"` 47 | } 48 | 49 | func (m *StatusRequest) Reset() { *m = StatusRequest{} } 50 | func (m *StatusRequest) String() string { return proto.CompactTextString(m) } 51 | func (*StatusRequest) ProtoMessage() {} 52 | func (*StatusRequest) Descriptor() ([]byte, []int) { 53 | return fileDescriptor_00212fb1f9d3bf1c, []int{0} 54 | } 55 | func (m *StatusRequest) XXX_Unmarshal(b []byte) error { 56 | return xxx_messageInfo_StatusRequest.Unmarshal(m, b) 57 | } 58 | func (m *StatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 59 | return xxx_messageInfo_StatusRequest.Marshal(b, m, deterministic) 60 | } 61 | func (m *StatusRequest) XXX_Merge(src proto.Message) { 62 | xxx_messageInfo_StatusRequest.Merge(m, src) 63 | } 64 | func (m *StatusRequest) XXX_Size() int { 65 | return xxx_messageInfo_StatusRequest.Size(m) 66 | } 67 | func (m *StatusRequest) XXX_DiscardUnknown() { 68 | xxx_messageInfo_StatusRequest.DiscardUnknown(m) 69 | } 70 | 71 | var xxx_messageInfo_StatusRequest proto.InternalMessageInfo 72 | 73 | type StatusResponse struct { 74 | // Version of the KMS gRPC plugin API. Must equal v2 to v2beta1 (v2 is recommended, but both are equivalent). 75 | Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` 76 | // Any value other than "ok" is failing healthz. On failure, the associated API server healthz endpoint will contain this value as part of the error message. 77 | Healthz string `protobuf:"bytes,2,opt,name=healthz,proto3" json:"healthz,omitempty"` 78 | // the current write key, used to determine staleness of data updated via value.Transformer.TransformFromStorage. 79 | // keyID must satisfy the following constraints: 80 | // 1. The keyID is not empty. 81 | // 2. The size of keyID is less than 1 kB. 82 | KeyId string `protobuf:"bytes,3,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"` 83 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 84 | XXX_unrecognized []byte `json:"-"` 85 | XXX_sizecache int32 `json:"-"` 86 | } 87 | 88 | func (m *StatusResponse) Reset() { *m = StatusResponse{} } 89 | func (m *StatusResponse) String() string { return proto.CompactTextString(m) } 90 | func (*StatusResponse) ProtoMessage() {} 91 | func (*StatusResponse) Descriptor() ([]byte, []int) { 92 | return fileDescriptor_00212fb1f9d3bf1c, []int{1} 93 | } 94 | func (m *StatusResponse) XXX_Unmarshal(b []byte) error { 95 | return xxx_messageInfo_StatusResponse.Unmarshal(m, b) 96 | } 97 | func (m *StatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 98 | return xxx_messageInfo_StatusResponse.Marshal(b, m, deterministic) 99 | } 100 | func (m *StatusResponse) XXX_Merge(src proto.Message) { 101 | xxx_messageInfo_StatusResponse.Merge(m, src) 102 | } 103 | func (m *StatusResponse) XXX_Size() int { 104 | return xxx_messageInfo_StatusResponse.Size(m) 105 | } 106 | func (m *StatusResponse) XXX_DiscardUnknown() { 107 | xxx_messageInfo_StatusResponse.DiscardUnknown(m) 108 | } 109 | 110 | var xxx_messageInfo_StatusResponse proto.InternalMessageInfo 111 | 112 | func (m *StatusResponse) GetVersion() string { 113 | if m != nil { 114 | return m.Version 115 | } 116 | return "" 117 | } 118 | 119 | func (m *StatusResponse) GetHealthz() string { 120 | if m != nil { 121 | return m.Healthz 122 | } 123 | return "" 124 | } 125 | 126 | func (m *StatusResponse) GetKeyId() string { 127 | if m != nil { 128 | return m.KeyId 129 | } 130 | return "" 131 | } 132 | 133 | type DecryptRequest struct { 134 | // The data to be decrypted. 135 | Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` 136 | // UID is a unique identifier for the request. 137 | Uid string `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"` 138 | // The keyID that was provided to the apiserver during encryption. 139 | // This represents the KMS KEK that was used to encrypt the data. 140 | KeyId string `protobuf:"bytes,3,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"` 141 | // Additional metadata that was sent by the KMS plugin during encryption. 142 | Annotations map[string][]byte `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 143 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 144 | XXX_unrecognized []byte `json:"-"` 145 | XXX_sizecache int32 `json:"-"` 146 | } 147 | 148 | func (m *DecryptRequest) Reset() { *m = DecryptRequest{} } 149 | func (m *DecryptRequest) String() string { return proto.CompactTextString(m) } 150 | func (*DecryptRequest) ProtoMessage() {} 151 | func (*DecryptRequest) Descriptor() ([]byte, []int) { 152 | return fileDescriptor_00212fb1f9d3bf1c, []int{2} 153 | } 154 | func (m *DecryptRequest) XXX_Unmarshal(b []byte) error { 155 | return xxx_messageInfo_DecryptRequest.Unmarshal(m, b) 156 | } 157 | func (m *DecryptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 158 | return xxx_messageInfo_DecryptRequest.Marshal(b, m, deterministic) 159 | } 160 | func (m *DecryptRequest) XXX_Merge(src proto.Message) { 161 | xxx_messageInfo_DecryptRequest.Merge(m, src) 162 | } 163 | func (m *DecryptRequest) XXX_Size() int { 164 | return xxx_messageInfo_DecryptRequest.Size(m) 165 | } 166 | func (m *DecryptRequest) XXX_DiscardUnknown() { 167 | xxx_messageInfo_DecryptRequest.DiscardUnknown(m) 168 | } 169 | 170 | var xxx_messageInfo_DecryptRequest proto.InternalMessageInfo 171 | 172 | func (m *DecryptRequest) GetCiphertext() []byte { 173 | if m != nil { 174 | return m.Ciphertext 175 | } 176 | return nil 177 | } 178 | 179 | func (m *DecryptRequest) GetUid() string { 180 | if m != nil { 181 | return m.Uid 182 | } 183 | return "" 184 | } 185 | 186 | func (m *DecryptRequest) GetKeyId() string { 187 | if m != nil { 188 | return m.KeyId 189 | } 190 | return "" 191 | } 192 | 193 | func (m *DecryptRequest) GetAnnotations() map[string][]byte { 194 | if m != nil { 195 | return m.Annotations 196 | } 197 | return nil 198 | } 199 | 200 | type DecryptResponse struct { 201 | // The decrypted data. 202 | Plaintext []byte `protobuf:"bytes,1,opt,name=plaintext,proto3" json:"plaintext,omitempty"` 203 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 204 | XXX_unrecognized []byte `json:"-"` 205 | XXX_sizecache int32 `json:"-"` 206 | } 207 | 208 | func (m *DecryptResponse) Reset() { *m = DecryptResponse{} } 209 | func (m *DecryptResponse) String() string { return proto.CompactTextString(m) } 210 | func (*DecryptResponse) ProtoMessage() {} 211 | func (*DecryptResponse) Descriptor() ([]byte, []int) { 212 | return fileDescriptor_00212fb1f9d3bf1c, []int{3} 213 | } 214 | func (m *DecryptResponse) XXX_Unmarshal(b []byte) error { 215 | return xxx_messageInfo_DecryptResponse.Unmarshal(m, b) 216 | } 217 | func (m *DecryptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 218 | return xxx_messageInfo_DecryptResponse.Marshal(b, m, deterministic) 219 | } 220 | func (m *DecryptResponse) XXX_Merge(src proto.Message) { 221 | xxx_messageInfo_DecryptResponse.Merge(m, src) 222 | } 223 | func (m *DecryptResponse) XXX_Size() int { 224 | return xxx_messageInfo_DecryptResponse.Size(m) 225 | } 226 | func (m *DecryptResponse) XXX_DiscardUnknown() { 227 | xxx_messageInfo_DecryptResponse.DiscardUnknown(m) 228 | } 229 | 230 | var xxx_messageInfo_DecryptResponse proto.InternalMessageInfo 231 | 232 | func (m *DecryptResponse) GetPlaintext() []byte { 233 | if m != nil { 234 | return m.Plaintext 235 | } 236 | return nil 237 | } 238 | 239 | type EncryptRequest struct { 240 | // The data to be encrypted. 241 | Plaintext []byte `protobuf:"bytes,1,opt,name=plaintext,proto3" json:"plaintext,omitempty"` 242 | // UID is a unique identifier for the request. 243 | Uid string `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"` 244 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 245 | XXX_unrecognized []byte `json:"-"` 246 | XXX_sizecache int32 `json:"-"` 247 | } 248 | 249 | func (m *EncryptRequest) Reset() { *m = EncryptRequest{} } 250 | func (m *EncryptRequest) String() string { return proto.CompactTextString(m) } 251 | func (*EncryptRequest) ProtoMessage() {} 252 | func (*EncryptRequest) Descriptor() ([]byte, []int) { 253 | return fileDescriptor_00212fb1f9d3bf1c, []int{4} 254 | } 255 | func (m *EncryptRequest) XXX_Unmarshal(b []byte) error { 256 | return xxx_messageInfo_EncryptRequest.Unmarshal(m, b) 257 | } 258 | func (m *EncryptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 259 | return xxx_messageInfo_EncryptRequest.Marshal(b, m, deterministic) 260 | } 261 | func (m *EncryptRequest) XXX_Merge(src proto.Message) { 262 | xxx_messageInfo_EncryptRequest.Merge(m, src) 263 | } 264 | func (m *EncryptRequest) XXX_Size() int { 265 | return xxx_messageInfo_EncryptRequest.Size(m) 266 | } 267 | func (m *EncryptRequest) XXX_DiscardUnknown() { 268 | xxx_messageInfo_EncryptRequest.DiscardUnknown(m) 269 | } 270 | 271 | var xxx_messageInfo_EncryptRequest proto.InternalMessageInfo 272 | 273 | func (m *EncryptRequest) GetPlaintext() []byte { 274 | if m != nil { 275 | return m.Plaintext 276 | } 277 | return nil 278 | } 279 | 280 | func (m *EncryptRequest) GetUid() string { 281 | if m != nil { 282 | return m.Uid 283 | } 284 | return "" 285 | } 286 | 287 | type EncryptResponse struct { 288 | // The encrypted data. 289 | // ciphertext must satisfy the following constraints: 290 | // 1. The ciphertext is not empty. 291 | // 2. The ciphertext is less than 1 kB. 292 | Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` 293 | // The KMS key ID used to encrypt the data. This must always refer to the KMS KEK and not any local KEKs that may be in use. 294 | // This can be used to inform staleness of data updated via value.Transformer.TransformFromStorage. 295 | // keyID must satisfy the following constraints: 296 | // 1. The keyID is not empty. 297 | // 2. The size of keyID is less than 1 kB. 298 | KeyId string `protobuf:"bytes,2,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"` 299 | // Additional metadata to be stored with the encrypted data. 300 | // This data is stored in plaintext in etcd. KMS plugin implementations are responsible for pre-encrypting any sensitive data. 301 | // Annotations must satisfy the following constraints: 302 | // 1. Annotation key must be a fully qualified domain name that conforms to the definition in DNS (RFC 1123). 303 | // 2. The size of annotations keys + values is less than 32 kB. 304 | Annotations map[string][]byte `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 305 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 306 | XXX_unrecognized []byte `json:"-"` 307 | XXX_sizecache int32 `json:"-"` 308 | } 309 | 310 | func (m *EncryptResponse) Reset() { *m = EncryptResponse{} } 311 | func (m *EncryptResponse) String() string { return proto.CompactTextString(m) } 312 | func (*EncryptResponse) ProtoMessage() {} 313 | func (*EncryptResponse) Descriptor() ([]byte, []int) { 314 | return fileDescriptor_00212fb1f9d3bf1c, []int{5} 315 | } 316 | func (m *EncryptResponse) XXX_Unmarshal(b []byte) error { 317 | return xxx_messageInfo_EncryptResponse.Unmarshal(m, b) 318 | } 319 | func (m *EncryptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 320 | return xxx_messageInfo_EncryptResponse.Marshal(b, m, deterministic) 321 | } 322 | func (m *EncryptResponse) XXX_Merge(src proto.Message) { 323 | xxx_messageInfo_EncryptResponse.Merge(m, src) 324 | } 325 | func (m *EncryptResponse) XXX_Size() int { 326 | return xxx_messageInfo_EncryptResponse.Size(m) 327 | } 328 | func (m *EncryptResponse) XXX_DiscardUnknown() { 329 | xxx_messageInfo_EncryptResponse.DiscardUnknown(m) 330 | } 331 | 332 | var xxx_messageInfo_EncryptResponse proto.InternalMessageInfo 333 | 334 | func (m *EncryptResponse) GetCiphertext() []byte { 335 | if m != nil { 336 | return m.Ciphertext 337 | } 338 | return nil 339 | } 340 | 341 | func (m *EncryptResponse) GetKeyId() string { 342 | if m != nil { 343 | return m.KeyId 344 | } 345 | return "" 346 | } 347 | 348 | func (m *EncryptResponse) GetAnnotations() map[string][]byte { 349 | if m != nil { 350 | return m.Annotations 351 | } 352 | return nil 353 | } 354 | 355 | func init() { 356 | proto.RegisterType((*StatusRequest)(nil), "v2.StatusRequest") 357 | proto.RegisterType((*StatusResponse)(nil), "v2.StatusResponse") 358 | proto.RegisterType((*DecryptRequest)(nil), "v2.DecryptRequest") 359 | proto.RegisterMapType((map[string][]byte)(nil), "v2.DecryptRequest.AnnotationsEntry") 360 | proto.RegisterType((*DecryptResponse)(nil), "v2.DecryptResponse") 361 | proto.RegisterType((*EncryptRequest)(nil), "v2.EncryptRequest") 362 | proto.RegisterType((*EncryptResponse)(nil), "v2.EncryptResponse") 363 | proto.RegisterMapType((map[string][]byte)(nil), "v2.EncryptResponse.AnnotationsEntry") 364 | } 365 | 366 | func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } 367 | 368 | var fileDescriptor_00212fb1f9d3bf1c = []byte{ 369 | // 403 bytes of a gzipped FileDescriptorProto 370 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x93, 0xcd, 0x6e, 0xda, 0x40, 371 | 0x10, 0xc7, 0xb1, 0x5d, 0x40, 0x0c, 0x14, 0xe8, 0x96, 0x4a, 0x16, 0xaa, 0x2a, 0xb4, 0xed, 0x81, 372 | 0x93, 0xad, 0xba, 0x3d, 0xa0, 0x1e, 0xaa, 0xb6, 0x2a, 0x95, 0xaa, 0xaa, 0x17, 0x73, 0x6b, 0x0f, 373 | 0xd1, 0x06, 0x46, 0x61, 0x65, 0x58, 0x3b, 0xde, 0xb5, 0x15, 0xe7, 0xbd, 0xf2, 0x1e, 0x79, 0x84, 374 | 0x3c, 0x4a, 0x64, 0x7b, 0x01, 0x1b, 0x94, 0xe4, 0x94, 0x9b, 0xe7, 0xf3, 0x3f, 0xf3, 0xdb, 0x31, 375 | 0x74, 0x58, 0xc4, 0x9d, 0x28, 0x0e, 0x55, 0x48, 0xcc, 0xd4, 0xa3, 0x03, 0x78, 0xb9, 0x50, 0x4c, 376 | 0x25, 0xd2, 0xc7, 0xcb, 0x04, 0xa5, 0xa2, 0xff, 0xa1, 0xbf, 0x73, 0xc8, 0x28, 0x14, 0x12, 0x89, 377 | 0x0d, 0xed, 0x14, 0x63, 0xc9, 0x43, 0x61, 0x1b, 0x13, 0x63, 0xda, 0xf1, 0x77, 0x66, 0x1e, 0x59, 378 | 0x23, 0xdb, 0xa8, 0xf5, 0xb5, 0x6d, 0x96, 0x11, 0x6d, 0x92, 0x37, 0xd0, 0x0a, 0x30, 0x3b, 0xe3, 379 | 0x2b, 0xdb, 0x2a, 0x02, 0xcd, 0x00, 0xb3, 0xdf, 0x2b, 0x7a, 0x67, 0x40, 0xff, 0x27, 0x2e, 0xe3, 380 | 0x2c, 0x52, 0x5a, 0x8f, 0xbc, 0x03, 0x58, 0xf2, 0x68, 0x8d, 0xb1, 0xc2, 0x2b, 0x55, 0x08, 0xf4, 381 | 0xfc, 0x8a, 0x87, 0x0c, 0xc1, 0x4a, 0xf8, 0x4a, 0xf7, 0xcf, 0x3f, 0x1f, 0xe8, 0x4d, 0xe6, 0xd0, 382 | 0x65, 0x42, 0x84, 0x8a, 0x29, 0x1e, 0x0a, 0x69, 0xbf, 0x98, 0x58, 0xd3, 0xae, 0xf7, 0xde, 0x49, 383 | 0x3d, 0xa7, 0xae, 0xe8, 0x7c, 0x3f, 0x64, 0xcd, 0x85, 0x8a, 0x33, 0xbf, 0x5a, 0x37, 0xfe, 0x0a, 384 | 0xc3, 0xe3, 0x84, 0x7c, 0x86, 0x00, 0x33, 0xbd, 0x7d, 0xfe, 0x49, 0x46, 0xd0, 0x4c, 0xd9, 0x26, 385 | 0xc1, 0x62, 0xae, 0x9e, 0x5f, 0x1a, 0x5f, 0xcc, 0x99, 0x41, 0x5d, 0x18, 0xec, 0xf5, 0x34, 0xc0, 386 | 0xb7, 0xd0, 0x89, 0x36, 0x8c, 0x8b, 0xca, 0x86, 0x07, 0x07, 0xfd, 0x06, 0xfd, 0xb9, 0xa8, 0x21, 387 | 0x79, 0x34, 0xff, 0x14, 0x08, 0xbd, 0x35, 0x60, 0xb0, 0x6f, 0xa1, 0x35, 0x9f, 0xc2, 0x7a, 0x80, 388 | 0x68, 0x56, 0x21, 0xfe, 0xaa, 0x43, 0xb4, 0x0a, 0x88, 0x1f, 0x72, 0x88, 0x47, 0x02, 0xcf, 0x4b, 389 | 0xd1, 0xbb, 0x31, 0x60, 0xf4, 0x07, 0xb3, 0xbf, 0x4c, 0xb0, 0x0b, 0xdc, 0xa2, 0x50, 0x0b, 0x8c, 390 | 0x53, 0xbe, 0x44, 0xf2, 0x11, 0x5a, 0xe5, 0x79, 0x92, 0x57, 0xf9, 0x54, 0xb5, 0xdb, 0x1d, 0x93, 391 | 0xaa, 0xab, 0x9c, 0x93, 0x36, 0xc8, 0x67, 0x68, 0xeb, 0x17, 0x21, 0xe4, 0xf4, 0x1c, 0xc6, 0xaf, 392 | 0x6b, 0xbe, 0x6a, 0x95, 0x5e, 0xb9, 0xac, 0xaa, 0xbf, 0x51, 0x59, 0x75, 0xc4, 0x84, 0x36, 0x7e, 393 | 0x8c, 0xfe, 0x91, 0x60, 0x26, 0x1d, 0x1e, 0xba, 0xc1, 0x56, 0xba, 0x2c, 0xe2, 0xd2, 0x4d, 0xbd, 394 | 0xf3, 0x56, 0xf1, 0xbf, 0x7d, 0xba, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x5f, 0xf8, 0x49, 0x17, 0x7c, 395 | 0x03, 0x00, 0x00, 396 | } 397 | 398 | // Reference imports to suppress errors if they are not otherwise used. 399 | var _ context.Context 400 | var _ grpc.ClientConn 401 | 402 | // This is a compile-time assertion to ensure that this generated file 403 | // is compatible with the grpc package it is being compiled against. 404 | const _ = grpc.SupportPackageIsVersion4 405 | 406 | // KeyManagementServiceClient is the client API for KeyManagementService service. 407 | // 408 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 409 | type KeyManagementServiceClient interface { 410 | // this API is meant to be polled 411 | Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) 412 | // Execute decryption operation in KMS provider. 413 | Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) 414 | // Execute encryption operation in KMS provider. 415 | Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) 416 | } 417 | 418 | type keyManagementServiceClient struct { 419 | cc *grpc.ClientConn 420 | } 421 | 422 | func NewKeyManagementServiceClient(cc *grpc.ClientConn) KeyManagementServiceClient { 423 | return &keyManagementServiceClient{cc} 424 | } 425 | 426 | func (c *keyManagementServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) { 427 | out := new(StatusResponse) 428 | err := c.cc.Invoke(ctx, "/v2.KeyManagementService/Status", in, out, opts...) 429 | if err != nil { 430 | return nil, err 431 | } 432 | return out, nil 433 | } 434 | 435 | func (c *keyManagementServiceClient) Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) { 436 | out := new(DecryptResponse) 437 | err := c.cc.Invoke(ctx, "/v2.KeyManagementService/Decrypt", in, out, opts...) 438 | if err != nil { 439 | return nil, err 440 | } 441 | return out, nil 442 | } 443 | 444 | func (c *keyManagementServiceClient) Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) { 445 | out := new(EncryptResponse) 446 | err := c.cc.Invoke(ctx, "/v2.KeyManagementService/Encrypt", in, out, opts...) 447 | if err != nil { 448 | return nil, err 449 | } 450 | return out, nil 451 | } 452 | 453 | // KeyManagementServiceServer is the server API for KeyManagementService service. 454 | type KeyManagementServiceServer interface { 455 | // this API is meant to be polled 456 | Status(context.Context, *StatusRequest) (*StatusResponse, error) 457 | // Execute decryption operation in KMS provider. 458 | Decrypt(context.Context, *DecryptRequest) (*DecryptResponse, error) 459 | // Execute encryption operation in KMS provider. 460 | Encrypt(context.Context, *EncryptRequest) (*EncryptResponse, error) 461 | } 462 | 463 | // UnimplementedKeyManagementServiceServer can be embedded to have forward compatible implementations. 464 | type UnimplementedKeyManagementServiceServer struct { 465 | } 466 | 467 | func (*UnimplementedKeyManagementServiceServer) Status(ctx context.Context, req *StatusRequest) (*StatusResponse, error) { 468 | return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") 469 | } 470 | func (*UnimplementedKeyManagementServiceServer) Decrypt(ctx context.Context, req *DecryptRequest) (*DecryptResponse, error) { 471 | return nil, status.Errorf(codes.Unimplemented, "method Decrypt not implemented") 472 | } 473 | func (*UnimplementedKeyManagementServiceServer) Encrypt(ctx context.Context, req *EncryptRequest) (*EncryptResponse, error) { 474 | return nil, status.Errorf(codes.Unimplemented, "method Encrypt not implemented") 475 | } 476 | 477 | func RegisterKeyManagementServiceServer(s *grpc.Server, srv KeyManagementServiceServer) { 478 | s.RegisterService(&_KeyManagementService_serviceDesc, srv) 479 | } 480 | 481 | func _KeyManagementService_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 482 | in := new(StatusRequest) 483 | if err := dec(in); err != nil { 484 | return nil, err 485 | } 486 | if interceptor == nil { 487 | return srv.(KeyManagementServiceServer).Status(ctx, in) 488 | } 489 | info := &grpc.UnaryServerInfo{ 490 | Server: srv, 491 | FullMethod: "/v2.KeyManagementService/Status", 492 | } 493 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 494 | return srv.(KeyManagementServiceServer).Status(ctx, req.(*StatusRequest)) 495 | } 496 | return interceptor(ctx, in, info, handler) 497 | } 498 | 499 | func _KeyManagementService_Decrypt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 500 | in := new(DecryptRequest) 501 | if err := dec(in); err != nil { 502 | return nil, err 503 | } 504 | if interceptor == nil { 505 | return srv.(KeyManagementServiceServer).Decrypt(ctx, in) 506 | } 507 | info := &grpc.UnaryServerInfo{ 508 | Server: srv, 509 | FullMethod: "/v2.KeyManagementService/Decrypt", 510 | } 511 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 512 | return srv.(KeyManagementServiceServer).Decrypt(ctx, req.(*DecryptRequest)) 513 | } 514 | return interceptor(ctx, in, info, handler) 515 | } 516 | 517 | func _KeyManagementService_Encrypt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 518 | in := new(EncryptRequest) 519 | if err := dec(in); err != nil { 520 | return nil, err 521 | } 522 | if interceptor == nil { 523 | return srv.(KeyManagementServiceServer).Encrypt(ctx, in) 524 | } 525 | info := &grpc.UnaryServerInfo{ 526 | Server: srv, 527 | FullMethod: "/v2.KeyManagementService/Encrypt", 528 | } 529 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 530 | return srv.(KeyManagementServiceServer).Encrypt(ctx, req.(*EncryptRequest)) 531 | } 532 | return interceptor(ctx, in, info, handler) 533 | } 534 | 535 | var _KeyManagementService_serviceDesc = grpc.ServiceDesc{ 536 | ServiceName: "v2.KeyManagementService", 537 | HandlerType: (*KeyManagementServiceServer)(nil), 538 | Methods: []grpc.MethodDesc{ 539 | { 540 | MethodName: "Status", 541 | Handler: _KeyManagementService_Status_Handler, 542 | }, 543 | { 544 | MethodName: "Decrypt", 545 | Handler: _KeyManagementService_Decrypt_Handler, 546 | }, 547 | { 548 | MethodName: "Encrypt", 549 | Handler: _KeyManagementService_Encrypt_Handler, 550 | }, 551 | }, 552 | Streams: []grpc.StreamDesc{}, 553 | Metadata: "api.proto", 554 | } 555 | -------------------------------------------------------------------------------- /apis/v2/api.proto: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // To regenerate api.pb.go run `hack/update-codegen.sh protobindings` 18 | syntax = "proto3"; 19 | 20 | package v2; 21 | option go_package = "k8s.io/kms/apis/v2"; 22 | 23 | // This service defines the public APIs for remote KMS provider. 24 | service KeyManagementService { 25 | // this API is meant to be polled 26 | rpc Status(StatusRequest) returns (StatusResponse) {} 27 | 28 | // Execute decryption operation in KMS provider. 29 | rpc Decrypt(DecryptRequest) returns (DecryptResponse) {} 30 | // Execute encryption operation in KMS provider. 31 | rpc Encrypt(EncryptRequest) returns (EncryptResponse) {} 32 | } 33 | 34 | message StatusRequest {} 35 | 36 | message StatusResponse { 37 | // Version of the KMS gRPC plugin API. Must equal v2 to v2beta1 (v2 is recommended, but both are equivalent). 38 | string version = 1; 39 | // Any value other than "ok" is failing healthz. On failure, the associated API server healthz endpoint will contain this value as part of the error message. 40 | string healthz = 2; 41 | // the current write key, used to determine staleness of data updated via value.Transformer.TransformFromStorage. 42 | // keyID must satisfy the following constraints: 43 | // 1. The keyID is not empty. 44 | // 2. The size of keyID is less than 1 kB. 45 | string key_id = 3; 46 | } 47 | 48 | message DecryptRequest { 49 | // The data to be decrypted. 50 | bytes ciphertext = 1; 51 | // UID is a unique identifier for the request. 52 | string uid = 2; 53 | // The keyID that was provided to the apiserver during encryption. 54 | // This represents the KMS KEK that was used to encrypt the data. 55 | string key_id = 3; 56 | // Additional metadata that was sent by the KMS plugin during encryption. 57 | map annotations = 4; 58 | } 59 | 60 | message DecryptResponse { 61 | // The decrypted data. 62 | bytes plaintext = 1; 63 | } 64 | 65 | message EncryptRequest { 66 | // The data to be encrypted. 67 | bytes plaintext = 1; 68 | // UID is a unique identifier for the request. 69 | string uid = 2; 70 | } 71 | 72 | message EncryptResponse { 73 | // The encrypted data. 74 | // ciphertext must satisfy the following constraints: 75 | // 1. The ciphertext is not empty. 76 | // 2. The ciphertext is less than 1 kB. 77 | bytes ciphertext = 1; 78 | // The KMS key ID used to encrypt the data. This must always refer to the KMS KEK and not any local KEKs that may be in use. 79 | // This can be used to inform staleness of data updated via value.Transformer.TransformFromStorage. 80 | // keyID must satisfy the following constraints: 81 | // 1. The keyID is not empty. 82 | // 2. The size of keyID is less than 1 kB. 83 | string key_id = 2; 84 | // Additional metadata to be stored with the encrypted data. 85 | // This data is stored in plaintext in etcd. KMS plugin implementations are responsible for pre-encrypting any sensitive data. 86 | // Annotations must satisfy the following constraints: 87 | // 1. Annotation key must be a fully qualified domain name that conforms to the definition in DNS (RFC 1123). 88 | // 2. The size of annotations keys + values is less than 32 kB. 89 | map annotations = 3; 90 | } 91 | -------------------------------------------------------------------------------- /apis/v2/v2.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v2 contains definition of kms-plugin's gRPC service. 18 | package v2 19 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package kms contains the proto definitions for the kms API. 18 | package kms 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | // This is a generated file. Do not edit directly. 2 | 3 | module k8s.io/kms 4 | 5 | go 1.24.0 6 | 7 | godebug default=go1.24 8 | 9 | require ( 10 | github.com/gogo/protobuf v1.3.2 11 | google.golang.org/grpc v1.72.1 12 | ) 13 | 14 | require ( 15 | github.com/google/go-cmp v0.7.0 // indirect 16 | go.opentelemetry.io/otel v1.35.0 // indirect 17 | golang.org/x/net v0.38.0 // indirect 18 | golang.org/x/sys v0.31.0 // indirect 19 | golang.org/x/text v0.23.0 // indirect 20 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect 21 | google.golang.org/protobuf v1.36.5 // indirect 22 | ) 23 | 24 | replace k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20250527161416-09ff13941cda 25 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 2 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 3 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 4 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 5 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 6 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 7 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 8 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 9 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 10 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 11 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 12 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 13 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 14 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 15 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 16 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 17 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 18 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 19 | go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= 20 | go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= 21 | go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= 22 | go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= 23 | go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= 24 | go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= 25 | go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= 26 | go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= 27 | go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= 28 | go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= 29 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 30 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 31 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 32 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 33 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 34 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 35 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 36 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 37 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 38 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 39 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 40 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 41 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 42 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 43 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 44 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 45 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 46 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 47 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 48 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 49 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 50 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 51 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 52 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 53 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 54 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 55 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 56 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 57 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 58 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 59 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 60 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= 61 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= 62 | google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= 63 | google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= 64 | google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 65 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 66 | -------------------------------------------------------------------------------- /internal/plugins/_mock/.gitignore: -------------------------------------------------------------------------------- 1 | # avoid constant churn as this file is not kept in sync with the root 2 | go.work.sum 3 | -------------------------------------------------------------------------------- /internal/plugins/_mock/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: this is just a default placeholder for convenience 16 | # To build this image properly, please invoke test/e2e/testing-manifests/auth/encrypt/run-e2e.sh 17 | ARG BUILDER_IMAGE=golang:latest 18 | FROM $BUILDER_IMAGE AS builder 19 | 20 | WORKDIR /workspace 21 | 22 | # Copy the source 23 | COPY apimachinery/ apimachinery/ 24 | COPY kms/ kms/ 25 | WORKDIR /workspace/kms/internal/plugins/_mock 26 | 27 | ARG TARGETARCH 28 | ARG TARGETPLATFORM 29 | ARG GOTOOLCHAIN 30 | RUN CGO_ENABLED=1 GOOS=linux GOARCH=${TARGETARCH} GO111MODULE=on go build -a -o mock-kms-plugin plugin.go 31 | 32 | FROM alpine:latest 33 | 34 | RUN apk add --update --no-cache ca-certificates gcompat 35 | RUN apk add --no-cache softhsm 36 | 37 | COPY --from=builder /workspace/kms/internal/plugins/_mock/mock-kms-plugin /usr/local/bin/mock-kms-plugin 38 | 39 | ENTRYPOINT [ "mock-kms-plugin" ] 40 | -------------------------------------------------------------------------------- /internal/plugins/_mock/README.md: -------------------------------------------------------------------------------- 1 | # Mock KMS Plugin 2 | 3 | This is a mock KMS plugin for testing purposes. It implements the KMS plugin using PKCS#11 interface backed by [SoftHSM](https://www.opendnssec.org/softhsm/). It is intended to be used for testing only and not for production use. 4 | 5 | The directory is named `_mock` so that it is ignored by the `go mod` tooling in the root directory. 6 | -------------------------------------------------------------------------------- /internal/plugins/_mock/go.mod: -------------------------------------------------------------------------------- 1 | module k8s.io/kms/plugins/mock 2 | 3 | go 1.24.0 4 | 5 | godebug default=go1.24 6 | 7 | require ( 8 | github.com/ThalesIgnite/crypto11 v1.2.5 9 | k8s.io/kms v0.0.0-00010101000000-000000000000 10 | ) 11 | 12 | require ( 13 | github.com/gogo/protobuf v1.3.2 // indirect 14 | github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f // indirect 15 | github.com/pkg/errors v0.9.1 // indirect 16 | github.com/thales-e-security/pool v0.0.2 // indirect 17 | golang.org/x/net v0.38.0 // indirect 18 | golang.org/x/sys v0.31.0 // indirect 19 | golang.org/x/text v0.23.0 // indirect 20 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect 21 | google.golang.org/grpc v1.72.1 // indirect 22 | google.golang.org/protobuf v1.36.5 // indirect 23 | ) 24 | 25 | replace k8s.io/kms => ../../../../kms 26 | -------------------------------------------------------------------------------- /internal/plugins/_mock/go.sum: -------------------------------------------------------------------------------- 1 | github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= 2 | github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= 3 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 6 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 7 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 8 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 9 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 10 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 11 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 12 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 13 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 14 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 15 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 16 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 17 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 18 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 19 | github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f h1:eVB9ELsoq5ouItQBr5Tj334bhPJG/MX+m7rTchmzVUQ= 20 | github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= 21 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 22 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 23 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 24 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 25 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 26 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 27 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 28 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 29 | github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= 30 | github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= 31 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 32 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 33 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 34 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 35 | go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= 36 | go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= 37 | go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= 38 | go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= 39 | go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= 40 | go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= 41 | go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= 42 | go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= 43 | go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= 44 | go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= 45 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 46 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 47 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 48 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 49 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 50 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 51 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 52 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 53 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 54 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 55 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 56 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 57 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 58 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 59 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 60 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 61 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 62 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 63 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 64 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 65 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 66 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 67 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 68 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 69 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 70 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 71 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 72 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 73 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 74 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 75 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 76 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= 77 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= 78 | google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= 79 | google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= 80 | google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 81 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 82 | -------------------------------------------------------------------------------- /internal/plugins/_mock/go.work: -------------------------------------------------------------------------------- 1 | // This is a hack, but it prevents go from climbing further and trying to 2 | // reconcile the various deps across the "real" modules and this one. 3 | 4 | go 1.24.0 5 | 6 | godebug default=go1.24 7 | 8 | use . 9 | -------------------------------------------------------------------------------- /internal/plugins/_mock/kms.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: mock-kmsv2-provider 5 | namespace: kube-system 6 | labels: 7 | tier: control-plane 8 | component: mock-kmsv2-provider 9 | spec: 10 | # hostNetwork: true is required because the plugin is run as a static pod 11 | # on the control plane node and needs to run before the CNI plugins are initialized. 12 | hostNetwork: true 13 | initContainers: 14 | - args: 15 | - | 16 | #!/bin/sh 17 | set -e 18 | set -x 19 | 20 | # if token exists, skip initialization 21 | if [ $(ls -1 /var/lib/softhsm/tokens | wc -l) -ge 1 ]; then 22 | echo "Skipping initialization of softhsm" 23 | exit 0 24 | fi 25 | 26 | mkdir -p /var/lib/softhsm/tokens 27 | apk add --update --no-cache ca-certificates jq 28 | apk add --no-cache ccid opensc softhsm 29 | 30 | TOKEN_LABEL=$(jq -r '.tokenLabel' /etc/softhsm-config.json) 31 | PIN=$(jq -r '.pin' /etc/softhsm-config.json) 32 | MODULE_PATH=$(jq -r '.path' /etc/softhsm-config.json) 33 | 34 | softhsm2-util --init-token --free --label $TOKEN_LABEL --pin $PIN --so-pin $PIN 35 | pkcs11-tool --module $MODULE_PATH --keygen --key-type aes:32 --pin $PIN --token-label $TOKEN_LABEL --label kms-test 36 | command: 37 | - /bin/sh 38 | - -c 39 | image: alpine:latest 40 | imagePullPolicy: IfNotPresent 41 | name: init-mock-kmsv2-provider 42 | volumeMounts: 43 | - mountPath: /var/lib/softhsm/tokens 44 | name: softhsm-tokens 45 | - mountPath: /etc/softhsm-config.json 46 | name: softhsm-config 47 | containers: 48 | - name: mock-kmsv2-provider 49 | image: localhost:5000/mock-kms-provider:e2e 50 | imagePullPolicy: IfNotPresent 51 | volumeMounts: 52 | - name: sock 53 | mountPath: /tmp 54 | - name: softhsm-config 55 | mountPath: /etc/softhsm-config.json 56 | - name: softhsm-tokens 57 | mountPath: /var/lib/softhsm/tokens 58 | volumes: 59 | - name: sock 60 | hostPath: 61 | path: /tmp 62 | - name: softhsm-config 63 | hostPath: 64 | path: /etc/softhsm-config.json 65 | type: File 66 | - name: softhsm-tokens 67 | hostPath: 68 | path: /var/lib/softhsm/tokens 69 | type: DirectoryOrCreate 70 | -------------------------------------------------------------------------------- /internal/plugins/_mock/pkcs11/pkcs11.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package pkcs11 18 | 19 | import ( 20 | "context" 21 | "crypto/cipher" 22 | "crypto/rand" 23 | "fmt" 24 | 25 | crypot11 "github.com/ThalesIgnite/crypto11" 26 | 27 | "k8s.io/kms/pkg/service" 28 | ) 29 | 30 | const ( 31 | mockAnnotationKey = "version.encryption.remote.io" 32 | ) 33 | 34 | var _ service.Service = &pkcs11RemoteService{} 35 | 36 | type pkcs11RemoteService struct { 37 | keyID string 38 | aead cipher.AEAD 39 | } 40 | 41 | // NewPKCS11RemoteService creates a new PKCS11 remote service with SoftHSMv2 configuration file and keyID 42 | func NewPKCS11RemoteService(configFilePath, keyID string) (service.Service, error) { 43 | ctx, err := crypot11.ConfigureFromFile(configFilePath) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | if len(keyID) == 0 { 49 | return nil, fmt.Errorf("invalid keyID") 50 | } 51 | 52 | remoteService := &pkcs11RemoteService{ 53 | keyID: keyID, 54 | } 55 | 56 | key, err := ctx.FindKey(nil, []byte(keyID)) 57 | if err != nil { 58 | return nil, err 59 | } 60 | if key == nil { 61 | return nil, fmt.Errorf("key not found") 62 | } 63 | if remoteService.aead, err = key.NewGCM(); err != nil { 64 | return nil, err 65 | } 66 | 67 | return remoteService, nil 68 | } 69 | 70 | func (s *pkcs11RemoteService) Encrypt(ctx context.Context, uid string, plaintext []byte) (*service.EncryptResponse, error) { 71 | nonceSize := s.aead.NonceSize() 72 | result := make([]byte, nonceSize+s.aead.Overhead()+len(plaintext)) 73 | n, err := rand.Read(result[:nonceSize]) 74 | if err != nil { 75 | return nil, err 76 | } 77 | if n != nonceSize { 78 | return nil, fmt.Errorf("unable to read sufficient random bytes") 79 | } 80 | cipherText := s.aead.Seal(result[nonceSize:nonceSize], result[:nonceSize], plaintext, []byte(s.keyID)) 81 | 82 | return &service.EncryptResponse{ 83 | Ciphertext: result[:nonceSize+len(cipherText)], 84 | KeyID: s.keyID, 85 | Annotations: map[string][]byte{ 86 | mockAnnotationKey: []byte("1"), 87 | }, 88 | }, nil 89 | } 90 | 91 | func (s *pkcs11RemoteService) Decrypt(ctx context.Context, uid string, req *service.DecryptRequest) ([]byte, error) { 92 | if len(req.Annotations) != 1 { 93 | return nil, fmt.Errorf("invalid annotations") 94 | } 95 | if v, ok := req.Annotations[mockAnnotationKey]; !ok || string(v) != "1" { 96 | return nil, fmt.Errorf("invalid version in annotations") 97 | } 98 | 99 | if req.KeyID != s.keyID { 100 | return nil, fmt.Errorf("invalid keyID") 101 | } 102 | 103 | nonceSize := s.aead.NonceSize() 104 | data := req.Ciphertext 105 | if len(data) < nonceSize { 106 | return nil, fmt.Errorf("the stored data was shorter than the required size") 107 | } 108 | 109 | return s.aead.Open(nil, data[:nonceSize], data[nonceSize:], []byte(s.keyID)) 110 | } 111 | 112 | func (s *pkcs11RemoteService) Status(ctx context.Context) (*service.StatusResponse, error) { 113 | return &service.StatusResponse{ 114 | Version: "v2", 115 | Healthz: "ok", 116 | KeyID: s.keyID, 117 | }, nil 118 | } 119 | -------------------------------------------------------------------------------- /internal/plugins/_mock/plugin.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "flag" 22 | "os" 23 | "os/signal" 24 | "syscall" 25 | "time" 26 | 27 | "k8s.io/kms/pkg/service" 28 | "k8s.io/kms/pkg/util" 29 | "k8s.io/kms/plugins/mock/pkcs11" 30 | ) 31 | 32 | var ( 33 | listenAddr = flag.String("listen-addr", "unix:///tmp/kms.socket", "gRPC listen address") 34 | timeout = flag.Duration("timeout", 5*time.Second, "gRPC timeout") 35 | configFilePath = flag.String("config-file-path", "/etc/softhsm-config.json", "SoftHSM config file path") 36 | ) 37 | 38 | func main() { 39 | flag.Parse() 40 | 41 | addr, err := util.ParseEndpoint(*listenAddr) 42 | if err != nil { 43 | panic("failed to parse endpoint: " + err.Error()) 44 | } 45 | 46 | remoteKMSService, err := pkcs11.NewPKCS11RemoteService(*configFilePath, "kms-test") 47 | if err != nil { 48 | panic("failed to create remote service: " + err.Error()) 49 | } 50 | 51 | ctx := withShutdownSignal(context.Background()) 52 | grpcService := service.NewGRPCService( 53 | addr, 54 | *timeout, 55 | remoteKMSService, 56 | ) 57 | 58 | go func() { 59 | if err := grpcService.ListenAndServe(); err != nil { 60 | panic("failed to serve: " + err.Error()) 61 | } 62 | }() 63 | 64 | <-ctx.Done() 65 | grpcService.Shutdown() 66 | } 67 | 68 | // withShutdownSignal returns a copy of the parent context that will close if 69 | // the process receives termination signals. 70 | func withShutdownSignal(ctx context.Context) context.Context { 71 | signalChan := make(chan os.Signal, 1) 72 | signal.Notify(signalChan, syscall.SIGTERM, syscall.SIGINT, os.Interrupt) 73 | 74 | nctx, cancel := context.WithCancel(ctx) 75 | 76 | go func() { 77 | <-signalChan 78 | cancel() 79 | }() 80 | return nctx 81 | } 82 | -------------------------------------------------------------------------------- /pkg/service/grpc_service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | "context" 21 | "net" 22 | "time" 23 | 24 | "google.golang.org/grpc" 25 | 26 | kmsapi "k8s.io/kms/apis/v2" 27 | ) 28 | 29 | // GRPCService is a grpc server that runs the kms v2 alpha1 API. 30 | type GRPCService struct { 31 | addr string 32 | timeout time.Duration 33 | server *grpc.Server 34 | 35 | kmsService Service 36 | } 37 | 38 | var _ kmsapi.KeyManagementServiceServer = (*GRPCService)(nil) 39 | 40 | // NewGRPCService creates an instance of GRPCService. 41 | func NewGRPCService( 42 | address string, 43 | timeout time.Duration, 44 | 45 | kmsService Service, 46 | ) *GRPCService { 47 | return &GRPCService{ 48 | addr: address, 49 | timeout: timeout, 50 | kmsService: kmsService, 51 | } 52 | } 53 | 54 | // ListenAndServe accepts incoming connections on a Unix socket. It is a blocking method. 55 | // Returns non-nil error unless Close or Shutdown is called. 56 | func (s *GRPCService) ListenAndServe() error { 57 | ln, err := net.Listen("unix", s.addr) 58 | if err != nil { 59 | return err 60 | } 61 | defer ln.Close() 62 | 63 | gs := grpc.NewServer( 64 | grpc.ConnectionTimeout(s.timeout), 65 | ) 66 | s.server = gs 67 | 68 | kmsapi.RegisterKeyManagementServiceServer(gs, s) 69 | 70 | return gs.Serve(ln) 71 | } 72 | 73 | // Shutdown performs a graceful shutdown. Doesn't accept new connections and 74 | // blocks until all pending RPCs are finished. 75 | func (s *GRPCService) Shutdown() { 76 | if s.server != nil { 77 | s.server.GracefulStop() 78 | } 79 | } 80 | 81 | // Close stops the server by closing all connections immediately and cancels 82 | // all active RPCs. 83 | func (s *GRPCService) Close() { 84 | if s.server != nil { 85 | s.server.Stop() 86 | } 87 | } 88 | 89 | // Status sends a status request to specified kms service. 90 | func (s *GRPCService) Status(ctx context.Context, _ *kmsapi.StatusRequest) (*kmsapi.StatusResponse, error) { 91 | res, err := s.kmsService.Status(ctx) 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | return &kmsapi.StatusResponse{ 97 | Version: res.Version, 98 | Healthz: res.Healthz, 99 | KeyId: res.KeyID, 100 | }, nil 101 | } 102 | 103 | // Decrypt sends a decryption request to specified kms service. 104 | func (s *GRPCService) Decrypt(ctx context.Context, req *kmsapi.DecryptRequest) (*kmsapi.DecryptResponse, error) { 105 | plaintext, err := s.kmsService.Decrypt(ctx, req.Uid, &DecryptRequest{ 106 | Ciphertext: req.Ciphertext, 107 | KeyID: req.KeyId, 108 | Annotations: req.Annotations, 109 | }) 110 | if err != nil { 111 | return nil, err 112 | } 113 | 114 | return &kmsapi.DecryptResponse{ 115 | Plaintext: plaintext, 116 | }, nil 117 | } 118 | 119 | // Encrypt sends an encryption request to specified kms service. 120 | func (s *GRPCService) Encrypt(ctx context.Context, req *kmsapi.EncryptRequest) (*kmsapi.EncryptResponse, error) { 121 | encRes, err := s.kmsService.Encrypt(ctx, req.Uid, req.Plaintext) 122 | if err != nil { 123 | return nil, err 124 | } 125 | 126 | return &kmsapi.EncryptResponse{ 127 | Ciphertext: encRes.Ciphertext, 128 | KeyId: encRes.KeyID, 129 | Annotations: encRes.Annotations, 130 | }, nil 131 | } 132 | -------------------------------------------------------------------------------- /pkg/service/grpc_service_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | "bytes" 21 | "context" 22 | "encoding/base64" 23 | "fmt" 24 | "math/rand" 25 | "net" 26 | "os" 27 | "path/filepath" 28 | "testing" 29 | "time" 30 | 31 | "google.golang.org/grpc" 32 | "google.golang.org/grpc/credentials/insecure" 33 | 34 | kmsapi "k8s.io/kms/apis/v2" 35 | ) 36 | 37 | const version = "v2" 38 | 39 | func TestGRPCService(t *testing.T) { 40 | t.Parallel() 41 | 42 | defaultTimeout := 30 * time.Second 43 | ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) 44 | t.Cleanup(cancel) 45 | 46 | address := filepath.Join(os.TempDir(), "kmsv2.sock") 47 | plaintext := []byte("lorem ipsum dolor sit amet") 48 | r := rand.New(rand.NewSource(time.Now().Unix())) 49 | id, err := makeID(r.Read) 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | 54 | kmsService := newBase64Service(id) 55 | server := NewGRPCService(address, defaultTimeout, kmsService) 56 | go func() { 57 | if err := server.ListenAndServe(); err != nil { 58 | panic(err) 59 | } 60 | }() 61 | t.Cleanup(server.Shutdown) 62 | 63 | client := newClient(t, address) 64 | 65 | // make sure the gRPC server is up before running tests 66 | ready: 67 | for { 68 | select { 69 | case <-ctx.Done(): 70 | t.Fatalf("server failed to start in time: %v", ctx.Err()) 71 | 72 | default: 73 | if done := func() bool { 74 | ctx, cancel := context.WithTimeout(ctx, 3*time.Second) 75 | defer cancel() 76 | 77 | _, err := client.Status(ctx, &kmsapi.StatusRequest{}) 78 | if err != nil { 79 | t.Logf("failed to get kms status: %v", err) 80 | } 81 | 82 | return err == nil 83 | }(); done { 84 | break ready 85 | } 86 | time.Sleep(time.Second) 87 | } 88 | } 89 | 90 | t.Run("should be able to encrypt and decrypt through unix domain sockets", func(t *testing.T) { 91 | t.Parallel() 92 | 93 | encRes, err := client.Encrypt(ctx, &kmsapi.EncryptRequest{ 94 | Plaintext: plaintext, 95 | Uid: id, 96 | }) 97 | if err != nil { 98 | t.Fatal(err) 99 | } 100 | 101 | if bytes.Equal(plaintext, encRes.Ciphertext) { 102 | t.Fatal("plaintext and ciphertext shouldn't be equal!") 103 | } 104 | 105 | decRes, err := client.Decrypt(ctx, &kmsapi.DecryptRequest{ 106 | Ciphertext: encRes.Ciphertext, 107 | KeyId: encRes.KeyId, 108 | Annotations: encRes.Annotations, 109 | Uid: id, 110 | }) 111 | if err != nil { 112 | t.Fatal(err) 113 | } 114 | 115 | if !bytes.Equal(decRes.Plaintext, plaintext) { 116 | t.Errorf("want: %q, have: %q", plaintext, decRes.Plaintext) 117 | } 118 | }) 119 | 120 | t.Run("should return status data", func(t *testing.T) { 121 | t.Parallel() 122 | 123 | status, err := client.Status(ctx, &kmsapi.StatusRequest{}) 124 | if err != nil { 125 | t.Fatal(err) 126 | } 127 | 128 | if status.Healthz != "ok" { 129 | t.Errorf("want: %q, have: %q", "ok", status.Healthz) 130 | } 131 | if len(status.KeyId) == 0 { 132 | t.Errorf("want: len(keyID) > 0, have: %d", len(status.KeyId)) 133 | } 134 | if status.Version != version { 135 | t.Errorf("want %q, have: %q", version, status.Version) 136 | } 137 | }) 138 | } 139 | 140 | func newClient(t *testing.T, address string) kmsapi.KeyManagementServiceClient { 141 | t.Helper() 142 | 143 | cnn, err := grpc.Dial( 144 | address, 145 | grpc.WithTransportCredentials(insecure.NewCredentials()), 146 | grpc.WithDialer(func(addr string, t time.Duration) (net.Conn, error) { 147 | return net.Dial("unix", addr) 148 | }), 149 | ) 150 | if err != nil { 151 | t.Fatal(err) 152 | } 153 | 154 | t.Cleanup(func() { _ = cnn.Close() }) 155 | 156 | return kmsapi.NewKeyManagementServiceClient(cnn) 157 | } 158 | 159 | type testService struct { 160 | decrypt func(ctx context.Context, uid string, req *DecryptRequest) ([]byte, error) 161 | encrypt func(ctx context.Context, uid string, data []byte) (*EncryptResponse, error) 162 | status func(ctx context.Context) (*StatusResponse, error) 163 | } 164 | 165 | var _ Service = (*testService)(nil) 166 | 167 | func (s *testService) Decrypt(ctx context.Context, uid string, req *DecryptRequest) ([]byte, error) { 168 | return s.decrypt(ctx, uid, req) 169 | } 170 | 171 | func (s *testService) Encrypt(ctx context.Context, uid string, data []byte) (*EncryptResponse, error) { 172 | return s.encrypt(ctx, uid, data) 173 | } 174 | 175 | func (s *testService) Status(ctx context.Context) (*StatusResponse, error) { 176 | return s.status(ctx) 177 | } 178 | 179 | func makeID(rand func([]byte) (int, error)) (string, error) { 180 | b := make([]byte, 10) 181 | if _, err := rand(b); err != nil { 182 | return "", err 183 | } 184 | 185 | return base64.StdEncoding.EncodeToString(b), nil 186 | } 187 | 188 | func newBase64Service(keyID string) *testService { 189 | decrypt := func(_ context.Context, _ string, req *DecryptRequest) ([]byte, error) { 190 | if req.KeyID != keyID { 191 | return nil, fmt.Errorf("keyID mismatch. want: %q, have: %q", keyID, req.KeyID) 192 | } 193 | 194 | return base64.StdEncoding.DecodeString(string(req.Ciphertext)) 195 | } 196 | 197 | encrypt := func(_ context.Context, _ string, data []byte) (*EncryptResponse, error) { 198 | return &EncryptResponse{ 199 | Ciphertext: []byte(base64.StdEncoding.EncodeToString(data)), 200 | KeyID: keyID, 201 | }, nil 202 | } 203 | 204 | status := func(_ context.Context) (*StatusResponse, error) { 205 | return &StatusResponse{ 206 | Version: version, 207 | Healthz: "ok", 208 | KeyID: keyID, 209 | }, nil 210 | } 211 | 212 | return &testService{ 213 | decrypt: decrypt, 214 | encrypt: encrypt, 215 | status: status, 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /pkg/service/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import "context" 20 | 21 | // Service allows encrypting and decrypting data using an external Key Management Service. 22 | type Service interface { 23 | // Decrypt a given bytearray to obtain the original data as bytes. 24 | Decrypt(ctx context.Context, uid string, req *DecryptRequest) ([]byte, error) 25 | // Encrypt bytes to a ciphertext. 26 | Encrypt(ctx context.Context, uid string, data []byte) (*EncryptResponse, error) 27 | // Status returns the status of the KMS. 28 | Status(ctx context.Context) (*StatusResponse, error) 29 | } 30 | 31 | // EncryptResponse is the response from the Envelope service when encrypting data. 32 | type EncryptResponse struct { 33 | Ciphertext []byte 34 | KeyID string 35 | Annotations map[string][]byte 36 | } 37 | 38 | // DecryptRequest is the request to the Envelope service when decrypting data. 39 | type DecryptRequest struct { 40 | Ciphertext []byte 41 | KeyID string 42 | Annotations map[string][]byte 43 | } 44 | 45 | // StatusResponse is the response from the Envelope service when getting the status of the service. 46 | type StatusResponse struct { 47 | Version string 48 | Healthz string 49 | KeyID string 50 | } 51 | -------------------------------------------------------------------------------- /pkg/util/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "fmt" 21 | "net/url" 22 | "strings" 23 | ) 24 | 25 | const ( 26 | // unixProtocol is the only supported protocol for remote KMS provider. 27 | unixProtocol = "unix" 28 | ) 29 | 30 | // ParseEndpoint parses the endpoint to extract schema, host or path. 31 | func ParseEndpoint(endpoint string) (string, error) { 32 | if len(endpoint) == 0 { 33 | return "", fmt.Errorf("remote KMS provider can't use empty string as endpoint") 34 | } 35 | 36 | u, err := url.Parse(endpoint) 37 | if err != nil { 38 | return "", fmt.Errorf("invalid endpoint %q for remote KMS provider, error: %v", endpoint, err) 39 | } 40 | 41 | if u.Scheme != unixProtocol { 42 | return "", fmt.Errorf("unsupported scheme %q for remote KMS provider", u.Scheme) 43 | } 44 | 45 | // Linux abstract namespace socket - no physical file required 46 | // Warning: Linux Abstract sockets have not concept of ACL (unlike traditional file based sockets). 47 | // However, Linux Abstract sockets are subject to Linux networking namespace, so will only be accessible to 48 | // containers within the same pod (unless host networking is used). 49 | if strings.HasPrefix(u.Path, "/@") { 50 | return strings.TrimPrefix(u.Path, "/"), nil 51 | } 52 | 53 | return u.Path, nil 54 | } 55 | -------------------------------------------------------------------------------- /pkg/util/util_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "strings" 21 | "testing" 22 | ) 23 | 24 | func TestParseEndpoint(t *testing.T) { 25 | testCases := []struct { 26 | desc string 27 | endpoint string 28 | want string 29 | }{ 30 | { 31 | desc: "path with prefix", 32 | endpoint: "unix:///@path", 33 | want: "@path", 34 | }, 35 | { 36 | desc: "path without prefix", 37 | endpoint: "unix:///path", 38 | want: "/path", 39 | }, 40 | } 41 | 42 | for _, tt := range testCases { 43 | t.Run(tt.desc, func(t *testing.T) { 44 | got, err := ParseEndpoint(tt.endpoint) 45 | if err != nil { 46 | t.Errorf("ParseEndpoint(%q) error: %v", tt.endpoint, err) 47 | } 48 | if got != tt.want { 49 | t.Errorf("ParseEndpoint(%q) = %q, want %q", tt.endpoint, got, tt.want) 50 | } 51 | }) 52 | } 53 | } 54 | 55 | func TestParseEndpointError(t *testing.T) { 56 | testCases := []struct { 57 | desc string 58 | endpoint string 59 | wantErr string 60 | }{ 61 | { 62 | desc: "empty endpoint", 63 | endpoint: "", 64 | wantErr: "remote KMS provider can't use empty string as endpoint", 65 | }, 66 | { 67 | desc: "invalid scheme", 68 | endpoint: "http:///path", 69 | wantErr: "unsupported scheme \"http\" for remote KMS provider", 70 | }, 71 | } 72 | 73 | for _, tt := range testCases { 74 | t.Run(tt.desc, func(t *testing.T) { 75 | _, err := ParseEndpoint(tt.endpoint) 76 | if err == nil { 77 | t.Errorf("ParseEndpoint(%q) error: %v", tt.endpoint, err) 78 | } 79 | if !strings.Contains(err.Error(), tt.wantErr) { 80 | t.Errorf("ParseEndpoint(%q) = %q, want %q", tt.endpoint, err, tt.wantErr) 81 | } 82 | }) 83 | } 84 | } 85 | --------------------------------------------------------------------------------