github.com/aavshr/aws-sdk-go@v1.41.3/service/s3/s3crypto/kms_key_handler.go (about) 1 package s3crypto 2 3 import ( 4 "github.com/aavshr/aws-sdk-go/aws" 5 "github.com/aavshr/aws-sdk-go/aws/awserr" 6 "github.com/aavshr/aws-sdk-go/service/kms" 7 "github.com/aavshr/aws-sdk-go/service/kms/kmsiface" 8 ) 9 10 const ( 11 // KMSWrap is a constant used during decryption to build a KMS key handler. 12 KMSWrap = "kms" 13 ) 14 15 // kmsKeyHandler will make calls to KMS to get the masterkey 16 type kmsKeyHandler struct { 17 kms kmsiface.KMSAPI 18 cmkID *string 19 20 // useProvidedCMK is toggled when using `kms` key wrapper with V2 client 21 useProvidedCMK bool 22 23 CipherData 24 } 25 26 // NewKMSKeyGenerator builds a new KMS key provider using the customer key ID and material 27 // description. 28 // 29 // Example: 30 // sess := session.Must(session.NewSession()) 31 // cmkID := "arn to key" 32 // matdesc := s3crypto.MaterialDescription{} 33 // handler := s3crypto.NewKMSKeyGenerator(kms.New(sess), cmkID) 34 // 35 // deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 36 func NewKMSKeyGenerator(kmsClient kmsiface.KMSAPI, cmkID string) CipherDataGenerator { 37 return NewKMSKeyGeneratorWithMatDesc(kmsClient, cmkID, MaterialDescription{}) 38 } 39 40 func newKMSKeyHandler(client kmsiface.KMSAPI, cmkID string, matdesc MaterialDescription) *kmsKeyHandler { 41 // These values are read only making them thread safe 42 kp := &kmsKeyHandler{ 43 kms: client, 44 cmkID: &cmkID, 45 } 46 47 if matdesc == nil { 48 matdesc = MaterialDescription{} 49 } 50 51 matdesc["kms_cmk_id"] = &cmkID 52 53 kp.CipherData.WrapAlgorithm = KMSWrap 54 kp.CipherData.MaterialDescription = matdesc 55 56 return kp 57 } 58 59 // NewKMSKeyGeneratorWithMatDesc builds a new KMS key provider using the customer key ID and material 60 // description. 61 // 62 // Example: 63 // sess := session.Must(session.NewSession()) 64 // cmkID := "arn to key" 65 // matdesc := s3crypto.MaterialDescription{} 66 // handler := s3crypto.NewKMSKeyGeneratorWithMatDesc(kms.New(sess), cmkID, matdesc) 67 // 68 // deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 69 func NewKMSKeyGeneratorWithMatDesc(kmsClient kmsiface.KMSAPI, cmkID string, matdesc MaterialDescription) CipherDataGenerator { 70 return newKMSKeyHandler(kmsClient, cmkID, matdesc) 71 } 72 73 // NewKMSWrapEntry builds returns a new KMS key provider and its decrypt handler. 74 // 75 // Example: 76 // sess := session.Must(session.NewSession()) 77 // customKMSClient := kms.New(sess) 78 // decryptHandler := s3crypto.NewKMSWrapEntry(customKMSClient) 79 // 80 // svc := s3crypto.NewDecryptionClient(sess, func(svc *s3crypto.DecryptionClient) { 81 // svc.WrapRegistry[s3crypto.KMSWrap] = decryptHandler 82 // })) 83 // 84 // deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 85 func NewKMSWrapEntry(kmsClient kmsiface.KMSAPI) WrapEntry { 86 kp := newKMSWrapEntry(kmsClient) 87 return kp.decryptHandler 88 } 89 90 // RegisterKMSWrapWithCMK registers the `kms` wrapping algorithm to the given WrapRegistry. The wrapper will be 91 // configured to call KMS Decrypt with the provided CMK. 92 // 93 // Example: 94 // sess := session.Must(session.NewSession()) 95 // cr := s3crypto.NewCryptoRegistry() 96 // if err := s3crypto.RegisterKMSWrapWithCMK(cr, kms.New(sess), "cmkId"); err != nil { 97 // panic(err) // handle error 98 // } 99 // 100 // deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 101 func RegisterKMSWrapWithCMK(registry *CryptoRegistry, client kmsiface.KMSAPI, cmkID string) error { 102 if registry == nil { 103 return errNilCryptoRegistry 104 } 105 return registry.AddWrap(KMSWrap, newKMSWrapEntryWithCMK(client, cmkID)) 106 } 107 108 // RegisterKMSWrapWithAnyCMK registers the `kms` wrapping algorithm to the given WrapRegistry. The wrapper will be 109 // configured to call KMS Decrypt without providing a CMK. 110 // 111 // Example: 112 // sess := session.Must(session.NewSession()) 113 // cr := s3crypto.NewCryptoRegistry() 114 // if err := s3crypto.RegisterKMSWrapWithAnyCMK(cr, kms.New(sess)); err != nil { 115 // panic(err) // handle error 116 // } 117 // 118 // deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 119 func RegisterKMSWrapWithAnyCMK(registry *CryptoRegistry, client kmsiface.KMSAPI) error { 120 if registry == nil { 121 return errNilCryptoRegistry 122 } 123 return registry.AddWrap(KMSWrap, NewKMSWrapEntry(client)) 124 } 125 126 // newKMSWrapEntryWithCMK builds returns a new KMS key provider and its decrypt handler. The wrap entry will be configured 127 // to only attempt to decrypt the data key using the provided CMK. 128 func newKMSWrapEntryWithCMK(kmsClient kmsiface.KMSAPI, cmkID string) WrapEntry { 129 kp := newKMSWrapEntry(kmsClient) 130 kp.useProvidedCMK = true 131 kp.cmkID = &cmkID 132 return kp.decryptHandler 133 } 134 135 func newKMSWrapEntry(kmsClient kmsiface.KMSAPI) *kmsKeyHandler { 136 // These values are read only making them thread safe 137 kp := &kmsKeyHandler{ 138 kms: kmsClient, 139 } 140 141 return kp 142 } 143 144 // decryptHandler initializes a KMS keyprovider with a material description. This 145 // is used with Decrypting kms content, due to the cmkID being in the material description. 146 func (kp kmsKeyHandler) decryptHandler(env Envelope) (CipherDataDecrypter, error) { 147 m := MaterialDescription{} 148 err := m.decodeDescription([]byte(env.MatDesc)) 149 if err != nil { 150 return nil, err 151 } 152 153 _, ok := m["kms_cmk_id"] 154 if !ok { 155 return nil, awserr.New("MissingCMKIDError", "Material description is missing CMK ID", nil) 156 } 157 158 kp.CipherData.MaterialDescription = m 159 kp.WrapAlgorithm = KMSWrap 160 161 return &kp, nil 162 } 163 164 // DecryptKey makes a call to KMS to decrypt the key. 165 func (kp *kmsKeyHandler) DecryptKey(key []byte) ([]byte, error) { 166 return kp.DecryptKeyWithContext(aws.BackgroundContext(), key) 167 } 168 169 // DecryptKeyWithContext makes a call to KMS to decrypt the key with request context. 170 func (kp *kmsKeyHandler) DecryptKeyWithContext(ctx aws.Context, key []byte) ([]byte, error) { 171 in := &kms.DecryptInput{ 172 EncryptionContext: kp.MaterialDescription, 173 CiphertextBlob: key, 174 GrantTokens: []*string{}, 175 } 176 177 // useProvidedCMK will be true if a constructor was used with the new V2 client 178 if kp.useProvidedCMK { 179 in.KeyId = kp.cmkID 180 } 181 182 out, err := kp.kms.DecryptWithContext(ctx, in) 183 if err != nil { 184 return nil, err 185 } 186 return out.Plaintext, nil 187 } 188 189 // GenerateCipherData makes a call to KMS to generate a data key, Upon making 190 // the call, it also sets the encrypted key. 191 func (kp *kmsKeyHandler) GenerateCipherData(keySize, ivSize int) (CipherData, error) { 192 return kp.GenerateCipherDataWithContext(aws.BackgroundContext(), keySize, ivSize) 193 } 194 195 // GenerateCipherDataWithContext makes a call to KMS to generate a data key, 196 // Upon making the call, it also sets the encrypted key. 197 func (kp *kmsKeyHandler) GenerateCipherDataWithContext(ctx aws.Context, keySize, ivSize int) (CipherData, error) { 198 cd := kp.CipherData.Clone() 199 200 out, err := kp.kms.GenerateDataKeyWithContext(ctx, 201 &kms.GenerateDataKeyInput{ 202 EncryptionContext: cd.MaterialDescription, 203 KeyId: kp.cmkID, 204 KeySpec: aws.String("AES_256"), 205 }) 206 if err != nil { 207 return CipherData{}, err 208 } 209 210 iv, err := generateBytes(ivSize) 211 if err != nil { 212 return CipherData{}, err 213 } 214 215 cd.Key = out.Plaintext 216 cd.IV = iv 217 cd.EncryptedKey = out.CiphertextBlob 218 219 return cd, nil 220 } 221 222 func (kp kmsKeyHandler) isAWSFixture() bool { 223 return true 224 } 225 226 var ( 227 _ CipherDataGenerator = (*kmsKeyHandler)(nil) 228 _ CipherDataGeneratorWithContext = (*kmsKeyHandler)(nil) 229 _ CipherDataDecrypter = (*kmsKeyHandler)(nil) 230 _ CipherDataDecrypterWithContext = (*kmsKeyHandler)(nil) 231 _ awsFixture = (*kmsKeyHandler)(nil) 232 )