mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-03-11 22:00:21 -04:00
Because of the support for provider-contributed functions, expression evaluation can potentially cause provider gRPC requests to happen, and so we'll need to be able to plumb OpenTelemetry trace information through to those calls. This initial commit focuses mainly on just getting the functions in lang.Scope set up to take context.Context, along with their companions in configs.StaticEvaluator, while leaving most of the callers just passing context.TODO() for now so we can gradually deal with the rest of the plumbing in later commits. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
135 lines
3.9 KiB
Go
135 lines
3.9 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package encryption
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/gohcl"
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
"github.com/opentofu/opentofu/internal/configs"
|
|
"github.com/opentofu/opentofu/internal/encryption/config"
|
|
"github.com/opentofu/opentofu/internal/encryption/method"
|
|
"github.com/opentofu/opentofu/internal/encryption/registry"
|
|
)
|
|
|
|
// setupMethod sets up a single method for encryption. It returns a list of diagnostics if the method is invalid.
|
|
func setupMethod(enc *config.EncryptionConfig, cfg config.MethodConfig, meta keyProviderMetadata, reg registry.Registry, staticEval *configs.StaticEvaluator) (method.Method, hcl.Diagnostics) {
|
|
// Lookup the definition of the encryption method from the registry
|
|
encryptionMethod, err := reg.GetMethodDescriptor(method.ID(cfg.Type))
|
|
if err != nil {
|
|
|
|
// Handle if the method was not found
|
|
var notFoundError *registry.MethodNotFoundError
|
|
if errors.Is(err, notFoundError) {
|
|
return nil, hcl.Diagnostics{{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Unknown encryption method type",
|
|
Detail: fmt.Sprintf("Can not find %q", cfg.Type),
|
|
}}
|
|
}
|
|
|
|
// Or, we don't know the error type, so we'll just return it as a generic error
|
|
return nil, hcl.Diagnostics{{
|
|
Severity: hcl.DiagError,
|
|
Summary: fmt.Sprintf("Error fetching encryption method %q", cfg.Type),
|
|
Detail: err.Error(),
|
|
}}
|
|
}
|
|
|
|
methodConfig := encryptionMethod.ConfigStruct()
|
|
|
|
deps, diags := gohcl.VariablesInBody(cfg.Body, methodConfig)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
kpConfigs, refs, kpDiags := filterKeyProviderReferences(enc, deps)
|
|
diags = diags.Extend(kpDiags)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
hclCtx, kpDiags := setupKeyProviders(enc, kpConfigs, meta, reg, staticEval)
|
|
diags = diags.Extend(kpDiags)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
hclCtx, evalDiags := staticEval.EvalContextWithParent(context.TODO(), hclCtx, configs.StaticIdentifier{
|
|
Module: addrs.RootModule,
|
|
Subject: fmt.Sprintf("encryption.method.%s.%s", cfg.Type, cfg.Name),
|
|
DeclRange: enc.DeclRange,
|
|
}, refs)
|
|
diags = diags.Extend(evalDiags)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
methodDiags := gohcl.DecodeBody(cfg.Body, hclCtx, methodConfig)
|
|
diags = diags.Extend(methodDiags)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
m, err := methodConfig.Build()
|
|
if err != nil {
|
|
// Convert the error to a diagnostic
|
|
diags = diags.Append(errorToDiagnostic(err))
|
|
}
|
|
|
|
return m, diags
|
|
}
|
|
|
|
func errorToDiagnostic(err error) *hcl.Diagnostic {
|
|
originalErr := err
|
|
|
|
for e := err; e != nil; e = errors.Unwrap(e) {
|
|
switch typedErr := e.(type) {
|
|
case *method.ErrEncryptionFailed:
|
|
return &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Encryption operation failed during method setup",
|
|
Detail: typedErr.Error(),
|
|
}
|
|
case *method.ErrDecryptionFailed:
|
|
return &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Decryption operation failed during method setup",
|
|
Detail: typedErr.Error(),
|
|
}
|
|
case *method.ErrDecryptionKeyUnavailable:
|
|
return &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Required key unavailable for method setup",
|
|
Detail: typedErr.Error(),
|
|
}
|
|
case *method.ErrCryptoFailure:
|
|
return &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Cryptographic operation failed during method setup",
|
|
Detail: typedErr.Error(),
|
|
}
|
|
case *method.ErrInvalidConfiguration:
|
|
return &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid method configuration",
|
|
Detail: typedErr.Error(),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generic fallback if no specific type was matched in the error chain
|
|
return &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Encryption method configuration error",
|
|
Detail: originalErr.Error(),
|
|
}
|
|
}
|