mirror of
https://github.com/gregtwallace/apc-p15-tool.git
synced 2025-01-22 08:14:08 +00:00
install: add support for native ssl command
The code should auto-select the native ssl method if the ssl command is available on the UPS. If this fails, install will drop back to the original install method used by this tool (which works on NMC2).
This commit is contained in:
parent
06c9263bc4
commit
dda11df624
5 changed files with 77 additions and 14 deletions
|
@ -79,7 +79,10 @@ func (cli *Client) cmd(command string) (*upsCmdResponse, error) {
|
||||||
codeTxtIndx := strings.Index(result, "\n")
|
codeTxtIndx := strings.Index(result, "\n")
|
||||||
res.codeText = result[:codeTxtIndx-1]
|
res.codeText = result[:codeTxtIndx-1]
|
||||||
|
|
||||||
res.resultText = result[codeTxtIndx+1 : len(result)-2]
|
// avoid out of bounds if no result text
|
||||||
|
if codeTxtIndx+1 <= len(result)-2 {
|
||||||
|
res.resultText = result[codeTxtIndx+1 : len(result)-2]
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,74 @@
|
||||||
package apcssh
|
package apcssh
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// InstallSSLCert installs the specified p15 cert file on the UPS. This
|
// InstallSSLCert installs the specified p15 key and p15 cert files on the
|
||||||
// function currently only works on NMC2.
|
// UPS. It has logic to deduce if the NMC is a newer version (e.g., NMC3 with
|
||||||
func (cli *Client) InstallSSLCert(keyCertP15 []byte) error {
|
// newer firmware) and acts accordingly.
|
||||||
// install NMC2 P15 file
|
func (cli *Client) InstallSSLCert(keyP15 []byte, certPem []byte, keyCertP15 []byte) error {
|
||||||
err := cli.UploadSCP("/ssl/defaultcert.p15", keyCertP15, 0600)
|
// run `ssl` command to check if it exists
|
||||||
|
result, err := cli.cmd("ssl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("apcssh: ssl cert install: failed to send file to ups over scp (%w)", err)
|
return fmt.Errorf("apcssh: ssl cert install: failed to send ssl cmd (%w)", err)
|
||||||
|
}
|
||||||
|
// E101 is the code for "Command Not Found"
|
||||||
|
supportsSSLCmd := strings.ToLower(result.code) != "e101"
|
||||||
|
|
||||||
|
// if SSL is supported, use that method
|
||||||
|
if supportsSSLCmd {
|
||||||
|
return cli.installSSLCertModern(keyP15, certPem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to legacy
|
||||||
|
return cli.installSSLCertLegacy(keyCertP15)
|
||||||
|
}
|
||||||
|
|
||||||
|
// installSSLCertModern installs the SSL key and certificate using the UPS built-in
|
||||||
|
// command `ssl`. This command is not present on older devices (e.g., NMC2) or firmwares.
|
||||||
|
func (cli *Client) installSSLCertModern(keyP15 []byte, certPem []byte) error {
|
||||||
|
// upload the key P15 file
|
||||||
|
err := cli.UploadSCP("/ssl/nmc.key", keyP15, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: failed to send nmc.key file to ups over scp (%w)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// upload the cert PEM file
|
||||||
|
err = cli.UploadSCP("/ssl/nmc.crt", certPem, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: failed to send nmc.key file to ups over scp (%w)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run `ssl` install commands
|
||||||
|
result, err := cli.cmd("ssl key -i /ssl/nmc.key")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: failed to send ssl key install cmd (%w)", err)
|
||||||
|
}
|
||||||
|
if strings.ToLower(result.code) != "e000" {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: ssl key install cmd returned error code (%s: %s)", result.code, result.codeText)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = cli.cmd("ssl cert -i /ssl/nmc.crt")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: failed to send ssl cert install cmd (%w)", err)
|
||||||
|
}
|
||||||
|
if strings.ToLower(result.code) != "e000" {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: ssl cert install cmd returned error code (%s: %s)", result.code, result.codeText)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// installSSLCertLegacy installs the SSL key and certificate by directly uploading
|
||||||
|
// them to a .p15 file on the UPS. This is used for older devices (e.g., NMC2) and
|
||||||
|
// firmwares that do not support the `ssl` command.
|
||||||
|
func (cli *Client) installSSLCertLegacy(keyCertP15 []byte) error {
|
||||||
|
// upload/install keyCert P15 file
|
||||||
|
err := cli.UploadSCP("/ssl/defaultcert.p15", keyCertP15, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("apcssh: ssl cert install: failed to send defaultcert.p15 file to ups over scp (%w)", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (app *app) cmdCreate(_ context.Context, args []string) error {
|
||||||
// validation done
|
// validation done
|
||||||
|
|
||||||
// make p15 files
|
// make p15 files
|
||||||
apcKeyCertFile, keyFile, err := app.pemToAPCP15s(keyPem, certPem, "create")
|
keyFile, apcKeyCertFile, err := app.pemToAPCP15(keyPem, certPem, "create")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
|
||||||
// validation done
|
// validation done
|
||||||
|
|
||||||
// make p15 file
|
// make p15 file
|
||||||
keyCertP15, _, err := app.pemToAPCP15s(keyPem, certPem, "install")
|
keyP15, keyCertP15, err := app.pemToAPCP15(keyPem, certPem, "install")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// install SSL Cert
|
// install SSL Cert
|
||||||
err = client.InstallSSLCert(keyCertP15)
|
err = client.InstallSSLCert(keyP15, certPem, keyCertP15)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("install: failed to send file to ups over scp (%w)", err)
|
return fmt.Errorf("install: failed to send file to ups over scp (%w)", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// pemToAPCP15s reads the specified pem files and returns the apc p15 files (both a
|
// pemToAPCP15 reads the specified pem files and returns the apc p15 files (both a
|
||||||
// p15 file with just the private key, and also a p15 file with both the private key
|
// p15 file with just the private key, and also a p15 file with both the private key
|
||||||
// and certificate). The key+cert file includes the required APC header, prepended.
|
// and certificate). The key+cert file includes the required APC header, prepended.
|
||||||
func (app *app) pemToAPCP15s(keyPem, certPem []byte, parentCmdName string) (apcKeyCertFile, keyFile []byte, err error) {
|
func (app *app) pemToAPCP15(keyPem, certPem []byte, parentCmdName string) (keyFile []byte, apcKeyCertFile []byte, err error) {
|
||||||
app.stdLogger.Printf("%s: making apc p15 file from pem", parentCmdName)
|
app.stdLogger.Printf("%s: making apc p15 file from pem", parentCmdName)
|
||||||
|
|
||||||
// make p15 struct
|
// make p15 struct
|
||||||
|
@ -36,5 +36,5 @@ func (app *app) pemToAPCP15s(keyPem, certPem []byte, parentCmdName string) (apcK
|
||||||
|
|
||||||
app.stdLogger.Printf("%s: apc p15 file data succesfully generated", parentCmdName)
|
app.stdLogger.Printf("%s: apc p15 file data succesfully generated", parentCmdName)
|
||||||
|
|
||||||
return apcKeyCertFile, keyFile, nil
|
return keyFile, apcKeyCertFile, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue