github.com/zntrio/harp/v2@v2.0.9/pkg/vault/transformer.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package vault 19 20 import ( 21 "fmt" 22 "path" 23 "strings" 24 25 "github.com/zntrio/harp/v2/pkg/sdk/value" 26 "github.com/zntrio/harp/v2/pkg/sdk/value/encryption" 27 "github.com/zntrio/harp/v2/pkg/sdk/value/encryption/aead" 28 "github.com/zntrio/harp/v2/pkg/sdk/value/encryption/envelope" 29 "github.com/zntrio/harp/v2/pkg/sdk/value/encryption/secretbox" 30 vaultpath "github.com/zntrio/harp/v2/pkg/vault/path" 31 ) 32 33 type DataEncryption string 34 35 var ( 36 AESGCM DataEncryption = "aesgcm" 37 Chacha20Poly1305 DataEncryption = "chacha20poly1305" 38 Secretbox DataEncryption = "secretbox" 39 ) 40 41 func init() { 42 encryption.Register("vault", FromKey) 43 } 44 45 // Vault returns an envelope encryption using a remote transit backend for key 46 // encryption. 47 // vault:<path>:<data encryption> 48 func FromKey(key string) (value.Transformer, error) { 49 // Remove the prefix 50 key = strings.TrimPrefix(key, "vault:") 51 52 // Split path / encryption 53 parts := strings.SplitN(key, ":", 2) 54 if len(parts) != 2 { 55 return nil, fmt.Errorf("key format error, invalid part count") 56 } 57 58 // Split transit backend path 59 mountPath, keyName := path.Split(parts[0]) 60 61 // Delegate to transformer 62 return Transformer(mountPath, keyName, DataEncryption(parts[1])) 63 } 64 65 func TransformerKey(mountPath, keyName string, dataEncryption DataEncryption) string { 66 return fmt.Sprintf("vault:%s/%s:%s", vaultpath.SanitizePath(mountPath), strings.TrimPrefix(keyName, "/"), dataEncryption) 67 } 68 69 // Transformer returns an envelope encryption using a remote transit backend for key 70 // encryption. 71 func Transformer(mountPath, keyName string, dataEncryption DataEncryption) (value.Transformer, error) { 72 // Create default vault client 73 client, err := DefaultClient() 74 if err != nil { 75 return nil, fmt.Errorf("unable to initialize vault client: %w", err) 76 } 77 78 // Create transit backend service 79 backend, err := client.Transit(vaultpath.SanitizePath(mountPath), keyName) 80 if err != nil { 81 return nil, fmt.Errorf("unable to initialize vault transit backend service: %w", err) 82 } 83 84 // Prepare data encryption 85 var dataEncryptionFunc encryption.TransformerFactoryFunc 86 switch dataEncryption { 87 case AESGCM: 88 dataEncryptionFunc = aead.AESGCM 89 case Chacha20Poly1305: 90 dataEncryptionFunc = aead.Chacha20Poly1305 91 case Secretbox: 92 dataEncryptionFunc = secretbox.Transformer 93 default: 94 return nil, fmt.Errorf("unsupported data encryption %q for envelope transformer", dataEncryption) 95 } 96 97 // Wrap the transformer with envelope 98 return envelope.Transformer(backend, dataEncryptionFunc) 99 }