1package command 2 3import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "os" 9 "strings" 10 "sync" 11 "time" 12 13 "golang.org/x/term" 14 15 wrapping "github.com/hashicorp/go-kms-wrapping" 16 "github.com/hashicorp/vault/helper/constants" 17 18 "github.com/docker/docker/pkg/ioutils" 19 "github.com/hashicorp/consul/api" 20 log "github.com/hashicorp/go-hclog" 21 uuid "github.com/hashicorp/go-uuid" 22 cserver "github.com/hashicorp/vault/command/server" 23 "github.com/hashicorp/vault/helper/metricsutil" 24 "github.com/hashicorp/vault/internalshared/configutil" 25 "github.com/hashicorp/vault/internalshared/listenerutil" 26 "github.com/hashicorp/vault/internalshared/reloadutil" 27 physconsul "github.com/hashicorp/vault/physical/consul" 28 "github.com/hashicorp/vault/physical/raft" 29 "github.com/hashicorp/vault/sdk/physical" 30 "github.com/hashicorp/vault/sdk/version" 31 sr "github.com/hashicorp/vault/serviceregistration" 32 srconsul "github.com/hashicorp/vault/serviceregistration/consul" 33 "github.com/hashicorp/vault/vault" 34 "github.com/hashicorp/vault/vault/diagnose" 35 "github.com/mitchellh/cli" 36 "github.com/posener/complete" 37) 38 39const OperatorDiagnoseEnableEnv = "VAULT_DIAGNOSE" 40 41const CoreConfigUninitializedErr = "Diagnose cannot attempt this step because core config could not be set." 42 43var ( 44 _ cli.Command = (*OperatorDiagnoseCommand)(nil) 45 _ cli.CommandAutocomplete = (*OperatorDiagnoseCommand)(nil) 46) 47 48type OperatorDiagnoseCommand struct { 49 *BaseCommand 50 diagnose *diagnose.Session 51 52 flagDebug bool 53 flagSkips []string 54 flagConfigs []string 55 cleanupGuard sync.Once 56 57 reloadFuncsLock *sync.RWMutex 58 reloadFuncs *map[string][]reloadutil.ReloadFunc 59 ServiceRegistrations map[string]sr.Factory 60 startedCh chan struct{} // for tests 61 reloadedCh chan struct{} // for tests 62 skipEndEnd bool // for tests 63} 64 65func (c *OperatorDiagnoseCommand) Synopsis() string { 66 return "Troubleshoot problems starting Vault" 67} 68 69func (c *OperatorDiagnoseCommand) Help() string { 70 helpText := ` 71Usage: vault operator diagnose 72 73 This command troubleshoots Vault startup issues, such as TLS configuration or 74 auto-unseal. It should be run using the same environment variables and configuration 75 files as the "vault server" command, so that startup problems can be accurately 76 reproduced. 77 78 Start diagnose with a configuration file: 79 80 $ vault operator diagnose -config=/etc/vault/config.hcl 81 82 Perform a diagnostic check while Vault is still running: 83 84 $ vault operator diagnose -config=/etc/vault/config.hcl -skip=listener 85 86` + c.Flags().Help() 87 return strings.TrimSpace(helpText) 88} 89 90func (c *OperatorDiagnoseCommand) Flags() *FlagSets { 91 set := NewFlagSets(c.UI) 92 f := set.NewFlagSet("Command Options") 93 94 f.StringSliceVar(&StringSliceVar{ 95 Name: "config", 96 Target: &c.flagConfigs, 97 Completion: complete.PredictOr( 98 complete.PredictFiles("*.hcl"), 99 complete.PredictFiles("*.json"), 100 complete.PredictDirs("*"), 101 ), 102 Usage: "Path to a Vault configuration file or directory of configuration " + 103 "files. This flag can be specified multiple times to load multiple " + 104 "configurations. If the path is a directory, all files which end in " + 105 ".hcl or .json are loaded.", 106 }) 107 108 f.StringSliceVar(&StringSliceVar{ 109 Name: "skip", 110 Target: &c.flagSkips, 111 Usage: "Skip the health checks named as arguments. May be 'listener', 'storage', or 'autounseal'.", 112 }) 113 114 f.BoolVar(&BoolVar{ 115 Name: "debug", 116 Target: &c.flagDebug, 117 Default: false, 118 Usage: "Dump all information collected by Diagnose.", 119 }) 120 121 f.StringVar(&StringVar{ 122 Name: "format", 123 Target: &c.flagFormat, 124 Usage: "The output format", 125 }) 126 return set 127} 128 129func (c *OperatorDiagnoseCommand) AutocompleteArgs() complete.Predictor { 130 return complete.PredictNothing 131} 132 133func (c *OperatorDiagnoseCommand) AutocompleteFlags() complete.Flags { 134 return c.Flags().Completions() 135} 136 137const ( 138 status_unknown = "[ ] " 139 status_ok = "\u001b[32m[ ok ]\u001b[0m " 140 status_failed = "\u001b[31m[failed]\u001b[0m " 141 status_warn = "\u001b[33m[ warn ]\u001b[0m " 142 same_line = "\u001b[F" 143) 144 145func (c *OperatorDiagnoseCommand) Run(args []string) int { 146 f := c.Flags() 147 if err := f.Parse(args); err != nil { 148 c.UI.Error(err.Error()) 149 return 3 150 } 151 return c.RunWithParsedFlags() 152} 153 154func (c *OperatorDiagnoseCommand) RunWithParsedFlags() int { 155 156 if len(c.flagConfigs) == 0 { 157 c.UI.Error("Must specify a configuration file using -config.") 158 return 3 159 } 160 161 if c.diagnose == nil { 162 if c.flagFormat == "json" { 163 c.diagnose = diagnose.New(&ioutils.NopWriter{}) 164 } else { 165 c.UI.Output(version.GetVersion().FullVersionNumber(true)) 166 c.diagnose = diagnose.New(os.Stdout) 167 } 168 } 169 ctx := diagnose.Context(context.Background(), c.diagnose) 170 c.diagnose.SkipFilters = c.flagSkips 171 err := c.offlineDiagnostics(ctx) 172 173 results := c.diagnose.Finalize(ctx) 174 if c.flagFormat == "json" { 175 resultsJS, err := json.MarshalIndent(results, "", " ") 176 if err != nil { 177 fmt.Fprintf(os.Stderr, "Error marshalling results: %v.", err) 178 return 4 179 } 180 c.UI.Output(string(resultsJS)) 181 } else { 182 c.UI.Output("\nResults:") 183 w, _, err := term.GetSize(0) 184 if err == nil { 185 results.Write(os.Stdout, w) 186 } else { 187 results.Write(os.Stdout, 0) 188 } 189 } 190 191 if err != nil { 192 return 4 193 } 194 // Use a different return code 195 switch results.Status { 196 case diagnose.WarningStatus: 197 return 2 198 case diagnose.ErrorStatus: 199 return 1 200 } 201 return 0 202} 203 204func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error { 205 rloadFuncs := make(map[string][]reloadutil.ReloadFunc) 206 server := &ServerCommand{ 207 // TODO: set up a different one? 208 // In particular, a UI instance that won't output? 209 BaseCommand: c.BaseCommand, 210 211 // TODO: refactor to a common place? 212 AuditBackends: auditBackends, 213 CredentialBackends: credentialBackends, 214 LogicalBackends: logicalBackends, 215 PhysicalBackends: physicalBackends, 216 ServiceRegistrations: serviceRegistrations, 217 218 // TODO: other ServerCommand options? 219 220 logger: log.NewInterceptLogger(&log.LoggerOptions{ 221 Level: log.Off, 222 }), 223 allLoggers: []log.Logger{}, 224 reloadFuncs: &rloadFuncs, 225 reloadFuncsLock: new(sync.RWMutex), 226 } 227 228 ctx, span := diagnose.StartSpan(ctx, "Vault Diagnose") 229 defer span.End() 230 231 // OS Specific checks 232 diagnose.OSChecks(ctx) 233 234 var config *cserver.Config 235 236 diagnose.Test(ctx, "Parse Configuration", func(ctx context.Context) (err error) { 237 server.flagConfigs = c.flagConfigs 238 var configErrors []configutil.ConfigError 239 config, configErrors, err = server.parseConfig() 240 if err != nil { 241 return fmt.Errorf("Could not parse configuration: %w.", err) 242 } 243 for _, ce := range configErrors { 244 diagnose.Warn(ctx, diagnose.CapitalizeFirstLetter(ce.String())+".") 245 } 246 diagnose.Success(ctx, "Vault configuration syntax is ok.") 247 return nil 248 }) 249 if config == nil { 250 return fmt.Errorf("No vault server configuration found.") 251 } 252 253 var metricSink *metricsutil.ClusterMetricSink 254 var metricsHelper *metricsutil.MetricsHelper 255 256 var backend *physical.Backend 257 diagnose.Test(ctx, "Check Storage", func(ctx context.Context) error { 258 259 // Ensure that there is a storage stanza 260 if config.Storage == nil { 261 diagnose.Advise(ctx, "To learn how to specify a storage backend, see the Vault server configuration documentation.") 262 return fmt.Errorf("No storage stanza in Vault server configuration.") 263 } 264 265 diagnose.Test(ctx, "Create Storage Backend", func(ctx context.Context) error { 266 b, err := server.setupStorage(config) 267 if err != nil { 268 return err 269 } 270 if b == nil { 271 diagnose.Advise(ctx, "To learn how to specify a storage backend, see the Vault server configuration documentation.") 272 return fmt.Errorf("Storage backend could not be initialized.") 273 } 274 backend = &b 275 return nil 276 }) 277 278 if backend == nil { 279 diagnose.Fail(ctx, "Diagnose could not initialize storage backend.") 280 span.End() 281 return fmt.Errorf("Diagnose could not initialize storage backend.") 282 } 283 284 // Check for raft quorum status 285 if config.Storage.Type == storageTypeRaft { 286 path := os.Getenv(raft.EnvVaultRaftPath) 287 if path == "" { 288 path, ok := config.Storage.Config["path"] 289 if !ok { 290 diagnose.SpotError(ctx, "Check Raft Folder Permissions", fmt.Errorf("Storage folder path is required.")) 291 } 292 diagnose.RaftFileChecks(ctx, path) 293 } 294 diagnose.RaftStorageQuorum(ctx, (*backend).(*raft.RaftBackend)) 295 } 296 297 // Consul storage checks 298 if config.Storage != nil && config.Storage.Type == storageTypeConsul { 299 diagnose.Test(ctx, "Check Consul TLS", func(ctx context.Context) error { 300 err := physconsul.SetupSecureTLS(ctx, api.DefaultConfig(), config.Storage.Config, server.logger, true) 301 if err != nil { 302 return err 303 } 304 return nil 305 }) 306 307 diagnose.Test(ctx, "Check Consul Direct Storage Access", func(ctx context.Context) error { 308 dirAccess := diagnose.ConsulDirectAccess(config.Storage.Config) 309 if dirAccess != "" { 310 diagnose.Warn(ctx, dirAccess) 311 } 312 if dirAccess == diagnose.DirAccessErr { 313 diagnose.Advise(ctx, diagnose.DirAccessAdvice) 314 } 315 return nil 316 }) 317 } 318 319 // Attempt to use storage backend 320 if !c.skipEndEnd && config.Storage.Type != storageTypeRaft { 321 diagnose.Test(ctx, "Check Storage Access", diagnose.WithTimeout(30*time.Second, func(ctx context.Context) error { 322 maxDurationCrudOperation := "write" 323 maxDuration := time.Duration(0) 324 uuidSuffix, err := uuid.GenerateUUID() 325 if err != nil { 326 return err 327 } 328 uuid := "diagnose/latency/" + uuidSuffix 329 dur, err := diagnose.EndToEndLatencyCheckWrite(ctx, uuid, *backend) 330 if err != nil { 331 return err 332 } 333 maxDuration = dur 334 dur, err = diagnose.EndToEndLatencyCheckRead(ctx, uuid, *backend) 335 if err != nil { 336 return err 337 } 338 if dur > maxDuration { 339 maxDuration = dur 340 maxDurationCrudOperation = "read" 341 } 342 dur, err = diagnose.EndToEndLatencyCheckDelete(ctx, uuid, *backend) 343 if err != nil { 344 return err 345 } 346 if dur > maxDuration { 347 maxDuration = dur 348 maxDurationCrudOperation = "delete" 349 } 350 351 if maxDuration > time.Duration(0) { 352 diagnose.Warn(ctx, diagnose.LatencyWarning+fmt.Sprintf("duration: %s, operation: %s", maxDuration, maxDurationCrudOperation)) 353 } 354 return nil 355 })) 356 } 357 return nil 358 }) 359 360 // Return from top-level span when backend is nil 361 if backend == nil { 362 return fmt.Errorf("Diagnose could not initialize storage backend.") 363 } 364 365 var configSR sr.ServiceRegistration 366 diagnose.Test(ctx, "Check Service Discovery", func(ctx context.Context) error { 367 if config.ServiceRegistration == nil || config.ServiceRegistration.Config == nil { 368 diagnose.Skipped(ctx, "No service registration configured.") 369 return nil 370 } 371 srConfig := config.ServiceRegistration.Config 372 373 diagnose.Test(ctx, "Check Consul Service Discovery TLS", func(ctx context.Context) error { 374 // SetupSecureTLS for service discovery uses the same cert and key to set up physical 375 // storage. See the consul package in physical for details. 376 err := srconsul.SetupSecureTLS(ctx, api.DefaultConfig(), srConfig, server.logger, true) 377 if err != nil { 378 return err 379 } 380 return nil 381 }) 382 383 if config.ServiceRegistration != nil && config.ServiceRegistration.Type == "consul" { 384 diagnose.Test(ctx, "Check Consul Direct Service Discovery", func(ctx context.Context) error { 385 dirAccess := diagnose.ConsulDirectAccess(config.ServiceRegistration.Config) 386 if dirAccess != "" { 387 diagnose.Warn(ctx, dirAccess) 388 } 389 if dirAccess == diagnose.DirAccessErr { 390 diagnose.Advise(ctx, diagnose.DirAccessAdvice) 391 } 392 return nil 393 }) 394 } 395 return nil 396 }) 397 398 sealcontext, sealspan := diagnose.StartSpan(ctx, "Create Vault Server Configuration Seals") 399 var seals []vault.Seal 400 var sealConfigError error 401 402 barrierSeal, barrierWrapper, unwrapSeal, seals, sealConfigError, err := setSeal(server, config, make([]string, 0), make(map[string]string)) 403 404 // Check error here 405 if err != nil { 406 diagnose.Advise(ctx, "For assistance with the seal stanza, see the Vault configuration documentation.") 407 diagnose.Fail(sealcontext, fmt.Sprintf("Seal creation resulted in the following error: %s.", err.Error())) 408 goto SEALFAIL 409 } 410 if sealConfigError != nil { 411 diagnose.Fail(sealcontext, "Seal could not be configured: seals may already be initialized.") 412 goto SEALFAIL 413 } 414 415 if seals != nil { 416 for _, seal := range seals { 417 // There is always one nil seal. We need to skip it so we don't start an empty Finalize-Seal-Shamir 418 // section. 419 if seal == nil { 420 continue 421 } 422 // Ensure that the seal finalizer is called, even if using verify-only 423 defer func(seal *vault.Seal) { 424 sealType := diagnose.CapitalizeFirstLetter((*seal).BarrierType()) 425 finalizeSealContext, finalizeSealSpan := diagnose.StartSpan(ctx, "Finalize "+sealType+" Seal") 426 err = (*seal).Finalize(finalizeSealContext) 427 if err != nil { 428 diagnose.Fail(finalizeSealContext, "Error finalizing seal.") 429 diagnose.Advise(finalizeSealContext, "This likely means that the barrier is still in use; therefore, finalizing the seal timed out.") 430 finalizeSealSpan.End() 431 } 432 finalizeSealSpan.End() 433 }(&seal) 434 } 435 } 436 437 if barrierSeal == nil { 438 diagnose.Fail(sealcontext, "Could not create barrier seal. No error was generated, but it is likely that the seal stanza is misconfigured. For guidance, see Vault's configuration documentation on the seal stanza.") 439 } 440 441SEALFAIL: 442 sealspan.End() 443 444 diagnose.Test(ctx, "Check Transit Seal TLS", func(ctx context.Context) error { 445 var checkSealTransit bool 446 for _, seal := range config.Seals { 447 if seal.Type == "transit" { 448 checkSealTransit = true 449 450 tlsSkipVerify, _ := seal.Config["tls_skip_verify"] 451 if tlsSkipVerify == "true" { 452 diagnose.Warn(ctx, "TLS verification is skipped. This is highly discouraged and decreases the security of data transmissions to and from the Vault server.") 453 return nil 454 } 455 456 // Checking tls_client_cert and tls_client_key 457 tlsClientCert, ok := seal.Config["tls_client_cert"] 458 if !ok { 459 diagnose.Warn(ctx, "Missing tls_client_cert in the seal configuration.") 460 return nil 461 } 462 tlsClientKey, ok := seal.Config["tls_client_key"] 463 if !ok { 464 diagnose.Warn(ctx, "Missing tls_client_key in the seal configuration.") 465 return nil 466 } 467 _, err := diagnose.TLSFileChecks(tlsClientCert, tlsClientKey) 468 if err != nil { 469 return fmt.Errorf("The TLS certificate and key configured through the tls_client_cert and tls_client_key fields of the transit seal configuration are invalid: %w.", err) 470 } 471 472 // checking tls_ca_cert 473 tlsCACert, ok := seal.Config["tls_ca_cert"] 474 if !ok { 475 diagnose.Warn(ctx, "Missing tls_ca_cert in the seal configuration.") 476 return nil 477 } 478 warnings, err := diagnose.TLSCAFileCheck(tlsCACert) 479 if len(warnings) != 0 { 480 for _, warning := range warnings { 481 diagnose.Warn(ctx, warning) 482 } 483 } 484 if err != nil { 485 return fmt.Errorf("The TLS CA certificate configured through the tls_ca_cert field of the transit seal configuration is invalid: %w.", err) 486 } 487 } 488 } 489 if !checkSealTransit { 490 diagnose.Skipped(ctx, "No transit seal found in seal configuration.") 491 } 492 return nil 493 }) 494 495 var coreConfig vault.CoreConfig 496 diagnose.Test(ctx, "Create Core Configuration", func(ctx context.Context) error { 497 var secureRandomReader io.Reader 498 // prepare a secure random reader for core 499 randReaderTestName := "Initialize Randomness for Core" 500 secureRandomReader, err = configutil.CreateSecureRandomReaderFunc(config.SharedConfig, barrierWrapper) 501 if err != nil { 502 return diagnose.SpotError(ctx, randReaderTestName, fmt.Errorf("Could not initialize randomness for core: %w.", err)) 503 } 504 diagnose.SpotOk(ctx, randReaderTestName, "") 505 coreConfig = createCoreConfig(server, config, *backend, configSR, barrierSeal, unwrapSeal, metricsHelper, metricSink, secureRandomReader) 506 return nil 507 }) 508 509 var disableClustering bool 510 diagnose.Test(ctx, "HA Storage", func(ctx context.Context) error { 511 diagnose.Test(ctx, "Create HA Storage Backend", func(ctx context.Context) error { 512 // Initialize the separate HA storage backend, if it exists 513 disableClustering, err = initHaBackend(server, config, &coreConfig, *backend) 514 if err != nil { 515 return err 516 } 517 return nil 518 }) 519 520 diagnose.Test(ctx, "Check HA Consul Direct Storage Access", func(ctx context.Context) error { 521 if config.HAStorage == nil { 522 diagnose.Skipped(ctx, "No HA storage stanza is configured.") 523 } else { 524 dirAccess := diagnose.ConsulDirectAccess(config.HAStorage.Config) 525 if dirAccess != "" { 526 diagnose.Warn(ctx, dirAccess) 527 } 528 if dirAccess == diagnose.DirAccessErr { 529 diagnose.Advise(ctx, diagnose.DirAccessAdvice) 530 } 531 } 532 return nil 533 }) 534 if config.HAStorage != nil && config.HAStorage.Type == storageTypeConsul { 535 diagnose.Test(ctx, "Check Consul TLS", func(ctx context.Context) error { 536 err = physconsul.SetupSecureTLS(ctx, api.DefaultConfig(), config.HAStorage.Config, server.logger, true) 537 if err != nil { 538 return err 539 } 540 return nil 541 }) 542 } 543 return nil 544 }) 545 546 // Determine the redirect address from environment variables 547 err = determineRedirectAddr(server, &coreConfig, config) 548 if err != nil { 549 return diagnose.SpotError(ctx, "Determine Redirect Address", fmt.Errorf("Redirect Address could not be determined: %w.", err)) 550 } 551 diagnose.SpotOk(ctx, "Determine Redirect Address", "") 552 553 err = findClusterAddress(server, &coreConfig, config, disableClustering) 554 if err != nil { 555 return diagnose.SpotError(ctx, "Check Cluster Address", fmt.Errorf("Cluster Address could not be determined or was invalid: %w.", err), 556 diagnose.Advice("Please check that the API and Cluster addresses are different, and that the API, Cluster and Redirect addresses have both a host and port.")) 557 } 558 diagnose.SpotOk(ctx, "Check Cluster Address", "Cluster address is logically valid and can be found.") 559 560 var vaultCore *vault.Core 561 562 // Run all the checks that are utilized when initializing a core object 563 // without actually calling core.Init. These are in the init-core section 564 // as they are runtime checks. 565 diagnose.Test(ctx, "Check Core Creation", func(ctx context.Context) error { 566 var newCoreError error 567 if coreConfig.RawConfig == nil { 568 return fmt.Errorf(CoreConfigUninitializedErr) 569 } 570 core, newCoreError := vault.CreateCore(&coreConfig) 571 if newCoreError != nil { 572 if vault.IsFatalError(newCoreError) { 573 return fmt.Errorf("Error initializing core: %s.", newCoreError) 574 } 575 diagnose.Warn(ctx, wrapAtLength( 576 "A non-fatal error occurred during initialization. Please check the logs for more information.")) 577 } else { 578 vaultCore = core 579 } 580 return nil 581 }) 582 583 if vaultCore == nil { 584 return fmt.Errorf("Diagnose could not initialize the Vault core from the Vault server configuration.") 585 } 586 587 licenseCtx, licenseSpan := diagnose.StartSpan(ctx, "Check For Autoloaded License") 588 // If we are not in enterprise, return from the check 589 if !constants.IsEnterprise { 590 diagnose.Skipped(licenseCtx, "License check will not run on OSS Vault.") 591 } else { 592 // Load License from environment variables. These take precedence over the 593 // configured license. 594 if envLicensePath := os.Getenv(EnvVaultLicensePath); envLicensePath != "" { 595 coreConfig.LicensePath = envLicensePath 596 } 597 if envLicense := os.Getenv(EnvVaultLicense); envLicense != "" { 598 coreConfig.License = envLicense 599 } 600 vault.DiagnoseCheckLicense(licenseCtx, vaultCore, coreConfig, false) 601 } 602 licenseSpan.End() 603 604 var lns []listenerutil.Listener 605 diagnose.Test(ctx, "Start Listeners", func(ctx context.Context) error { 606 disableClustering := config.HAStorage != nil && config.HAStorage.DisableClustering 607 infoKeys := make([]string, 0, 10) 608 info := make(map[string]string) 609 var listeners []listenerutil.Listener 610 var status int 611 612 diagnose.ListenerChecks(ctx, config.Listeners) 613 614 diagnose.Test(ctx, "Create Listeners", func(ctx context.Context) error { 615 status, listeners, _, err = server.InitListeners(config, disableClustering, &infoKeys, &info) 616 if status != 0 { 617 return err 618 } 619 return nil 620 }) 621 622 lns = listeners 623 624 // Make sure we close all listeners from this point on 625 listenerCloseFunc := func() { 626 for _, ln := range lns { 627 ln.Listener.Close() 628 } 629 } 630 631 c.cleanupGuard.Do(listenerCloseFunc) 632 633 return nil 634 }) 635 636 // TODO: Diagnose logging configuration 637 638 // The unseal diagnose check will simply attempt to use the barrier to encrypt and 639 // decrypt a mock value. It will not call runUnseal. 640 diagnose.Test(ctx, "Check Autounseal Encryption", diagnose.WithTimeout(30*time.Second, func(ctx context.Context) error { 641 if barrierSeal == nil { 642 return fmt.Errorf("Diagnose could not create a barrier seal object.") 643 } 644 if barrierSeal.BarrierType() == wrapping.Shamir { 645 diagnose.Skipped(ctx, "Skipping barrier encryption test. Only supported for auto-unseal.") 646 return nil 647 } 648 barrierUUID, err := uuid.GenerateUUID() 649 if err != nil { 650 return fmt.Errorf("Diagnose could not create unique UUID for unsealing.") 651 } 652 barrierEncValue := "diagnose-" + barrierUUID 653 ciphertext, err := barrierWrapper.Encrypt(ctx, []byte(barrierEncValue), nil) 654 if err != nil { 655 return fmt.Errorf("Error encrypting with seal barrier: %w.", err) 656 } 657 plaintext, err := barrierWrapper.Decrypt(ctx, ciphertext, nil) 658 if err != nil { 659 return fmt.Errorf("Error decrypting with seal barrier: %w", err) 660 661 } 662 if string(plaintext) != barrierEncValue { 663 return fmt.Errorf("Barrier returned incorrect decrypted value for mock data.") 664 } 665 return nil 666 })) 667 668 // The following block contains static checks that are run during the 669 // startHttpServers portion of server run. In other words, they are static 670 // checks during resource creation. Currently there is nothing important in this 671 // diagnose check. For now it is a placeholder for any checks that will be done 672 // before server run. 673 diagnose.Test(ctx, "Check Server Before Runtime", func(ctx context.Context) error { 674 for _, ln := range lns { 675 if ln.Config == nil { 676 return fmt.Errorf("Found no listener config after parsing the Vault configuration.") 677 } 678 } 679 return nil 680 }) 681 return nil 682} 683