Update to encryption key provider interface (#1351)

Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
Christian Mesh 2024-03-08 07:55:08 -05:00 committed by GitHub
parent 8cd4036af0
commit cef62ea738
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 50 additions and 50 deletions

View File

@ -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,
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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{

View File

@ -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()