Also adds a test to ensure the new VAULT_CACERT_BYTES functionality works. Conflicts: go.mod go.sum
This commit is contained in:
parent
553b065fbd
commit
ed25ab6cf4
|
@ -0,0 +1,4 @@
|
||||||
|
```release-note:bug
|
||||||
|
agent: Environment variable VAULT_CACERT_BYTES now works for Vault Agent templates.
|
||||||
|
```
|
||||||
|
|
|
@ -324,40 +324,7 @@ func TestAgent_RequireRequestHeader(t *testing.T) {
|
||||||
serverClient := cluster.Cores[0].Client
|
serverClient := cluster.Cores[0].Client
|
||||||
|
|
||||||
// Enable the approle auth method
|
// Enable the approle auth method
|
||||||
req := serverClient.NewRequest("POST", "/v1/sys/auth/approle")
|
roleIDPath, secretIDPath := setupAppRole(t, serverClient)
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"type": "approle"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Create a named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"secret_id_num_uses": "10",
|
|
||||||
"secret_id_ttl": "1m",
|
|
||||||
"token_max_ttl": "1m",
|
|
||||||
"token_num_uses": "10",
|
|
||||||
"token_ttl": "1m"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Fetch the RoleID of the named role
|
|
||||||
req = serverClient.NewRequest("GET", "/v1/auth/approle/role/test-role/role-id")
|
|
||||||
body := request(t, serverClient, req, 200)
|
|
||||||
data := body["data"].(map[string]interface{})
|
|
||||||
roleID := data["role_id"].(string)
|
|
||||||
|
|
||||||
// Get a SecretID issued against the named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role/secret-id")
|
|
||||||
body = request(t, serverClient, req, 200)
|
|
||||||
data = body["data"].(map[string]interface{})
|
|
||||||
secretID := data["secret_id"].(string)
|
|
||||||
|
|
||||||
// Write the RoleID and SecretID to temp files
|
|
||||||
roleIDPath := makeTempFile(t, "role_id.txt", roleID+"\n")
|
|
||||||
secretIDPath := makeTempFile(t, "secret_id.txt", secretID+"\n")
|
|
||||||
defer os.Remove(roleIDPath)
|
|
||||||
defer os.Remove(secretIDPath)
|
|
||||||
|
|
||||||
// Create a config file
|
// Create a config file
|
||||||
config := `
|
config := `
|
||||||
|
@ -440,7 +407,7 @@ listener "tcp" {
|
||||||
// Test against a listener configuration that omits
|
// Test against a listener configuration that omits
|
||||||
// 'require_request_header', with the header missing from the request.
|
// 'require_request_header', with the header missing from the request.
|
||||||
agentClient := newApiClient("http://"+listenAddr1, false)
|
agentClient := newApiClient("http://"+listenAddr1, false)
|
||||||
req = agentClient.NewRequest("GET", "/v1/sys/health")
|
req := agentClient.NewRequest("GET", "/v1/sys/health")
|
||||||
request(t, agentClient, req, 200)
|
request(t, agentClient, req, 200)
|
||||||
|
|
||||||
// Test against a listener configuration that sets 'require_request_header'
|
// Test against a listener configuration that sets 'require_request_header'
|
||||||
|
@ -558,74 +525,7 @@ func TestAgent_Template_UserAgent(t *testing.T) {
|
||||||
defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress))
|
defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress))
|
||||||
os.Setenv(api.EnvVaultAddress, serverClient.Address())
|
os.Setenv(api.EnvVaultAddress, serverClient.Address())
|
||||||
|
|
||||||
// Enable the approle auth method
|
roleIDPath, secretIDPath := setupAppRoleAndKVMounts(t, serverClient)
|
||||||
req := serverClient.NewRequest("POST", "/v1/sys/auth/approle")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"type": "approle"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// give test-role permissions to read the kv secret
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/sys/policy/myapp-read")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"policy": "path \"secret/*\" { capabilities = [\"read\", \"list\"] }"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Create a named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"token_ttl": "5m",
|
|
||||||
"token_policies":"default,myapp-read",
|
|
||||||
"policies":"default,myapp-read"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Fetch the RoleID of the named role
|
|
||||||
req = serverClient.NewRequest("GET", "/v1/auth/approle/role/test-role/role-id")
|
|
||||||
body := request(t, serverClient, req, 200)
|
|
||||||
data := body["data"].(map[string]interface{})
|
|
||||||
roleID := data["role_id"].(string)
|
|
||||||
|
|
||||||
// Get a SecretID issued against the named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role/secret-id")
|
|
||||||
body = request(t, serverClient, req, 200)
|
|
||||||
data = body["data"].(map[string]interface{})
|
|
||||||
secretID := data["secret_id"].(string)
|
|
||||||
|
|
||||||
// Write the RoleID and SecretID to temp files
|
|
||||||
roleIDPath := makeTempFile(t, "role_id.txt", roleID+"\n")
|
|
||||||
secretIDPath := makeTempFile(t, "secret_id.txt", secretID+"\n")
|
|
||||||
defer os.Remove(roleIDPath)
|
|
||||||
defer os.Remove(secretIDPath)
|
|
||||||
|
|
||||||
// setup the kv secrets
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/sys/mounts/secret/tune")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"options": {"version": "2"}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate a secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/myapp")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "bar",
|
|
||||||
"password": "zap"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate another secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/otherapp")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "barstuff",
|
|
||||||
"password": "zap",
|
|
||||||
"cert": "something"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// make a temp directory to hold renders. Each test will create a temp dir
|
// make a temp directory to hold renders. Each test will create a temp dir
|
||||||
// inside this one
|
// inside this one
|
||||||
|
@ -669,7 +569,7 @@ auto_auth {
|
||||||
config = {
|
config = {
|
||||||
role_id_file_path = "%s"
|
role_id_file_path = "%s"
|
||||||
secret_id_file_path = "%s"
|
secret_id_file_path = "%s"
|
||||||
remove_secret_id_file_after_reading = false
|
remove_secret_id_file_after_reading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,74 +697,7 @@ func TestAgent_Template_Basic(t *testing.T) {
|
||||||
defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress))
|
defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress))
|
||||||
os.Setenv(api.EnvVaultAddress, serverClient.Address())
|
os.Setenv(api.EnvVaultAddress, serverClient.Address())
|
||||||
|
|
||||||
// Enable the approle auth method
|
roleIDPath, secretIDPath := setupAppRoleAndKVMounts(t, serverClient)
|
||||||
req := serverClient.NewRequest("POST", "/v1/sys/auth/approle")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"type": "approle"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// give test-role permissions to read the kv secret
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/sys/policy/myapp-read")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"policy": "path \"secret/*\" { capabilities = [\"read\", \"list\"] }"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Create a named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"token_ttl": "5m",
|
|
||||||
"token_policies":"default,myapp-read",
|
|
||||||
"policies":"default,myapp-read"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Fetch the RoleID of the named role
|
|
||||||
req = serverClient.NewRequest("GET", "/v1/auth/approle/role/test-role/role-id")
|
|
||||||
body := request(t, serverClient, req, 200)
|
|
||||||
data := body["data"].(map[string]interface{})
|
|
||||||
roleID := data["role_id"].(string)
|
|
||||||
|
|
||||||
// Get a SecretID issued against the named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role/secret-id")
|
|
||||||
body = request(t, serverClient, req, 200)
|
|
||||||
data = body["data"].(map[string]interface{})
|
|
||||||
secretID := data["secret_id"].(string)
|
|
||||||
|
|
||||||
// Write the RoleID and SecretID to temp files
|
|
||||||
roleIDPath := makeTempFile(t, "role_id.txt", roleID+"\n")
|
|
||||||
secretIDPath := makeTempFile(t, "secret_id.txt", secretID+"\n")
|
|
||||||
defer os.Remove(roleIDPath)
|
|
||||||
defer os.Remove(secretIDPath)
|
|
||||||
|
|
||||||
// setup the kv secrets
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/sys/mounts/secret/tune")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"options": {"version": "2"}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate a secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/myapp")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "bar",
|
|
||||||
"password": "zap"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate another secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/otherapp")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "barstuff",
|
|
||||||
"password": "zap",
|
|
||||||
"cert": "something"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// make a temp directory to hold renders. Each test will create a temp dir
|
// make a temp directory to hold renders. Each test will create a temp dir
|
||||||
// inside this one
|
// inside this one
|
||||||
|
@ -934,7 +767,7 @@ auto_auth {
|
||||||
config = {
|
config = {
|
||||||
role_id_file_path = "%s"
|
role_id_file_path = "%s"
|
||||||
secret_id_file_path = "%s"
|
secret_id_file_path = "%s"
|
||||||
remove_secret_id_file_after_reading = false
|
remove_secret_id_file_after_reading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1048,6 +881,255 @@ auto_auth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupAppRole(t *testing.T, serverClient *api.Client) (string, string) {
|
||||||
|
t.Helper()
|
||||||
|
// Enable the approle auth method
|
||||||
|
req := serverClient.NewRequest("POST", "/v1/sys/auth/approle")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"type": "approle"
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 204)
|
||||||
|
|
||||||
|
// Create a named role
|
||||||
|
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"token_ttl": "5m",
|
||||||
|
"token_policies":"default,myapp-read",
|
||||||
|
"policies":"default,myapp-read"
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 204)
|
||||||
|
|
||||||
|
// Fetch the RoleID of the named role
|
||||||
|
req = serverClient.NewRequest("GET", "/v1/auth/approle/role/test-role/role-id")
|
||||||
|
body := request(t, serverClient, req, 200)
|
||||||
|
data := body["data"].(map[string]interface{})
|
||||||
|
roleID := data["role_id"].(string)
|
||||||
|
|
||||||
|
// Get a SecretID issued against the named role
|
||||||
|
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role/secret-id")
|
||||||
|
body = request(t, serverClient, req, 200)
|
||||||
|
data = body["data"].(map[string]interface{})
|
||||||
|
secretID := data["secret_id"].(string)
|
||||||
|
|
||||||
|
// Write the RoleID and SecretID to temp files
|
||||||
|
roleIDPath := makeTempFile(t, "role_id.txt", roleID+"\n")
|
||||||
|
secretIDPath := makeTempFile(t, "secret_id.txt", secretID+"\n")
|
||||||
|
t.Cleanup(func() {
|
||||||
|
os.Remove(roleIDPath)
|
||||||
|
os.Remove(secretIDPath)
|
||||||
|
})
|
||||||
|
|
||||||
|
return roleIDPath, secretIDPath
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupAppRoleAndKVMounts(t *testing.T, serverClient *api.Client) (string, string) {
|
||||||
|
roleIDPath, secretIDPath := setupAppRole(t, serverClient)
|
||||||
|
|
||||||
|
// give test-role permissions to read the kv secret
|
||||||
|
req := serverClient.NewRequest("PUT", "/v1/sys/policy/myapp-read")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"policy": "path \"secret/*\" { capabilities = [\"read\", \"list\"] }"
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 204)
|
||||||
|
|
||||||
|
// setup the kv secrets
|
||||||
|
req = serverClient.NewRequest("POST", "/v1/sys/mounts/secret/tune")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"options": {"version": "2"}
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 200)
|
||||||
|
|
||||||
|
// Secret: myapp
|
||||||
|
req = serverClient.NewRequest("POST", "/v1/secret/data/myapp")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"data": {
|
||||||
|
"username": "bar",
|
||||||
|
"password": "zap"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 200)
|
||||||
|
|
||||||
|
// Secret: myapp2
|
||||||
|
req = serverClient.NewRequest("POST", "/v1/secret/data/myapp2")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"data": {
|
||||||
|
"username": "barstuff",
|
||||||
|
"password": "zap"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 200)
|
||||||
|
|
||||||
|
// Secret: otherapp
|
||||||
|
req = serverClient.NewRequest("POST", "/v1/secret/data/otherapp")
|
||||||
|
req.BodyBytes = []byte(`{
|
||||||
|
"data": {
|
||||||
|
"username": "barstuff",
|
||||||
|
"password": "zap",
|
||||||
|
"cert": "something"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
request(t, serverClient, req, 200)
|
||||||
|
|
||||||
|
return roleIDPath, secretIDPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAgent_Template_VaultClientFromEnv tests that Vault Agent can read in its
|
||||||
|
// required `vault` client details from environment variables instead of config.
|
||||||
|
func TestAgent_Template_VaultClientFromEnv(t *testing.T) {
|
||||||
|
//----------------------------------------------------
|
||||||
|
// Start the server and agent
|
||||||
|
//----------------------------------------------------
|
||||||
|
logger := logging.NewVaultLogger(hclog.Trace)
|
||||||
|
cluster := vault.NewTestCluster(t,
|
||||||
|
&vault.CoreConfig{
|
||||||
|
CredentialBackends: map[string]logical.Factory{
|
||||||
|
"approle": credAppRole.Factory,
|
||||||
|
},
|
||||||
|
LogicalBackends: map[string]logical.Factory{
|
||||||
|
"kv": logicalKv.Factory,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&vault.TestClusterOptions{
|
||||||
|
HandlerFunc: vaulthttp.Handler,
|
||||||
|
})
|
||||||
|
cluster.Start()
|
||||||
|
defer cluster.Cleanup()
|
||||||
|
|
||||||
|
vault.TestWaitActive(t, cluster.Cores[0].Core)
|
||||||
|
serverClient := cluster.Cores[0].Client
|
||||||
|
|
||||||
|
roleIDPath, secretIDPath := setupAppRoleAndKVMounts(t, serverClient)
|
||||||
|
|
||||||
|
// make a temp directory to hold renders. Each test will create a temp dir
|
||||||
|
// inside this one
|
||||||
|
tmpDirRoot, err := os.MkdirTemp("", "agent-test-renders")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDirRoot)
|
||||||
|
|
||||||
|
vaultAddr := "https://" + cluster.Cores[0].Listeners[0].Address.String()
|
||||||
|
testCases := map[string]struct {
|
||||||
|
env map[string]string
|
||||||
|
}{
|
||||||
|
"VAULT_ADDR and VAULT_CACERT": {
|
||||||
|
env: map[string]string{
|
||||||
|
api.EnvVaultAddress: vaultAddr,
|
||||||
|
api.EnvVaultCACert: cluster.CACertPEMFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"VAULT_ADDR and VAULT_CACERT_BYTES": {
|
||||||
|
env: map[string]string{
|
||||||
|
api.EnvVaultAddress: vaultAddr,
|
||||||
|
api.EnvVaultCACertBytes: string(cluster.CACertPEM),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcname, tc := range testCases {
|
||||||
|
t.Run(tcname, func(t *testing.T) {
|
||||||
|
for k, v := range tc.env {
|
||||||
|
t.Setenv(k, v)
|
||||||
|
}
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
// Make a template.
|
||||||
|
templateFile := filepath.Join(tmpDir, "render.tmpl")
|
||||||
|
if err := os.WriteFile(templateFile, []byte(templateContents(0)), 0o600); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// build up the template config to be added to the Agent config.hcl file
|
||||||
|
targetFile := filepath.Join(tmpDir, "render.json")
|
||||||
|
templateConfig := fmt.Sprintf(`
|
||||||
|
template {
|
||||||
|
source = "%s"
|
||||||
|
destination = "%s"
|
||||||
|
}
|
||||||
|
`, templateFile, targetFile)
|
||||||
|
|
||||||
|
// Create a config file
|
||||||
|
config := `
|
||||||
|
auto_auth {
|
||||||
|
method "approle" {
|
||||||
|
mount_path = "auth/approle"
|
||||||
|
config = {
|
||||||
|
role_id_file_path = "%s"
|
||||||
|
secret_id_file_path = "%s"
|
||||||
|
remove_secret_id_file_after_reading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%s
|
||||||
|
`
|
||||||
|
|
||||||
|
config = fmt.Sprintf(config, roleIDPath, secretIDPath, templateConfig)
|
||||||
|
configPath := makeTempFile(t, "config.hcl", config)
|
||||||
|
defer os.Remove(configPath)
|
||||||
|
|
||||||
|
// Start the agent
|
||||||
|
ui, cmd := testAgentCommand(t, logger)
|
||||||
|
cmd.client = serverClient
|
||||||
|
cmd.startedCh = make(chan struct{})
|
||||||
|
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
code := cmd.Run([]string{"-config", configPath})
|
||||||
|
if code != 0 {
|
||||||
|
t.Errorf("non-zero return code when running agent: %d", code)
|
||||||
|
t.Logf("STDOUT from agent:\n%s", ui.OutputWriter.String())
|
||||||
|
t.Logf("STDERR from agent:\n%s", ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-cmd.startedCh:
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
t.Errorf("timeout")
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
cmd.ShutdownCh <- struct{}{}
|
||||||
|
wg.Wait()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// We need to poll for a bit to give Agent time to render the
|
||||||
|
// templates. Without this this, the test will attempt to read
|
||||||
|
// the temp dir before Agent has had time to render and will
|
||||||
|
// likely fail the test
|
||||||
|
tick := time.Tick(1 * time.Second)
|
||||||
|
timeout := time.After(10 * time.Second)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timeout:
|
||||||
|
t.Fatalf("timed out waiting for templates to render, last error: %v", err)
|
||||||
|
case <-tick:
|
||||||
|
}
|
||||||
|
|
||||||
|
contents, err := os.ReadFile(targetFile)
|
||||||
|
if err != nil {
|
||||||
|
// If the file simply doesn't exist, continue waiting for
|
||||||
|
// the template rendering to complete.
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(contents) != templateRendered(0) {
|
||||||
|
t.Fatalf("expected=%q, got=%q", templateRendered(0), string(contents))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success! Break out of the retry loop.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testListFiles(t *testing.T, dir, extension string) int {
|
func testListFiles(t *testing.T, dir, extension string) int {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
@ -1100,84 +1182,7 @@ func TestAgent_Template_ExitCounter(t *testing.T) {
|
||||||
defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress))
|
defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress))
|
||||||
os.Setenv(api.EnvVaultAddress, serverClient.Address())
|
os.Setenv(api.EnvVaultAddress, serverClient.Address())
|
||||||
|
|
||||||
// Enable the approle auth method
|
roleIDPath, secretIDPath := setupAppRoleAndKVMounts(t, serverClient)
|
||||||
req := serverClient.NewRequest("POST", "/v1/sys/auth/approle")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"type": "approle"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// give test-role permissions to read the kv secret
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/sys/policy/myapp-read")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"policy": "path \"secret/*\" { capabilities = [\"read\", \"list\"] }"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Create a named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"token_ttl": "5m",
|
|
||||||
"token_policies":"default,myapp-read",
|
|
||||||
"policies":"default,myapp-read"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Fetch the RoleID of the named role
|
|
||||||
req = serverClient.NewRequest("GET", "/v1/auth/approle/role/test-role/role-id")
|
|
||||||
body := request(t, serverClient, req, 200)
|
|
||||||
data := body["data"].(map[string]interface{})
|
|
||||||
roleID := data["role_id"].(string)
|
|
||||||
|
|
||||||
// Get a SecretID issued against the named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role/secret-id")
|
|
||||||
body = request(t, serverClient, req, 200)
|
|
||||||
data = body["data"].(map[string]interface{})
|
|
||||||
secretID := data["secret_id"].(string)
|
|
||||||
|
|
||||||
// Write the RoleID and SecretID to temp files
|
|
||||||
roleIDPath := makeTempFile(t, "role_id.txt", roleID+"\n")
|
|
||||||
secretIDPath := makeTempFile(t, "secret_id.txt", secretID+"\n")
|
|
||||||
defer os.Remove(roleIDPath)
|
|
||||||
defer os.Remove(secretIDPath)
|
|
||||||
|
|
||||||
// setup the kv secrets
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/sys/mounts/secret/tune")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"options": {"version": "2"}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate a secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/myapp")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "bar",
|
|
||||||
"password": "zap"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate another secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/myapp2")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "barstuff",
|
|
||||||
"password": "zap"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// populate another, another secret
|
|
||||||
req = serverClient.NewRequest("POST", "/v1/secret/data/otherapp")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"data": {
|
|
||||||
"username": "barstuff",
|
|
||||||
"password": "zap",
|
|
||||||
"cert": "something"
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 200)
|
|
||||||
|
|
||||||
// make a temp directory to hold renders. Each test will create a temp dir
|
// make a temp directory to hold renders. Each test will create a temp dir
|
||||||
// inside this one
|
// inside this one
|
||||||
|
@ -1197,7 +1202,7 @@ func TestAgent_Template_ExitCounter(t *testing.T) {
|
||||||
config := `
|
config := `
|
||||||
vault {
|
vault {
|
||||||
address = "%s"
|
address = "%s"
|
||||||
tls_skip_verify = true
|
tls_skip_verify = true
|
||||||
}
|
}
|
||||||
|
|
||||||
auto_auth {
|
auto_auth {
|
||||||
|
@ -1206,7 +1211,7 @@ auto_auth {
|
||||||
config = {
|
config = {
|
||||||
role_id_file_path = "%s"
|
role_id_file_path = "%s"
|
||||||
secret_id_file_path = "%s"
|
secret_id_file_path = "%s"
|
||||||
remove_secret_id_file_after_reading = false
|
remove_secret_id_file_after_reading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1237,7 @@ template {
|
||||||
{{ end }}
|
{{ end }}
|
||||||
EOF
|
EOF
|
||||||
destination = "%s/render-other.txt"
|
destination = "%s/render-other.txt"
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_after_auth = true
|
exit_after_auth = true
|
||||||
`
|
`
|
||||||
|
@ -1702,7 +1707,7 @@ auto_auth {
|
||||||
config = {
|
config = {
|
||||||
role_id_file_path = "%s"
|
role_id_file_path = "%s"
|
||||||
secret_id_file_path = "%s"
|
secret_id_file_path = "%s"
|
||||||
remove_secret_id_file_after_reading = false
|
remove_secret_id_file_after_reading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1745,41 +1750,7 @@ func TestAgent_AutoAuth_UserAgent(t *testing.T) {
|
||||||
serverClient := cluster.Cores[0].Client
|
serverClient := cluster.Cores[0].Client
|
||||||
|
|
||||||
// Enable the approle auth method
|
// Enable the approle auth method
|
||||||
req := serverClient.NewRequest("POST", "/v1/sys/auth/approle")
|
roleIDPath, secretIDPath := setupAppRole(t, serverClient)
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"type": "approle"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Create a named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role")
|
|
||||||
req.BodyBytes = []byte(`{
|
|
||||||
"secret_id_num_uses": "10",
|
|
||||||
"secret_id_ttl": "1m",
|
|
||||||
"token_max_ttl": "1m",
|
|
||||||
"token_num_uses": "10",
|
|
||||||
"token_ttl": "1m",
|
|
||||||
"policies": "default"
|
|
||||||
}`)
|
|
||||||
request(t, serverClient, req, 204)
|
|
||||||
|
|
||||||
// Fetch the RoleID of the named role
|
|
||||||
req = serverClient.NewRequest("GET", "/v1/auth/approle/role/test-role/role-id")
|
|
||||||
body := request(t, serverClient, req, 200)
|
|
||||||
data := body["data"].(map[string]interface{})
|
|
||||||
roleID := data["role_id"].(string)
|
|
||||||
|
|
||||||
// Get a SecretID issued against the named role
|
|
||||||
req = serverClient.NewRequest("PUT", "/v1/auth/approle/role/test-role/secret-id")
|
|
||||||
body = request(t, serverClient, req, 200)
|
|
||||||
data = body["data"].(map[string]interface{})
|
|
||||||
secretID := data["secret_id"].(string)
|
|
||||||
|
|
||||||
// Write the RoleID and SecretID to temp files
|
|
||||||
roleIDPath := makeTempFile(t, "role_id.txt", roleID+"\n")
|
|
||||||
secretIDPath := makeTempFile(t, "secret_id.txt", secretID+"\n")
|
|
||||||
defer os.Remove(roleIDPath)
|
|
||||||
defer os.Remove(secretIDPath)
|
|
||||||
|
|
||||||
sinkf, err := os.CreateTemp("", "sink.test.")
|
sinkf, err := os.CreateTemp("", "sink.test.")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1868,8 +1839,8 @@ api_proxy {
|
||||||
// Wait for the token to be sent to syncs and be available to be used
|
// Wait for the token to be sent to syncs and be available to be used
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
req = agentClient.NewRequest("GET", "/v1/auth/token/lookup-self")
|
req := agentClient.NewRequest("GET", "/v1/auth/token/lookup-self")
|
||||||
body = request(t, agentClient, req, 200)
|
request(t, agentClient, req, 200)
|
||||||
|
|
||||||
close(cmd.ShutdownCh)
|
close(cmd.ShutdownCh)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
12
go.mod
12
go.mod
|
@ -72,8 +72,8 @@ require (
|
||||||
github.com/google/go-metrics-stackdriver v0.2.0
|
github.com/google/go-metrics-stackdriver v0.2.0
|
||||||
github.com/google/tink/go v1.7.0
|
github.com/google/tink/go v1.7.0
|
||||||
github.com/hashicorp/cap v0.3.0
|
github.com/hashicorp/cap v0.3.0
|
||||||
github.com/hashicorp/consul-template v0.32.0
|
github.com/hashicorp/consul-template v0.33.0
|
||||||
github.com/hashicorp/consul/api v1.20.0
|
github.com/hashicorp/consul/api v1.23.0
|
||||||
github.com/hashicorp/errwrap v1.1.0
|
github.com/hashicorp/errwrap v1.1.0
|
||||||
github.com/hashicorp/eventlogger v0.2.1
|
github.com/hashicorp/eventlogger v0.2.1
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||||
|
@ -208,10 +208,10 @@ require (
|
||||||
go.uber.org/goleak v1.2.1
|
go.uber.org/goleak v1.2.1
|
||||||
golang.org/x/crypto v0.11.0
|
golang.org/x/crypto v0.11.0
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
|
||||||
golang.org/x/net v0.12.0
|
golang.org/x/net v0.13.0
|
||||||
golang.org/x/oauth2 v0.10.0
|
golang.org/x/oauth2 v0.10.0
|
||||||
golang.org/x/sync v0.2.0
|
golang.org/x/sync v0.2.0
|
||||||
golang.org/x/sys v0.10.0
|
golang.org/x/sys v0.11.0
|
||||||
golang.org/x/term v0.10.0
|
golang.org/x/term v0.10.0
|
||||||
golang.org/x/text v0.11.0
|
golang.org/x/text v0.11.0
|
||||||
golang.org/x/tools v0.7.0
|
golang.org/x/tools v0.7.0
|
||||||
|
@ -254,7 +254,7 @@ require (
|
||||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
||||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||||
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
||||||
github.com/Jeffail/gabs v1.1.1 // indirect
|
github.com/Jeffail/gabs v1.1.1 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
|
@ -379,7 +379,7 @@ require (
|
||||||
github.com/hashicorp/mdns v1.0.4 // indirect
|
github.com/hashicorp/mdns v1.0.4 // indirect
|
||||||
github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 // indirect
|
github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 // indirect
|
||||||
github.com/hashicorp/serf v0.10.1 // indirect
|
github.com/hashicorp/serf v0.10.1 // indirect
|
||||||
github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 // indirect
|
github.com/hashicorp/vault/api/auth/kubernetes v0.4.1 // indirect
|
||||||
github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 // indirect
|
github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||||
github.com/huandu/xstrings v1.4.0 // indirect
|
github.com/huandu/xstrings v1.4.0 // indirect
|
||||||
|
|
21
go.sum
21
go.sum
|
@ -625,8 +625,9 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
|
||||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||||
github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4=
|
github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4=
|
||||||
|
@ -1688,13 +1689,13 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/hashicorp/cap v0.3.0 h1:zFzVxuWy78lO6QRLHu/ONkjx/Jh0lpfvPgmpDGri43E=
|
github.com/hashicorp/cap v0.3.0 h1:zFzVxuWy78lO6QRLHu/ONkjx/Jh0lpfvPgmpDGri43E=
|
||||||
github.com/hashicorp/cap v0.3.0/go.mod h1:dHTmyMIVbzT981XxRoci5G//dfWmd/HhuNiCH6J5+IA=
|
github.com/hashicorp/cap v0.3.0/go.mod h1:dHTmyMIVbzT981XxRoci5G//dfWmd/HhuNiCH6J5+IA=
|
||||||
github.com/hashicorp/consul-template v0.32.0 h1:VIfKjoJLkBYLgHdLH4mR7RstPc549qqHJiecqPwYTis=
|
github.com/hashicorp/consul-template v0.33.0 h1:UNyf7V/nFeh8edh5X6pP8f+9LZVn+DG9uNLLcTpLsFc=
|
||||||
github.com/hashicorp/consul-template v0.32.0/go.mod h1:r9mcCoHVkTeVln7aL4Ky+RfKupOtbEW70i8n9YuEe+w=
|
github.com/hashicorp/consul-template v0.33.0/go.mod h1:3RayddSLvOGQwdifbbe4doVwamgJU4QvxTtf5DNeclw=
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/api v1.20.0 h1:9IHTjNVSZ7MIwjlW3N3a7iGiykCMDpxZu8jsxFJh0yc=
|
github.com/hashicorp/consul/api v1.23.0 h1:L6e4v1AfoumqAHq/Rrsmuulev+nd7vltM3k8H329tyI=
|
||||||
github.com/hashicorp/consul/api v1.20.0/go.mod h1:nR64eD44KQ59Of/ECwt2vUmIK2DKsDzAwTmwmLl8Wpo=
|
github.com/hashicorp/consul/api v1.23.0/go.mod h1:SfvUIT74b0EplDuNgAJQ/FVqSO6KyK2ia80UI39/Ye8=
|
||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
github.com/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY=
|
github.com/hashicorp/consul/sdk v0.14.0 h1:Hly+BMNMssVzoWddbBnBFi3W+Fzytvm0haSkihhj3GU=
|
||||||
github.com/hashicorp/cronexpr v1.1.1 h1:NJZDd87hGXjoZBdvyCF9mX4DCq5Wy7+A/w+A7q0wn6c=
|
github.com/hashicorp/cronexpr v1.1.1 h1:NJZDd87hGXjoZBdvyCF9mX4DCq5Wy7+A/w+A7q0wn6c=
|
||||||
github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
|
github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
|
||||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
@ -3148,8 +3149,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
|
||||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -3363,8 +3364,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|
Loading…
Reference in New Issue