github.com/opentofu/opentofu@v1.7.1/internal/encryption/keyprovider/openbao/config.go (about)

     1  package openbao
     2  
     3  import (
     4  	"fmt"
     5  
     6  	openbao "github.com/openbao/openbao/api"
     7  	"github.com/opentofu/opentofu/internal/encryption/keyprovider"
     8  )
     9  
    10  type Config struct {
    11  	Address string `hcl:"address,optional"`
    12  	Token   string `hcl:"token,optional"`
    13  
    14  	KeyName           string        `hcl:"key_name"`
    15  	KeyLength         DataKeyLength `hcl:"key_length,optional"`
    16  	TransitEnginePath string        `hcl:"transit_engine_path,optional"`
    17  }
    18  
    19  const (
    20  	defaultDataKeyLength     DataKeyLength = 32
    21  	defaultTransitEnginePath string        = "/transit"
    22  )
    23  
    24  func (c Config) Build() (keyprovider.KeyProvider, keyprovider.KeyMeta, error) {
    25  	if c.KeyName == "" {
    26  		return nil, nil, &keyprovider.ErrInvalidConfiguration{
    27  			Message: "no key name found",
    28  		}
    29  	}
    30  
    31  	if c.KeyLength == 0 {
    32  		c.KeyLength = defaultDataKeyLength
    33  	}
    34  
    35  	if err := c.KeyLength.Validate(); err != nil {
    36  		return nil, nil, &keyprovider.ErrInvalidConfiguration{
    37  			Cause: err,
    38  		}
    39  	}
    40  
    41  	if c.TransitEnginePath == "" {
    42  		c.TransitEnginePath = defaultTransitEnginePath
    43  	}
    44  
    45  	// DefaultConfig reads BAO_ADDR and some other optional env variables.
    46  	config := openbao.DefaultConfig()
    47  	if config.Error != nil {
    48  		return nil, nil, &keyprovider.ErrInvalidConfiguration{
    49  			Cause: config.Error,
    50  		}
    51  	}
    52  
    53  	// Address from HCL supersedes BAO_ADDR.
    54  	if c.Address != "" {
    55  		config.Address = c.Address
    56  	}
    57  
    58  	client, err := newClient(config, c.Token)
    59  	if err != nil {
    60  		return nil, nil, &keyprovider.ErrInvalidConfiguration{
    61  			Cause: err,
    62  		}
    63  	}
    64  
    65  	return &keyProvider{
    66  		svc: service{
    67  			c:           client,
    68  			transitPath: c.TransitEnginePath,
    69  		},
    70  		keyName:   c.KeyName,
    71  		keyLength: c.KeyLength,
    72  	}, new(keyMeta), nil
    73  }
    74  
    75  type DataKeyLength int
    76  
    77  func (l DataKeyLength) Validate() error {
    78  	switch l {
    79  	case 16, 32, 64:
    80  		return nil
    81  	default:
    82  		return fmt.Errorf("data key length should one of 16, 32 or 64 bytes: got %v", l)
    83  	}
    84  }
    85  
    86  func (l DataKeyLength) Bits() int {
    87  	return int(l) * 8
    88  }
    89  
    90  type clientConstructor func(config *openbao.Config, token string) (client, error)
    91  
    92  // newClient variable allows to inject different client implementations.
    93  // In order to keep client interface simple, token setting is in this function as well.
    94  // It's not possible to pass token in config.
    95  var newClient clientConstructor = newOpenBaoClient
    96  
    97  func newOpenBaoClient(config *openbao.Config, token string) (client, error) {
    98  	// NewClient reads BAO_TOKEN and some other optional env variables.
    99  	c, err := openbao.NewClient(config)
   100  	if err != nil {
   101  		return nil, fmt.Errorf("error creating OpenBao client: %w", err)
   102  	}
   103  
   104  	// Token from HCL supersedes BAO_TOKEN.
   105  	if token != "" {
   106  		c.SetToken(token)
   107  	}
   108  
   109  	return c.Logical(), nil
   110  }