Documentation
¶
Overview ¶
Example ¶
This example demonstrates how to use the encryption package to encrypt and decrypt data.
package main
import (
"fmt"
"github.com/terramate-io/hcl/v2"
"github.com/terramate-io/opentofulib/internal/configs"
"github.com/terramate-io/opentofulib/internal/encryption"
"github.com/terramate-io/opentofulib/internal/encryption/config"
"github.com/terramate-io/opentofulib/internal/encryption/keyprovider/static"
"github.com/terramate-io/opentofulib/internal/encryption/method/aesgcm"
"github.com/terramate-io/opentofulib/internal/encryption/registry/lockingencryptionregistry"
)
var (
ConfigA = `
state {
enforced = true
}
`
ConfigB = `
key_provider "static" "basic" {
key = "6f6f706830656f67686f6834616872756f3751756165686565796f6f72653169"
}
method "aes_gcm" "example" {
keys = key_provider.static.basic
}
state {
method = method.aes_gcm.example
}
`
)
// This example demonstrates how to use the encryption package to encrypt and decrypt data.
func main() {
// Construct a new registry
// the registry is where we store the key providers and methods
reg := lockingencryptionregistry.New()
if err := reg.RegisterKeyProvider(static.New()); err != nil {
panic(err)
}
if err := reg.RegisterMethod(aesgcm.New()); err != nil {
panic(err)
}
// Load the 2 different configurations
cfgA, diags := config.LoadConfigFromString("Test Source A", ConfigA)
handleDiags(diags)
cfgB, diags := config.LoadConfigFromString("Test Source B", ConfigB)
handleDiags(diags)
// Merge the configurations
cfg := config.MergeConfigs(cfgA, cfgB)
// Construct static evaluator to pass additional values into encryption configuration.
staticEval := configs.NewStaticEvaluator(nil, configs.RootModuleCallForTesting())
// Construct the encryption object
enc, diags := encryption.New(reg, cfg, staticEval)
handleDiags(diags)
sfe := enc.State()
// Encrypt the data, for this example we will be using the string `{"serial": 42, "lineage": "magic"}`,
// but in a real world scenario this would be the plan file.
sourceData := []byte(`{"serial": 42, "lineage": "magic"}`)
encrypted, err := sfe.EncryptState(sourceData)
if err != nil {
panic(err)
}
if string(encrypted) == `{"serial": 42, "lineage": "magic"}` {
panic("The data has not been encrypted!")
}
// Decrypt
decryptedState, err := sfe.DecryptState(encrypted)
if err != nil {
panic(err)
}
fmt.Printf("%s\n", decryptedState)
}
func handleDiags(diags hcl.Diagnostics) {
for _, d := range diags {
println(d.Error())
}
if diags.HasErrors() {
panic(diags.Error())
}
}
Output: {"serial": 42, "lineage": "magic"}
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultRegistry = lockingencryptionregistry.New()
Functions ¶
func IsEncryptionPayload ¶
Types ¶
type Encryption ¶
type Encryption interface {
// State produces a StateEncryption overlay for encrypting and decrypting state files for local storage.
State() StateEncryption
// Plan produces a PlanEncryption overlay for encrypting and decrypting plan files.
Plan() PlanEncryption
// RemoteState produces a StateEncryption for reading remote states using the terraform_remote_state data
// source.
RemoteState(string) StateEncryption
}
Encryption contains the methods for obtaining a StateEncryption or PlanEncryption correctly configured for a specific purpose. If no encryption configuration is present, it should return a pass through method that doesn't do anything.
func Disabled ¶
func Disabled() Encryption
func New ¶
func New(reg registry.Registry, cfg *config.EncryptionConfig, staticEval *configs.StaticEvaluator) (Encryption, hcl.Diagnostics)
New creates a new Encryption provider from the given configuration and registry.
type PlanEncryption ¶
type PlanEncryption interface {
// EncryptPlan encrypts a plan file and returns the encrypted form.
//
// When implementing this function:
//
// Plan files are opaque values. You may expect a valid plan file on the input, but you can produce binary data
// that is not necessarily a valid plan file. If no encryption is configured, this function should pass through
// any data it receives without modification, even if the plan file is invalid.
//
// When using this function:
//
// Make sure that you pass a valid plan file as an input. Failing to provide a valid plan file may result in an
// error. However, output values may not be valid plan files and you should not pass the encrypted plan file to any
// additional functions that normally work with plan files.
EncryptPlan([]byte) ([]byte, error)
// DecryptPlan decrypts an encrypted plan file.
//
// When implementing this function:
//
// If the user has configured no encryption, pass through any input unmodified regardless if the input is a valid
// plan file. If the user configured encryption, decrypt the plan file and return the decrypted plan file as a
// binary without further evaluating its validity.
//
// When using this function:
//
// Pass a potentially encrypted plan file as an input, and you will receive the decrypted plan file or an error as
// a result.
DecryptPlan([]byte) ([]byte, error)
}
PlanEncryption describes the methods that you can use for encrypting a plan file. Plan files are opaque values with no standardized format, so the encrypted form should be treated equally an opaque value.
func PlanEncryptionDisabled ¶
func PlanEncryptionDisabled() PlanEncryption
type StateEncryption ¶
type StateEncryption interface {
// DecryptState decrypts a potentially encrypted state file and returns a valid JSON-serialized state file.
//
// When implementing this function:
//
// If the user configured no encryption, also return the input as-is regardless if the state file is valid. If the
// user configured encryption unserialize the input as JSON and check for the presence of the field specified in the
// StateEncryptionMarkerField. If the field is not present, return the input as-is and return a warning that an
// unexpected unencrypted state file was encountered. Otherwise, decrypt the state file and return the decrypted
// state file as serialized JSON. If the state file cannot be decrypted, return an error in the diagnostics.
//
// When using this function:
//
// After reading the state file from its source (local file, remote backend, etc.), pass in the state file to this
// function. Do not attempt to determine if the state file is encrypted as this function will take care of any
// and all encryption-related matters. After the function returns, use the returned byte array as a normal state
// file.
DecryptState([]byte) ([]byte, error)
// EncryptState encrypts a state file and returns the encrypted form.
//
// When implementing this function:
//
// The file should take a JSON-serialized state file as an input and encrypt it according to the configuration.
// The encrypted form should also return a JSON which contains, at least, the key specified in
// StateEncryptionMarkerField to identify the state file as encrypted. This is necessary because some backends
// expect a state file to always be a JSON file.
//
// If the user configured no encryption, this function should be a no-op and return the input unchanged. If the
// input is not a valid state file, this function should return an error in the diagnostics return.
//
// When using this function:
//
// Pass in a valid JSON-serialized state file as an input and store the output. Note that you should not pass the
// output to any additional functions that require a valid state file as it may not contain the fields typically
// present in a state file.
EncryptState([]byte) ([]byte, error)
}
StateEncryption describes the interface for encrypting state files.
func StateEncryptionDisabled ¶
func StateEncryptionDisabled() StateEncryption
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
pbkdf2
Package pbkdf2 contains a key provider that takes a passphrase and emits a PBKDF2 hash of the configured length.
|
Package pbkdf2 contains a key provider that takes a passphrase and emits a PBKDF2 hash of the configured length. |
|
static
Package static contains a key provider that emits a static key.
|
Package static contains a key provider that emits a static key. |