Skip to content

Commit

Permalink
changes auth UI to use config file cf fgeller#70
Browse files Browse the repository at this point in the history
this break the existing ui for auth, replacing the former tlsCA, tlsCert,
tlsCertKey arguments with a single JSON configuration file that will allow a
single interface when adding more auth methods and makes support for
configuration via ENV variables easier.

$ # for example:
$ kt topic -tlsca x -tlscert y -tlscertkey z
$ # becomes
$ kt topic -auth auth.json
$ cat auth.json
{
  "mode": "TLS",
  "ca-certificate": "x",
  "client-certificate": "y",
  "client-certificate-key": "z"
}

Co-Authored-By: Enrique J. Hernández <enrique@heetch.com>
  • Loading branch information
fgeller and sixstone-qq committed Nov 12, 2021
1 parent b57dc96 commit b96c512
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 16 deletions.
90 changes: 74 additions & 16 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ type commonFlags struct {
verbose bool
version sarama.KafkaVersion
tlsRequested bool
tlsCA string
tlsCert string
tlsCertKey string
auth authConfig
authFile string

brokerStrs []string
}
Expand All @@ -63,9 +62,7 @@ func (f *commonFlags) addFlags(flags *flag.FlagSet) {
flags.Var(listFlag{&f.brokerStrs}, "brokers", "Comma-separated list of brokers. Each broker definition may optionally contain a port number. The port defaults to 9092 when omitted.")
flags.Var(kafkaVersionFlag{v: &f.version}, "version", "Kafka protocol version")
flags.BoolVar(&f.tlsRequested, "tls", false, "Request server-side TLS without client-side.")
flags.StringVar(&f.tlsCA, "tlsca", "", "Path to the TLS certificate authority file")
flags.StringVar(&f.tlsCert, "tlscert", "", "Path to the TLS client certificate file")
flags.StringVar(&f.tlsCertKey, "tlscertkey", "", "Path to the TLS client certificate key file")
flags.StringVar(&f.authFile, "auth", "", "Path to auth configuration file")
flags.BoolVar(&f.verbose, "verbose", false, "More verbose logging to stderr.")
}

Expand All @@ -82,17 +79,12 @@ func (f *commonFlags) saramaConfig(name string) (*sarama.Config, error) {
}
cfg.ClientID = "kt-" + name + "-" + sanitizeUsername(username)

tlsConfig, err := setUpCerts(f.tlsCert, f.tlsCA, f.tlsCertKey)
if err != nil {
return nil, fmt.Errorf("cannot set up certificates: %v", err)
}
if tlsConfig == nil && f.tlsRequested {
// client-side not configured, but server-side TLS requested
tlsConfig = &tls.Config{}
if err = readAuthFile(f.authFile, &f.auth); err != nil {
return nil, fmt.Errorf("failed to read auth file: %w", err)
}
if tlsConfig != nil {
cfg.Net.TLS.Enable = true
cfg.Net.TLS.Config = tlsConfig

if err = setupAuth(f.auth, cfg); err != nil {
return nil, fmt.Errorf("failed to setup auth: %w", err)
}
if f.verbose {
fmt.Fprintf(os.Stderr, "sarama client configuration %#v\n", cfg)
Expand Down Expand Up @@ -296,3 +288,69 @@ func min(x, y int64) int64 {
}
return y
}

type authConfig struct {
Mode string `json:"mode"`
CACert string `json:"ca-certificate"`
ClientCert string `json:"client-certificate"`
ClientCertKey string `json:"client-certificate-key"`
}

func setupAuth(auth authConfig, saramaCfg *sarama.Config) error {
if auth.Mode == "" {
return nil
}

if auth.Mode == "TLS" {
return setupAuthTLS(auth, saramaCfg)
} else {
return fmt.Errorf("unsupport auth mode: %#v", auth.Mode)
}
}

func setupAuthTLS(auth authConfig, saramaCfg *sarama.Config) error {
if auth.CACert == "" || auth.ClientCert == "" || auth.ClientCertKey == "" {
return fmt.Errorf("client-certificate, client-certificate-key and ca-certificate are required - got auth=%#v", auth)
}

caString, err := ioutil.ReadFile(auth.CACert)
if err != nil {
return fmt.Errorf("failed to read ca-certificate err=%v", err)
}

caPool := x509.NewCertPool()
ok := caPool.AppendCertsFromPEM(caString)
if !ok {
return fmt.Errorf("unable to add ca-certificate at %s to certificate pool", auth.CACert)
}

clientCert, err := tls.LoadX509KeyPair(auth.ClientCert, auth.ClientCertKey)
if err != nil {
return err
}

tlsCfg := &tls.Config{RootCAs: caPool, Certificates: []tls.Certificate{clientCert}}
tlsCfg.BuildNameToCertificate()

saramaCfg.Net.TLS.Enable = true
saramaCfg.Net.TLS.Config = tlsCfg

return nil
}

func readAuthFile(fn string, target *authConfig) error {
if fn == "" {
return nil
}

byts, err := ioutil.ReadFile(fn)
if err != nil {
return fmt.Errorf("failed to read auth file: %w", err)
}

if err := json.Unmarshal(byts, target); err != nil {
return fmt.Errorf("failed to unmarshal auth file: %w", err)
}

return nil
}
2 changes: 2 additions & 0 deletions consume.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func (cmd *consumeCmd) run(args []string) error {
}
cmd.allPartitions = keyPartitions
}

resolvedOffsets, limits, err := cmd.resolveOffsets(context.TODO(), offsets)
if err != nil {
return fmt.Errorf("cannot resolve offsets: %v", err)
Expand Down Expand Up @@ -191,6 +192,7 @@ func (cmd *consumeCmd) consume(partitions map[int32]resolvedInterval, limits map
if interval.end > limits[p] {
interval.end = limits[p]
}

outc := make(chan *sarama.ConsumerMessage)
go func() {
defer wg.Done()
Expand Down
6 changes: 6 additions & 0 deletions test-secrets/auth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"mode": "TLS",
"client-certificate": "test-secrets/kt-test.crt",
"client-certificate-key": "test-secrets/kt-test.key",
"ca-certificate": "test-secrets/snakeoil-ca-1.crt"
}

0 comments on commit b96c512

Please sign in to comment.