loadECHConfig loads the config from storage with the given configID. An error is not actually returned in some cases the config fails to load because in some cases it just means the config ID folder has been cleaned up in storage, maybe due to an incomplete set of keys or corrupted contents; in any
(ctx caddy.Context, configID string)
| 527 | // corrupted keys fails, for example). Check the returned echConfig for |
| 528 | // non-nil privKeyBin and configBin values before using. |
| 529 | func loadECHConfig(ctx caddy.Context, configID string) (echConfig, error) { |
| 530 | storage := ctx.Storage() |
| 531 | logger := ctx.Logger() |
| 532 | |
| 533 | cfgIDKey := path.Join(echConfigsKey, configID) |
| 534 | keyKey := path.Join(cfgIDKey, "key.bin") |
| 535 | configKey := path.Join(cfgIDKey, "config.bin") |
| 536 | metaKey := path.Join(cfgIDKey, "meta.json") |
| 537 | |
| 538 | // if loading anything fails, might as well delete this folder and free up |
| 539 | // the config ID; spec is designed to rotate configs frequently anyway |
| 540 | // (I consider it a more serious error if we can't clean up the folder, |
| 541 | // since leaving stray storage keys is confusing) |
| 542 | privKeyBytes, err := storage.Load(ctx, keyKey) |
| 543 | if err != nil { |
| 544 | delErr := storage.Delete(ctx, cfgIDKey) |
| 545 | if delErr != nil { |
| 546 | return echConfig{}, fmt.Errorf("error loading private key (%v) and cleaning up parent storage key %s: %v", err, cfgIDKey, delErr) |
| 547 | } |
| 548 | logger.Warn("could not load ECH private key; deleting its config folder", |
| 549 | zap.String("config_id", configID), |
| 550 | zap.Error(err)) |
| 551 | return echConfig{}, nil |
| 552 | } |
| 553 | echConfigBytes, err := storage.Load(ctx, configKey) |
| 554 | if err != nil { |
| 555 | delErr := storage.Delete(ctx, cfgIDKey) |
| 556 | if delErr != nil { |
| 557 | return echConfig{}, fmt.Errorf("error loading ECH config (%v) and cleaning up parent storage key %s: %v", err, cfgIDKey, delErr) |
| 558 | } |
| 559 | logger.Warn("could not load ECH config; deleting its config folder", |
| 560 | zap.String("config_id", configID), |
| 561 | zap.Error(err)) |
| 562 | return echConfig{}, nil |
| 563 | } |
| 564 | var cfg echConfig |
| 565 | if err := cfg.UnmarshalBinary(echConfigBytes); err != nil { |
| 566 | delErr := storage.Delete(ctx, cfgIDKey) |
| 567 | if delErr != nil { |
| 568 | return echConfig{}, fmt.Errorf("error loading ECH config (%v) and cleaning up parent storage key %s: %v", err, cfgIDKey, delErr) |
| 569 | } |
| 570 | logger.Warn("could not load ECH config; deleted its config folder", |
| 571 | zap.String("config_id", configID), |
| 572 | zap.Error(err)) |
| 573 | return echConfig{}, nil |
| 574 | } |
| 575 | metaBytes, err := storage.Load(ctx, metaKey) |
| 576 | if errors.Is(err, fs.ErrNotExist) { |
| 577 | logger.Warn("ECH config metadata file missing; will recreate at next publication", |
| 578 | zap.String("config_id", configID), |
| 579 | zap.Error(err)) |
| 580 | } else if err != nil { |
| 581 | delErr := storage.Delete(ctx, cfgIDKey) |
| 582 | if delErr != nil { |
| 583 | return echConfig{}, fmt.Errorf("error loading ECH config metadata (%v) and cleaning up parent storage key %s: %v", err, cfgIDKey, delErr) |
| 584 | } |
| 585 | logger.Warn("could not load ECH config metadata; deleted its folder", |
| 586 | zap.String("config_id", configID), |
no test coverage detected