github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/client/allocrunner/taskrunner/connect_native_hook_test.go (about)

     1  package taskrunner
     2  
     3  import (
     4  	"context"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	consulapi "github.com/hashicorp/consul/api"
    11  	consultest "github.com/hashicorp/consul/sdk/testutil"
    12  	"github.com/hashicorp/nomad/client/allocdir"
    13  	"github.com/hashicorp/nomad/client/allocrunner/interfaces"
    14  	"github.com/hashicorp/nomad/client/taskenv"
    15  	"github.com/hashicorp/nomad/client/testutil"
    16  	agentconsul "github.com/hashicorp/nomad/command/agent/consul"
    17  	"github.com/hashicorp/nomad/helper"
    18  	"github.com/hashicorp/nomad/helper/testlog"
    19  	"github.com/hashicorp/nomad/helper/uuid"
    20  	"github.com/hashicorp/nomad/nomad/mock"
    21  	"github.com/hashicorp/nomad/nomad/structs"
    22  	"github.com/hashicorp/nomad/nomad/structs/config"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  func getTestConsul(t *testing.T) *consultest.TestServer {
    27  	testConsul, err := consultest.NewTestServerConfigT(t, func(c *consultest.TestServerConfig) {
    28  		if !testing.Verbose() { // disable consul logging if -v not set
    29  			c.Stdout = ioutil.Discard
    30  			c.Stderr = ioutil.Discard
    31  		}
    32  	})
    33  	require.NoError(t, err, "failed to start test consul server")
    34  	return testConsul
    35  }
    36  
    37  func TestConnectNativeHook_Name(t *testing.T) {
    38  	t.Parallel()
    39  	name := new(connectNativeHook).Name()
    40  	require.Equal(t, "connect_native", name)
    41  }
    42  
    43  func setupCertDirs(t *testing.T) (string, string) {
    44  	fd, err := ioutil.TempFile("", "connect_native_testcert")
    45  	require.NoError(t, err)
    46  	_, err = fd.WriteString("ABCDEF")
    47  	require.NoError(t, err)
    48  	err = fd.Close()
    49  	require.NoError(t, err)
    50  
    51  	d, err := ioutil.TempDir("", "connect_native_testsecrets")
    52  	require.NoError(t, err)
    53  	return fd.Name(), d
    54  }
    55  
    56  func cleanupCertDirs(t *testing.T, original, secrets string) {
    57  	err := os.Remove(original)
    58  	require.NoError(t, err)
    59  	err = os.RemoveAll(secrets)
    60  	require.NoError(t, err)
    61  }
    62  
    63  func TestConnectNativeHook_copyCertificate(t *testing.T) {
    64  	t.Parallel()
    65  
    66  	f, d := setupCertDirs(t)
    67  	defer cleanupCertDirs(t, f, d)
    68  
    69  	t.Run("no source", func(t *testing.T) {
    70  		err := new(connectNativeHook).copyCertificate("", d, "out.pem")
    71  		require.NoError(t, err)
    72  	})
    73  
    74  	t.Run("normal", func(t *testing.T) {
    75  		err := new(connectNativeHook).copyCertificate(f, d, "out.pem")
    76  		require.NoError(t, err)
    77  		b, err := ioutil.ReadFile(filepath.Join(d, "out.pem"))
    78  		require.NoError(t, err)
    79  		require.Equal(t, "ABCDEF", string(b))
    80  	})
    81  }
    82  
    83  func TestConnectNativeHook_copyCertificates(t *testing.T) {
    84  	t.Parallel()
    85  
    86  	f, d := setupCertDirs(t)
    87  	defer cleanupCertDirs(t, f, d)
    88  
    89  	t.Run("normal", func(t *testing.T) {
    90  		err := new(connectNativeHook).copyCertificates(consulTransportConfig{
    91  			CAFile:   f,
    92  			CertFile: f,
    93  			KeyFile:  f,
    94  		}, d)
    95  		require.NoError(t, err)
    96  		ls, err := ioutil.ReadDir(d)
    97  		require.NoError(t, err)
    98  		require.Equal(t, 3, len(ls))
    99  	})
   100  
   101  	t.Run("no source", func(t *testing.T) {
   102  		err := new(connectNativeHook).copyCertificates(consulTransportConfig{
   103  			CAFile:   "/does/not/exist.pem",
   104  			CertFile: "/does/not/exist.pem",
   105  			KeyFile:  "/does/not/exist.pem",
   106  		}, d)
   107  		require.EqualError(t, err, "failed to open consul TLS certificate: open /does/not/exist.pem: no such file or directory")
   108  	})
   109  }
   110  
   111  func TestConnectNativeHook_tlsEnv(t *testing.T) {
   112  	t.Parallel()
   113  
   114  	// the hook config comes from client config
   115  	emptyHook := new(connectNativeHook)
   116  	fullHook := &connectNativeHook{
   117  		consulConfig: consulTransportConfig{
   118  			Auth:      "user:password",
   119  			SSL:       "true",
   120  			VerifySSL: "true",
   121  			CAFile:    "/not/real/ca.pem",
   122  			CertFile:  "/not/real/cert.pem",
   123  			KeyFile:   "/not/real/key.pem",
   124  		},
   125  	}
   126  
   127  	// existing config from task env stanza
   128  	taskEnv := map[string]string{
   129  		"CONSUL_CACERT":          "fakeCA.pem",
   130  		"CONSUL_CLIENT_CERT":     "fakeCert.pem",
   131  		"CONSUL_CLIENT_KEY":      "fakeKey.pem",
   132  		"CONSUL_HTTP_AUTH":       "foo:bar",
   133  		"CONSUL_HTTP_SSL":        "false",
   134  		"CONSUL_HTTP_SSL_VERIFY": "false",
   135  	}
   136  
   137  	t.Run("empty hook and empty task", func(t *testing.T) {
   138  		result := emptyHook.tlsEnv(nil)
   139  		require.Empty(t, result)
   140  	})
   141  
   142  	t.Run("empty hook and non-empty task", func(t *testing.T) {
   143  		result := emptyHook.tlsEnv(taskEnv)
   144  		require.Empty(t, result) // tlsEnv only overrides; task env is actually set elsewhere
   145  	})
   146  
   147  	t.Run("non-empty hook and empty task", func(t *testing.T) {
   148  		result := fullHook.tlsEnv(nil)
   149  		require.Equal(t, map[string]string{
   150  			// ca files are specifically copied into FS namespace
   151  			"CONSUL_CACERT":          "/secrets/consul_ca_file.pem",
   152  			"CONSUL_CLIENT_CERT":     "/secrets/consul_cert_file.pem",
   153  			"CONSUL_CLIENT_KEY":      "/secrets/consul_key_file.pem",
   154  			"CONSUL_HTTP_SSL":        "true",
   155  			"CONSUL_HTTP_SSL_VERIFY": "true",
   156  		}, result)
   157  	})
   158  
   159  	t.Run("non-empty hook and non-empty task", func(t *testing.T) {
   160  		result := fullHook.tlsEnv(taskEnv) // task env takes precedence, nothing gets set here
   161  		require.Empty(t, result)
   162  	})
   163  }
   164  
   165  func TestConnectNativeHook_bridgeEnv_bridge(t *testing.T) {
   166  	t.Parallel()
   167  
   168  	hook := new(connectNativeHook)
   169  	hook.alloc = mock.ConnectNativeAlloc("bridge")
   170  
   171  	t.Run("consul address env not preconfigured", func(t *testing.T) {
   172  		result := hook.bridgeEnv(nil)
   173  		require.Equal(t, map[string]string{
   174  			"CONSUL_HTTP_ADDR": "unix:///alloc/tmp/consul_http.sock",
   175  		}, result)
   176  	})
   177  
   178  	t.Run("consul address env is preconfigured", func(t *testing.T) {
   179  		result := hook.bridgeEnv(map[string]string{
   180  			"CONSUL_HTTP_ADDR": "10.1.1.1",
   181  		})
   182  		require.Empty(t, result)
   183  	})
   184  }
   185  
   186  func TestConnectNativeHook_bridgeEnv_host(t *testing.T) {
   187  	t.Parallel()
   188  
   189  	hook := new(connectNativeHook)
   190  	hook.alloc = mock.ConnectNativeAlloc("host")
   191  
   192  	t.Run("consul address env not preconfigured", func(t *testing.T) {
   193  		result := hook.bridgeEnv(nil)
   194  		require.Empty(t, result)
   195  	})
   196  
   197  	t.Run("consul address env is preconfigured", func(t *testing.T) {
   198  		result := hook.bridgeEnv(map[string]string{
   199  			"CONSUL_HTTP_ADDR": "10.1.1.1",
   200  		})
   201  		require.Empty(t, result)
   202  	})
   203  }
   204  
   205  func TestTaskRunner_ConnectNativeHook_Noop(t *testing.T) {
   206  	t.Parallel()
   207  	logger := testlog.HCLogger(t)
   208  
   209  	allocDir, cleanup := allocdir.TestAllocDir(t, logger, "ConnectNative")
   210  	defer cleanup()
   211  
   212  	alloc := mock.Alloc()
   213  	task := alloc.Job.LookupTaskGroup(alloc.TaskGroup).Tasks[0]
   214  
   215  	// run the connect native hook. use invalid consul address as it should not get hit
   216  	h := newConnectNativeHook(newConnectNativeHookConfig(alloc, &config.ConsulConfig{
   217  		Addr: "http://127.0.0.2:1",
   218  	}, logger))
   219  
   220  	request := &interfaces.TaskPrestartRequest{
   221  		Task:    task,
   222  		TaskDir: allocDir.NewTaskDir(task.Name),
   223  	}
   224  	require.NoError(t, request.TaskDir.Build(false, nil))
   225  
   226  	response := new(interfaces.TaskPrestartResponse)
   227  
   228  	// Run the hook
   229  	require.NoError(t, h.Prestart(context.Background(), request, response))
   230  
   231  	// Assert the hook is Done
   232  	require.True(t, response.Done)
   233  
   234  	// Assert secrets dir is empty (no TLS config set)
   235  	checkFilesInDir(t, request.TaskDir.SecretsDir,
   236  		nil,
   237  		[]string{sidsTokenFile, secretCAFilename, secretCertfileFilename, secretKeyfileFilename},
   238  	)
   239  }
   240  
   241  func TestTaskRunner_ConnectNativeHook_Ok(t *testing.T) {
   242  	t.Parallel()
   243  	testutil.RequireConsul(t)
   244  
   245  	testConsul := getTestConsul(t)
   246  	defer testConsul.Stop()
   247  
   248  	alloc := mock.Alloc()
   249  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{{Mode: "host", IP: "1.1.1.1"}}
   250  	tg := alloc.Job.TaskGroups[0]
   251  	tg.Services = []*structs.Service{{
   252  		Name:     "cn-service",
   253  		TaskName: tg.Tasks[0].Name,
   254  		Connect: &structs.ConsulConnect{
   255  			Native: true,
   256  		}},
   257  	}
   258  	tg.Tasks[0].Kind = structs.NewTaskKind("connect-native", "cn-service")
   259  
   260  	logger := testlog.HCLogger(t)
   261  
   262  	allocDir, cleanup := allocdir.TestAllocDir(t, logger, "ConnectNative")
   263  	defer cleanup()
   264  
   265  	// register group services
   266  	consulConfig := consulapi.DefaultConfig()
   267  	consulConfig.Address = testConsul.HTTPAddr
   268  	consulAPIClient, err := consulapi.NewClient(consulConfig)
   269  	require.NoError(t, err)
   270  
   271  	consulClient := agentconsul.NewServiceClient(consulAPIClient.Agent(), logger, true)
   272  	go consulClient.Run()
   273  	defer consulClient.Shutdown()
   274  	require.NoError(t, consulClient.RegisterWorkload(agentconsul.BuildAllocServices(mock.Node(), alloc, agentconsul.NoopRestarter())))
   275  
   276  	// Run Connect Native hook
   277  	h := newConnectNativeHook(newConnectNativeHookConfig(alloc, &config.ConsulConfig{
   278  		Addr: consulConfig.Address,
   279  	}, logger))
   280  	request := &interfaces.TaskPrestartRequest{
   281  		Task:    tg.Tasks[0],
   282  		TaskDir: allocDir.NewTaskDir(tg.Tasks[0].Name),
   283  		TaskEnv: taskenv.NewEmptyTaskEnv(),
   284  	}
   285  	require.NoError(t, request.TaskDir.Build(false, nil))
   286  
   287  	response := new(interfaces.TaskPrestartResponse)
   288  
   289  	// Run the Connect Native hook
   290  	require.NoError(t, h.Prestart(context.Background(), request, response))
   291  
   292  	// Assert the hook is Done
   293  	require.True(t, response.Done)
   294  
   295  	// Assert no environment variables configured to be set
   296  	require.Empty(t, response.Env)
   297  
   298  	// Assert no secrets were written
   299  	checkFilesInDir(t, request.TaskDir.SecretsDir,
   300  		nil,
   301  		[]string{sidsTokenFile, secretCAFilename, secretCertfileFilename, secretKeyfileFilename},
   302  	)
   303  }
   304  
   305  func TestTaskRunner_ConnectNativeHook_with_SI_token(t *testing.T) {
   306  	t.Parallel()
   307  	testutil.RequireConsul(t)
   308  
   309  	testConsul := getTestConsul(t)
   310  	defer testConsul.Stop()
   311  
   312  	alloc := mock.Alloc()
   313  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{{Mode: "host", IP: "1.1.1.1"}}
   314  	tg := alloc.Job.TaskGroups[0]
   315  	tg.Services = []*structs.Service{{
   316  		Name:     "cn-service",
   317  		TaskName: tg.Tasks[0].Name,
   318  		Connect: &structs.ConsulConnect{
   319  			Native: true,
   320  		}},
   321  	}
   322  	tg.Tasks[0].Kind = structs.NewTaskKind("connect-native", "cn-service")
   323  
   324  	logger := testlog.HCLogger(t)
   325  
   326  	allocDir, cleanup := allocdir.TestAllocDir(t, logger, "ConnectNative")
   327  	defer cleanup()
   328  
   329  	// register group services
   330  	consulConfig := consulapi.DefaultConfig()
   331  	consulConfig.Address = testConsul.HTTPAddr
   332  	consulAPIClient, err := consulapi.NewClient(consulConfig)
   333  	require.NoError(t, err)
   334  
   335  	consulClient := agentconsul.NewServiceClient(consulAPIClient.Agent(), logger, true)
   336  	go consulClient.Run()
   337  	defer consulClient.Shutdown()
   338  	require.NoError(t, consulClient.RegisterWorkload(agentconsul.BuildAllocServices(mock.Node(), alloc, agentconsul.NoopRestarter())))
   339  
   340  	// Run Connect Native hook
   341  	h := newConnectNativeHook(newConnectNativeHookConfig(alloc, &config.ConsulConfig{
   342  		Addr: consulConfig.Address,
   343  	}, logger))
   344  	request := &interfaces.TaskPrestartRequest{
   345  		Task:    tg.Tasks[0],
   346  		TaskDir: allocDir.NewTaskDir(tg.Tasks[0].Name),
   347  		TaskEnv: taskenv.NewEmptyTaskEnv(),
   348  	}
   349  	require.NoError(t, request.TaskDir.Build(false, nil))
   350  
   351  	// Insert service identity token in the secrets directory
   352  	token := uuid.Generate()
   353  	siTokenFile := filepath.Join(request.TaskDir.SecretsDir, sidsTokenFile)
   354  	err = ioutil.WriteFile(siTokenFile, []byte(token), 0440)
   355  	require.NoError(t, err)
   356  
   357  	response := new(interfaces.TaskPrestartResponse)
   358  	response.Env = make(map[string]string)
   359  
   360  	// Run the Connect Native hook
   361  	require.NoError(t, h.Prestart(context.Background(), request, response))
   362  
   363  	// Assert the hook is Done
   364  	require.True(t, response.Done)
   365  
   366  	// Assert environment variable for token is set
   367  	require.NotEmpty(t, response.Env)
   368  	require.Equal(t, token, response.Env["CONSUL_HTTP_TOKEN"])
   369  
   370  	// Assert no additional secrets were written
   371  	checkFilesInDir(t, request.TaskDir.SecretsDir,
   372  		[]string{sidsTokenFile},
   373  		[]string{secretCAFilename, secretCertfileFilename, secretKeyfileFilename},
   374  	)
   375  }
   376  
   377  func TestTaskRunner_ConnectNativeHook_shareTLS(t *testing.T) {
   378  	t.Parallel()
   379  	testutil.RequireConsul(t)
   380  
   381  	try := func(t *testing.T, shareSSL *bool) {
   382  		fakeCert, fakeCertDir := setupCertDirs(t)
   383  		defer cleanupCertDirs(t, fakeCert, fakeCertDir)
   384  
   385  		testConsul := getTestConsul(t)
   386  		defer testConsul.Stop()
   387  
   388  		alloc := mock.Alloc()
   389  		alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{{Mode: "host", IP: "1.1.1.1"}}
   390  		tg := alloc.Job.TaskGroups[0]
   391  		tg.Services = []*structs.Service{{
   392  			Name:     "cn-service",
   393  			TaskName: tg.Tasks[0].Name,
   394  			Connect: &structs.ConsulConnect{
   395  				Native: true,
   396  			}},
   397  		}
   398  		tg.Tasks[0].Kind = structs.NewTaskKind("connect-native", "cn-service")
   399  
   400  		logger := testlog.HCLogger(t)
   401  
   402  		allocDir, cleanup := allocdir.TestAllocDir(t, logger, "ConnectNative")
   403  		defer cleanup()
   404  
   405  		// register group services
   406  		consulConfig := consulapi.DefaultConfig()
   407  		consulConfig.Address = testConsul.HTTPAddr
   408  		consulAPIClient, err := consulapi.NewClient(consulConfig)
   409  		require.NoError(t, err)
   410  
   411  		consulClient := agentconsul.NewServiceClient(consulAPIClient.Agent(), logger, true)
   412  		go consulClient.Run()
   413  		defer consulClient.Shutdown()
   414  		require.NoError(t, consulClient.RegisterWorkload(agentconsul.BuildAllocServices(mock.Node(), alloc, agentconsul.NoopRestarter())))
   415  
   416  		// Run Connect Native hook
   417  		h := newConnectNativeHook(newConnectNativeHookConfig(alloc, &config.ConsulConfig{
   418  			Addr: consulConfig.Address,
   419  
   420  			// TLS config consumed by native application
   421  			ShareSSL:  shareSSL,
   422  			EnableSSL: helper.BoolToPtr(true),
   423  			VerifySSL: helper.BoolToPtr(true),
   424  			CAFile:    fakeCert,
   425  			CertFile:  fakeCert,
   426  			KeyFile:   fakeCert,
   427  			Auth:      "user:password",
   428  			Token:     uuid.Generate(),
   429  		}, logger))
   430  		request := &interfaces.TaskPrestartRequest{
   431  			Task:    tg.Tasks[0],
   432  			TaskDir: allocDir.NewTaskDir(tg.Tasks[0].Name),
   433  			TaskEnv: taskenv.NewEmptyTaskEnv(), // nothing set in env stanza
   434  		}
   435  		require.NoError(t, request.TaskDir.Build(false, nil))
   436  
   437  		response := new(interfaces.TaskPrestartResponse)
   438  		response.Env = make(map[string]string)
   439  
   440  		// Run the Connect Native hook
   441  		require.NoError(t, h.Prestart(context.Background(), request, response))
   442  
   443  		// Assert the hook is Done
   444  		require.True(t, response.Done)
   445  
   446  		// Assert environment variable for token is set
   447  		require.NotEmpty(t, response.Env)
   448  		require.Equal(t, map[string]string{
   449  			"CONSUL_CACERT":          "/secrets/consul_ca_file.pem",
   450  			"CONSUL_CLIENT_CERT":     "/secrets/consul_cert_file.pem",
   451  			"CONSUL_CLIENT_KEY":      "/secrets/consul_key_file.pem",
   452  			"CONSUL_HTTP_SSL":        "true",
   453  			"CONSUL_HTTP_SSL_VERIFY": "true",
   454  		}, response.Env)
   455  		require.NotContains(t, response.Env, "CONSUL_HTTP_AUTH")  // explicitly not shared
   456  		require.NotContains(t, response.Env, "CONSUL_HTTP_TOKEN") // explicitly not shared
   457  
   458  		// Assert 3 pem files were written
   459  		checkFilesInDir(t, request.TaskDir.SecretsDir,
   460  			[]string{secretCAFilename, secretCertfileFilename, secretKeyfileFilename},
   461  			[]string{sidsTokenFile},
   462  		)
   463  	}
   464  
   465  	// The default behavior is that share_ssl is true (similar to allow_unauthenticated)
   466  	// so make sure an unset value turns the feature on.
   467  
   468  	t.Run("share_ssl is true", func(t *testing.T) {
   469  		try(t, helper.BoolToPtr(true))
   470  	})
   471  
   472  	t.Run("share_ssl is nil", func(t *testing.T) {
   473  		try(t, nil)
   474  	})
   475  }
   476  
   477  func checkFilesInDir(t *testing.T, dir string, includes, excludes []string) {
   478  	ls, err := ioutil.ReadDir(dir)
   479  	require.NoError(t, err)
   480  
   481  	var present []string
   482  	for _, fInfo := range ls {
   483  		present = append(present, fInfo.Name())
   484  	}
   485  
   486  	for _, filename := range includes {
   487  		require.Contains(t, present, filename)
   488  	}
   489  	for _, filename := range excludes {
   490  		require.NotContains(t, present, filename)
   491  	}
   492  }
   493  
   494  func TestTaskRunner_ConnectNativeHook_shareTLS_override(t *testing.T) {
   495  	t.Parallel()
   496  	testutil.RequireConsul(t)
   497  
   498  	fakeCert, fakeCertDir := setupCertDirs(t)
   499  	defer cleanupCertDirs(t, fakeCert, fakeCertDir)
   500  
   501  	testConsul := getTestConsul(t)
   502  	defer testConsul.Stop()
   503  
   504  	alloc := mock.Alloc()
   505  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{{Mode: "host", IP: "1.1.1.1"}}
   506  	tg := alloc.Job.TaskGroups[0]
   507  	tg.Services = []*structs.Service{{
   508  		Name:     "cn-service",
   509  		TaskName: tg.Tasks[0].Name,
   510  		Connect: &structs.ConsulConnect{
   511  			Native: true,
   512  		}},
   513  	}
   514  	tg.Tasks[0].Kind = structs.NewTaskKind("connect-native", "cn-service")
   515  
   516  	logger := testlog.HCLogger(t)
   517  
   518  	allocDir, cleanup := allocdir.TestAllocDir(t, logger, "ConnectNative")
   519  	defer cleanup()
   520  
   521  	// register group services
   522  	consulConfig := consulapi.DefaultConfig()
   523  	consulConfig.Address = testConsul.HTTPAddr
   524  	consulAPIClient, err := consulapi.NewClient(consulConfig)
   525  	require.NoError(t, err)
   526  
   527  	consulClient := agentconsul.NewServiceClient(consulAPIClient.Agent(), logger, true)
   528  	go consulClient.Run()
   529  	defer consulClient.Shutdown()
   530  	require.NoError(t, consulClient.RegisterWorkload(agentconsul.BuildAllocServices(mock.Node(), alloc, agentconsul.NoopRestarter())))
   531  
   532  	// Run Connect Native hook
   533  	h := newConnectNativeHook(newConnectNativeHookConfig(alloc, &config.ConsulConfig{
   534  		Addr: consulConfig.Address,
   535  
   536  		// TLS config consumed by native application
   537  		ShareSSL:  helper.BoolToPtr(true),
   538  		EnableSSL: helper.BoolToPtr(true),
   539  		VerifySSL: helper.BoolToPtr(true),
   540  		CAFile:    fakeCert,
   541  		CertFile:  fakeCert,
   542  		KeyFile:   fakeCert,
   543  		Auth:      "user:password",
   544  	}, logger))
   545  
   546  	taskEnv := taskenv.NewEmptyTaskEnv()
   547  	taskEnv.EnvMap = map[string]string{
   548  		"CONSUL_CACERT":          "/foo/ca.pem",
   549  		"CONSUL_CLIENT_CERT":     "/foo/cert.pem",
   550  		"CONSUL_CLIENT_KEY":      "/foo/key.pem",
   551  		"CONSUL_HTTP_AUTH":       "foo:bar",
   552  		"CONSUL_HTTP_SSL_VERIFY": "false",
   553  		// CONSUL_HTTP_SSL (check the default value is assumed from client config)
   554  	}
   555  
   556  	request := &interfaces.TaskPrestartRequest{
   557  		Task:    tg.Tasks[0],
   558  		TaskDir: allocDir.NewTaskDir(tg.Tasks[0].Name),
   559  		TaskEnv: taskEnv, // env stanza is configured w/ non-default tls configs
   560  	}
   561  	require.NoError(t, request.TaskDir.Build(false, nil))
   562  
   563  	response := new(interfaces.TaskPrestartResponse)
   564  	response.Env = make(map[string]string)
   565  
   566  	// Run the Connect Native hook
   567  	require.NoError(t, h.Prestart(context.Background(), request, response))
   568  
   569  	// Assert the hook is Done
   570  	require.True(t, response.Done)
   571  
   572  	// Assert environment variable for CONSUL_HTTP_SSL is set, because it was
   573  	// the only one not overridden by task env stanza config
   574  	require.NotEmpty(t, response.Env)
   575  	require.Equal(t, map[string]string{
   576  		"CONSUL_HTTP_SSL": "true",
   577  	}, response.Env)
   578  
   579  	// Assert 3 pem files were written (even though they will be ignored)
   580  	// as this is gated by share_tls, not the presense of ca environment variables.
   581  	checkFilesInDir(t, request.TaskDir.SecretsDir,
   582  		[]string{secretCAFilename, secretCertfileFilename, secretKeyfileFilename},
   583  		[]string{sidsTokenFile},
   584  	)
   585  }