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 }