Repository: hashicorp/nomad
File: nomad/encrypter_test.go (Go)

Code before:
	     "key_id": %q
	   }
	 },
	 "WrappedRSAKey": {},
	 "KEK": %s
	}
	`, key.Meta.KeyID, wrappedDEKCipher, key.Meta.KeyID, kek)

	path := filepath.Join(tmpDir, key.Meta.KeyID+".nks.json")
	err = os.WriteFile(path, []byte(testData), 0o600)
	must.NoError(t, err)

	unwrappedKey, err := encrypter.loadKeyFromStore(path)
	must.NoError(t, err)
	must.NotNil(t, unwrappedKey)
}

// TestEncrypter_HAFailedWrites exercises the behavior of keyring rotation with
// HA KMS (for Nomad Enterprise) when one of the KMS is down. We want to fail
// the rotation here and not persist the keys.
func TestEncrypter_HAFailedWrites(t *testing.T) {

	srv := &Server{
		logger:      testlog.HCLogger(t),
		config:      &Config{},
		shutdownCtx: context.TODO(),
	}

	tmpDir := t.TempDir()
	encrypter, err := NewEncrypter(srv, tmpDir)
	must.NoError(t, err)

	// build two fake Vault transit encryption servers so we can control the
	// failed responses
	newMockVaultServer := func(name string, enabled *atomic.Bool) *httptest.Server {
		return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			t.Logf("vault %s got %s", name, r.URL)
			if !enabled.Load() {
				w.WriteHeader(http.StatusServiceUnavailable)
				json.NewEncoder(w).Encode(map[string]any{
					"errors": []string{"Vault is sealed or unavailable"},
				})
				return
			}
			if strings.Contains(r.URL.Path, "/transit/encrypt/") {
				var req map[string]any
				if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
					w.WriteHeader(http.StatusBadRequest)
					return
				}


Review comment (suggestion):
`testing.T` (and its siblings) has a neat built-in cancel context:

```suggestion
		shutdownCtx: t.Context(),
```

https://pkg.go.dev/testing#T.Context

Code after:
	     "key_id": %q
	   }
	 },
	 "WrappedRSAKey": {},
	 "KEK": %s
	}
	`, key.Meta.KeyID, wrappedDEKCipher, key.Meta.KeyID, kek)

	path := filepath.Join(tmpDir, key.Meta.KeyID+".nks.json")
	err = os.WriteFile(path, []byte(testData), 0o600)
	must.NoError(t, err)

	unwrappedKey, err := encrypter.loadKeyFromStore(path)
	must.NoError(t, err)
	must.NotNil(t, unwrappedKey)
}

// TestEncrypter_HAFailedWrites exercises the behavior of keyring rotation with
// HA KMS (for Nomad Enterprise) when one of the KMS is down. We want to fail
// the rotation here and not persist the keys.
func TestEncrypter_HAFailedWrites(t *testing.T) {

	srv := &Server{
		logger:      testlog.HCLogger(t),
		config:      &Config{},
		shutdownCtx: t.Context(),
	}

	tmpDir := t.TempDir()
	encrypter, err := NewEncrypter(srv, tmpDir)
	must.NoError(t, err)

	// build two fake Vault transit encryption servers so we can control the
	// failed responses
	newMockVaultServer := func(name string, enabled *atomic.Bool) *httptest.Server {
		return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			t.Logf("vault %s got %s", name, r.URL)
			if !enabled.Load() {
				w.WriteHeader(http.StatusServiceUnavailable)
				json.NewEncoder(w).Encode(map[string]any{
					"errors": []string{"Vault is sealed or unavailable"},
				})
				return
			}
			if strings.Contains(r.URL.Path, "/transit/encrypt/") {
				var req map[string]any
				if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
					w.WriteHeader(http.StatusBadRequest)
					return
				}