From 37aa3fec18324ea32e9897d1d36fc8f40db4b5ff Mon Sep 17 00:00:00 2001 From: Josh Dolitsky Date: Wed, 5 Jan 2022 14:42:57 -0600 Subject: [PATCH] Enable server settings via config file and env vars Modify the viper settings in the serve subcommand to allow users to provide a config file using -c/--config vs. setting everything using command line flags. Sinc this is based upon viper, the following config file extensions are supported: "json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", and "ini". This change also allows using env vars prefixed with FULCIO_SERVE to provide configuration settings as well. Resolves #314 Signed-off-by: Josh Dolitsky --- .github/workflows/verify-k8s.yml | 17 ++++++---- cmd/app/serve.go | 57 +++++++++++++++++++++++++++++--- config/deployment.yaml | 7 ++-- config/fulcio-config.yaml | 7 ++++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/.github/workflows/verify-k8s.yml b/.github/workflows/verify-k8s.yml index 03dbef87f..480ea4116 100644 --- a/.github/workflows/verify-k8s.yml +++ b/.github/workflows/verify-k8s.yml @@ -136,10 +136,6 @@ jobs: # Reduce the resource requests of Fulcio sed -i -e 's,memory: "1G",memory: "100m",g' ${{ github.workspace }}/config/deployment.yaml sed -i -e 's,cpu: ".5",cpu: "50m",g' ${{ github.workspace }}/config/deployment.yaml - # Switch to the ephemeralca for testing. - sed -i -e 's,--ca=googleca,--ca=ephemeralca,g' ${{ github.workspace }}/config/deployment.yaml - # Drop the ct-log flag's value to elide CT-log uploads. - sed -i -E 's,"--ct-log-url=[^"]+","--ct-log-url=",g' ${{ github.workspace }}/config/deployment.yaml # Switch to one replica to make it easier to test the scraping of # metrics since we know all the requests then go to the same server. sed -i -E 's,replicas: 3,replicas: 1,g' ${{ github.workspace }}/config/deployment.yaml @@ -171,9 +167,16 @@ jobs: namespace: fulcio-dev data: config.json: |- - { - ${{ matrix.issuer-config }} - } + { + ${{ matrix.issuer-config }} + } + server.yaml: |- + host: 0.0.0.0 + port: 5555 + ca: ephemeralca + gcp_private_ca_version: v1 + ct-log-url: "" + log_type: prod EOF kubectl create ns fulcio-dev diff --git a/cmd/app/serve.go b/cmd/app/serve.go index 2c4a9fbe9..4f39f8406 100644 --- a/cmd/app/serve.go +++ b/cmd/app/serve.go @@ -19,7 +19,11 @@ import ( "flag" "fmt" "net/http" + "os" + "path/filepath" + "strings" + "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sigstore/fulcio/pkg/api" certauth "github.com/sigstore/fulcio/pkg/ca" @@ -34,6 +38,10 @@ import ( "github.com/spf13/viper" ) +const serveCmdEnvPrefix = "FULCIO_SERVE" + +var serveCmdConfigFilePath string + func newServeCmd() *cobra.Command { cmd := &cobra.Command{ Use: "serve", @@ -42,6 +50,7 @@ func newServeCmd() *cobra.Command { Run: runServeCmd, } + cmd.Flags().StringVarP(&serveCmdConfigFilePath, "config", "c", "", "config file containing all settings") cmd.Flags().String("log_type", "dev", "logger type to use (dev/prod)") cmd.Flags().String("ca", "", "googleca | pkcs11ca | fileca | ephemeralca (for testing)") cmd.Flags().String("aws-hsm-root-ca-path", "", "Path to root CA on disk (only used with AWS HSM)") @@ -58,20 +67,27 @@ func newServeCmd() *cobra.Command { cmd.Flags().String("host", "0.0.0.0", "The host on which to serve requests") cmd.Flags().String("port", "8080", "The port on which to serve requests") - err := cmd.MarkFlagRequired("ca") - if err != nil { - log.Logger.Fatal(`Failed to mark flag as required`) - } - return cmd } func runServeCmd(cmd *cobra.Command, args []string) { + // If a config file is provided, modify the viper config to locate and read it + if err := checkServeCmdConfigFile(); err != nil { + log.Logger.Fatal(err) + } + if err := viper.BindPFlags(cmd.Flags()); err != nil { log.Logger.Fatal(err) } + // Allow recognition of environment variables such as FULCIO_SERVE_CA etc. + viper.SetEnvPrefix(serveCmdEnvPrefix) + viper.AutomaticEnv() + switch viper.GetString("ca") { + case "": + log.Logger.Fatal("required flag \"ca\" not set") + case "pkcs11ca": if !viper.IsSet("hsm-caroot-id") { log.Logger.Fatal("hsm-caroot-id must be set when using pkcs11ca") @@ -186,3 +202,34 @@ func runServeCmd(cmd *cobra.Command, args []string) { log.Logger.Fatal(err) } } + +func checkServeCmdConfigFile() error { + if serveCmdConfigFilePath != "" { + if _, err := os.Stat(serveCmdConfigFilePath); err != nil { + return errors.Wrap(err, "unable to stat config file provided") + } + abspath, err := filepath.Abs(serveCmdConfigFilePath) + if err != nil { + return errors.Wrap(err, "unable to determine absolute path of config file provided") + } + extWithDot := filepath.Ext(abspath) + ext := strings.TrimPrefix(extWithDot, ".") + var extIsValid bool + for _, validExt := range viper.SupportedExts { + if ext == validExt { + extIsValid = true + break + } + } + if !extIsValid { + return fmt.Errorf("config file must have one of the following extensions: %s", strings.Join(viper.SupportedExts, ", ")) + } + viper.SetConfigName(strings.TrimSuffix(filepath.Base(abspath), extWithDot)) + viper.SetConfigType(ext) + viper.AddConfigPath(filepath.Dir(serveCmdConfigFilePath)) + if err := viper.ReadInConfig(); err != nil { + return errors.Wrap(err, "unable to parse config file provided") + } + } + return nil +} diff --git a/config/deployment.yaml b/config/deployment.yaml index 4161b1473..b1bb9f01e 100644 --- a/config/deployment.yaml +++ b/config/deployment.yaml @@ -41,13 +41,10 @@ spec: - containerPort: 5555 - containerPort: 2112 # metrics args: [ - "serve", - "--host=0.0.0.0", "--port=5555", - "--ca=googleca", "--gcp_private_ca_parent=$(CA_PARENT)", "--gcp_private_ca_version=v1", - "--ct-log-url=http://ct-log/test", "--log_type=prod", + "serve", "-c", "/etc/fulcio-config/server.yaml", ] env: - - name: CA_PARENT + - name: FULCIO_SERVE_GCP_PRIVATE_CA_PARENT valueFrom: configMapKeyRef: name: private-ca diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index b036c411b..257a0120c 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -55,6 +55,13 @@ data: } } } + server.yaml: |- + host: 0.0.0.0 + port: 5555 + ca: googleca + gcp_private_ca_version: v1 + ct-log-url: http://ct-log/test + log_type: prod kind: ConfigMap metadata: name: fulcio-config