-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
shelly set-user-ca + put-tls-client-cert + put-tls-client-key
- Loading branch information
1 parent
7a8b553
commit 16f4683
Showing
5 changed files
with
247 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package cmd | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/jcodybaker/go-shelly" | ||
"github.com/jcodybaker/shellyctl/pkg/discovery" | ||
"github.com/mongoose-os/mos/common/mgrpc/frame" | ||
"github.com/rs/zerolog/log" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
type reqBuilder func(data *string, append bool) shelly.RPCRequestBody | ||
type runE func(cmd *cobra.Command, args []string) error | ||
|
||
func newDataCommand(reqBuilder reqBuilder, strParam, fileParam, nullParam string) runE { | ||
return func(cmd *cobra.Command, args []string) error { | ||
ctx := cmd.Context() | ||
method := reqBuilder(nil, false).Method() | ||
ll := log.Ctx(ctx).With().Str("method", method).Logger() | ||
|
||
var b *bytes.Buffer | ||
data := viper.GetString(strParam) | ||
dataFile := viper.GetString(fileParam) | ||
remove := viper.GetBool(nullParam) | ||
if (data != "" && dataFile != "") || (data != "" && remove) || (dataFile != "" && remove) { | ||
return fmt.Errorf("--%s, --%s, and --%s options are mutually exclusive", strParam, fileParam, nullParam) | ||
} | ||
if data == "" && dataFile == "" && !remove { | ||
return fmt.Errorf("exactly one of --%s, --%s, and --%s options are required", strParam, fileParam, nullParam) | ||
} | ||
if data != "" { | ||
b = bytes.NewBufferString(data) | ||
} else if dataFile == "-" { | ||
b = &bytes.Buffer{} | ||
if _, err := io.Copy(b, os.Stdin); err != nil { | ||
ll.Fatal().Err(err).Msg(fmt.Sprintf("reading stdin for --%s", strParam)) | ||
} | ||
} else if dataFile != "" { | ||
b = &bytes.Buffer{} | ||
f, err := os.Open(dataFile) | ||
if err != nil { | ||
ll.Fatal().Err(err).Str(fileParam, dataFile).Msg(fmt.Sprintf("opening --%s", fileParam)) | ||
} | ||
n, err := io.Copy(b, f) | ||
if err != nil { | ||
ll.Fatal().Err(err).Str(fileParam, dataFile).Msg(fmt.Sprintf("reading --%s", fileParam)) | ||
} | ||
ll.Debug().Int64("bytes_read", n).Str(fileParam, dataFile).Msg(fmt.Sprintf("finished reading --%s", fileParam)) | ||
if err := f.Close(); err != nil { | ||
ll.Warn().Err(err).Str(fileParam, dataFile).Msg(fmt.Sprintf("closing --%s", fileParam)) | ||
} | ||
} | ||
|
||
dOpts, err := discoveryOptionsFromFlags(cmd.Flags()) | ||
if err != nil { | ||
ll.Fatal().Err(err).Msg("parsing flags") | ||
} | ||
|
||
discoverer := discovery.NewDiscoverer(dOpts...) | ||
if err := discoveryAddDevices(ctx, discoverer); err != nil { | ||
ll.Fatal().Err(err).Msg("adding devices") | ||
} | ||
|
||
if _, err := discoverer.Search(ctx); err != nil { | ||
return err | ||
} | ||
|
||
for _, d := range discoverer.AllDevices() { | ||
ll := d.Log(ll) | ||
conn, err := d.Open(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
defer func() { | ||
if err := conn.Disconnect(ctx); err != nil { | ||
ll.Warn().Err(err).Msg("disconnecting from device") | ||
} | ||
}() | ||
if remove { | ||
req := reqBuilder(nil, false) | ||
resp := req.NewResponse() | ||
ll.Debug(). | ||
Str("method", req.Method()). | ||
Any("request_body", req). | ||
Msg("sending request to clear data") | ||
_, err = shelly.Do(ctx, conn, d.AuthCallback(ctx), req, resp) | ||
if err != nil { | ||
if viper.GetBool("skip-failed-hosts") { | ||
ll.Err(err).Msg("error executing request; contining because --skip-failed-hosts=true") | ||
continue | ||
} else { | ||
ll.Fatal().Err(err).Msg("error executing request") | ||
} | ||
} | ||
ll.Info().Str("method", req.Method()).Msg("successfully cleared data") | ||
continue | ||
} | ||
s := bufio.NewScanner(b) | ||
var line int | ||
var resp any | ||
var rawResp *frame.Response | ||
for s.Scan() { | ||
line++ | ||
req := reqBuilder(shelly.StrPtr(s.Text()), line > 1) | ||
resp = req.NewResponse() | ||
ll.Debug(). | ||
Str("method", req.Method()). | ||
Int("line", line). | ||
Any("request_body", req). | ||
Msg("sending data") | ||
rawResp, err = shelly.Do(ctx, conn, d.AuthCallback(ctx), req, resp) | ||
if err != nil { | ||
return err | ||
} | ||
ll.Debug(). | ||
Str("method", req.Method()). | ||
Int("line", line). | ||
Any("request_body", req). | ||
Msg("request succeeded") | ||
} | ||
if err := s.Err(); err != nil { | ||
// We're reading memory buffered data here, so this isn't likely an emphermal IO failure | ||
// but rather something like line larger than the buffer size. | ||
ll.Fatal().Err(err).Msg("reading input data") | ||
} | ||
Output( | ||
ctx, | ||
fmt.Sprintf("Response to %s command for %s", method, d.BestName()), | ||
"response", | ||
resp, | ||
rawResp.Response, | ||
) | ||
} | ||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/jcodybaker/go-shelly" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
shellyPutTLSClientCertCmd = &cobra.Command{ | ||
Use: "put-tls-client-cert", | ||
} | ||
) | ||
|
||
func init() { | ||
// Passing a whole cert as a cmd argument is awkward, but viper supports config files which | ||
// should facilitate multi-line strings in yaml, JSON, etc. | ||
shellyPutTLSClientCertCmd.Flags().String( | ||
"data", "", "PEM encoded certificate data. (one of --data, --data-file, or --remove-cert is required)", | ||
) | ||
shellyPutTLSClientCertCmd.Flags().String( | ||
"data-file", "", "path to a file containing PEM encoded certificate data.", | ||
) | ||
shellyPutTLSClientCertCmd.Flags().Bool( | ||
"remove-cert", false, "remove an existing certificate from the device", | ||
) | ||
shellyComponent.Parent.AddCommand(shellyPutTLSClientCertCmd) | ||
discoveryFlags(shellyPutTLSClientCertCmd.Flags(), discoveryFlagsOptions{interactive: true}) | ||
shellyPutTLSClientCertCmd.RunE = newDataCommand( | ||
func(data *string, append bool) shelly.RPCRequestBody { | ||
return &shelly.ShellyPutTLSClientCertRequest{ | ||
Data: data, | ||
Append: append, | ||
} | ||
}, "data", "data-file", "remove-cert") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/jcodybaker/go-shelly" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
shellyPutTLSClientKeyCmd = &cobra.Command{ | ||
Use: "put-tls-client-key", | ||
} | ||
) | ||
|
||
func init() { | ||
// Passing a whole key as a cmd argument is awkward, but viper supports config files which | ||
// should facilitate multi-line strings in yaml, JSON, etc. | ||
shellyPutTLSClientKeyCmd.Flags().String( | ||
"data", "", "PEM encoded key data. (one of --data, --data-file, or --remove-key is required)", | ||
) | ||
shellyPutTLSClientKeyCmd.Flags().String( | ||
"data-file", "", "path to a file containing PEM encoded key data.", | ||
) | ||
shellyPutTLSClientKeyCmd.Flags().Bool( | ||
"remove-key", false, "remove an existing key from the device", | ||
) | ||
shellyComponent.Parent.AddCommand(shellyPutTLSClientKeyCmd) | ||
discoveryFlags(shellyPutTLSClientKeyCmd.Flags(), discoveryFlagsOptions{interactive: true}) | ||
shellyPutTLSClientKeyCmd.RunE = newDataCommand( | ||
func(data *string, append bool) shelly.RPCRequestBody { | ||
return &shelly.ShellyPutTLSClientKeyRequest{ | ||
Data: data, | ||
Append: append, | ||
} | ||
}, "data", "data-file", "remove-key") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/jcodybaker/go-shelly" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
shellyPutUserCACmd = &cobra.Command{ | ||
Use: "put-user-ca", | ||
} | ||
) | ||
|
||
func init() { | ||
// Passing a whole cert as a cmd argument is awkward, but viper supports config files which | ||
// should facilitate multi-line strings in yaml, JSON, etc. | ||
shellyPutUserCACmd.Flags().String( | ||
"data", "", "PEM encoded certificate authority data. (one of --data, --data-file, or --remove-ca is required)", | ||
) | ||
shellyPutUserCACmd.Flags().String( | ||
"data-file", "", "path to a file containing PEM encoded certificate authority data.", | ||
) | ||
shellyPutUserCACmd.Flags().Bool( | ||
"remove-ca", false, "remove an existing CA certificate from the device", | ||
) | ||
shellyComponent.Parent.AddCommand(shellyPutUserCACmd) | ||
discoveryFlags(shellyPutUserCACmd.Flags(), discoveryFlagsOptions{interactive: true}) | ||
shellyPutUserCACmd.RunE = newDataCommand( | ||
func(data *string, append bool) shelly.RPCRequestBody { | ||
return &shelly.ShellyPutUserCARequest{ | ||
Data: data, | ||
Append: append, | ||
} | ||
}, "data", "data-file", "remove-ca") | ||
} |
Oops, something went wrong.