github.com/hernad/nomad@v1.6.112/nomad/structs/config/vault.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package config
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/hernad/nomad/helper/pointer"
    10  	vault "github.com/hashicorp/vault/api"
    11  )
    12  
    13  const (
    14  	// DefaultVaultConnectRetryIntv is the retry interval between trying to
    15  	// connect to Vault
    16  	DefaultVaultConnectRetryIntv = 30 * time.Second
    17  )
    18  
    19  // VaultConfig contains the configuration information necessary to
    20  // communicate with Vault in order to:
    21  //
    22  // - Renew Vault tokens/leases.
    23  //
    24  // - Pass a token for the Nomad Server to derive sub-tokens.
    25  //
    26  // - Create child tokens with policy subsets of the Server's token.
    27  type VaultConfig struct {
    28  
    29  	// Enabled enables or disables Vault support.
    30  	Enabled *bool `hcl:"enabled"`
    31  
    32  	// Token is the Vault token given to Nomad such that it can
    33  	// derive child tokens. Nomad will renew this token at half its lease
    34  	// lifetime.
    35  	Token string `hcl:"token"`
    36  
    37  	// Role sets the role in which to create tokens from. The Token given to
    38  	// Nomad does not have to be created from this role but must have "update"
    39  	// capability on "auth/token/create/<create_from_role>". If this value is
    40  	// unset and the token is created from a role, the value is defaulted to the
    41  	// role the token is from.
    42  	Role string `hcl:"create_from_role"`
    43  
    44  	// Namespace sets the Vault namespace used for all calls against the
    45  	// Vault API. If this is unset, then Nomad does not use Vault namespaces.
    46  	Namespace string `mapstructure:"namespace"`
    47  
    48  	// AllowUnauthenticated allows users to submit jobs requiring Vault tokens
    49  	// without providing a Vault token proving they have access to these
    50  	// policies.
    51  	AllowUnauthenticated *bool `hcl:"allow_unauthenticated"`
    52  
    53  	// TaskTokenTTL is the TTL of the tokens created by Nomad Servers and used
    54  	// by the client.  There should be a minimum time value such that the client
    55  	// does not have to renew with Vault at a very high frequency
    56  	TaskTokenTTL string `hcl:"task_token_ttl"`
    57  
    58  	// Addr is the address of the local Vault agent. This should be a complete
    59  	// URL such as "http://vault.example.com"
    60  	Addr string `hcl:"address"`
    61  
    62  	// ConnectionRetryIntv is the interval to wait before re-attempting to
    63  	// connect to Vault.
    64  	ConnectionRetryIntv time.Duration
    65  
    66  	// TLSCaFile is the path to a PEM-encoded CA cert file to use to verify the
    67  	// Vault server SSL certificate.
    68  	TLSCaFile string `hcl:"ca_file"`
    69  
    70  	// TLSCaFile is the path to a directory of PEM-encoded CA cert files to
    71  	// verify the Vault server SSL certificate.
    72  	TLSCaPath string `hcl:"ca_path"`
    73  
    74  	// TLSCertFile is the path to the certificate for Vault communication
    75  	TLSCertFile string `hcl:"cert_file"`
    76  
    77  	// TLSKeyFile is the path to the private key for Vault communication
    78  	TLSKeyFile string `hcl:"key_file"`
    79  
    80  	// TLSSkipVerify enables or disables SSL verification
    81  	TLSSkipVerify *bool `hcl:"tls_skip_verify"`
    82  
    83  	// TLSServerName, if set, is used to set the SNI host when connecting via TLS.
    84  	TLSServerName string `hcl:"tls_server_name"`
    85  }
    86  
    87  // DefaultVaultConfig returns the canonical defaults for the Nomad
    88  // `vault` configuration.
    89  func DefaultVaultConfig() *VaultConfig {
    90  	return &VaultConfig{
    91  		Addr:                 "https://vault.service.consul:8200",
    92  		ConnectionRetryIntv:  DefaultVaultConnectRetryIntv,
    93  		AllowUnauthenticated: pointer.Of(true),
    94  	}
    95  }
    96  
    97  // IsEnabled returns whether the config enables Vault integration
    98  func (c *VaultConfig) IsEnabled() bool {
    99  	return c.Enabled != nil && *c.Enabled
   100  }
   101  
   102  // AllowsUnauthenticated returns whether the config allows unauthenticated
   103  // access to Vault
   104  func (c *VaultConfig) AllowsUnauthenticated() bool {
   105  	return c.AllowUnauthenticated != nil && *c.AllowUnauthenticated
   106  }
   107  
   108  // Merge merges two Vault configurations together.
   109  func (c *VaultConfig) Merge(b *VaultConfig) *VaultConfig {
   110  	result := *c
   111  
   112  	if b.Enabled != nil {
   113  		result.Enabled = b.Enabled
   114  	}
   115  	if b.Token != "" {
   116  		result.Token = b.Token
   117  	}
   118  	if b.Role != "" {
   119  		result.Role = b.Role
   120  	}
   121  	if b.Namespace != "" {
   122  		result.Namespace = b.Namespace
   123  	}
   124  	if b.AllowUnauthenticated != nil {
   125  		result.AllowUnauthenticated = b.AllowUnauthenticated
   126  	}
   127  	if b.TaskTokenTTL != "" {
   128  		result.TaskTokenTTL = b.TaskTokenTTL
   129  	}
   130  	if b.Addr != "" {
   131  		result.Addr = b.Addr
   132  	}
   133  	if b.ConnectionRetryIntv.Nanoseconds() != 0 {
   134  		result.ConnectionRetryIntv = b.ConnectionRetryIntv
   135  	}
   136  	if b.TLSCaFile != "" {
   137  		result.TLSCaFile = b.TLSCaFile
   138  	}
   139  	if b.TLSCaPath != "" {
   140  		result.TLSCaPath = b.TLSCaPath
   141  	}
   142  	if b.TLSCertFile != "" {
   143  		result.TLSCertFile = b.TLSCertFile
   144  	}
   145  	if b.TLSKeyFile != "" {
   146  		result.TLSKeyFile = b.TLSKeyFile
   147  	}
   148  	if b.TLSSkipVerify != nil {
   149  		result.TLSSkipVerify = b.TLSSkipVerify
   150  	}
   151  	if b.TLSServerName != "" {
   152  		result.TLSServerName = b.TLSServerName
   153  	}
   154  
   155  	return &result
   156  }
   157  
   158  // ApiConfig returns a usable Vault config that can be passed directly to
   159  // hashicorp/vault/api.
   160  func (c *VaultConfig) ApiConfig() (*vault.Config, error) {
   161  	conf := vault.DefaultConfig()
   162  	tlsConf := &vault.TLSConfig{
   163  		CACert:        c.TLSCaFile,
   164  		CAPath:        c.TLSCaPath,
   165  		ClientCert:    c.TLSCertFile,
   166  		ClientKey:     c.TLSKeyFile,
   167  		TLSServerName: c.TLSServerName,
   168  	}
   169  	if c.TLSSkipVerify != nil {
   170  		tlsConf.Insecure = *c.TLSSkipVerify
   171  	} else {
   172  		tlsConf.Insecure = false
   173  	}
   174  
   175  	if err := conf.ConfigureTLS(tlsConf); err != nil {
   176  		return nil, err
   177  	}
   178  
   179  	conf.Address = c.Addr
   180  	return conf, nil
   181  }
   182  
   183  // Copy returns a copy of this Vault config.
   184  func (c *VaultConfig) Copy() *VaultConfig {
   185  	if c == nil {
   186  		return nil
   187  	}
   188  
   189  	nc := new(VaultConfig)
   190  	*nc = *c
   191  	return nc
   192  }
   193  
   194  // Equal compares two Vault configurations and returns a boolean indicating
   195  // if they are equal.
   196  func (c *VaultConfig) Equal(b *VaultConfig) bool {
   197  	if c == nil && b != nil {
   198  		return false
   199  	}
   200  	if c != nil && b == nil {
   201  		return false
   202  	}
   203  
   204  	if c.Enabled == nil || b.Enabled == nil {
   205  		if c.Enabled != b.Enabled {
   206  			return false
   207  		}
   208  	} else if *c.Enabled != *b.Enabled {
   209  		return false
   210  	}
   211  
   212  	if c.Token != b.Token {
   213  		return false
   214  	}
   215  	if c.Role != b.Role {
   216  		return false
   217  	}
   218  	if c.Namespace != b.Namespace {
   219  		return false
   220  	}
   221  
   222  	if c.AllowUnauthenticated == nil || b.AllowUnauthenticated == nil {
   223  		if c.AllowUnauthenticated != b.AllowUnauthenticated {
   224  			return false
   225  		}
   226  	} else if *c.AllowUnauthenticated != *b.AllowUnauthenticated {
   227  		return false
   228  	}
   229  
   230  	if c.TaskTokenTTL != b.TaskTokenTTL {
   231  		return false
   232  	}
   233  	if c.Addr != b.Addr {
   234  		return false
   235  	}
   236  	if c.ConnectionRetryIntv.Nanoseconds() != b.ConnectionRetryIntv.Nanoseconds() {
   237  		return false
   238  	}
   239  	if c.TLSCaFile != b.TLSCaFile {
   240  		return false
   241  	}
   242  	if c.TLSCaPath != b.TLSCaPath {
   243  		return false
   244  	}
   245  	if c.TLSCertFile != b.TLSCertFile {
   246  		return false
   247  	}
   248  	if c.TLSKeyFile != b.TLSKeyFile {
   249  		return false
   250  	}
   251  
   252  	if c.TLSSkipVerify == nil || b.TLSSkipVerify == nil {
   253  		if c.TLSSkipVerify != b.TLSSkipVerify {
   254  			return false
   255  		}
   256  	} else if *c.TLSSkipVerify != *b.TLSSkipVerify {
   257  		return false
   258  	}
   259  
   260  	if c.TLSServerName != b.TLSServerName {
   261  		return false
   262  	}
   263  
   264  	return true
   265  }