diff --git a/cmd/guaccollect/cmd/gcs.go b/cmd/guaccollect/cmd/gcs.go index bf7c88e71e..b5ee233fd1 100644 --- a/cmd/guaccollect/cmd/gcs.go +++ b/cmd/guaccollect/cmd/gcs.go @@ -20,7 +20,6 @@ import ( type gcsOptions struct { pubSubAddr string blobAddr string - graphqlEndpoint string csubClientOptions csub_client.CsubClientOptions bucket string } @@ -39,7 +38,6 @@ var gcsCmd = &cobra.Command{ opts, err := validateGCSFlags( viper.GetString("pubsub-addr"), viper.GetString("blob-addr"), - viper.GetString("gql-addr"), viper.GetString("csub-addr"), viper.GetString(gcsCredentialsPathFlag), viper.GetBool("csub-tls"), @@ -93,7 +91,6 @@ var gcsCmd = &cobra.Command{ func validateGCSFlags( pubSubAddr, blobAddr, - gqlEndpoint, csubAddr, credentialsPath string, csubTls, @@ -101,9 +98,8 @@ func validateGCSFlags( args []string, ) (gcsOptions, error) { opts := gcsOptions{ - pubSubAddr: pubSubAddr, - blobAddr: blobAddr, - graphqlEndpoint: gqlEndpoint, + pubSubAddr: pubSubAddr, + blobAddr: blobAddr, } csubOpts, err := csub_client.ValidateCsubClientFlags(csubAddr, csubTls, csubTlsSkipVerify) diff --git a/cmd/guaccollect/cmd/s3.go b/cmd/guaccollect/cmd/s3.go index b1b89da922..f83de9f072 100644 --- a/cmd/guaccollect/cmd/s3.go +++ b/cmd/guaccollect/cmd/s3.go @@ -28,7 +28,6 @@ type s3Options struct { mp string // message provider name (sqs or kafka, will default to kafka) mpEndpoint string // endpoint for the message provider (only for polling behaviour) poll bool // polling or non-polling behaviour? (defaults to non-polling) - graphqlEndpoint string // endpoint for the graphql server csubClientOptions csub_client.CsubClientOptions // options for the collectsub client } @@ -64,7 +63,6 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll s3Opts, err := validateS3Opts( viper.GetString("pubsub-addr"), viper.GetString("blob-addr"), - viper.GetString("gql-addr"), viper.GetString("csub-addr"), viper.GetString("s3-url"), viper.GetString("s3-bucket"), @@ -116,7 +114,6 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll func validateS3Opts( pubSubAddr, blobAddr, - graphqlEndpoint, csubAddr, s3url, s3bucket, @@ -162,7 +159,6 @@ func validateS3Opts( mp: mp, mpEndpoint: mpEndpoint, poll: poll, - graphqlEndpoint: graphqlEndpoint, csubClientOptions: csubClientOptions, } diff --git a/cmd/guacingest/cmd/ingest.go b/cmd/guacingest/cmd/ingest.go index ede3a34c64..639c221c24 100644 --- a/cmd/guacingest/cmd/ingest.go +++ b/cmd/guacingest/cmd/ingest.go @@ -18,6 +18,7 @@ package cmd import ( "context" "fmt" + "net/http" "os" "os/signal" "strings" @@ -25,6 +26,7 @@ import ( "syscall" "github.com/guacsec/guac/pkg/blob" + "github.com/guacsec/guac/pkg/cli" "github.com/guacsec/guac/pkg/collectsub/client" csub_client "github.com/guacsec/guac/pkg/collectsub/client" "github.com/guacsec/guac/pkg/emitter" @@ -41,17 +43,18 @@ type options struct { blobAddr string csubClientOptions client.CsubClientOptions graphqlEndpoint string + headerFile string } func ingest(cmd *cobra.Command, args []string) { - opts, err := validateFlags( viper.GetString("pubsub-addr"), viper.GetString("blob-addr"), viper.GetString("csub-addr"), + viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetBool("csub-tls"), viper.GetBool("csub-tls-skip-verify"), - viper.GetString("gql-addr"), args) if err != nil { fmt.Printf("unable to validate flags: %v\n", err) @@ -61,6 +64,7 @@ func ingest(cmd *cobra.Command, args []string) { ctx, cf := context.WithCancel(logging.WithLogger(context.Background())) logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) if strings.HasPrefix(opts.pubsubAddr, "nats://") { // initialize jetstream @@ -90,7 +94,7 @@ func ingest(cmd *cobra.Command, args []string) { defer csubClient.Close() emit := func(d *processor.Document) error { - if err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csubClient); err != nil { + if err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csubClient); err != nil { logger.Errorf("unable to ingest document %q : %v", d.SourceInformation.Source, err) } return nil @@ -116,7 +120,7 @@ func ingest(cmd *cobra.Command, args []string) { wg.Wait() } -func validateFlags(pubsubAddr string, blobAddr string, csubAddr string, csubTls bool, csubTlsSkipVerify bool, graphqlEndpoint string, args []string) (options, error) { +func validateFlags(pubsubAddr, blobAddr, csubAddr, graphqlEndpoint, headerFile string, csubTls, csubTlsSkipVerify bool, args []string) (options, error) { var opts options opts.pubsubAddr = pubsubAddr opts.blobAddr = blobAddr @@ -126,6 +130,7 @@ func validateFlags(pubsubAddr string, blobAddr string, csubAddr string, csubTls } opts.csubClientOptions = csubOpts opts.graphqlEndpoint = graphqlEndpoint + opts.headerFile = headerFile return opts, nil } diff --git a/cmd/guacingest/cmd/root.go b/cmd/guacingest/cmd/root.go index 54c70a8dd4..40fe74a50e 100644 --- a/cmd/guacingest/cmd/root.go +++ b/cmd/guacingest/cmd/root.go @@ -30,7 +30,7 @@ import ( func init() { cobra.OnInitialize(cli.InitConfig) - set, err := cli.BuildFlags([]string{"pubsub-addr", "blob-addr", "csub-addr", "gql-addr"}) + set, err := cli.BuildFlags([]string{"pubsub-addr", "blob-addr", "csub-addr", "gql-addr", "header-file"}) if err != nil { fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) os.Exit(1) diff --git a/cmd/guacone/cmd/bad.go b/cmd/guacone/cmd/bad.go index 72d0eb1c57..ff729df839 100644 --- a/cmd/guacone/cmd/bad.go +++ b/cmd/guacone/cmd/bad.go @@ -57,12 +57,7 @@ var queryBadCmd = &cobra.Command{ os.Exit(1) } - transport, err := cli.NewHTTPHeaderTransport(opts.headerFile, http.DefaultTransport) - if err != nil { - logger.Fatalf("unable to create HTTP transport: %v", err) - } - - httpClient := http.Client{Transport: transport} + httpClient := http.Client{Transport: cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport)} gqlclient := graphql.NewClient(opts.graphqlEndpoint, &httpClient) certifyBadResponse, err := model.CertifyBads(ctx, gqlclient, model.CertifyBadSpec{}) @@ -258,7 +253,7 @@ func validateQueryBadFlags(graphqlEndpoint, headerFile string, depth int) (query } func init() { - set, err := cli.BuildFlags([]string{"header-file", "search-depth"}) + set, err := cli.BuildFlags([]string{"search-depth"}) if err != nil { fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) os.Exit(1) diff --git a/cmd/guacone/cmd/certify.go b/cmd/guacone/cmd/certify.go index 2580b00cad..6be2073280 100644 --- a/cmd/guacone/cmd/certify.go +++ b/cmd/guacone/cmd/certify.go @@ -18,6 +18,7 @@ package cmd import ( "context" "fmt" + "net/http" "os" "strings" "time" @@ -35,6 +36,7 @@ import ( type certifyOptions struct { // gql endpoint graphqlEndpoint string + headerFile string // // certifyBad/certifyGood good bool certifyType string @@ -53,23 +55,24 @@ var certifyCmd = &cobra.Command{ is in the form of "" for package, "+" for source, or ":" for artifact.`, TraverseChildren: true, Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateCertifyFlags( viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetBool("cert-good"), viper.GetBool("package-name"), args, ) - if err != nil { fmt.Printf("unable to validate flags: %v\n", err) _ = cmd.Help() os.Exit(1) } - assemblerFunc := ingestor.GetAssembler(ctx, logger, opts.graphqlEndpoint) + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + + assemblerFunc := ingestor.GetAssembler(ctx, logger, opts.graphqlEndpoint, transport) preds := &assembler.IngestPredicates{} var pkgInput *model.PkgInputSpec @@ -156,9 +159,10 @@ var certifyCmd = &cobra.Command{ }, } -func validateCertifyFlags(graphqlEndpoint string, good, pkgName bool, args []string) (certifyOptions, error) { +func validateCertifyFlags(graphqlEndpoint, headerFile string, good, pkgName bool, args []string) (certifyOptions, error) { var opts certifyOptions opts.graphqlEndpoint = graphqlEndpoint + opts.headerFile = headerFile opts.good = good opts.pkgName = pkgName if len(args) != 3 { diff --git a/cmd/guacone/cmd/deps_dev.go b/cmd/guacone/cmd/deps_dev.go index e8c83d6bda..8d3ea55be4 100644 --- a/cmd/guacone/cmd/deps_dev.go +++ b/cmd/guacone/cmd/deps_dev.go @@ -18,6 +18,7 @@ package cmd import ( "context" "fmt" + "net/http" "os" "os/signal" "sync" @@ -48,15 +49,13 @@ type depsDevOptions struct { retrieveDependencies bool // gql endpoint graphqlEndpoint string + headerFile string } var depsDevCmd = &cobra.Command{ Use: "deps_dev [flags] ...", Short: "takes purls and queries them against deps.dev to find additional metadata to add to GUAC graph utilizing Nats pubsub and blob store", Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, csc, err := validateDepsDevFlags(args) if err != nil { fmt.Printf("unable to validate flags: %v\n", err) @@ -64,6 +63,10 @@ var depsDevCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + // Register collector depsDevCollector, err := deps_dev.NewDepsCollector(ctx, opts.dataSource, opts.poll, opts.retrieveDependencies, 30*time.Second) if err != nil { @@ -80,7 +83,7 @@ var depsDevCmd = &cobra.Command{ emit := func(d *processor.Document) error { totalNum += 1 - if err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csc); err != nil { + if err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csc); err != nil { gotErr = true return fmt.Errorf("unable to ingest document: %w", err) } @@ -135,6 +138,7 @@ func validateDepsDevFlags(args []string) (*depsDevOptions, client.Client, error) poll: viper.GetBool("poll"), retrieveDependencies: viper.GetBool("retrieve-dependencies"), graphqlEndpoint: viper.GetString("gql-addr"), + headerFile: viper.GetString("header-file"), } useCsub := viper.GetBool("use-csub") if useCsub { diff --git a/cmd/guacone/cmd/files.go b/cmd/guacone/cmd/files.go index c9d643d297..9ceea328d6 100644 --- a/cmd/guacone/cmd/files.go +++ b/cmd/guacone/cmd/files.go @@ -19,6 +19,7 @@ import ( "context" "errors" "fmt" + "net/http" "os" "strings" "time" @@ -48,6 +49,7 @@ type fileOptions struct { path string // gql endpoint graphqlEndpoint string + headerFile string // csub client options for identifier strings csubClientOptions client.CsubClientOptions } @@ -56,13 +58,11 @@ var filesCmd = &cobra.Command{ Use: "files [flags] file_path", Short: "take a folder of files and create a GUAC graph, this command talks directly to the graphQL endpoint", Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateFilesFlags( viper.GetString("verifier-key-path"), viper.GetString("verifier-key-id"), viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetString("csub-addr"), viper.GetBool("csub-tls"), viper.GetBool("csub-tls-skip-verify"), @@ -73,6 +73,10 @@ var filesCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + // Register Keystore inmemory := inmemory.NewInmemoryProvider() err = key.RegisterKeyProvider(inmemory, inmemory.Type()) @@ -122,7 +126,7 @@ var filesCmd = &cobra.Command{ emit := func(d *processor.Document) error { totalNum += 1 - if err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csubClient); err != nil { + if err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csubClient); err != nil { gotErr = true filesWithErrors = append(filesWithErrors, d.SourceInformation.Source) return fmt.Errorf("unable to ingest document: %w", err) @@ -154,9 +158,10 @@ var filesCmd = &cobra.Command{ }, } -func validateFilesFlags(keyPath string, keyID string, graphqlEndpoint string, csubAddr string, csubTls bool, csubTlsSkipVerify bool, args []string) (fileOptions, error) { +func validateFilesFlags(keyPath, keyID, graphqlEndpoint, headerFile, csubAddr string, csubTls, csubTlsSkipVerify bool, args []string) (fileOptions, error) { var opts fileOptions opts.graphqlEndpoint = graphqlEndpoint + opts.headerFile = headerFile if keyPath != "" { if strings.HasSuffix(keyPath, "pem") { diff --git a/cmd/guacone/cmd/gcs.go b/cmd/guacone/cmd/gcs.go index 847d7bc9d9..d2ca3bc5cc 100644 --- a/cmd/guacone/cmd/gcs.go +++ b/cmd/guacone/cmd/gcs.go @@ -18,6 +18,7 @@ package cmd import ( "context" "fmt" + "net/http" "os" "cloud.google.com/go/storage" @@ -37,6 +38,7 @@ import ( type gcsOptions struct { graphqlEndpoint string + headerFile string csubClientOptions client.CsubClientOptions bucket string } @@ -49,15 +51,13 @@ var gcsCmd = &cobra.Command{ Example: "guacone collect gcs my-bucket --gcs-credentials-path /secret/sa.json", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateGCSFlags( viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetString("csub-addr"), + viper.GetString(gcsCredentialsPathFlag), viper.GetBool("csub-tls"), viper.GetBool("csub-tls-skip-verify"), - viper.GetString(gcsCredentialsPathFlag), args) if err != nil { fmt.Printf("unable to validate flags: %v\n", err) @@ -65,6 +65,10 @@ var gcsCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + gcsOpts := []option.ClientOption{ option.WithUserAgent(version.UserAgent), } @@ -105,7 +109,7 @@ var gcsCmd = &cobra.Command{ emit := func(d *processor.Document) error { totalNum += 1 - err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csubClient) + err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csubClient) if err != nil { gotErr = true @@ -135,9 +139,10 @@ var gcsCmd = &cobra.Command{ }, } -func validateGCSFlags(gqlEndpoint string, csubAddr string, csubTls bool, csubTlsSkipVerify bool, credentialsPath string, args []string) (gcsOptions, error) { +func validateGCSFlags(gqlEndpoint, headerFile, csubAddr, credentialsPath string, csubTls, csubTlsSkipVerify bool, args []string) (gcsOptions, error) { var opts gcsOptions opts.graphqlEndpoint = gqlEndpoint + opts.headerFile = headerFile csubOpts, err := client.ValidateCsubClientFlags(csubAddr, csubTls, csubTlsSkipVerify) if err != nil { diff --git a/cmd/guacone/cmd/gcs_test.go b/cmd/guacone/cmd/gcs_test.go index c4e9594d15..cb41774976 100644 --- a/cmd/guacone/cmd/gcs_test.go +++ b/cmd/guacone/cmd/gcs_test.go @@ -62,7 +62,7 @@ func TestValidateGCSFlags(t *testing.T) { t.Setenv("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/creds.json") } - o, err := validateGCSFlags("", "", false, false, tc.credentialsPath, tc.args) + o, err := validateGCSFlags("", "", "", tc.credentialsPath, false, false, tc.args) if err != nil { if tc.errorMsg != err.Error() { t.Errorf("expected error message: %s, got: %s", tc.errorMsg, err.Error()) diff --git a/cmd/guacone/cmd/github.go b/cmd/guacone/cmd/github.go index 94df8a8179..b4074b8420 100644 --- a/cmd/guacone/cmd/github.go +++ b/cmd/guacone/cmd/github.go @@ -18,16 +18,20 @@ package cmd import ( "context" "fmt" - "github.com/guacsec/guac/pkg/cli" - "github.com/guacsec/guac/pkg/collectsub/datasource/csubsource" - "github.com/guacsec/guac/pkg/handler/processor" - "github.com/guacsec/guac/pkg/ingestor" + "net/http" "os" "strings" "sync" "syscall" "time" + "github.com/guacsec/guac/pkg/cli" + "github.com/guacsec/guac/pkg/collectsub/datasource/csubsource" + "github.com/guacsec/guac/pkg/handler/processor" + "github.com/guacsec/guac/pkg/ingestor" + + "os/signal" + "github.com/guacsec/guac/internal/client/githubclient" "github.com/guacsec/guac/pkg/collectsub/client" csubclient "github.com/guacsec/guac/pkg/collectsub/client" @@ -38,7 +42,6 @@ import ( "github.com/guacsec/guac/pkg/logging" "github.com/spf13/cobra" "github.com/spf13/viper" - "os/signal" ) const ( @@ -64,6 +67,7 @@ type githubOptions struct { csubClientOptions client.CsubClientOptions // graphql endpoint graphqlEndpoint string + headerFile string } var githubCmd = &cobra.Command{ @@ -73,10 +77,9 @@ var githubCmd = &cobra.Command{ if is "release" then [flags] release_url1 release_url2..., otherwise if is "workflow" then [flags] /.`, Args: cobra.MinimumNArgs(0), Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateGithubFlags( + viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetString(githubMode), viper.GetString(githubSbom), viper.GetString(githubWorkflowFile), @@ -92,6 +95,10 @@ var githubCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + // GITHUB_TOKEN is the default token name ghc, err := githubclient.NewGithubClient(ctx, os.Getenv("GITHUB_TOKEN")) if err != nil { @@ -145,7 +152,7 @@ var githubCmd = &cobra.Command{ var errFound bool emit := func(d *processor.Document) error { - err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csubClient) + err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csubClient) if err != nil { errFound = true @@ -198,8 +205,10 @@ var githubCmd = &cobra.Command{ }, } -func validateGithubFlags(githubMode, sbomName, workflowFileName, csubAddr string, csubTls, csubTlsSkipVerify, useCsub, poll bool, args []string) (githubOptions, error) { +func validateGithubFlags(graphqlEndpoint, headerFile, githubMode, sbomName, workflowFileName, csubAddr string, csubTls, csubTlsSkipVerify, useCsub, poll bool, args []string) (githubOptions, error) { var opts githubOptions + opts.graphqlEndpoint = graphqlEndpoint + opts.headerFile = headerFile opts.poll = poll opts.githubMode = githubMode opts.sbomName = sbomName diff --git a/cmd/guacone/cmd/known.go b/cmd/guacone/cmd/known.go index d6fce65634..f31ba7e27a 100644 --- a/cmd/guacone/cmd/known.go +++ b/cmd/guacone/cmd/known.go @@ -102,12 +102,7 @@ var queryKnownCmd = &cobra.Command{ os.Exit(1) } - transport, err := cli.NewHTTPHeaderTransport(opts.headerFile, http.DefaultTransport) - if err != nil { - logger.Fatalf("unable to create HTTP transport: %v", err) - } - - httpClient := http.Client{Transport: transport} + httpClient := http.Client{Transport: cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport)} gqlclient := graphql.NewClient(opts.graphqlEndpoint, &httpClient) t := table.NewWriter() @@ -472,16 +467,5 @@ func validateQueryKnownFlags(graphqlEndpoint, headerFile string, args []string) } func init() { - set, err := cli.BuildFlags([]string{"header-file"}) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) - os.Exit(1) - } - queryKnownCmd.Flags().AddFlagSet(set) - if err := viper.BindPFlags(queryKnownCmd.Flags()); err != nil { - fmt.Fprintf(os.Stderr, "failed to bind flags: %v", err) - os.Exit(1) - } - queryCmd.AddCommand(queryKnownCmd) } diff --git a/cmd/guacone/cmd/oci.go b/cmd/guacone/cmd/oci.go index 5127670ebe..1da5629bdb 100644 --- a/cmd/guacone/cmd/oci.go +++ b/cmd/guacone/cmd/oci.go @@ -18,9 +18,11 @@ package cmd import ( "context" "fmt" + "net/http" "os" "time" + "github.com/guacsec/guac/pkg/cli" "github.com/guacsec/guac/pkg/collectsub/client" csub_client "github.com/guacsec/guac/pkg/collectsub/client" "github.com/guacsec/guac/pkg/collectsub/datasource" @@ -37,6 +39,7 @@ import ( type ociOptions struct { graphqlEndpoint string + headerFile string dataSource datasource.CollectSource csubClientOptions client.CsubClientOptions } @@ -46,11 +49,9 @@ var ociCmd = &cobra.Command{ Short: "takes images to download sbom and attestation stored in OCI to add to GUAC graph, this command talks directly to the graphQL endpoint", Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateOCIFlags( viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetString("csub-addr"), viper.GetBool("csub-tls"), viper.GetBool("csub-tls-skip-verify"), @@ -61,6 +62,10 @@ var ociCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + // Register collector ociCollector := oci.NewOCICollector(ctx, opts.dataSource, false, 10*time.Minute) err = collector.RegisterDocumentCollector(ociCollector, oci.OCICollector) @@ -82,7 +87,7 @@ var ociCmd = &cobra.Command{ // Set emit function to go through the entire pipeline emit := func(d *processor.Document) error { totalNum += 1 - err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csubClient) + err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csubClient) if err != nil { gotErr = true @@ -112,9 +117,10 @@ var ociCmd = &cobra.Command{ }, } -func validateOCIFlags(gqlEndpoint string, csubAddr string, csubTls bool, csubTlsSkipVerify bool, args []string) (ociOptions, error) { +func validateOCIFlags(gqlEndpoint, headerFile, csubAddr string, csubTls, csubTlsSkipVerify bool, args []string) (ociOptions, error) { var opts ociOptions opts.graphqlEndpoint = gqlEndpoint + opts.headerFile = headerFile csubOpts, err := client.ValidateCsubClientFlags(csubAddr, csubTls, csubTlsSkipVerify) if err != nil { diff --git a/cmd/guacone/cmd/osv.go b/cmd/guacone/cmd/osv.go index 220c346e5a..fd075b1475 100644 --- a/cmd/guacone/cmd/osv.go +++ b/cmd/guacone/cmd/osv.go @@ -53,9 +53,6 @@ var osvCmd = &cobra.Command{ Use: "osv [flags]", Short: "runs the osv certifier", Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateOSVFlags( viper.GetString("gql-addr"), viper.GetString("header-file"), @@ -71,6 +68,10 @@ var osvCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + if err := certify.RegisterCertifier(osv.NewOSVCertificationParser, certifier.CertifierOSV); err != nil { logger.Fatalf("unable to register certifier: %v", err) } @@ -84,11 +85,6 @@ var osvCmd = &cobra.Command{ defer csubClient.Close() } - transport, err := cli.NewHTTPHeaderTransport(opts.headerFile, http.DefaultTransport) - if err != nil { - logger.Fatalf("unable to create HTTP transport: %v", err) - } - httpClient := http.Client{Transport: transport} gqlclient := graphql.NewClient(opts.graphqlEndpoint, &httpClient) packageQuery := root_package.NewPackageQuery(gqlclient, 0) @@ -110,7 +106,7 @@ var osvCmd = &cobra.Command{ select { case <-ticker.C: if len(totalDocs) > 0 { - err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, csubClient) + err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, transport, csubClient) if err != nil { stop = true atomic.StoreInt32(&gotErr, 1) @@ -123,7 +119,7 @@ var osvCmd = &cobra.Command{ totalNum += 1 totalDocs = append(totalDocs, d) if len(totalDocs) >= threshold { - err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, csubClient) + err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, transport, csubClient) if err != nil { stop = true atomic.StoreInt32(&gotErr, 1) @@ -142,7 +138,7 @@ var osvCmd = &cobra.Command{ totalNum += 1 totalDocs = append(totalDocs, <-docChan) if len(totalDocs) >= threshold { - err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, csubClient) + err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, transport, csubClient) if err != nil { atomic.StoreInt32(&gotErr, 1) logger.Errorf("unable to ingest documents: %v", err) @@ -151,7 +147,7 @@ var osvCmd = &cobra.Command{ } } if len(totalDocs) > 0 { - err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, csubClient) + err = ingestor.MergedIngest(ctx, totalDocs, opts.graphqlEndpoint, transport, csubClient) if err != nil { atomic.StoreInt32(&gotErr, 1) logger.Errorf("unable to ingest documents: %v", err) @@ -239,16 +235,5 @@ func validateOSVFlags( } func init() { - set, err := cli.BuildFlags([]string{"header-file"}) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) - os.Exit(1) - } - osvCmd.Flags().AddFlagSet(set) - if err := viper.BindPFlags(osvCmd.Flags()); err != nil { - fmt.Fprintf(os.Stderr, "failed to bind flags: %v", err) - os.Exit(1) - } - certifierCmd.AddCommand(osvCmd) } diff --git a/cmd/guacone/cmd/patch.go b/cmd/guacone/cmd/patch.go index 5f49f8c691..3137a858d5 100644 --- a/cmd/guacone/cmd/patch.go +++ b/cmd/guacone/cmd/patch.go @@ -62,12 +62,7 @@ var queryPatchCmd = &cobra.Command{ logger.Fatalf("unable to validate flags: %s\n", err) } - transport, err := cli.NewHTTPHeaderTransport(opts.headerFile, http.DefaultTransport) - if err != nil { - logger.Fatalf("unable to create HTTP transport: %v", err) - } - - httpClient := http.Client{Transport: transport} + httpClient := http.Client{Transport: cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport)} gqlClient := graphql.NewClient(opts.graphqlEndpoint, &httpClient) var startID string @@ -304,7 +299,6 @@ func validateQueryPatchFlags( func init() { set, err := cli.BuildFlags([]string{ - "header-file", "start-purl", "stop-purl", "search-depth", diff --git a/cmd/guacone/cmd/root.go b/cmd/guacone/cmd/root.go index a56e8ddd11..b6ca9c1f8a 100644 --- a/cmd/guacone/cmd/root.go +++ b/cmd/guacone/cmd/root.go @@ -30,7 +30,7 @@ import ( func init() { cobra.OnInitialize(cli.InitConfig) - set, err := cli.BuildFlags([]string{"gql-addr", "csub-addr", "csub-tls", "csub-tls-skip-verify"}) + set, err := cli.BuildFlags([]string{"gql-addr", "header-file", "csub-addr", "csub-tls", "csub-tls-skip-verify"}) if err != nil { fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) os.Exit(1) diff --git a/cmd/guacone/cmd/s3.go b/cmd/guacone/cmd/s3.go index 6a6f93abd2..bde8d540a1 100644 --- a/cmd/guacone/cmd/s3.go +++ b/cmd/guacone/cmd/s3.go @@ -18,6 +18,7 @@ package cmd import ( "context" "fmt" + "net/http" "os" "os/signal" "sync" @@ -36,15 +37,16 @@ import ( // s3Options flags for configuring the command type s3Options struct { - s3url string // base url of the s3 to collect from - s3bucket string // name of bucket to collect from - s3item string // s3 item (only for non-polling behaviour) - region string // AWS region, for s3/sqs configuration (defaults to us-east-1) - queues string // comma-separated list of queues/topics (only for polling behaviour) - mp string // message provider name (sqs or kafka, will default to kafka) - mpEndpoint string // endpoint for the message provider (only for polling behaviour) - poll bool // polling or non-polling behaviour? (defaults to non-polling) - graphqlEndpoint string // endpoint for the graphql server + s3url string // base url of the s3 to collect from + s3bucket string // name of bucket to collect from + s3item string // s3 item (only for non-polling behaviour) + region string // AWS region, for s3/sqs configuration (defaults to us-east-1) + queues string // comma-separated list of queues/topics (only for polling behaviour) + mp string // message provider name (sqs or kafka, will default to kafka) + mpEndpoint string // endpoint for the message provider (only for polling behaviour) + poll bool // polling or non-polling behaviour? (defaults to non-polling) + graphqlEndpoint string // endpoint for the graphql server + headerFile string csubClientOptions csub_client.CsubClientOptions // options for the collectsub client } @@ -74,14 +76,10 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll `, Args: cobra.MinimumNArgs(0), Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - s3Opts, err := validateS3Opts( viper.GetString("gql-addr"), + viper.GetString("header-file"), viper.GetString("csub-addr"), - viper.GetBool("csub-tls"), - viper.GetBool("csub-tls-skip-verify"), viper.GetString("s3-url"), viper.GetString("s3-bucket"), viper.GetString("s3-region"), @@ -89,6 +87,8 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll viper.GetString("s3-mp"), viper.GetString("s3-mp-endpoint"), viper.GetString("s3-queues"), + viper.GetBool("csub-tls"), + viper.GetBool("csub-tls-skip-verify"), viper.GetBool("poll"), ) if err != nil { @@ -97,6 +97,10 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, s3Opts.headerFile, http.DefaultTransport) + signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) @@ -126,7 +130,7 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll errFound := false emit := func(d *processor.Document) error { - err := ingestor.Ingest(ctx, d, s3Opts.graphqlEndpoint, csubClient) + err := ingestor.Ingest(ctx, d, s3Opts.graphqlEndpoint, transport, csubClient) if err != nil { errFound = true @@ -172,7 +176,7 @@ $ guacone collect s3 --s3-url http://localhost:9000 --s3-bucket guac-test --poll }, } -func validateS3Opts(graphqlEndpoint string, csubAddr string, csubTls bool, csubTlsSkipVerify bool, s3url string, s3bucket string, region string, s3item string, mp string, mpEndpoint string, queues string, poll bool) (s3Options, error) { +func validateS3Opts(graphqlEndpoint, headerFile, csubAddr, s3url, s3bucket, region, s3item, mp, mpEndpoint, queues string, csubTls, csubTlsSkipVerify, poll bool) (s3Options, error) { var opts s3Options if poll { @@ -195,7 +199,7 @@ func validateS3Opts(graphqlEndpoint string, csubAddr string, csubTls bool, csubT return opts, fmt.Errorf("unable to validate csub client flags: %w", err) } - opts = s3Options{s3url, s3bucket, s3item, region, queues, mp, mpEndpoint, poll, graphqlEndpoint, csubClientOptions} + opts = s3Options{s3url, s3bucket, s3item, region, queues, mp, mpEndpoint, poll, graphqlEndpoint, headerFile, csubClientOptions} return opts, nil } diff --git a/cmd/guacone/cmd/scorecard.go b/cmd/guacone/cmd/scorecard.go index ac54cbfa0a..8c6642917c 100644 --- a/cmd/guacone/cmd/scorecard.go +++ b/cmd/guacone/cmd/scorecard.go @@ -54,9 +54,6 @@ var scorecardCmd = &cobra.Command{ Use: "scorecard [flags]", Short: "runs the scorecard certifier", Run: func(cmd *cobra.Command, args []string) { - ctx := logging.WithLogger(context.Background()) - logger := logging.FromContext(ctx) - opts, err := validateScorecardFlags( viper.GetString("gql-addr"), viper.GetString("header-file"), @@ -72,6 +69,10 @@ var scorecardCmd = &cobra.Command{ os.Exit(1) } + ctx := logging.WithLogger(context.Background()) + logger := logging.FromContext(ctx) + transport := cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport) + // scorecard runner is the scorecard library that runs the scorecard checks scorecardRunner, err := scorecard.NewScorecardRunner(ctx) if err != nil { @@ -89,11 +90,6 @@ var scorecardCmd = &cobra.Command{ defer csubClient.Close() } - transport, err := cli.NewHTTPHeaderTransport(opts.headerFile, http.DefaultTransport) - if err != nil { - logger.Fatalf("unable to create HTTP transport: %v", err) - } - httpClient := http.Client{Transport: transport} gqlclient := graphql.NewClient(opts.graphqlEndpoint, &httpClient) @@ -128,7 +124,7 @@ var scorecardCmd = &cobra.Command{ // Set emit function to go through the entire pipeline emit := func(d *processor.Document) error { totalNum += 1 - err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, csubClient) + err := ingestor.Ingest(ctx, d, opts.graphqlEndpoint, transport, csubClient) if err != nil { return fmt.Errorf("unable to ingest document: %v", err) @@ -207,16 +203,5 @@ func validateScorecardFlags( } func init() { - set, err := cli.BuildFlags([]string{"header-file"}) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) - os.Exit(1) - } - scorecardCmd.Flags().AddFlagSet(set) - if err := viper.BindPFlags(scorecardCmd.Flags()); err != nil { - fmt.Fprintf(os.Stderr, "failed to bind flags: %v", err) - os.Exit(1) - } - certifierCmd.AddCommand(scorecardCmd) } diff --git a/cmd/guacone/cmd/vulnerability.go b/cmd/guacone/cmd/vulnerability.go index 0d08fd352e..05671ea574 100644 --- a/cmd/guacone/cmd/vulnerability.go +++ b/cmd/guacone/cmd/vulnerability.go @@ -18,7 +18,6 @@ package cmd import ( "context" "fmt" - "log" "net/http" "os" "strings" @@ -69,12 +68,7 @@ var queryVulnCmd = &cobra.Command{ os.Exit(1) } - transport, err := cli.NewHTTPHeaderTransport(opts.headerFile, http.DefaultTransport) - if err != nil { - log.Fatalf("unable to create HTTP transport: %v", err) - } - - httpClient := http.Client{Transport: transport} + httpClient := http.Client{Transport: cli.HTTPHeaderTransport(ctx, opts.headerFile, http.DefaultTransport)} gqlclient := graphql.NewClient(opts.graphqlEndpoint, &httpClient) t := table.NewWriter() @@ -667,7 +661,7 @@ func validateQueryVulnFlags(graphqlEndpoint, headerFile, vulnID string, depth, p } func init() { - set, err := cli.BuildFlags([]string{"header-file", "vuln-id", "search-depth", "num-path"}) + set, err := cli.BuildFlags([]string{"vuln-id", "search-depth", "num-path"}) if err != nil { fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err) os.Exit(1) diff --git a/cmd/guacrest/cmd/server.go b/cmd/guacrest/cmd/server.go index 5a44e14abb..664e6e374f 100644 --- a/cmd/guacrest/cmd/server.go +++ b/cmd/guacrest/cmd/server.go @@ -37,12 +37,7 @@ func startServer() { ctx := logging.WithLogger(context.Background()) logger := logging.FromContext(ctx) - transport, err := cli.NewHTTPHeaderTransport(flags.headerFile, http.DefaultTransport) - if err != nil { - logger.Fatalf("unable to create HTTP transport: %+v", err) - } - - httpClient := &http.Client{Transport: transport} + httpClient := &http.Client{Transport: cli.HTTPHeaderTransport(ctx, flags.headerFile, http.DefaultTransport)} gqlClient := getGraphqlServerClientOrExit(ctx, httpClient) restApiHandler := gen.Handler(gen.NewStrictHandler(server.NewDefaultServer(gqlClient), nil)) diff --git a/pkg/cli/headers.go b/pkg/cli/headers.go index f47b01b167..96160e9546 100644 --- a/pkg/cli/headers.go +++ b/pkg/cli/headers.go @@ -15,10 +15,12 @@ package cli import ( + "context" "net/http" "os" "github.com/ProtonMail/gluon/rfc822" + "github.com/guacsec/guac/pkg/logging" ) type httpHeaderTransport struct { @@ -26,19 +28,21 @@ type httpHeaderTransport struct { http.RoundTripper } -func NewHTTPHeaderTransport(filename string, transport http.RoundTripper) (http.RoundTripper, error) { +func HTTPHeaderTransport(ctx context.Context, filename string, transport http.RoundTripper) http.RoundTripper { if filename == "" { - return transport, nil + return transport } + logger := logging.FromContext(ctx) + b, err := os.ReadFile(filename) if err != nil { - return nil, err + logger.Fatalf("error reading header file: %v", err) } rh, err := rfc822.NewHeader(b) if err != nil { - return nil, err + logger.Fatalf("error parsing header file: %v", err) } h := make(map[string][]string) @@ -46,7 +50,7 @@ func NewHTTPHeaderTransport(filename string, transport http.RoundTripper) (http. h[k] = append(h[k], v) }) - return &httpHeaderTransport{h, transport}, nil + return &httpHeaderTransport{h, transport} } func (t *httpHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error) { diff --git a/pkg/cli/headers_test.go b/pkg/cli/headers_test.go index b81011575d..b60aec7996 100644 --- a/pkg/cli/headers_test.go +++ b/pkg/cli/headers_test.go @@ -15,18 +15,23 @@ package cli import ( + "context" "net/http" "net/http/httptest" "testing" + "github.com/guacsec/guac/pkg/logging" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) -func TestNewHTTPHeaderTransport(t *testing.T) { +func TestHTTPHeaderTransport(t *testing.T) { type test struct { name string headerFile string - wantErr string + wantErr any wantHeaders map[string][]string } @@ -34,7 +39,7 @@ func TestNewHTTPHeaderTransport(t *testing.T) { { name: "creating a header transport with a non-existent file results in an error", headerFile: "does-not-exist.txt", - wantErr: "open does-not-exist.txt: no such file or directory", + wantErr: "error reading header file: open does-not-exist.txt: no such file or directory", }, { name: "creating a header transport with a valid RFC 822 header file works", @@ -54,21 +59,35 @@ func TestNewHTTPHeaderTransport(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - transport, err := NewHTTPHeaderTransport(test.headerFile, http.DefaultTransport) - if err != nil { - if err.Error() == test.wantErr { - return - } else if test.wantErr == "" { - t.Fatalf("did not want an error, but got %v", err) - } + // The zap.WithFatalHook value WriteThenPanic makes it so that instead of + // exiting on .Fatal() calls, the logger panics. You can recover from these + // panics in a goroutine, and this makes it possible to test such cases. + logging.InitLogger(logging.Debug, zap.WithFatalHook(zapcore.WriteThenPanic)) + ctx := logging.WithLogger(context.Background()) - t.Fatalf("want error %s, but got %v", test.wantErr, err) - } + var transport http.RoundTripper + recovered := make(chan any) + finished := false + + go func() { + defer func() { + recovered <- recover() + }() + + transport = HTTPHeaderTransport(ctx, test.headerFile, http.DefaultTransport) - if test.wantErr != "" { - t.Fatalf("want error %s, but got %v", test.wantErr, err) + finished = true + }() + + require.Equal(t, test.wantErr, <-recovered, "fatal error message") + + if test.wantErr != nil { + assert.False(t, finished, "call did not finish") + return } + assert.True(t, finished, "call finished") + var gotHeaders map[string][]string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotHeaders = r.Header @@ -77,12 +96,12 @@ func TestNewHTTPHeaderTransport(t *testing.T) { client := http.Client{Transport: transport} - _, err = client.Get(srv.URL) + _, err := client.Get(srv.URL) if err != nil { t.Fatalf("error making test server request: %+v", err) } - assert.Equalf(t, test.wantHeaders, gotHeaders, "headers as expected") + assert.Equalf(t, test.wantHeaders, gotHeaders, "headers") }) } } diff --git a/pkg/ingestor/ingestor.go b/pkg/ingestor/ingestor.go index 34b74dd7ee..df3848be1e 100644 --- a/pkg/ingestor/ingestor.go +++ b/pkg/ingestor/ingestor.go @@ -18,10 +18,11 @@ package ingestor import ( "context" "fmt" - "go.uber.org/zap" "net/http" "time" + "go.uber.org/zap" + "github.com/Khan/genqlient/graphql" "github.com/guacsec/guac/pkg/assembler" "github.com/guacsec/guac/pkg/assembler/clients/helpers" @@ -35,13 +36,19 @@ import ( ) // Synchronously ingest document using GraphQL endpoint -func Ingest(ctx context.Context, d *processor.Document, graphqlEndpoint string, csubClient csub_client.Client) error { +func Ingest( + ctx context.Context, + d *processor.Document, + graphqlEndpoint string, + transport http.RoundTripper, + csubClient csub_client.Client, +) error { logger := d.ChildLogger // Get pipeline of components processorFunc := GetProcessor(ctx) ingestorFunc := GetIngestor(ctx) collectSubEmitFunc := GetCollectSubEmit(ctx, csubClient) - assemblerFunc := GetAssembler(ctx, d.ChildLogger, graphqlEndpoint) + assemblerFunc := GetAssembler(ctx, d.ChildLogger, graphqlEndpoint, transport) start := time.Now() @@ -69,13 +76,19 @@ func Ingest(ctx context.Context, d *processor.Document, graphqlEndpoint string, return nil } -func MergedIngest(ctx context.Context, docs []*processor.Document, graphqlEndpoint string, csubClient csub_client.Client) error { +func MergedIngest( + ctx context.Context, + docs []*processor.Document, + graphqlEndpoint string, + transport http.RoundTripper, + csubClient csub_client.Client, +) error { logger := logging.FromContext(ctx) // Get pipeline of components processorFunc := GetProcessor(ctx) ingestorFunc := GetIngestor(ctx) collectSubEmitFunc := GetCollectSubEmit(ctx, csubClient) - assemblerFunc := GetAssembler(ctx, logger, graphqlEndpoint) + assemblerFunc := GetAssembler(ctx, logger, graphqlEndpoint, transport) start := time.Now() @@ -152,8 +165,13 @@ func GetIngestor(ctx context.Context) func(processor.DocumentTree) ([]assembler. } } -func GetAssembler(ctx context.Context, childLogger *zap.SugaredLogger, graphqlEndpoint string) func([]assembler.IngestPredicates) error { - httpClient := http.Client{} +func GetAssembler( + ctx context.Context, + childLogger *zap.SugaredLogger, + graphqlEndpoint string, + transport http.RoundTripper, +) func([]assembler.IngestPredicates) error { + httpClient := http.Client{Transport: transport} gqlclient := graphql.NewClient(graphqlEndpoint, &httpClient) f := helpers.GetBulkAssembler(ctx, childLogger, gqlclient) return f diff --git a/pkg/logging/logger.go b/pkg/logging/logger.go index 9182db2a95..f02c71fdd2 100644 --- a/pkg/logging/logger.go +++ b/pkg/logging/logger.go @@ -18,9 +18,10 @@ package logging import ( "context" "fmt" - "github.com/guacsec/guac/pkg/version" "strings" + "github.com/guacsec/guac/pkg/version" + "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -48,7 +49,7 @@ const ( type loggerKey struct{} // Initializes the logger with the input level, defaulting to Info if the input is invalid -func InitLogger(level LogLevel) { +func InitLogger(level LogLevel, opts ...zap.Option) { zapLevel, levelErr := zapcore.ParseLevel(string(level)) if levelErr != nil { zapLevel = zapcore.InfoLevel @@ -69,7 +70,7 @@ func InitLogger(level LogLevel) { _ = zapLogger.Sync() }() - logger = zapLogger.Sugar().With(guacVersion, version.Version) + logger = zapLogger.Sugar().With(guacVersion, version.Version).WithOptions(opts...) if levelErr != nil { logger.Infof("Invalid log level %s: ", level, levelErr)