mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	 6cac3b3bf5
			
		
	
	6cac3b3bf5
	
	
	
		
			
			* Agent Auto Auth Self Healing for Templates * Added changelog * Edited go.sum * Edit changelog wording
		
			
				
	
	
		
			156 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) HashiCorp, Inc.
 | |
| // SPDX-License-Identifier: BUSL-1.1
 | |
| 
 | |
| package agent
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	log "github.com/hashicorp/go-hclog"
 | |
| 	"github.com/hashicorp/vault/command/agentproxyshared/auth"
 | |
| 	token_file "github.com/hashicorp/vault/command/agentproxyshared/auth/token-file"
 | |
| 	"github.com/hashicorp/vault/command/agentproxyshared/sink"
 | |
| 	"github.com/hashicorp/vault/command/agentproxyshared/sink/file"
 | |
| 	vaulthttp "github.com/hashicorp/vault/http"
 | |
| 	"github.com/hashicorp/vault/sdk/helper/logging"
 | |
| 	"github.com/hashicorp/vault/vault"
 | |
| )
 | |
| 
 | |
| func TestTokenFileEndToEnd(t *testing.T) {
 | |
| 	logger := logging.NewVaultLogger(log.Trace)
 | |
| 	cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
 | |
| 		HandlerFunc: vaulthttp.Handler,
 | |
| 	})
 | |
| 
 | |
| 	cluster.Start()
 | |
| 	defer cluster.Cleanup()
 | |
| 
 | |
| 	cores := cluster.Cores
 | |
| 
 | |
| 	vault.TestWaitActive(t, cores[0].Core)
 | |
| 
 | |
| 	client := cores[0].Client
 | |
| 
 | |
| 	secret, err := client.Auth().Token().Create(nil)
 | |
| 	if err != nil || secret == nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	tokenFile, err := os.Create(filepath.Join(t.TempDir(), "token_file"))
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	tokenFileName := tokenFile.Name()
 | |
| 	tokenFile.Close() // WriteFile doesn't need it open
 | |
| 	os.WriteFile(tokenFileName, []byte(secret.Auth.ClientToken), 0o666)
 | |
| 	defer os.Remove(tokenFileName)
 | |
| 
 | |
| 	ahConfig := &auth.AuthHandlerConfig{
 | |
| 		Logger: logger.Named("auth.handler"),
 | |
| 		Client: client,
 | |
| 	}
 | |
| 
 | |
| 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 | |
| 
 | |
| 	am, err := token_file.NewTokenFileAuthMethod(&auth.AuthConfig{
 | |
| 		Logger: logger.Named("auth.method"),
 | |
| 		Config: map[string]interface{}{
 | |
| 			"token_file_path": tokenFileName,
 | |
| 		},
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	ah := auth.NewAuthHandler(ahConfig)
 | |
| 	errCh := make(chan error)
 | |
| 	go func() {
 | |
| 		errCh <- ah.Run(ctx, am)
 | |
| 	}()
 | |
| 	defer func() {
 | |
| 		select {
 | |
| 		case <-ctx.Done():
 | |
| 		case err := <-errCh:
 | |
| 			if err != nil {
 | |
| 				t.Fatal(err)
 | |
| 			}
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	// We close these right away because we're just basically testing
 | |
| 	// permissions and finding a usable file name
 | |
| 	sinkFile, err := os.Create(filepath.Join(t.TempDir(), "auth.tokensink.test."))
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	tokenSinkFileName := sinkFile.Name()
 | |
| 	sinkFile.Close()
 | |
| 	os.Remove(tokenSinkFileName)
 | |
| 	t.Logf("output: %s", tokenSinkFileName)
 | |
| 
 | |
| 	config := &sink.SinkConfig{
 | |
| 		Logger: logger.Named("sink.file"),
 | |
| 		Config: map[string]interface{}{
 | |
| 			"path": tokenSinkFileName,
 | |
| 		},
 | |
| 		WrapTTL: 10 * time.Second,
 | |
| 	}
 | |
| 
 | |
| 	fs, err := file.NewFileSink(config)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	config.Sink = fs
 | |
| 
 | |
| 	ss := sink.NewSinkServer(&sink.SinkServerConfig{
 | |
| 		Logger: logger.Named("sink.server"),
 | |
| 		Client: client,
 | |
| 	})
 | |
| 	go func() {
 | |
| 		errCh <- ss.Run(ctx, ah.OutputCh, []*sink.SinkConfig{config}, ah.AuthInProgress)
 | |
| 	}()
 | |
| 	defer func() {
 | |
| 		select {
 | |
| 		case <-ctx.Done():
 | |
| 		case err := <-errCh:
 | |
| 			if err != nil {
 | |
| 				t.Fatal(err)
 | |
| 			}
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	// This has to be after the other defers, so it happens first. It allows
 | |
| 	// successful test runs to immediately cancel all of the runner goroutines
 | |
| 	// and unblock any of the blocking defer calls by the runner's DoneCh that
 | |
| 	// comes before this and avoid successful tests from taking the entire
 | |
| 	// timeout duration.
 | |
| 	defer cancel()
 | |
| 
 | |
| 	if stat, err := os.Lstat(tokenSinkFileName); err == nil {
 | |
| 		t.Fatalf("expected err but got %s", stat)
 | |
| 	} else if !os.IsNotExist(err) {
 | |
| 		t.Fatal("expected notexist err")
 | |
| 	}
 | |
| 
 | |
| 	// Wait 2 seconds for the env variables to be detected and an auth to be generated.
 | |
| 	time.Sleep(time.Second * 2)
 | |
| 
 | |
| 	token, err := readToken(tokenSinkFileName)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	if token.Token == "" {
 | |
| 		t.Fatal("expected token but didn't receive it")
 | |
| 	}
 | |
| 
 | |
| 	_, err = os.Stat(tokenFileName)
 | |
| 	if err != nil {
 | |
| 		t.Fatal("Token file removed")
 | |
| 	}
 | |
| }
 |