mirror of
https://github.com/davidallendj/configurator.git
synced 2025-12-20 03:27:02 -07:00
Merge pull request #22 from OpenCHAMI/fix-minor-issues
Fix minor issues
This commit is contained in:
commit
5b351d2cac
9 changed files with 91 additions and 51 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,3 +5,4 @@
|
||||||
**.conf
|
**.conf
|
||||||
**.ignore
|
**.ignore
|
||||||
**.tar.gz
|
**.tar.gz
|
||||||
|
dist/
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ builds:
|
||||||
- amd64
|
- amd64
|
||||||
- arm64
|
- arm64
|
||||||
flags:
|
flags:
|
||||||
- -tags:all
|
- -tags=all
|
||||||
archives:
|
archives:
|
||||||
- format: tar.gz
|
- format: tar.gz
|
||||||
# this name template makes the OS and Arch compatible with the results of uname.
|
# this name template makes the OS and Arch compatible with the results of uname.
|
||||||
|
|
@ -27,7 +27,6 @@ archives:
|
||||||
- LICENSE
|
- LICENSE
|
||||||
- CHANGELOG.md
|
- CHANGELOG.md
|
||||||
- README.md
|
- README.md
|
||||||
- lib/
|
|
||||||
dockers:
|
dockers:
|
||||||
-
|
-
|
||||||
image_templates:
|
image_templates:
|
||||||
|
|
@ -45,7 +44,6 @@ dockers:
|
||||||
- LICENSE
|
- LICENSE
|
||||||
- CHANGELOG.md
|
- CHANGELOG.md
|
||||||
- README.md
|
- README.md
|
||||||
- lib/
|
|
||||||
checksum:
|
checksum:
|
||||||
name_template: 'checksums.txt'
|
name_template: 'checksums.txt'
|
||||||
snapshot:
|
snapshot:
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,13 @@ FROM cgr.dev/chainguard/wolfi-base
|
||||||
|
|
||||||
RUN apk add --no-cache tini bash
|
RUN apk add --no-cache tini bash
|
||||||
RUN mkdir -p /configurator
|
RUN mkdir -p /configurator
|
||||||
RUN mkdir -p /configurator/lib
|
|
||||||
|
|
||||||
# nobody 65534:65534
|
# nobody 65534:65534
|
||||||
USER 65534:65534
|
USER 65534:65534
|
||||||
|
|
||||||
# copy the binary and all of the default plugins
|
# copy the binary and all of the default plugins
|
||||||
COPY configurator /configurator/configurator
|
COPY configurator /configurator/configurator
|
||||||
COPY lib/* /configurator/lib/*
|
|
||||||
|
|
||||||
CMD ["/configurator"]
|
CMD ["/configurator/configurator"]
|
||||||
|
|
||||||
ENTRYPOINT [ "/sbin/tini", "--" ]
|
ENTRYPOINT [ "/sbin/tini", "--" ]
|
||||||
|
|
@ -20,7 +20,6 @@ var (
|
||||||
tokenFetchRetries int
|
tokenFetchRetries int
|
||||||
templatePaths []string
|
templatePaths []string
|
||||||
pluginPath string
|
pluginPath string
|
||||||
cacertPath string
|
|
||||||
useCompression bool
|
useCompression bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -175,7 +174,6 @@ func init() {
|
||||||
generateCmd.Flags().StringSliceVar(&templatePaths, "template", []string{}, "set the paths for the Jinja 2 templates to use")
|
generateCmd.Flags().StringSliceVar(&templatePaths, "template", []string{}, "set the paths for the Jinja 2 templates to use")
|
||||||
generateCmd.Flags().StringVar(&pluginPath, "plugin", "", "set the generator plugin path")
|
generateCmd.Flags().StringVar(&pluginPath, "plugin", "", "set the generator plugin path")
|
||||||
generateCmd.Flags().StringVarP(&outputPath, "output", "o", "", "set the output path for config targets")
|
generateCmd.Flags().StringVarP(&outputPath, "output", "o", "", "set the output path for config targets")
|
||||||
generateCmd.Flags().StringVar(&cacertPath, "cacert", "", "path to CA cert. (defaults to system CAs)")
|
|
||||||
generateCmd.Flags().IntVar(&tokenFetchRetries, "fetch-retries", 5, "set the number of retries to fetch an access token")
|
generateCmd.Flags().IntVar(&tokenFetchRetries, "fetch-retries", 5, "set the number of retries to fetch an access token")
|
||||||
generateCmd.Flags().StringVar(&remoteHost, "host", "http://localhost", "set the remote host")
|
generateCmd.Flags().StringVar(&remoteHost, "host", "http://localhost", "set the remote host")
|
||||||
generateCmd.Flags().IntVar(&remotePort, "port", 80, "set the remote port")
|
generateCmd.Flags().IntVar(&remotePort, "port", 80, "set the remote port")
|
||||||
|
|
|
||||||
14
cmd/root.go
14
cmd/root.go
|
|
@ -6,12 +6,14 @@ import (
|
||||||
|
|
||||||
configurator "github.com/OpenCHAMI/configurator/pkg"
|
configurator "github.com/OpenCHAMI/configurator/pkg"
|
||||||
"github.com/OpenCHAMI/configurator/pkg/util"
|
"github.com/OpenCHAMI/configurator/pkg/util"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
configPath string
|
|
||||||
config configurator.Config
|
config configurator.Config
|
||||||
|
configPath string
|
||||||
|
cacertPath string
|
||||||
verbose bool
|
verbose bool
|
||||||
targets []string
|
targets []string
|
||||||
outputPath string
|
outputPath string
|
||||||
|
|
@ -40,11 +42,13 @@ func Execute() {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "./config.yaml", "set the config path")
|
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "set the config path")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "set to enable verbose output")
|
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "set to enable verbose output")
|
||||||
|
rootCmd.PersistentFlags().StringVar(&cacertPath, "cacert", "", "path to CA cert. (defaults to system CAs)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConfig() {
|
func initConfig() {
|
||||||
|
// empty from not being set
|
||||||
if configPath != "" {
|
if configPath != "" {
|
||||||
exists, err := util.PathExists(configPath)
|
exists, err := util.PathExists(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -53,9 +57,13 @@ func initConfig() {
|
||||||
} else if exists {
|
} else if exists {
|
||||||
config = configurator.LoadConfig(configPath)
|
config = configurator.LoadConfig(configPath)
|
||||||
} else {
|
} else {
|
||||||
config = configurator.NewConfig()
|
// show error and exit since a path was specified
|
||||||
|
log.Error().Str("path", configPath).Msg("config file not found")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// set to the default value and create a new one
|
||||||
|
configPath = "./config.yaml"
|
||||||
config = configurator.NewConfig()
|
config = configurator.NewConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ var serveCmd = &cobra.Command{
|
||||||
fmt.Printf("%v\n", string(b))
|
fmt.Printf("%v\n", string(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up the routes and start the server
|
// set up the routes and start the serve
|
||||||
server := server.Server{
|
server := server.Server{
|
||||||
Config: &config,
|
Config: &config,
|
||||||
Server: &http.Server{
|
Server: &http.Server{
|
||||||
|
|
@ -56,14 +56,14 @@ var serveCmd = &cobra.Command{
|
||||||
},
|
},
|
||||||
GeneratorParams: generator.Params{
|
GeneratorParams: generator.Params{
|
||||||
Args: args,
|
Args: args,
|
||||||
PluginPath: pluginPath,
|
// PluginPath: pluginPath,
|
||||||
// Target: target, // NOTE: targets are set via HTTP requests (ex: curl http://configurator:3334/generate?target=dnsmasq)
|
// Target: target, // NOTE: targets are set via HTTP requests (ex: curl http://configurator:3334/generate?target=dnsmasq)
|
||||||
Verbose: verbose,
|
Verbose: verbose,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// start listening with the server
|
// start listening with the server
|
||||||
err := server.Serve()
|
err := server.Serve(cacertPath)
|
||||||
if errors.Is(err, http.ErrServerClosed) {
|
if errors.Is(err, http.ErrServerClosed) {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Printf("Server closed.")
|
fmt.Printf("Server closed.")
|
||||||
|
|
@ -78,7 +78,7 @@ var serveCmd = &cobra.Command{
|
||||||
func init() {
|
func init() {
|
||||||
serveCmd.Flags().StringVar(&config.Server.Host, "host", config.Server.Host, "set the server host")
|
serveCmd.Flags().StringVar(&config.Server.Host, "host", config.Server.Host, "set the server host")
|
||||||
serveCmd.Flags().IntVar(&config.Server.Port, "port", config.Server.Port, "set the server port")
|
serveCmd.Flags().IntVar(&config.Server.Port, "port", config.Server.Port, "set the server port")
|
||||||
serveCmd.Flags().StringVar(&pluginPath, "plugin", "", "set the generator plugins directory path")
|
// serveCmd.Flags().StringVar(&pluginPath, "plugin", "", "set the generator plugins directory path")
|
||||||
serveCmd.Flags().StringVar(&config.Server.Jwks.Uri, "jwks-uri", config.Server.Jwks.Uri, "set the JWKS url to fetch public key")
|
serveCmd.Flags().StringVar(&config.Server.Jwks.Uri, "jwks-uri", config.Server.Jwks.Uri, "set the JWKS url to fetch public key")
|
||||||
serveCmd.Flags().IntVar(&config.Server.Jwks.Retries, "jwks-fetch-retries", config.Server.Jwks.Retries, "set the JWKS fetch retry count")
|
serveCmd.Flags().IntVar(&config.Server.Jwks.Retries, "jwks-fetch-retries", config.Server.Jwks.Retries, "set the JWKS fetch retry count")
|
||||||
rootCmd.AddCommand(serveCmd)
|
rootCmd.AddCommand(serveCmd)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/OpenCHAMI/configurator/pkg/util"
|
"github.com/OpenCHAMI/configurator/pkg/util"
|
||||||
"github.com/nikolalohinski/gonja/v2"
|
"github.com/nikolalohinski/gonja/v2"
|
||||||
"github.com/nikolalohinski/gonja/v2/exec"
|
"github.com/nikolalohinski/gonja/v2/exec"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
@ -35,6 +36,7 @@ type (
|
||||||
TemplatePaths []string
|
TemplatePaths []string
|
||||||
PluginPath string
|
PluginPath string
|
||||||
Target string
|
Target string
|
||||||
|
Client *configurator.SmdClient
|
||||||
Verbose bool
|
Verbose bool
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -408,17 +410,24 @@ func Generate(config *configurator.Config, params Params) (FileMap, error) {
|
||||||
func GenerateWithTarget(config *configurator.Config, params Params) (FileMap, error) {
|
func GenerateWithTarget(config *configurator.Config, params Params) (FileMap, error) {
|
||||||
// load generator plugins to generate configs or to print
|
// load generator plugins to generate configs or to print
|
||||||
var (
|
var (
|
||||||
|
client configurator.SmdClient
|
||||||
|
target configurator.Target
|
||||||
|
generator Generator
|
||||||
|
err error
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// check if we have a client from params first and create new one if not
|
||||||
|
if params.Client == nil {
|
||||||
client = configurator.NewSmdClient(
|
client = configurator.NewSmdClient(
|
||||||
configurator.WithHost(config.SmdClient.Host),
|
configurator.WithHost(config.SmdClient.Host),
|
||||||
configurator.WithPort(config.SmdClient.Port),
|
configurator.WithPort(config.SmdClient.Port),
|
||||||
configurator.WithAccessToken(config.AccessToken),
|
configurator.WithAccessToken(config.AccessToken),
|
||||||
configurator.WithCertPoolFile(config.CertPath),
|
configurator.WithCertPoolFile(config.CertPath),
|
||||||
)
|
)
|
||||||
target configurator.Target
|
} else {
|
||||||
generator Generator
|
client = *params.Client
|
||||||
err error
|
}
|
||||||
ok bool
|
|
||||||
)
|
|
||||||
|
|
||||||
// check if a target is supplied
|
// check if a target is supplied
|
||||||
if len(params.Args) == 0 && params.Target == "" {
|
if len(params.Args) == 0 && params.Target == "" {
|
||||||
|
|
@ -440,6 +449,7 @@ func GenerateWithTarget(config *configurator.Config, params Params) (FileMap, er
|
||||||
generator, ok = DefaultGenerators[params.Target]
|
generator, ok = DefaultGenerators[params.Target]
|
||||||
if !ok {
|
if !ok {
|
||||||
// only load the plugin needed for this target if we don't find default
|
// only load the plugin needed for this target if we don't find default
|
||||||
|
log.Error().Msg("did not find target in default generators")
|
||||||
generator, err = LoadPlugin(target.PluginPath)
|
generator, err = LoadPlugin(target.PluginPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load plugin: %w", err)
|
return nil, fmt.Errorf("failed to load plugin: %w", err)
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,11 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -60,13 +63,33 @@ func New(config *configurator.Config) *Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main function to start up configurator as a service.
|
// Main function to start up configurator as a service.
|
||||||
func (s *Server) Serve() error {
|
func (s *Server) Serve(cacertPath string) error {
|
||||||
// create client just for the server to use to fetch data from SMD
|
// create client just for the server to use to fetch data from SMD
|
||||||
_ = &configurator.SmdClient{
|
client := &configurator.SmdClient{
|
||||||
Host: s.Config.SmdClient.Host,
|
Host: s.Config.SmdClient.Host,
|
||||||
Port: s.Config.SmdClient.Port,
|
Port: s.Config.SmdClient.Port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add cert to client if `--cacert` flag is passed
|
||||||
|
if cacertPath != "" {
|
||||||
|
cacert, _ := os.ReadFile(cacertPath)
|
||||||
|
certPool := x509.NewCertPool()
|
||||||
|
certPool.AppendCertsFromPEM(cacert)
|
||||||
|
client.Transport = &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
RootCAs: certPool,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
Dial: (&net.Dialer{
|
||||||
|
Timeout: 120 * time.Second,
|
||||||
|
KeepAlive: 120 * time.Second,
|
||||||
|
}).Dial,
|
||||||
|
TLSHandshakeTimeout: 120 * time.Second,
|
||||||
|
ResponseHeaderTimeout: 120 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set the server address with config values
|
// set the server address with config values
|
||||||
s.Server.Addr = fmt.Sprintf("%s:%d", s.Config.Server.Host, s.Config.Server.Port)
|
s.Server.Addr = fmt.Sprintf("%s:%d", s.Config.Server.Host, s.Config.Server.Port)
|
||||||
|
|
||||||
|
|
@ -76,7 +99,7 @@ func (s *Server) Serve() error {
|
||||||
var err error
|
var err error
|
||||||
tokenAuth, err = configurator.FetchPublicKeyFromURL(s.Config.Server.Jwks.Uri)
|
tokenAuth, err = configurator.FetchPublicKeyFromURL(s.Config.Server.Jwks.Uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("failed to fetch JWKS: %w", err)
|
logrus.Errorf("failed to fetch JWKS: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
@ -104,12 +127,12 @@ func (s *Server) Serve() error {
|
||||||
)
|
)
|
||||||
|
|
||||||
// protected routes if using auth
|
// protected routes if using auth
|
||||||
r.HandleFunc("/generate", s.Generate)
|
r.HandleFunc("/generate", s.Generate(client))
|
||||||
r.HandleFunc("/templates", s.ManageTemplates)
|
r.HandleFunc("/templates", s.ManageTemplates)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// public routes without auth
|
// public routes without auth
|
||||||
router.HandleFunc("/generate", s.Generate)
|
router.HandleFunc("/generate", s.Generate(client))
|
||||||
router.HandleFunc("/templates", s.ManageTemplates)
|
router.HandleFunc("/templates", s.ManageTemplates)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,9 +150,12 @@ func (s *Server) Close() {
|
||||||
// This is the corresponding service function to generate templated files, that
|
// This is the corresponding service function to generate templated files, that
|
||||||
// works similarly to the CLI variant. This function takes similiar arguments as
|
// works similarly to the CLI variant. This function takes similiar arguments as
|
||||||
// query parameters that are included in the HTTP request URL.
|
// query parameters that are included in the HTTP request URL.
|
||||||
func (s *Server) Generate(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) Generate(client *configurator.SmdClient) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
// get all of the expect query URL params and validate
|
// get all of the expect query URL params and validate
|
||||||
s.GeneratorParams.Target = r.URL.Query().Get("target")
|
s.GeneratorParams.Target = r.URL.Query().Get("target")
|
||||||
|
s.GeneratorParams.Client = client
|
||||||
if s.GeneratorParams.Target == "" {
|
if s.GeneratorParams.Target == "" {
|
||||||
writeErrorResponse(w, "must specify a target")
|
writeErrorResponse(w, "must specify a target")
|
||||||
return
|
return
|
||||||
|
|
@ -138,7 +164,7 @@ func (s *Server) Generate(w http.ResponseWriter, r *http.Request) {
|
||||||
// generate a new config file from supplied params
|
// generate a new config file from supplied params
|
||||||
outputs, err := generator.GenerateWithTarget(s.Config, s.GeneratorParams)
|
outputs, err := generator.GenerateWithTarget(s.Config, s.GeneratorParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(w, "failed to generate file: %w", err)
|
writeErrorResponse(w, "failed to generate file: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,14 +172,15 @@ func (s *Server) Generate(w http.ResponseWriter, r *http.Request) {
|
||||||
tmp := generator.ConvertContentsToString(outputs)
|
tmp := generator.ConvertContentsToString(outputs)
|
||||||
b, err := json.Marshal(tmp)
|
b, err := json.Marshal(tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(w, "failed to marshal output: %w", err)
|
writeErrorResponse(w, "failed to marshal output: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = w.Write(b)
|
_, err = w.Write(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(w, "failed to write response: %w", err)
|
writeErrorResponse(w, "failed to write response: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Incomplete WIP function for managing templates remotely. There is currently no
|
// Incomplete WIP function for managing templates remotely. There is currently no
|
||||||
|
|
@ -163,7 +190,7 @@ func (s *Server) Generate(w http.ResponseWriter, r *http.Request) {
|
||||||
func (s *Server) ManageTemplates(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) ManageTemplates(w http.ResponseWriter, r *http.Request) {
|
||||||
_, err := w.Write([]byte("this is not implemented yet"))
|
_, err := w.Write([]byte("this is not implemented yet"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(w, "failed to write response: %w", err)
|
writeErrorResponse(w, "failed to write response: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue