mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-12 09:01:58 -06:00
Update to encryption key provider interface (#1351)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
parent
8cd4036af0
commit
cef62ea738
@ -36,14 +36,14 @@ func newBaseEncryption(enc *encryption, target *config.TargetConfig, enforced bo
|
||||
}
|
||||
// This performs a e2e validation run of the config -> methods flow. It serves as a validation step and allows us to
|
||||
// return detailed diagnostics here and simple errors below
|
||||
_, diags := base.buildTargetMethods(make(map[keyprovider.Addr]any))
|
||||
_, diags := base.buildTargetMethods(make(map[keyprovider.Addr][]byte))
|
||||
return base, diags
|
||||
}
|
||||
|
||||
type basedata struct {
|
||||
Meta map[keyprovider.Addr]any `json:"meta"`
|
||||
Data []byte `json:"encrypted_data"`
|
||||
Version string `json:"encryption_version"` // This is both a sigil for a valid encrypted payload and a future compatability field
|
||||
Meta map[keyprovider.Addr][]byte `json:"meta"`
|
||||
Data []byte `json:"encrypted_data"`
|
||||
Version string `json:"encryption_version"` // This is both a sigil for a valid encrypted payload and a future compatability field
|
||||
}
|
||||
|
||||
func IsEncryptionPayload(data []byte) (bool, error) {
|
||||
@ -64,7 +64,7 @@ func (s *baseEncryption) encrypt(data []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
es := basedata{
|
||||
Meta: make(map[keyprovider.Addr]any),
|
||||
Meta: make(map[keyprovider.Addr][]byte),
|
||||
Version: encryptionVersion,
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,10 @@
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption/config"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
@ -164,36 +163,9 @@ func (e *targetBuilder) setupKeyProvider(cfg config.KeyProviderConfig, stack []c
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
// Add the metadata
|
||||
if meta, ok := e.keyProviderMetadata[metakey]; ok {
|
||||
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
// We want all metadata fields to be consumed:
|
||||
ErrorUnused: true,
|
||||
// Fill the results in this struct:
|
||||
Result: &keyProviderConfig,
|
||||
// Use the "meta" tag:
|
||||
TagName: "meta",
|
||||
// Ignore fields not tagged with "meta":
|
||||
IgnoreUntaggedFields: true,
|
||||
})
|
||||
if err != nil {
|
||||
return append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unable to decode encrypted metadata (did you change your encryption config?)",
|
||||
Detail: fmt.Sprintf("initializing metadata decoder for %s failed with error: %s", metakey, err.Error()),
|
||||
})
|
||||
}
|
||||
if err := decoder.Decode(meta); err != nil {
|
||||
return append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unable to decode encrypted metadata (did you change your encryption config?)",
|
||||
Detail: fmt.Sprintf("decoding %s failed with error: %s", metakey, err.Error()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Build the Key Provider from the configuration
|
||||
keyProvider, err := keyProviderConfig.Build()
|
||||
keyProvider, keyMetaIn, err := keyProviderConfig.Build()
|
||||
if err != nil {
|
||||
return append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
@ -202,7 +174,19 @@ func (e *targetBuilder) setupKeyProvider(cfg config.KeyProviderConfig, stack []c
|
||||
})
|
||||
}
|
||||
|
||||
output, err := keyProvider.Provide()
|
||||
// Add the metadata
|
||||
if meta, ok := e.keyProviderMetadata[metakey]; ok {
|
||||
err := json.Unmarshal(meta, keyMetaIn)
|
||||
if err != nil {
|
||||
return append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unable to decode encrypted metadata (did you change your encryption config?)",
|
||||
Detail: fmt.Sprintf("metadata decoder for %s failed with error: %s", metakey, err.Error()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
output, keyMetaOut, err := keyProvider.Provide(keyMetaIn)
|
||||
if err != nil {
|
||||
return append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
@ -211,8 +195,20 @@ func (e *targetBuilder) setupKeyProvider(cfg config.KeyProviderConfig, stack []c
|
||||
})
|
||||
}
|
||||
|
||||
e.keyProviderMetadata[metakey] = output.Metadata
|
||||
if keyMetaOut != nil {
|
||||
e.keyProviderMetadata[metakey], err = json.Marshal(keyMetaOut)
|
||||
|
||||
if err != nil {
|
||||
return append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unable to encode encrypted metadata",
|
||||
Detail: fmt.Sprintf("metadata encoder for %s failed with error: %s", metakey, err.Error()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
e.keyValues[cfg.Type][cfg.Name] = output.Cty()
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
@ -5,8 +5,11 @@
|
||||
|
||||
package keyprovider
|
||||
|
||||
// Reference to struct with json tags
|
||||
type KeyMeta any
|
||||
|
||||
type Config interface {
|
||||
Build() (KeyProvider, error)
|
||||
Build() (KeyProvider, KeyMeta, error)
|
||||
}
|
||||
|
||||
type Descriptor interface {
|
||||
@ -24,5 +27,5 @@ type Descriptor interface {
|
||||
|
||||
type KeyProvider interface {
|
||||
// Provide provides an encryption and decryption keys. If the process fails, it returns an error.
|
||||
Provide() (Output, error)
|
||||
Provide(KeyMeta) (Output, KeyMeta, error)
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import "github.com/zclconf/go-cty/cty"
|
||||
type Output struct {
|
||||
EncryptionKey []byte `hcl:"encryption_key" cty:"encryption_key" json:"encryption_key" yaml:"encryption_key"`
|
||||
DecryptionKey []byte `hcl:"decryption_key" cty:"decryption_key" json:"decryption_key" yaml:"decryption_key"`
|
||||
Metadata any
|
||||
}
|
||||
|
||||
func (o *Output) Cty() cty.Value {
|
||||
|
@ -16,10 +16,10 @@ type Config struct {
|
||||
Key string `hcl:"key"`
|
||||
}
|
||||
|
||||
func (c Config) Build() (keyprovider.KeyProvider, error) {
|
||||
func (c Config) Build() (keyprovider.KeyProvider, keyprovider.KeyMeta, error) {
|
||||
decodedData, err := hex.DecodeString(c.Key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to hex-decode the provided key (%w)", err)
|
||||
return nil, nil, fmt.Errorf("failed to hex-decode the provided key (%w)", err)
|
||||
}
|
||||
return &staticKeyProvider{decodedData}, nil
|
||||
return &staticKeyProvider{decodedData}, nil, nil
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ type staticKeyProvider struct {
|
||||
key []byte
|
||||
}
|
||||
|
||||
func (p staticKeyProvider) Provide() (keyprovider.Output, error) {
|
||||
func (p staticKeyProvider) Provide(meta keyprovider.KeyMeta) (keyprovider.Output, keyprovider.KeyMeta, error) {
|
||||
return keyprovider.Output{
|
||||
EncryptionKey: p.key,
|
||||
DecryptionKey: p.key,
|
||||
}, nil
|
||||
}, nil, nil
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ func TestKeyProvider(t *testing.T) {
|
||||
c.Key = tc.key
|
||||
}
|
||||
|
||||
keyProvider, buildErr := c.Build()
|
||||
keyProvider, keyMeta, buildErr := c.Build()
|
||||
if tc.expectSuccess {
|
||||
if buildErr != nil {
|
||||
t.Fatalf("unexpected error: %v", buildErr)
|
||||
}
|
||||
|
||||
output, err := keyProvider.Provide()
|
||||
output, _, err := keyProvider.Provide(keyMeta)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ type targetBuilder struct {
|
||||
// Used to evaluate hcl expressions
|
||||
ctx *hcl.EvalContext
|
||||
|
||||
keyProviderMetadata map[keyprovider.Addr]any
|
||||
keyProviderMetadata map[keyprovider.Addr][]byte
|
||||
|
||||
// Used to build EvalContext (and related mappings)
|
||||
keyValues map[string]map[string]cty.Value
|
||||
@ -32,7 +32,7 @@ type targetBuilder struct {
|
||||
methods map[method.Addr]method.Method
|
||||
}
|
||||
|
||||
func (base *baseEncryption) buildTargetMethods(meta map[keyprovider.Addr]any) ([]method.Method, hcl.Diagnostics) {
|
||||
func (base *baseEncryption) buildTargetMethods(meta map[keyprovider.Addr][]byte) ([]method.Method, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
builder := &targetBuilder{
|
||||
|
@ -54,7 +54,9 @@ func findVariablesInBodyStruct(body hcl.Body, val reflect.Value) ([]hcl.Traversa
|
||||
|
||||
for name := range tags.Attributes {
|
||||
attr := content.Attributes[name]
|
||||
variables = append(variables, attr.Expr.Variables()...)
|
||||
if attr != nil {
|
||||
variables = append(variables, attr.Expr.Variables()...)
|
||||
}
|
||||
}
|
||||
|
||||
blocksByType := content.Blocks.ByType()
|
||||
|
Loading…
Reference in New Issue
Block a user