@@ -2,13 +2,11 @@ package run
2
2
3
3
import (
4
4
"context"
5
- "crypto/x509"
6
5
"errors"
7
6
"flag"
8
7
"fmt"
9
8
"io"
10
9
"net"
11
- "net/http"
12
10
"net/url"
13
11
"os"
14
12
"os/signal"
@@ -26,18 +24,16 @@ import (
26
24
"github.com/imdario/mergo"
27
25
"github.com/mitchellh/cli"
28
26
"github.com/sirupsen/logrus"
29
- "github.com/spiffe/go-spiffe/v2/spiffeid"
30
27
"github.com/spiffe/spire/pkg/agent"
28
+ "github.com/spiffe/spire/pkg/agent/trustbundlesources"
31
29
"github.com/spiffe/spire/pkg/agent/workloadkey"
32
- "github.com/spiffe/spire/pkg/common/bundleutil"
33
30
"github.com/spiffe/spire/pkg/common/catalog"
34
31
common_cli "github.com/spiffe/spire/pkg/common/cli"
35
32
"github.com/spiffe/spire/pkg/common/config"
36
33
"github.com/spiffe/spire/pkg/common/fflag"
37
34
"github.com/spiffe/spire/pkg/common/health"
38
35
"github.com/spiffe/spire/pkg/common/idutil"
39
36
"github.com/spiffe/spire/pkg/common/log"
40
- "github.com/spiffe/spire/pkg/common/pemutil"
41
37
"github.com/spiffe/spire/pkg/common/telemetry"
42
38
"github.com/spiffe/spire/pkg/common/tlspolicy"
43
39
)
@@ -75,6 +71,8 @@ type agentConfig struct {
75
71
AdminSocketPath string `hcl:"admin_socket_path"`
76
72
InsecureBootstrap bool `hcl:"insecure_bootstrap"`
77
73
RetryBootstrap bool `hcl:"retry_bootstrap"`
74
+ Rebootstrap bool `hcl:"rebootstrap"`
75
+ RebootstrapDelay string `hcl:"rebootstrap_delay"`
78
76
JoinToken string `hcl:"join_token"`
79
77
LogFile string `hcl:"log_file"`
80
78
LogFormat string `hcl:"log_format"`
@@ -353,6 +351,8 @@ func parseFlags(name string, args []string, output io.Writer) (*agentConfig, err
353
351
flags .BoolVar (& c .AllowUnauthenticatedVerifiers , "allowUnauthenticatedVerifiers" , false , "If true, the agent permits the retrieval of X509 certificate bundles by unregistered clients" )
354
352
flags .BoolVar (& c .InsecureBootstrap , "insecureBootstrap" , false , "If true, the agent bootstraps without verifying the server's identity" )
355
353
flags .BoolVar (& c .RetryBootstrap , "retryBootstrap" , false , "If true, the agent retries bootstrap with backoff" )
354
+ flags .BoolVar (& c .Rebootstrap , "rebootstrap" , false , "If true, the agent will retry bootstrapping after seeing an x509 cert mismatch from the server" )
355
+ flags .StringVar (& c .RebootstrapDelay , "rebootstrapDelay" , "10m" , "The time to delay after seeing a x509 cert mismatch from the server before rebootstrapping" )
356
356
flags .BoolVar (& c .ExpandEnv , "expandEnv" , false , "Expand environment variables in SPIRE config file" )
357
357
358
358
c .addOSFlags (flags )
@@ -387,103 +387,6 @@ func mergeInput(fileInput *Config, cliInput *agentConfig) (*Config, error) {
387
387
return c , nil
388
388
}
389
389
390
- func parseTrustBundle (bundleBytes []byte , trustBundleContentType string ) ([]* x509.Certificate , error ) {
391
- switch trustBundleContentType {
392
- case bundleFormatPEM :
393
- bundle , err := pemutil .ParseCertificates (bundleBytes )
394
- if err != nil {
395
- return nil , err
396
- }
397
- return bundle , nil
398
- case bundleFormatSPIFFE :
399
- bundle , err := bundleutil .Unmarshal (spiffeid.TrustDomain {}, bundleBytes )
400
- if err != nil {
401
- return nil , fmt .Errorf ("unable to parse SPIFFE trust bundle: %w" , err )
402
- }
403
- return bundle .X509Authorities (), nil
404
- }
405
-
406
- return nil , fmt .Errorf ("unknown trust bundle format: %s" , trustBundleContentType )
407
- }
408
-
409
- func downloadTrustBundle (trustBundleURL string , trustBundleUnixSocket string ) ([]byte , error ) {
410
- var req * http.Request
411
- client := & http.Client {}
412
- if trustBundleUnixSocket != "" {
413
- client = & http.Client {
414
- Transport : & http.Transport {
415
- DialContext : func (_ context.Context , _ , _ string ) (net.Conn , error ) {
416
- return net .Dial ("unix" , trustBundleUnixSocket )
417
- },
418
- },
419
- }
420
- }
421
- req , err := http .NewRequest ("GET" , trustBundleURL , nil )
422
- if err != nil {
423
- return nil , err
424
- }
425
-
426
- // Download the trust bundle URL from the user specified URL
427
- // We use gosec -- the annotation below will disable a security check that URLs are not tainted
428
- /* #nosec G107 */
429
- resp , err := client .Do (req )
430
- if err != nil {
431
- return nil , fmt .Errorf ("unable to fetch trust bundle URL %s: %w" , trustBundleURL , err )
432
- }
433
-
434
- defer resp .Body .Close ()
435
-
436
- if resp .StatusCode != http .StatusOK {
437
- return nil , fmt .Errorf ("error downloading trust bundle: %s" , resp .Status )
438
- }
439
- pemBytes , err := io .ReadAll (resp .Body )
440
- if err != nil {
441
- return nil , fmt .Errorf ("unable to read from trust bundle URL %s: %w" , trustBundleURL , err )
442
- }
443
-
444
- return pemBytes , nil
445
- }
446
-
447
- func setupTrustBundle (ac * agent.Config , c * Config ) error {
448
- // Either download the trust bundle if TrustBundleURL is set, or read it
449
- // from disk if TrustBundlePath is set
450
- ac .InsecureBootstrap = c .Agent .InsecureBootstrap
451
-
452
- var bundleBytes []byte
453
- var err error
454
-
455
- switch {
456
- case c .Agent .TrustBundleURL != "" :
457
- bundleBytes , err = downloadTrustBundle (c .Agent .TrustBundleURL , c .Agent .TrustBundleUnixSocket )
458
- if err != nil {
459
- return err
460
- }
461
- case c .Agent .TrustBundlePath != "" :
462
- bundleBytes , err = loadTrustBundle (c .Agent .TrustBundlePath )
463
- if err != nil {
464
- return fmt .Errorf ("could not parse trust bundle: %w" , err )
465
- }
466
- default :
467
- // If InsecureBootstrap is configured, the bundle is not required
468
- if ac .InsecureBootstrap {
469
- return nil
470
- }
471
- }
472
-
473
- bundle , err := parseTrustBundle (bundleBytes , c .Agent .TrustBundleFormat )
474
- if err != nil {
475
- return err
476
- }
477
-
478
- if len (bundle ) == 0 {
479
- return errors .New ("no certificates found in trust bundle" )
480
- }
481
-
482
- ac .TrustBundle = bundle
483
-
484
- return nil
485
- }
486
-
487
390
func NewAgentConfig (c * Config , logOptions []log.Option , allowUnknownConfig bool ) (* agent.Config , error ) {
488
391
ac := & agent.Config {}
489
392
@@ -492,6 +395,16 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
492
395
}
493
396
494
397
ac .RetryBootstrap = c .Agent .RetryBootstrap
398
+ if c .Agent .Rebootstrap {
399
+ delay , err := time .ParseDuration (c .Agent .RebootstrapDelay )
400
+ if err != nil {
401
+ return nil , fmt .Errorf ("error parsing duration:" , err )
402
+ }
403
+ ac .RebootstrapDelay = & delay
404
+ if ! ac .RetryBootstrap {
405
+ return nil , fmt .Errorf ("RetryBootstrap needs to be true to support rebootstrapping" )
406
+ }
407
+ }
495
408
496
409
if c .Agent .Experimental .SyncInterval != "" {
497
410
var err error
@@ -575,11 +488,19 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
575
488
}
576
489
ac .DisableSPIFFECertValidation = c .Agent .SDS .DisableSPIFFECertValidation
577
490
578
- err = setupTrustBundle (ac , c )
579
- if err != nil {
580
- return nil , err
491
+ ts := & trustbundlesources.Config {
492
+ InsecureBootstrap : c .Agent .InsecureBootstrap ,
493
+ TrustBundleFormat : c .Agent .TrustBundleFormat ,
494
+ TrustBundlePath : c .Agent .TrustBundlePath ,
495
+ TrustBundleURL : c .Agent .TrustBundleURL ,
496
+ TrustBundleUnixSocket : c .Agent .TrustBundleURL ,
497
+ TrustDomain : c .Agent .TrustDomain ,
498
+ ServerAddress : c .Agent .ServerAddress ,
499
+ ServerPort : c .Agent .ServerPort ,
581
500
}
582
501
502
+ ac .TrustBundleSources = trustbundlesources .New (ts , ac .Log .WithField ("Logger" , "TrustBundleSources" ))
503
+
583
504
ac .WorkloadKeyType = workloadkey .ECP256
584
505
if c .Agent .WorkloadX509SVIDKeyType != "" {
585
506
ac .WorkloadKeyType , err = workloadkey .KeyTypeFromString (c .Agent .WorkloadX509SVIDKeyType )
@@ -737,12 +658,3 @@ func defaultConfig() *Config {
737
658
738
659
return c
739
660
}
740
-
741
- func loadTrustBundle (path string ) ([]byte , error ) {
742
- bundleBytes , err := os .ReadFile (path )
743
- if err != nil {
744
- return nil , err
745
- }
746
-
747
- return bundleBytes , nil
748
- }
0 commit comments