diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f3153e49..b4e9e454 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,6 @@ on: push: branches: [ main ] pull_request: - branches: [ main ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -42,14 +41,21 @@ jobs: run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi - name: Run go vet run: go vet ./... + - name: Run go lint + if: ${{ matrix.os == 'ubuntu-20.04' }} + uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 + with: + version: latest - name: Install Test Converter and run tests if: ${{ matrix.os == 'ubuntu-20.04' }} run: | export GOPATH="$HOME/go/" export PATH=$PATH:$GOPATH/bin go install github.com/jstemmer/go-junit-report/v2@latest - go test -v 2>&1 ./... | go-junit-report -set-exit-code > rpc-go-unit.xml - + go test -covermode=atomic -coverprofile=coverage.out -race -v ./... > test_output.txt 2>&1 || true + cat test_output.txt + cat test_output.txt | go-junit-report -set-exit-code > junit.xml + if grep -q "FAIL" test_output.txt; then exit 1; fi - name: run the tests with coverage run: go test ./... -coverprofile=coverage.out -covermode=atomic diff --git a/.vscode/launch.json b/.vscode/launch.json index 7e8c471e..23cef9b7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -69,8 +69,11 @@ "program": "${workspaceFolder}/cmd/main.go", "args": [ "configure", - "enablewifiport", - "-h" + "mebx", + "-mebxpassword", + "P@ssw0rd", + "-password", + "P@ssw0rd" ], "console": "integratedTerminal" }, diff --git a/cmd/lib.go b/cmd/lib.go index 9c5c9818..deecf5fb 100644 --- a/cmd/lib.go +++ b/cmd/lib.go @@ -19,11 +19,11 @@ import ( //export rpcCheckAccess func rpcCheckAccess() int { - rc, err := checkAccess() + err := checkAccess() if err != nil { - log.Error(err.Error()) + return handleError(err) } - return int(rc) + return int(utils.Success) } //export rpcExec @@ -41,12 +41,22 @@ func rpcExec(Input *C.char, Output **C.char) int { args, err := r.Read() if err != nil { log.Error(err.Error()) - return int(utils.InvalidParameterCombination) + return utils.InvalidParameterCombination.Code } args = append([]string{"rpc"}, args...) - rc := runRPC(args) - if rc != utils.Success { + err = runRPC(args) + if err != nil { *Output = C.CString("rpcExec failed: " + inputString) } - return int(rc) + return handleError(err) +} + +func handleError(err error) int { + if customErr, ok := err.(utils.CustomError); ok { + log.Error(customErr.Error()) + return customErr.Code + } else { + log.Error(err.Error()) + return utils.GenericFailure.Code + } } diff --git a/cmd/main.go b/cmd/main.go index c9b386eb..37926d31 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,32 +20,32 @@ const AccessErrMsg = "Failed to execute due to access issues. " + "the MEI driver is installed, " + "and the runtime has administrator or root privileges." -func checkAccess() (utils.ReturnCode, error) { +func checkAccess() error { amtCommand := amt.NewAMTCommand() - rc, err := amtCommand.Initialize() - if rc != utils.Success || err != nil { - return utils.AmtNotDetected, err + err := amtCommand.Initialize() + if err != nil { + return err } - return utils.Success, nil + return nil } -func runRPC(args []string) utils.ReturnCode { - flags, rc := parseCommandLine(args) - if rc != utils.Success { - return rc +func runRPC(args []string) error { + flags, err := parseCommandLine(args) + if err != nil { + return err } if flags.Local { - rc = local.ExecuteCommand(flags) + err = local.ExecuteCommand(flags) } else { - rc = rps.ExecuteCommand(flags) + err = rps.ExecuteCommand(flags) } - return rc + return err } -func parseCommandLine(args []string) (*flags.Flags, utils.ReturnCode) { +func parseCommandLine(args []string) (*flags.Flags, error) { //process flags flags := flags.NewFlags(args) - rc := flags.ParseFlags() + error := flags.ParseFlags() if flags.Verbose { log.SetLevel(log.TraceLevel) @@ -67,21 +67,28 @@ func parseCommandLine(args []string) (*flags.Flags, utils.ReturnCode) { FullTimestamp: true, }) } - return flags, rc + return flags, error } func main() { - rc, err := checkAccess() - if rc != utils.Success { - if err != nil { - log.Error(err.Error()) - } + err := checkAccess() + if err != nil { log.Error(AccessErrMsg) - os.Exit(int(rc)) + handleErrorAndExit(err) } - rc = runRPC(os.Args) + + err = runRPC(os.Args) if err != nil { + handleErrorAndExit(err) + } +} + +func handleErrorAndExit(err error) { + if customErr, ok := err.(utils.CustomError); ok { + log.Error(customErr.Error()) + os.Exit(customErr.Code) + } else { log.Error(err.Error()) + os.Exit(utils.GenericFailure.Code) } - os.Exit(int(rc)) } diff --git a/go.mod b/go.mod index 5f52a97b..15c05336 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,14 @@ module rpc go 1.20 // uncomment if developing with go-wsman-messages locally -// replace github.com/open-amt-cloud-toolkit/go-wsman-messages => ../go-wsman-messages +// replace github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 => ../go-wsman-messages require ( + github.com/google/uuid v1.4.0 github.com/gorilla/websocket v1.5.1 github.com/hirochachacha/go-smb2 v1.1.0 github.com/ilyakaznacheev/cleanenv v1.5.0 - github.com/open-amt-cloud-toolkit/go-wsman-messages v1.14.0 + github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.1.1 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 golang.org/x/sys v0.16.0 diff --git a/go.sum b/go.sum index cf2f537f..aed53d4a 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI= @@ -13,8 +15,8 @@ github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2l github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/open-amt-cloud-toolkit/go-wsman-messages v1.14.0 h1:m8SCNN3JXr0+aTo+gJ/VxbXL34dO+ztVhTQA0lgsp/8= -github.com/open-amt-cloud-toolkit/go-wsman-messages v1.14.0/go.mod h1:+cN55LgpvGZsTNu1mAh2XbhKJkk0AbMdJZOeyB5CzkI= +github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.1.1 h1:p05Atv8KwPD31n2z59TY6knQTUFX/9c6CcTF1CdB558= +github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.1.1/go.mod h1:bwbM46G0ryPI8djtb9wdJH5EW6/g2/RjCaKg7qRsgK0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= diff --git a/internal/amt/commands.go b/internal/amt/commands.go index a3e4ec17..79c6bce2 100644 --- a/internal/amt/commands.go +++ b/internal/amt/commands.go @@ -81,7 +81,7 @@ func (r ChangeEnabledResponse) IsNewInterfaceVersion() bool { } type Interface interface { - Initialize() (utils.ReturnCode, error) + Initialize() error GetChangeEnabled() (ChangeEnabledResponse, error) EnableAMT() error DisableAMT() error @@ -117,20 +117,20 @@ func NewAMTCommand() AMTCommand { } // Initialize determines if rpc is able to initialize the heci driver -func (amt AMTCommand) Initialize() (utils.ReturnCode, error) { +func (amt AMTCommand) Initialize() error { // initialize HECI interface err := amt.PTHI.Open(false) if err != nil { if err.Error() == "The handle is invalid." { - return utils.HECIDriverNotDetected, errors.New("AMT not found: MEI/driver is missing or the call to the HECI driver failed") + return utils.HECIDriverNotDetected //, errors.New("AMT not found: MEI/driver is missing or the call to the HECI driver failed") } else { - return utils.HECIDriverNotDetected, errors.New("unable to initialize") + return utils.HECIDriverNotDetected //, errors.New("unable to initialize") } } defer amt.PTHI.Close() - return utils.Success, nil + return nil } // GetVersionDataFromME ... @@ -177,6 +177,9 @@ func (amt AMTCommand) GetChangeEnabled() (ChangeEnabledResponse, error) { } defer amt.PTHI.Close() rawVal, err := amt.PTHI.GetIsAMTEnabled() + if err != nil { + return ChangeEnabledResponse(0), err + } return ChangeEnabledResponse(rawVal), nil } diff --git a/internal/amt/commands_test.go b/internal/amt/commands_test.go index 47625f1a..214a92ed 100644 --- a/internal/amt/commands_test.go +++ b/internal/amt/commands_test.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "rpc/pkg/pthi" + "rpc/pkg/utils" "testing" "time" @@ -153,19 +154,19 @@ func init() { amt.PTHI = MockPTHICommands{} } func TestInitializeNoError(t *testing.T) { - result, err := amt.Initialize() - assert.NoError(t, err, result) + err := amt.Initialize() + assert.NoError(t, err) } func TestInitializeMEIError(t *testing.T) { flag = true - result, err := amt.Initialize() - assert.Error(t, err, result) + err := amt.Initialize() + assert.Error(t, err, utils.HECIDriverNotDetected) flag = false } func TestInitializeError(t *testing.T) { flag1 = true - result, err := amt.Initialize() - assert.Error(t, err, result) + err := amt.Initialize() + assert.Error(t, err, utils.HECIDriverNotDetected) flag1 = false } func TestGetVersionDataFromME(t *testing.T) { @@ -179,19 +180,19 @@ func TestGetVersionDataFromMEError(t *testing.T) { assert.Equal(t, "", result) } -func TestGetVersionDataFromMETimeout1sec(t *testing.T) { - returnError = true - result, err := amt.GetVersionDataFromME("", 1*time.Second) - assert.Equal(t, "amt internal error", err.Error()) - assert.Equal(t, "", result) -} +// func TestGetVersionDataFromMETimeout1sec(t *testing.T) { +// returnError = true +// result, err := amt.GetVersionDataFromME("", 1*time.Second) +// assert.Equal(t, "amt internal error", err.Error()) +// assert.Equal(t, "", result) +// } -func TestGetVersionDataFromMETimeout16sec(t *testing.T) { - returnError = true - result, err := amt.GetVersionDataFromME("", 16*time.Second) - assert.Equal(t, "amt internal error", err.Error()) - assert.Equal(t, "", result) -} +// func TestGetVersionDataFromMETimeout16sec(t *testing.T) { +// returnError = true +// result, err := amt.GetVersionDataFromME("", 16*time.Second) +// assert.Equal(t, "amt internal error", err.Error()) +// assert.Equal(t, "", result) +// } func TestGetIsAMTEnabled(t *testing.T) { result, err := amt.GetChangeEnabled() assert.NoError(t, err) diff --git a/internal/config/local.go b/internal/config/local.go index c187b7cd..1fa9ae72 100644 --- a/internal/config/local.go +++ b/internal/config/local.go @@ -2,13 +2,12 @@ package config type ( Config struct { - Password string `yaml:"password"` - WifiConfigs `yaml:"wifiConfigs"` - Ieee8021xConfigs `yaml:"ieee8021xConfigs"` - ACMSettings `yaml:"acmactivate"` + Password string `yaml:"password"` + WifiConfigs []WifiConfig `yaml:"wifiConfigs"` + Ieee8021xConfigs []Ieee8021xConfig `yaml:"ieee8021xConfigs"` + ACMSettings ACMSettings `yaml:"acmactivate"` } - WifiConfigs []WifiConfig - WifiConfig struct { + WifiConfig struct { ProfileName string `yaml:"profileName"` SSID string `yaml:"ssid"` Priority int `yaml:"priority"` @@ -26,8 +25,7 @@ type ( PrivateKey string `yaml:"privateKey"` Password string `yaml:"password"` } - Ieee8021xConfigs []Ieee8021xConfig - Ieee8021xConfig struct { + Ieee8021xConfig struct { ProfileName string `yaml:"profileName"` Username string `yaml:"username"` Password string `yaml:"password"` diff --git a/internal/flags/activate.go b/internal/flags/activate.go index 35900a77..687e3e34 100644 --- a/internal/flags/activate.go +++ b/internal/flags/activate.go @@ -9,7 +9,7 @@ import ( log "github.com/sirupsen/logrus" ) -func (f *Flags) handleActivateCommand() utils.ReturnCode { +func (f *Flags) handleActivateCommand() error { f.amtActivateCommand.StringVar(&f.DNS, "d", f.lookupEnvOrString("DNS_SUFFIX", ""), "dns suffix override") f.amtActivateCommand.StringVar(&f.Hostname, "h", f.lookupEnvOrString("HOSTNAME", ""), "hostname override") f.amtActivateCommand.StringVar(&f.Profile, "profile", f.lookupEnvOrString("PROFILE", ""), "name of the profile to use") @@ -34,20 +34,19 @@ func (f *Flags) handleActivateCommand() utils.ReturnCode { } if err := f.amtActivateCommand.Parse(f.commandLineArgs[2:]); err != nil { re := regexp.MustCompile(`: .*`) - var rc = utils.IncorrectCommandLineParameters switch re.FindString(err.Error()) { case ": -d": - rc = utils.MissingDNSSuffix + err = utils.MissingDNSSuffix case ": -p": - rc = utils.MissingProxyAddressAndPort + err = utils.MissingProxyAddressAndPort case ": -h": - rc = utils.MissingHostname + err = utils.MissingHostname case ": -profile": - rc = utils.MissingOrIncorrectProfile + err = utils.MissingOrIncorrectProfile default: - rc = utils.IncorrectCommandLineParameters + err = utils.IncorrectCommandLineParameters } - return rc + return err } if f.Local && f.URL != "" { fmt.Println("provide either a 'url' or a 'local', but not both") @@ -66,10 +65,10 @@ func (f *Flags) handleActivateCommand() utils.ReturnCode { return utils.MissingOrIncorrectProfile } if f.UUID != "" { - rc := f.validateUUIDOverride() - if rc != utils.Success { + err := f.validateUUIDOverride() + if err != nil { f.amtActivateCommand.Usage() - return rc + return utils.InvalidUUID } fmt.Println("Warning: Overriding UUID prevents device from connecting to MPS") } @@ -80,9 +79,9 @@ func (f *Flags) handleActivateCommand() utils.ReturnCode { } if f.UseACM { - rc := f.handleLocalConfig() - if rc != utils.Success { - return rc + err := f.handleLocalConfig() + if err != nil { + return utils.FailedReadingConfiguration } // Check if all fields are filled v := reflect.ValueOf(f.LocalConfig.ACMSettings) @@ -97,7 +96,7 @@ func (f *Flags) handleActivateCommand() utils.ReturnCode { // Only for CCM it asks for password. if !f.UseACM && f.Password == "" { - if _, rc := f.ReadPasswordFromUser(); rc != utils.Success { + if _, rc := f.ReadPasswordFromUser(); rc != nil { return utils.MissingOrIncorrectPassword } } @@ -109,5 +108,5 @@ func (f *Flags) handleActivateCommand() utils.ReturnCode { return utils.InvalidParameterCombination } } - return utils.Success + return nil } diff --git a/internal/flags/activate_test.go b/internal/flags/activate_test.go index c6b6f412..579a3672 100644 --- a/internal/flags/activate_test.go +++ b/internal/flags/activate_test.go @@ -21,7 +21,7 @@ func TestHandleActivateCommand(t *testing.T) { flags := NewFlags(args) var AMTTimeoutDuration time.Duration = 120000000000 rc := flags.ParseFlags() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, "profileName", flags.Profile) assert.Equal(t, utils.CommandActivate, flags.Command) @@ -38,7 +38,7 @@ func TestHandleActivateCommandWithTimeOut(t *testing.T) { flags := NewFlags(args) var AMTTimeoutDuration time.Duration = 2000000000 rc := flags.ParseFlags() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, "profileName", flags.Profile) assert.Equal(t, utils.CommandActivate, flags.Command) @@ -51,7 +51,7 @@ func TestHandleActivateCommandWithLMS(t *testing.T) { args := []string{"./rpc", "activate", "-u", "wss://localhost", "-profile", "profileName", "-lmsaddress", "1.1.1.1", "-lmsport", "99"} flags := NewFlags(args) rc := flags.ParseFlags() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, "profileName", flags.Profile) assert.Equal(t, utils.CommandActivate, flags.Command) @@ -62,7 +62,7 @@ func TestHandleActivateCommandWithFriendlyName(t *testing.T) { args := []string{"./rpc", "activate", "-u", "wss://localhost", "-profile", "profileName", "-name", "friendlyName"} flags := NewFlags(args) rc := flags.ParseFlags() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, "profileName", flags.Profile) assert.Equal(t, utils.CommandActivate, flags.Command) @@ -86,7 +86,7 @@ func TestHandleActivateCommandWithENV(t *testing.T) { args := []string{"./rpc", "activate", "-u", "wss://localhost"} flags := NewFlags(args) rc := flags.ParseFlags() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, "envprofile", flags.Profile) assert.Equal(t, utils.CommandActivate, flags.Command) @@ -102,7 +102,7 @@ func TestActivateOverrideUUID(t *testing.T) { args := []string{"./rpc", "activate", "-u", "wss://localhost", "-uuid", "4c2e8db8-1c7a-00ea-279c-d17395b1f584"} flags := NewFlags(args) rc := flags.ParseFlags() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, flags.UUID, "4c2e8db8-1c7a-00ea-279c-d17395b1f584") os.Clearenv() } @@ -198,7 +198,7 @@ func TestHandleActivateCommandLocal(t *testing.T) { tests := map[string]struct { cmdLine string - wantResult utils.ReturnCode + wantResult error }{ "should fail with both URL and local": { cmdLine: "./rpc activate -local -u wss://localhost", @@ -226,14 +226,14 @@ func TestHandleActivateCommandLocal(t *testing.T) { }, "should pass if acm with example config file": { cmdLine: "./rpc activate -local -acm -config ../../config.yaml", - wantResult: utils.Success, + wantResult: nil, }, "should pass wif acm and ACM Settings specified": { cmdLine: "./rpc activate -local -acm " + " -amtPassword " + trickyPassword + ` -provisioningCert MIIW/gIBAzCCFroGCSqGSIb3DQEHAaCCFqsEghanMIIWozCCBgwGCSqGSIb3DQEHAaCCBf0EggX5MIIF9TCCBfEGCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvc` + " -provisioningCertPwd " + trickyPassword, - wantResult: utils.Success, + wantResult: nil, }, } diff --git a/internal/flags/configure.go b/internal/flags/configure.go index 76d3bc1b..6189bdf4 100644 --- a/internal/flags/configure.go +++ b/internal/flags/configure.go @@ -10,7 +10,8 @@ import ( "rpc/internal/config" "rpc/pkg/utils" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/models" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/ips/ieee8021x" "github.com/ilyakaznacheev/cleanenv" log "github.com/sirupsen/logrus" @@ -77,35 +78,39 @@ func (f *Flags) printConfigurationUsage() string { usage += " Example: " + baseCommand + " " + utils.SubCommandAddWifiSettings + " -password YourAMTPassword -config wificonfig.yaml\n" usage += " " + utils.SubCommandEnableWifiPort + " Enables WiFi port and local profile synchronization settings in AMT. AMT password is required.\n" usage += " Example: " + baseCommand + " " + utils.SubCommandEnableWifiPort + " -password YourAMTPassword\n" - usage += " " + utils.SubCommandConfigureTLS + " Configures TLS in AMT. AMT password is required.\n" + usage += " " + utils.SubCommandConfigureTLS + " Configures TLS in AMT. AMT password is required.\n" usage += " Example: " + baseCommand + " " + utils.SubCommandConfigureTLS + " -mode Server -password YourAMTPassword\n" + usage += " " + utils.SubCommandSetMEBx + " Configure MEBx Password. AMT password is required.\n" + usage += " Example: " + baseCommand + " " + utils.SubCommandConfigureTLS + " -mebxpassword YourMEBxPassword -password YourAMTPassword\n" usage += "\nRun '" + baseCommand + " COMMAND -h' for more information on a command.\n" fmt.Println(usage) return usage } -func (f *Flags) handleConfigureCommand() utils.ReturnCode { +func (f *Flags) handleConfigureCommand() error { if len(f.commandLineArgs) == 2 { f.printConfigurationUsage() return utils.IncorrectCommandLineParameters } - var rc = utils.Success + var err error f.SubCommand = f.commandLineArgs[2] switch f.SubCommand { case utils.SubCommandAddWifiSettings: - rc = f.handleAddWifiSettings() + err = f.handleAddWifiSettings() case utils.SubCommandEnableWifiPort: - rc = f.handleEnableWifiPort() + err = f.handleEnableWifiPort() case utils.SubCommandConfigureTLS: - rc = f.handleConfigureTLS() + err = f.handleConfigureTLS() + case utils.SubCommandSetMEBx: + err = f.handleMEBxPassword() default: f.printConfigurationUsage() - rc = utils.IncorrectCommandLineParameters + err = utils.IncorrectCommandLineParameters } - if rc != utils.Success { - return rc + if err != nil { + return err } f.Local = true @@ -113,7 +118,7 @@ func (f *Flags) handleConfigureCommand() utils.ReturnCode { if f.LocalConfig.Password != "" { f.Password = f.LocalConfig.Password } else { - if _, rc = f.ReadPasswordFromUser(); rc != utils.Success { + if _, err = f.ReadPasswordFromUser(); err != nil { return utils.MissingOrIncorrectPassword } f.LocalConfig.Password = f.Password @@ -126,7 +131,45 @@ func (f *Flags) handleConfigureCommand() utils.ReturnCode { return utils.MissingOrIncorrectPassword } } - return utils.Success + return nil +} + +func (f *Flags) handleMEBxPassword() error { + var err error + if len(f.commandLineArgs) == 3 { + f.printConfigurationUsage() + return utils.IncorrectCommandLineParameters + } + f.flagSetMEBx.BoolVar(&f.Verbose, "v", false, "Verbose output") + f.flagSetMEBx.StringVar(&f.LogLevel, "l", "info", "Log level (panic,fatal,error,warn,info,debug,trace)") + f.flagSetMEBx.BoolVar(&f.JsonOutput, "json", false, "JSON output") + f.flagSetMEBx.StringVar(&f.Password, "password", f.lookupEnvOrString("AMT_PASSWORD", ""), "AMT password") + f.flagSetMEBx.StringVar(&f.MEBxPassword, "mebxpassword", f.lookupEnvOrString("MEBX_PASSWORD", ""), "MEBX password") + + if err = f.flagSetMEBx.Parse(f.commandLineArgs[3:]); err != nil { + f.printConfigurationUsage() + return utils.IncorrectCommandLineParameters + } + return nil +} + +func (f *Flags) handleEnableWifiPort() error { + var err error + // var rc error + if len(f.commandLineArgs) > 5 { + f.printConfigurationUsage() + return utils.IncorrectCommandLineParameters + } + f.flagSetEnableWifiPort.BoolVar(&f.Verbose, "v", false, "Verbose output") + f.flagSetEnableWifiPort.StringVar(&f.LogLevel, "l", "info", "Log level (panic,fatal,error,warn,info,debug,trace)") + f.flagSetEnableWifiPort.BoolVar(&f.JsonOutput, "json", false, "JSON output") + f.flagSetEnableWifiPort.StringVar(&f.Password, "password", f.lookupEnvOrString("AMT_PASSWORD", ""), "AMT password") + + if err = f.flagSetEnableWifiPort.Parse(f.commandLineArgs[3:]); err != nil { + f.printConfigurationUsage() + return utils.IncorrectCommandLineParameters + } + return nil } func (f *Flags) NewConfigureFlagSet(subCommand string) *flag.FlagSet { @@ -139,7 +182,7 @@ func (f *Flags) NewConfigureFlagSet(subCommand string) *flag.FlagSet { return fs } -func (f *Flags) handleConfigureTLS() utils.ReturnCode { +func (f *Flags) handleConfigureTLS() error { fs := f.NewConfigureFlagSet(utils.SubCommandConfigureTLS) tlsModeUsage := fmt.Sprintf("TLS authentication usage model (%s) (default %s)", TLSModesToString(), f.ConfigTLSInfo.TLSMode) fs.Func("mode", tlsModeUsage, func(flagValue string) error { @@ -148,51 +191,56 @@ func (f *Flags) handleConfigureTLS() utils.ReturnCode { return e }) fs.IntVar(&f.ConfigTLSInfo.DelayInSeconds, "delay", 3, "Delay time in seconds after putting remote TLS settings") - return f.parseAndCheckArgCount(fs, 3, 0) -} - -func (f *Flags) handleEnableWifiPort() utils.ReturnCode { - fs := f.NewConfigureFlagSet(utils.SubCommandEnableWifiPort) - return f.parseAndCheckArgCount(fs, 3, 0) + if len(f.commandLineArgs) < (3 + 0) { + fs.Usage() + return utils.IncorrectCommandLineParameters + } + if err := fs.Parse(f.commandLineArgs[3:]); err != nil { + return utils.IncorrectCommandLineParameters + } + if len(fs.Args()) > 0 { + fmt.Printf("unhandled additional args: %v\n", fs.Args()) + fs.Usage() + return utils.IncorrectCommandLineParameters + } + return nil } -func (f *Flags) handleAddWifiSettings() utils.ReturnCode { +func (f *Flags) handleAddWifiSettings() error { var err error - var rc utils.ReturnCode var secretsFilePath string var wifiSecretConfig config.SecretConfig var configJson string - fs := f.NewConfigureFlagSet(utils.SubCommandAddWifiSettings) - fs.StringVar(&f.configContent, "config", "", "specify a config file or smb: file share URL") - fs.StringVar(&configJson, "configJson", "", "configuration as a JSON string") - fs.StringVar(&secretsFilePath, "secrets", "", "specify a secrets file ") + f.flagSetAddWifiSettings.StringVar(&f.configContent, "config", "", "specify a config file or smb: file share URL") + f.flagSetAddWifiSettings.StringVar(&configJson, "configJson", "", "configuration as a JSON string") + f.flagSetAddWifiSettings.StringVar(&secretsFilePath, "secrets", "", "specify a secrets file ") // Params for entering a single wifi config from command line wifiCfg := config.WifiConfig{} ieee8021xCfg := config.Ieee8021xConfig{} - fs.StringVar(&wifiCfg.ProfileName, "profileName", "", "specify wifi profile name name") - fs.IntVar(&wifiCfg.AuthenticationMethod, "authenticationMethod", 0, "specify authentication method") - fs.IntVar(&wifiCfg.EncryptionMethod, "encryptionMethod", 0, "specify encryption method") - fs.StringVar(&wifiCfg.SSID, "ssid", "", "specify ssid") - fs.StringVar(&wifiCfg.PskPassphrase, "pskPassphrase", f.lookupEnvOrString("PSK_PASSPHRASE", ""), "specify psk passphrase") - fs.IntVar(&wifiCfg.Priority, "priority", 0, "specify priority") - fs.StringVar(&ieee8021xCfg.Username, "username", "", "specify username") - fs.StringVar(&ieee8021xCfg.Password, "ieee8021xPassword", f.lookupEnvOrString("IEE8021X_PASSWORD", ""), "8021x password if authenticationProtocol is PEAPv0/EAP-MSCHAPv2(2)") - fs.IntVar(&ieee8021xCfg.AuthenticationProtocol, "authenticationProtocol", 0, "specify authentication protocol") - fs.StringVar(&ieee8021xCfg.ClientCert, "clientCert", "", "specify client certificate") - fs.StringVar(&ieee8021xCfg.CACert, "caCert", "", "specify CA certificate") - fs.StringVar(&ieee8021xCfg.PrivateKey, "privateKey", f.lookupEnvOrString("IEE8021X_PRIVATE_KEY", ""), "specify private key") + f.flagSetAddWifiSettings.StringVar(&wifiCfg.ProfileName, "profileName", "", "specify wifi profile name name") + f.flagSetAddWifiSettings.IntVar(&wifiCfg.AuthenticationMethod, "authenticationMethod", 0, "specify authentication method") + f.flagSetAddWifiSettings.IntVar(&wifiCfg.EncryptionMethod, "encryptionMethod", 0, "specify encryption method") + f.flagSetAddWifiSettings.StringVar(&wifiCfg.SSID, "ssid", "", "specify ssid") + f.flagSetAddWifiSettings.StringVar(&wifiCfg.PskPassphrase, "pskPassphrase", f.lookupEnvOrString("PSK_PASSPHRASE", ""), "specify psk passphrase") + f.flagSetAddWifiSettings.IntVar(&wifiCfg.Priority, "priority", 0, "specify priority") + f.flagSetAddWifiSettings.StringVar(&ieee8021xCfg.Username, "username", "", "specify username") + f.flagSetAddWifiSettings.StringVar(&ieee8021xCfg.Password, "ieee8021xPassword", f.lookupEnvOrString("IEE8021X_PASSWORD", ""), "8021x password if authenticationProtocol is PEAPv0/EAP-MSCHAPv2(2)") + f.flagSetAddWifiSettings.IntVar(&ieee8021xCfg.AuthenticationProtocol, "authenticationProtocol", 0, "specify authentication protocol") + f.flagSetAddWifiSettings.StringVar(&ieee8021xCfg.ClientCert, "clientCert", "", "specify client certificate") + f.flagSetAddWifiSettings.StringVar(&ieee8021xCfg.CACert, "caCert", "", "specify CA certificate") + f.flagSetAddWifiSettings.StringVar(&ieee8021xCfg.PrivateKey, "privateKey", f.lookupEnvOrString("IEE8021X_PRIVATE_KEY", ""), "specify private key") // rpc configure addwifisettings -configstring "{ prop: val, prop2: val }" // rpc configure add -config "filename" -secrets "someotherfile" - rc = f.parseAndCheckArgCount(fs, 3, 2) - if rc != utils.Success { - return rc + if err = f.flagSetAddWifiSettings.Parse(f.commandLineArgs[3:]); err != nil { + f.printConfigurationUsage() + return utils.IncorrectCommandLineParameters } if wifiCfg.ProfileName != "" { - authMethod := models.AuthenticationMethod(wifiCfg.AuthenticationMethod) - if authMethod == models.AuthenticationMethod_WPA_IEEE8021x || - authMethod == models.AuthenticationMethod_WPA2_IEEE8021x { + authMethod := wifi.AuthenticationMethod(wifiCfg.AuthenticationMethod) + if authMethod == wifi.AuthenticationMethod_WPA_IEEE8021x || + authMethod == wifi.AuthenticationMethod_WPA2_IEEE8021x { // reuse profilename as configuration reference wifiCfg.Ieee8021xProfileName = wifiCfg.ProfileName ieee8021xCfg.ProfileName = wifiCfg.ProfileName @@ -201,9 +249,9 @@ func (f *Flags) handleAddWifiSettings() utils.ReturnCode { f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfg) f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfg) - rc = f.handleLocalConfig() - if rc != utils.Success { - return rc + err = f.handleLocalConfig() + if err != nil { + return utils.FailedReadingConfiguration } if configJson != "" { err := json.Unmarshal([]byte(configJson), &f.LocalConfig) @@ -227,25 +275,25 @@ func (f *Flags) handleAddWifiSettings() utils.ReturnCode { } // merge secrets with configs - rc = f.mergeWifiSecrets(wifiSecretConfig) - if rc != utils.Success { - return rc + err = f.mergeWifiSecrets(wifiSecretConfig) + if err != nil { + return err } // prompt for missing secrets - rc = f.promptForSecrets() - if rc != utils.Success { - return rc + err = f.promptForSecrets() + if err != nil { + return err } // verify configs - rc = f.verifyWifiConfigurations() - if rc != utils.Success { - return rc + err = f.verifyWifiConfigurations() + if err != nil { + return err } - return utils.Success + return nil } -func (f *Flags) mergeWifiSecrets(wifiSecretConfig config.SecretConfig) utils.ReturnCode { +func (f *Flags) mergeWifiSecrets(wifiSecretConfig config.SecretConfig) error { for _, secret := range wifiSecretConfig.Secrets { if secret.ProfileName == "" { continue @@ -275,21 +323,21 @@ func (f *Flags) mergeWifiSecrets(wifiSecretConfig config.SecretConfig) utils.Ret } } } - return utils.Success + return nil } -func (f *Flags) promptForSecrets() utils.ReturnCode { +func (f *Flags) promptForSecrets() error { for i := range f.LocalConfig.WifiConfigs { item := &f.LocalConfig.WifiConfigs[i] if item.ProfileName == "" { continue } - authMethod := models.AuthenticationMethod(item.AuthenticationMethod) - if (authMethod == models.AuthenticationMethod_WPA_PSK || authMethod == models.AuthenticationMethod_WPA2_PSK) && + authMethod := wifi.AuthenticationMethod(item.AuthenticationMethod) + if (authMethod == wifi.AuthenticationMethod_WPA_PSK || authMethod == wifi.AuthenticationMethod_WPA2_PSK) && item.PskPassphrase == "" { - rc := f.PromptUserInput("Please enter PskPassphrase for "+item.ProfileName+": ", &item.PskPassphrase) - if rc != utils.Success { - return rc + err := f.PromptUserInput("Please enter PskPassphrase for "+item.ProfileName+": ", &item.PskPassphrase) + if err != nil { + return err } } } @@ -298,24 +346,24 @@ func (f *Flags) promptForSecrets() utils.ReturnCode { if item.ProfileName == "" { continue } - authProtocol := models.AuthenticationProtocol(item.AuthenticationProtocol) - if authProtocol == models.AuthenticationProtocolPEAPv0_EAPMSCHAPv2 && item.Password == "" { - rc := f.PromptUserInput("Please enter password for "+item.ProfileName+": ", &item.Password) - if rc != utils.Success { - return rc + authProtocol := ieee8021x.AuthenticationProtocol(item.AuthenticationProtocol) + if authProtocol == ieee8021x.AuthenticationProtocolPEAPv0_EAPMSCHAPv2 && item.Password == "" { + err := f.PromptUserInput("Please enter password for "+item.ProfileName+": ", &item.Password) + if err != nil { + return err } } - if authProtocol == models.AuthenticationProtocolEAPTLS && item.PrivateKey == "" { - rc := f.PromptUserInput("Please enter private key for "+item.ProfileName+": ", &item.PrivateKey) - if rc != utils.Success { - return rc + if authProtocol == ieee8021x.AuthenticationProtocolEAPTLS && item.PrivateKey == "" { + err := f.PromptUserInput("Please enter private key for "+item.ProfileName+": ", &item.PrivateKey) + if err != nil { + return err } } } - return utils.Success + return nil } -func (f *Flags) verifyWifiConfigurations() utils.ReturnCode { +func (f *Flags) verifyWifiConfigurations() error { priorities := make(map[int]bool) for _, cfg := range f.LocalConfig.WifiConfigs { //Check profile name is not empty @@ -340,19 +388,19 @@ func (f *Flags) verifyWifiConfigurations() utils.ReturnCode { } priorities[cfg.Priority] = true - authenticationMethod := models.AuthenticationMethod(cfg.AuthenticationMethod) + authenticationMethod := wifi.AuthenticationMethod(cfg.AuthenticationMethod) switch authenticationMethod { - case models.AuthenticationMethod_WPA_PSK: + case wifi.AuthenticationMethod_WPA_PSK: fallthrough - case models.AuthenticationMethod_WPA2_PSK: + case wifi.AuthenticationMethod_WPA2_PSK: if cfg.PskPassphrase == "" { log.Error("missing PskPassphrase for config: ", cfg.ProfileName) return utils.MissingOrInvalidConfiguration } break - case models.AuthenticationMethod_WPA_IEEE8021x: + case wifi.AuthenticationMethod_WPA_IEEE8021x: fallthrough - case models.AuthenticationMethod_WPA2_IEEE8021x: + case wifi.AuthenticationMethod_WPA2_IEEE8021x: if cfg.ProfileName == "" { log.Error("missing ieee8021x profile name") return utils.MissingOrInvalidConfiguration @@ -361,30 +409,30 @@ func (f *Flags) verifyWifiConfigurations() utils.ReturnCode { log.Errorf("wifi configuration for 8021x contains passphrase: %s", cfg.ProfileName) return utils.MissingOrInvalidConfiguration } - rc := f.verifyMatchingIeee8021xConfig(cfg.Ieee8021xProfileName) - if rc != utils.Success { - return rc + err := f.verifyMatchingIeee8021xConfig(cfg.Ieee8021xProfileName) + if err != nil { + return err } break - case models.AuthenticationMethod_Other: + case wifi.AuthenticationMethod_Other: log.Errorf("unsupported AuthenticationMethod_Other (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.AuthenticationMethod_OpenSystem: + case wifi.AuthenticationMethod_OpenSystem: log.Errorf("unsupported AuthenticationMethod_OpenSystem (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.AuthenticationMethod_SharedKey: + case wifi.AuthenticationMethod_SharedKey: log.Errorf("unsupported AuthenticationMethod_SharedKey (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.AuthenticationMethod_DMTFReserved: + case wifi.AuthenticationMethod_DMTFReserved: log.Errorf("unsupported AuthenticationMethod_DMTFReserved (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.AuthenticationMethod_WPA3_SAE: + case wifi.AuthenticationMethod_WPA3_SAE: log.Errorf("unsupported AuthenticationMethod_WPA3_SAE (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.AuthenticationMethod_WPA3_OWE: + case wifi.AuthenticationMethod_WPA3_OWE: log.Errorf("unsupported AuthenticationMethod_WPA3_OWE (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.AuthenticationMethod_VendorReserved: + case wifi.AuthenticationMethod_VendorReserved: log.Errorf("unsupported AuthenticationMethod_VendorReserved (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration default: @@ -392,23 +440,23 @@ func (f *Flags) verifyWifiConfigurations() utils.ReturnCode { return utils.MissingOrInvalidConfiguration } - encryptionMethod := models.EncryptionMethod(cfg.EncryptionMethod) + encryptionMethod := wifi.EncryptionMethod(cfg.EncryptionMethod) // NOTE: this is only switch encryptionMethod { - case models.EncryptionMethod_TKIP: + case wifi.EncryptionMethod_TKIP: fallthrough - case models.EncryptionMethod_CCMP: + case wifi.EncryptionMethod_CCMP: break - case models.EncryptionMethod_Other: + case wifi.EncryptionMethod_Other: log.Errorf("unsupported EncryptionMethod_Other (%d) for config: %s", cfg.EncryptionMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.EncryptionMethod_WEP: + case wifi.EncryptionMethod_WEP: log.Errorf("unsupported EncryptionMethod_WEP (%d) for config: %s", cfg.EncryptionMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.EncryptionMethod_None: + case wifi.EncryptionMethod_None: log.Errorf("unsupported EncryptionMethod_None (%d) for config: %s", cfg.EncryptionMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration - case models.EncryptionMethod_DMTFReserved: + case wifi.EncryptionMethod_DMTFReserved: log.Errorf("unsupported EncryptionMethod_DMTFReserved (%d) for config: %s", cfg.EncryptionMethod, cfg.ProfileName) return utils.MissingOrInvalidConfiguration default: @@ -416,10 +464,10 @@ func (f *Flags) verifyWifiConfigurations() utils.ReturnCode { return utils.MissingOrInvalidConfiguration } } - return utils.Success + return nil } -func (f *Flags) verifyMatchingIeee8021xConfig(profileName string) utils.ReturnCode { +func (f *Flags) verifyMatchingIeee8021xConfig(profileName string) error { foundOne := false for _, ieee802xCfg := range f.LocalConfig.Ieee8021xConfigs { if profileName != ieee802xCfg.ProfileName { @@ -427,81 +475,82 @@ func (f *Flags) verifyMatchingIeee8021xConfig(profileName string) utils.ReturnCo } if foundOne { log.Error("duplicate IEEE802x Profile names: ", ieee802xCfg.ProfileName) + return utils.MissingOrInvalidConfiguration } foundOne = true - rc := f.verifyIeee8021xConfig(ieee802xCfg) - if rc != utils.Success { - return rc + err := f.verifyIeee8021xConfig(ieee802xCfg) + if err != nil { + return utils.MissingOrInvalidConfiguration } } if !foundOne { log.Error("missing IEEE802x Profile: ", profileName) return utils.MissingOrInvalidConfiguration } - return utils.Success + return nil } -func (f *Flags) verifyIeee8021xConfig(cfg config.Ieee8021xConfig) utils.ReturnCode { - +func (f *Flags) verifyIeee8021xConfig(cfg config.Ieee8021xConfig) error { + var err error = utils.MissingOrInvalidConfiguration if cfg.Username == "" { log.Error("missing username for config: ", cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err } if cfg.CACert == "" { log.Error("missing caCert for config: ", cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err } - authenticationProtocol := models.AuthenticationProtocol(cfg.AuthenticationProtocol) + authenticationProtocol := ieee8021x.AuthenticationProtocol(cfg.AuthenticationProtocol) // not all defined protocols are supported switch authenticationProtocol { - case models.AuthenticationProtocolEAPTLS: + case ieee8021x.AuthenticationProtocolEAPTLS: if cfg.ClientCert == "" { log.Error("missing clientCert for config: ", cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err } if cfg.PrivateKey == "" { log.Error("missing privateKey for config: ", cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err } break - case models.AuthenticationProtocolPEAPv0_EAPMSCHAPv2: + case ieee8021x.AuthenticationProtocolPEAPv0_EAPMSCHAPv2: if cfg.Password == "" { log.Error("missing password for for PEAPv0_EAPMSCHAPv2 config: ", cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err } break - case models.AuthenticationProtocolEAPTTLS_MSCHAPv2: + case ieee8021x.AuthenticationProtocolEAPTTLS_MSCHAPv2: log.Errorf("unsupported AuthenticationProtocolEAPTTLS_MSCHAPv2 (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolPEAPv1_EAPGTC: + return err + case ieee8021x.AuthenticationProtocolPEAPv1_EAPGTC: log.Errorf("unsupported AuthenticationProtocolPEAPv1_EAPGTC (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAPFAST_MSCHAPv2: + return err + case ieee8021x.AuthenticationProtocolEAPFAST_MSCHAPv2: log.Errorf("unsupported AuthenticationProtocolEAPFAST_MSCHAPv2 (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAPFAST_GTC: + return err + case ieee8021x.AuthenticationProtocolEAPFAST_GTC: log.Errorf("unsupported AuthenticationProtocolEAPFAST_GTC (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAP_MD5: + return err + case ieee8021x.AuthenticationProtocolEAP_MD5: log.Errorf("unsupported AuthenticationProtocolEAP_MD5 (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAP_PSK: + return err + case ieee8021x.AuthenticationProtocolEAP_PSK: log.Errorf("unsupported AuthenticationProtocolEAP_PSK (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAP_SIM: + return err + case ieee8021x.AuthenticationProtocolEAP_SIM: log.Errorf("unsupported AuthenticationProtocolEAP_SIM (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAP_AKA: + return err + case ieee8021x.AuthenticationProtocolEAP_AKA: log.Errorf("unsupported AuthenticationProtocolEAP_AKA (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration - case models.AuthenticationProtocolEAPFAST_TLS: + return err + case ieee8021x.AuthenticationProtocolEAPFAST_TLS: log.Errorf("unsupported AuthenticationProtocolEAPFAST_TLS (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err default: log.Errorf("invalid AuthenticationProtocol (%d) for config: %s", cfg.AuthenticationProtocol, cfg.ProfileName) - return utils.MissingOrInvalidConfiguration + return err } - return utils.Success + return nil } diff --git a/internal/flags/configure_test.go b/internal/flags/configure_test.go index 978cb25d..b3c18035 100644 --- a/internal/flags/configure_test.go +++ b/internal/flags/configure_test.go @@ -8,7 +8,9 @@ import ( "strings" "testing" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/models" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/models" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/ips/ieee8021x" "github.com/stretchr/testify/assert" ) @@ -30,7 +32,7 @@ func TestPromptForSecrets(t *testing.T) { defer userInput(t, "userInput\nuserInput\nuserInput")() f := getPromptForSecretsFlags() rc := f.promptForSecrets() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) assert.Equal(t, "userInput", f.LocalConfig.WifiConfigs[0].PskPassphrase) assert.Equal(t, "userInput", f.LocalConfig.Ieee8021xConfigs[0].PrivateKey) assert.Equal(t, "userInput", f.LocalConfig.Ieee8021xConfigs[1].Password) @@ -81,7 +83,7 @@ func TestHandleConfigureCommand(t *testing.T) { } f := NewFlags(cmdLine) gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) + assert.Equal(t, nil, gotResult) assert.Equal(t, true, f.Local) assert.Equal(t, f.Password, f.LocalConfig.Password) }) @@ -93,7 +95,7 @@ func TestHandleConfigureCommand(t *testing.T) { } f := NewFlags(cmdLine) gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) + assert.Equal(t, nil, gotResult) assert.Equal(t, expected, f.Password) }) t.Run("expect Success password from environment", func(t *testing.T) { @@ -106,7 +108,7 @@ func TestHandleConfigureCommand(t *testing.T) { } f := NewFlags(cmdLine) gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) + assert.Equal(t, nil, gotResult) assert.Equal(t, expected, f.Password) if origPresent { err = os.Setenv("AMT_PASSWORD", orig) @@ -128,8 +130,7 @@ func TestAddWifiSettings(t *testing.T) { } f := NewFlags(cmdLine) gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) - assert.Equal(t, utils.SubCommandAddWifiSettings, f.SubCommand) + assert.Equal(t, nil, gotResult) assert.Equal(t, true, f.Local) assert.Equal(t, f.Password, f.LocalConfig.Password) }) @@ -148,7 +149,7 @@ func TestAddWifiSettings(t *testing.T) { `-configJson`, jsonCfgStr, }) gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) + assert.Equal(t, nil, gotResult) }) t.Run("expect Success when password is in config file", func(t *testing.T) { defer userInput(t, "userP@ssw0rd!")() @@ -158,7 +159,7 @@ func TestAddWifiSettings(t *testing.T) { }) f.LocalConfig.Password = "localP@ssw0rd!" gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) + assert.Equal(t, nil, gotResult) }) t.Run("expect MissingOrIncorrectPassword when passwords do not match", func(t *testing.T) { f := NewFlags([]string{ @@ -181,10 +182,24 @@ func TestEnableWifiPort(t *testing.T) { } f := NewFlags(cmdLine) gotResult := f.ParseFlags() - assert.Equal(t, utils.Success, gotResult) - assert.Equal(t, utils.SubCommandEnableWifiPort, f.SubCommand) + assert.Equal(t, nil, gotResult) assert.Equal(t, true, f.Local) - assert.Equal(t, f.Password, expectedPassword) + assert.Equal(t, f.Password, f.LocalConfig.Password) + }) + t.Run("enablewifiport: expect MissingOrIncorrectPassword", func(t *testing.T) { + f := NewFlags([]string{ + `rpc`, `configure`, `enablewifiport`, `-password`, + }) + gotResult := f.ParseFlags() + assert.Equal(t, utils.IncorrectCommandLineParameters, gotResult) + }) + t.Run("enablewifiport: expect Success on password prompt", func(t *testing.T) { + defer userInput(t, "userP@ssw0rd!")() + f := NewFlags([]string{ + `rpc`, `configure`, `enablewifiport`, + }) + gotResult := f.ParseFlags() + assert.Equal(t, nil, gotResult) }) t.Run("enablewifiport: expect IncorrectCommandLineParameters", func(t *testing.T) { f := NewFlags([]string{ @@ -258,14 +273,14 @@ func TestConfigJson(t *testing.T) { args := strings.Fields(cmdLine) flags := NewFlags(args) gotResult := flags.ParseFlags() - assert.Equal(t, utils.Success, gotResult) + assert.Equal(t, nil, gotResult) } func TestHandleAddWifiSettings(t *testing.T) { cases := []struct { description string cmdLine string - expectedResult utils.ReturnCode + expectedResult error }{ {description: "Missing Ieee8021xProfileName value", cmdLine: "rpc configure addwifisettings -password Passw0rd! -profilename cliprofname -authenticationMethod 6 -encryptionMethod 4 -ssid \"myclissid\" -priority 1 -PskPassphrase \"mypassword\" -Ieee8021xProfileName", @@ -309,11 +324,11 @@ func TestHandleAddWifiSettings(t *testing.T) { }, {description: "Basic wifi config command line", cmdLine: `rpc configure addwifisettings -password Passw0rd! -profileName cliprofname -authenticationMethod 6 -encryptionMethod 4 -ssid "myclissid" -priority 1 -pskPassphrase "mypassword"`, - expectedResult: utils.Success, + expectedResult: nil, }, {description: "Valid with reading from file", cmdLine: "rpc configure addwifisettings -password Passw0rd! -config ../../config.yaml -secrets ../../secrets.yaml", - expectedResult: utils.Success, + expectedResult: nil, }, } for _, tc := range cases { @@ -330,8 +345,8 @@ var wifiCfgWPA = config.WifiConfig{ ProfileName: "wifiWPA", SSID: "ssid", Priority: 1, - AuthenticationMethod: int(models.AuthenticationMethod_WPA_PSK), - EncryptionMethod: int(models.EncryptionMethod_TKIP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA_PSK), + EncryptionMethod: int(wifi.EncryptionMethod_TKIP), PskPassphrase: "wifiWPAPassPhrase", } @@ -339,8 +354,8 @@ var wifiCfgWPA2 = config.WifiConfig{ ProfileName: "wifiWPA2", SSID: "ssid", Priority: 2, - AuthenticationMethod: int(models.AuthenticationMethod_WPA2_PSK), - EncryptionMethod: int(models.EncryptionMethod_CCMP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA2_PSK), + EncryptionMethod: int(wifi.EncryptionMethod_CCMP), PskPassphrase: "wifiWPA2PassPhrase", } @@ -348,8 +363,8 @@ var wifiCfgWPA8021xEAPTLS = config.WifiConfig{ ProfileName: "wifiWPA28021x", SSID: "ssid", Priority: 3, - AuthenticationMethod: int(models.AuthenticationMethod_WPA_IEEE8021x), - EncryptionMethod: int(models.EncryptionMethod_CCMP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA_IEEE8021x), + EncryptionMethod: int(wifi.EncryptionMethod_CCMP), Ieee8021xProfileName: "ieee8021xCfgEAPTLS", } @@ -367,8 +382,8 @@ var wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2 = config.WifiConfig{ ProfileName: "wifiWPA28021x", SSID: "ssid", Priority: 4, - AuthenticationMethod: int(models.AuthenticationMethod_WPA2_IEEE8021x), - EncryptionMethod: int(models.EncryptionMethod_CCMP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA2_IEEE8021x), + EncryptionMethod: int(wifi.EncryptionMethod_CCMP), Ieee8021xProfileName: "ieee8021xCfgPEAPv0_EAPMSCHAPv2", } @@ -376,20 +391,16 @@ var ieee8021xCfgPEAPv0_EAPMSCHAPv2 = config.Ieee8021xConfig{ ProfileName: "ieee8021xCfgPEAPv0_EAPMSCHAPv2", Username: "username", Password: "password", - AuthenticationProtocol: int(models.AuthenticationProtocolPEAPv0_EAPMSCHAPv2), + AuthenticationProtocol: int(ieee8021x.AuthenticationProtocolPEAPv0_EAPMSCHAPv2), ClientCert: "", CACert: "caCert", PrivateKey: "", } -func runVerifyWifiConfiguration(t *testing.T, expectedResult utils.ReturnCode, wifiCfgs config.WifiConfigs, ieee8021xCfgs config.Ieee8021xConfigs) { +func runVerifyWifiConfiguration(t *testing.T, expectedResult error, wifiCfgs []config.WifiConfig, ieee8021xCfgs []config.Ieee8021xConfig) { f := Flags{} - for _, cfg := range wifiCfgs { - f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, cfg) - } - for _, cfg := range ieee8021xCfgs { - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, cfg) - } + f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgs...) + f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgs...) gotResult := f.verifyWifiConfigurations() assert.Equal(t, expectedResult, gotResult) } @@ -397,86 +408,86 @@ func runVerifyWifiConfiguration(t *testing.T, expectedResult utils.ReturnCode, w func TestVerifyWifiConfiguration(t *testing.T) { t.Run("expect Success for correct configs", func(t *testing.T) { - runVerifyWifiConfiguration(t, utils.Success, - config.WifiConfigs{wifiCfgWPA, wifiCfgWPA2, wifiCfgWPA8021xEAPTLS, wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2}, - config.Ieee8021xConfigs{ieee8021xCfgEAPTLS, ieee8021xCfgPEAPv0_EAPMSCHAPv2}) + runVerifyWifiConfiguration(t, nil, + []config.WifiConfig{wifiCfgWPA, wifiCfgWPA2, wifiCfgWPA8021xEAPTLS, wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2}, + []config.Ieee8021xConfig{ieee8021xCfgEAPTLS, ieee8021xCfgPEAPv0_EAPMSCHAPv2}) }) t.Run("expect MissingOrInvalidConfiguration when missing ProfileName", func(t *testing.T) { orig := wifiCfgWPA.ProfileName wifiCfgWPA.ProfileName = "" runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA}, + []config.Ieee8021xConfig{}) wifiCfgWPA.ProfileName = orig }) t.Run("expect MissingOrInvalidConfiguration when missing SSID", func(t *testing.T) { orig := wifiCfgWPA.SSID wifiCfgWPA.SSID = "" runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA}, + []config.Ieee8021xConfig{}) wifiCfgWPA.SSID = orig }) t.Run("expect MissingOrInvalidConfiguration with invalid Priority", func(t *testing.T) { orig := wifiCfgWPA.Priority wifiCfgWPA.Priority = 0 runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA}, + []config.Ieee8021xConfig{}) wifiCfgWPA.Priority = orig }) t.Run("expect MissingOrInvalidConfiguration with duplicate Priority", func(t *testing.T) { orig := wifiCfgWPA.Priority wifiCfgWPA.Priority = wifiCfgWPA2.Priority runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA, wifiCfgWPA2}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA, wifiCfgWPA2}, + []config.Ieee8021xConfig{}) wifiCfgWPA.Priority = orig }) t.Run("expect MissingOrInvalidConfiguration with invalid AuthenticationMethod", func(t *testing.T) { orig := wifiCfgWPA.AuthenticationMethod - wifiCfgWPA.AuthenticationMethod = int(models.AuthenticationMethod_DMTFReserved) + wifiCfgWPA.AuthenticationMethod = int(wifi.AuthenticationMethod_DMTFReserved) runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA}, + []config.Ieee8021xConfig{}) wifiCfgWPA.AuthenticationMethod = orig }) t.Run("expect MissingOrInvalidConfiguration with invalid EncryptionMethod", func(t *testing.T) { orig := wifiCfgWPA.EncryptionMethod - wifiCfgWPA.EncryptionMethod = int(models.EncryptionMethod_DMTFReserved) + wifiCfgWPA.EncryptionMethod = int(wifi.EncryptionMethod_DMTFReserved) runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA}, + []config.Ieee8021xConfig{}) wifiCfgWPA.EncryptionMethod = orig }) t.Run("expect MissingOrInvalidConfiguration with missing passphrase", func(t *testing.T) { orig := wifiCfgWPA2.PskPassphrase wifiCfgWPA2.PskPassphrase = "" runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA2}, - config.Ieee8021xConfigs{}) + []config.WifiConfig{wifiCfgWPA2}, + []config.Ieee8021xConfig{}) wifiCfgWPA2.PskPassphrase = orig }) t.Run("expect MissingOrInvalidConfiguration with missing ieee8021x ProfileName", func(t *testing.T) { orig8021xName := ieee8021xCfgEAPTLS.ProfileName ieee8021xCfgEAPTLS.ProfileName = "" runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA8021xEAPTLS}, - config.Ieee8021xConfigs{ieee8021xCfgEAPTLS}) + []config.WifiConfig{wifiCfgWPA8021xEAPTLS}, + []config.Ieee8021xConfig{ieee8021xCfgEAPTLS}) ieee8021xCfgEAPTLS.ProfileName = orig8021xName }) t.Run("expect MissingOrInvalidConfiguration with PskPassphrase is present for ieee8021x profile", func(t *testing.T) { wifiCfgWPA8021xEAPTLS.PskPassphrase = "shouldn't be here" runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA8021xEAPTLS}, - config.Ieee8021xConfigs{ieee8021xCfgEAPTLS}) + []config.WifiConfig{wifiCfgWPA8021xEAPTLS}, + []config.Ieee8021xConfig{ieee8021xCfgEAPTLS}) wifiCfgWPA8021xEAPTLS.PskPassphrase = "" }) t.Run("expect MissingOrInvalidConfiguration with PskPassphrase is present for ieee8021x profile", func(t *testing.T) { wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2.PskPassphrase = "shouldn't be here" runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2}, - config.Ieee8021xConfigs{ieee8021xCfgPEAPv0_EAPMSCHAPv2}) + []config.WifiConfig{wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2}, + []config.Ieee8021xConfig{ieee8021xCfgPEAPv0_EAPMSCHAPv2}) wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2.PskPassphrase = "" }) @@ -486,12 +497,12 @@ func TestVerifyWifiConfiguration(t *testing.T) { wifiCfgWPA8021xEAPTLS.Ieee8021xProfileName = ieee8021xCfgPEAPv0_EAPMSCHAPv2.ProfileName // authMethod 5 runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA8021xEAPTLS}, - config.Ieee8021xConfigs{ieee8021xCfgEAPTLS, ieee8021xCfgPEAPv0_EAPMSCHAPv2}) + []config.WifiConfig{wifiCfgWPA8021xEAPTLS}, + []config.Ieee8021xConfig{ieee8021xCfgEAPTLS, ieee8021xCfgPEAPv0_EAPMSCHAPv2}) // authMethod 7 runVerifyWifiConfiguration(t, utils.MissingOrInvalidConfiguration, - config.WifiConfigs{wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2}, - config.Ieee8021xConfigs{ieee8021xCfgEAPTLS, ieee8021xCfgPEAPv0_EAPMSCHAPv2}) + []config.WifiConfig{wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2}, + []config.Ieee8021xConfig{ieee8021xCfgEAPTLS, ieee8021xCfgPEAPv0_EAPMSCHAPv2}) ieee8021xCfgEAPTLS.ProfileName = orig8021xName wifiCfgWPA8021xEAPTLS.Ieee8021xProfileName = ieee8021xCfgEAPTLS.ProfileName }) @@ -539,7 +550,7 @@ func TestVerifyMatchingIeee8021xConfig(t *testing.T) { t.Run("expect Success", func(t *testing.T) { f.LocalConfig.Ieee8021xConfigs[0].AuthenticationProtocol = int(models.AuthenticationProtocolEAPTLS) rc := f.verifyMatchingIeee8021xConfig(name) - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) }) t.Run("expect MissingOrInvalidConfiguration for unsupported AuthenticationProtocolEAPTTLS_MSCHAPv2", func(t *testing.T) { f.LocalConfig.Ieee8021xConfigs[0].AuthenticationProtocol = int(models.AuthenticationProtocolEAPTTLS_MSCHAPv2) @@ -552,15 +563,15 @@ func TestInvalidAuthenticationMethods(t *testing.T) { f := Flags{} f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgWPA) cases := []struct { - method models.AuthenticationMethod + method wifi.AuthenticationMethod }{ - {method: models.AuthenticationMethod_Other}, - {method: models.AuthenticationMethod_OpenSystem}, - {method: models.AuthenticationMethod_SharedKey}, - {method: models.AuthenticationMethod_DMTFReserved}, - {method: models.AuthenticationMethod_WPA3_SAE}, - {method: models.AuthenticationMethod_WPA3_OWE}, - {method: models.AuthenticationMethod_VendorReserved}, + {method: wifi.AuthenticationMethod_Other}, + {method: wifi.AuthenticationMethod_OpenSystem}, + {method: wifi.AuthenticationMethod_SharedKey}, + {method: wifi.AuthenticationMethod_DMTFReserved}, + {method: wifi.AuthenticationMethod_WPA3_SAE}, + {method: wifi.AuthenticationMethod_WPA3_OWE}, + {method: wifi.AuthenticationMethod_VendorReserved}, {method: 599}, } for _, tc := range cases { @@ -577,12 +588,12 @@ func TestInvalidEncryptionMethods(t *testing.T) { f := Flags{} f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgWPA) cases := []struct { - method models.EncryptionMethod + method wifi.EncryptionMethod }{ - {method: models.EncryptionMethod_Other}, - {method: models.EncryptionMethod_WEP}, - {method: models.EncryptionMethod_None}, - {method: models.EncryptionMethod_DMTFReserved}, + {method: wifi.EncryptionMethod_Other}, + {method: wifi.EncryptionMethod_WEP}, + {method: wifi.EncryptionMethod_None}, + {method: wifi.EncryptionMethod_DMTFReserved}, {method: 599}, } for _, tc := range cases { @@ -599,25 +610,25 @@ func TestInvalidAuthenticationProtocols(t *testing.T) { f := Flags{} f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgEAPTLS) cases := []struct { - protocol models.AuthenticationProtocol + protocol ieee8021x.AuthenticationProtocol }{ - {protocol: models.AuthenticationProtocolEAPTTLS_MSCHAPv2}, - {protocol: models.AuthenticationProtocolPEAPv1_EAPGTC}, - {protocol: models.AuthenticationProtocolEAPFAST_MSCHAPv2}, - {protocol: models.AuthenticationProtocolEAPFAST_GTC}, - {protocol: models.AuthenticationProtocolEAP_MD5}, - {protocol: models.AuthenticationProtocolEAP_PSK}, - {protocol: models.AuthenticationProtocolEAP_SIM}, - {protocol: models.AuthenticationProtocolEAP_AKA}, - {protocol: models.AuthenticationProtocolEAPFAST_TLS}, + {protocol: ieee8021x.AuthenticationProtocolEAPTTLS_MSCHAPv2}, + {protocol: ieee8021x.AuthenticationProtocolPEAPv1_EAPGTC}, + {protocol: ieee8021x.AuthenticationProtocolEAPFAST_MSCHAPv2}, + {protocol: ieee8021x.AuthenticationProtocolEAPFAST_GTC}, + {protocol: ieee8021x.AuthenticationProtocolEAP_MD5}, + {protocol: ieee8021x.AuthenticationProtocolEAP_PSK}, + {protocol: ieee8021x.AuthenticationProtocolEAP_SIM}, + {protocol: ieee8021x.AuthenticationProtocolEAP_AKA}, + {protocol: ieee8021x.AuthenticationProtocolEAPFAST_TLS}, {protocol: 599}, } for _, tc := range cases { t.Run(fmt.Sprintf("expect MissingOrInvalidConfiguration for AuthenticationProtocol %d", tc.protocol), func(t *testing.T) { f.LocalConfig.Ieee8021xConfigs[0].AuthenticationProtocol = int(tc.protocol) - rc := f.verifyIeee8021xConfig(f.LocalConfig.Ieee8021xConfigs[0]) - assert.Equal(t, utils.MissingOrInvalidConfiguration, rc) + err := f.verifyIeee8021xConfig(f.LocalConfig.Ieee8021xConfigs[0]) + assert.Equal(t, utils.MissingOrInvalidConfiguration, err) }) } } diff --git a/internal/flags/deactivate.go b/internal/flags/deactivate.go index a8703628..95443895 100644 --- a/internal/flags/deactivate.go +++ b/internal/flags/deactivate.go @@ -5,7 +5,7 @@ import ( "rpc/pkg/utils" ) -func (f *Flags) handleDeactivateCommand() utils.ReturnCode { +func (f *Flags) handleDeactivateCommand() error { f.amtDeactivateCommand.BoolVar(&f.Local, "local", false, "Execute command to AMT directly without cloud interaction") if len(f.commandLineArgs) == 2 { f.amtDeactivateCommand.PrintDefaults() @@ -25,10 +25,10 @@ func (f *Flags) handleDeactivateCommand() utils.ReturnCode { return utils.MissingOrIncorrectURL } if f.Password == "" { - if _, rc := f.ReadPasswordFromUser(); rc != 0 { + if _, err := f.ReadPasswordFromUser(); err != nil { return utils.MissingOrIncorrectPassword } } } - return utils.Success + return nil } diff --git a/internal/flags/deactivate_test.go b/internal/flags/deactivate_test.go index 2c3e420f..d963cea2 100644 --- a/internal/flags/deactivate_test.go +++ b/internal/flags/deactivate_test.go @@ -28,7 +28,7 @@ func TestHandleDeactivateCommandNoPasswordPrompt(t *testing.T) { defer userInput(t, password)() flags := NewFlags(args) success := flags.ParseFlags() - assert.EqualValues(t, success, utils.Success) + assert.EqualValues(t, success, nil) assert.Equal(t, utils.CommandDeactivate, flags.Command) assert.Equal(t, password, flags.Password) } @@ -51,7 +51,7 @@ func TestHandleDeactivateCommand(t *testing.T) { expected := utils.CommandDeactivate flags := NewFlags(args) success := flags.ParseFlags() - assert.EqualValues(t, success, utils.Success) + assert.EqualValues(t, success, nil) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, expected, flags.Command) } @@ -68,7 +68,7 @@ func TestHandleDeactivateCommandWithForce(t *testing.T) { expected := utils.CommandDeactivate flags := NewFlags(args) success := flags.ParseFlags() - assert.EqualValues(t, success, utils.Success) + assert.EqualValues(t, success, nil) assert.Equal(t, "wss://localhost", flags.URL) assert.Equal(t, true, flags.Force) assert.Equal(t, expected, flags.Command) @@ -78,14 +78,14 @@ func TestHandleLocalDeactivationWithPassword(t *testing.T) { args := []string{"./rpc", "deactivate", "-local", "--password", "p@ssword"} flags := NewFlags(args) errCode := flags.ParseFlags() - assert.Equal(t, errCode, utils.Success) + assert.Equal(t, errCode, nil) } func TestHandleLocalDeactivationWithoutPassword(t *testing.T) { args := []string{"./rpc", "deactivate", "-local"} flags := NewFlags(args) rc := flags.ParseFlags() - assert.Equal(t, rc, utils.Success) + assert.Equal(t, rc, nil) } func TestParseFlagsDeactivate(t *testing.T) { diff --git a/internal/flags/flags.go b/internal/flags/flags.go index 737df488..1387b2b9 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -12,7 +12,6 @@ import ( "net" "os" "path/filepath" - "regexp" "rpc/internal/amt" "rpc/internal/config" "rpc/internal/smb" @@ -21,6 +20,7 @@ import ( "strings" "time" + "github.com/google/uuid" "github.com/ilyakaznacheev/cleanenv" log "github.com/sirupsen/logrus" @@ -82,6 +82,9 @@ type Flags struct { amtMaintenanceChangePasswordCommand *flag.FlagSet amtMaintenanceSyncDeviceInfoCommand *flag.FlagSet versionCommand *flag.FlagSet + flagSetAddWifiSettings *flag.FlagSet + flagSetEnableWifiPort *flag.FlagSet + flagSetMEBx *flag.FlagSet amtCommand amt.AMTCommand netEnumerator NetEnumerator IpConfiguration IPConfiguration @@ -91,6 +94,7 @@ type Flags struct { AmtInfo AmtInfoFlags SkipIPRenew bool SambaService smb.ServiceInterface + MEBxPassword string ConfigTLSInfo ConfigTLSInfo } @@ -112,6 +116,10 @@ func NewFlags(args []string) *Flags { flags.versionCommand = flag.NewFlagSet(utils.CommandVersion, flag.ContinueOnError) flags.versionCommand.BoolVar(&flags.JsonOutput, "json", false, "json output") + flags.flagSetAddWifiSettings = flag.NewFlagSet(utils.SubCommandAddWifiSettings, flag.ContinueOnError) + flags.flagSetEnableWifiPort = flag.NewFlagSet(utils.SubCommandEnableWifiPort, flag.ContinueOnError) + flags.flagSetMEBx = flag.NewFlagSet(utils.SubCommandSetMEBx, flag.ContinueOnError) + flags.amtCommand = amt.NewAMTCommand() flags.netEnumerator = NetEnumerator{} flags.netEnumerator.Interfaces = net.Interfaces @@ -124,29 +132,29 @@ func NewFlags(args []string) *Flags { } // ParseFlags is used for understanding the command line flags -func (f *Flags) ParseFlags() utils.ReturnCode { - var rc utils.ReturnCode +func (f *Flags) ParseFlags() error { + var err error if len(f.commandLineArgs) > 1 { f.Command = f.commandLineArgs[1] } switch f.Command { case utils.CommandAMTInfo: - rc = f.handleAMTInfo(f.amtInfoCommand) + err = f.handleAMTInfo(f.amtInfoCommand) case utils.CommandActivate: - rc = f.handleActivateCommand() + err = f.handleActivateCommand() case utils.CommandDeactivate: - rc = f.handleDeactivateCommand() + err = f.handleDeactivateCommand() case utils.CommandMaintenance: - rc = f.handleMaintenanceCommand() + err = f.handleMaintenanceCommand() case utils.CommandVersion: - rc = f.handleVersionCommand() + err = f.handleVersionCommand() case utils.CommandConfigure: - rc = f.handleConfigureCommand() + err = f.handleConfigureCommand() default: - rc = utils.IncorrectCommandLineParameters + err = utils.IncorrectCommandLineParameters f.printUsage() } - return rc + return err } func (f *Flags) printUsage() string { @@ -200,30 +208,13 @@ func (f *Flags) setupCommonFlags() { } } } - -func (f *Flags) parseAndCheckArgCount(fs *flag.FlagSet, parseIndex int, minNumReq int) utils.ReturnCode { - if len(f.commandLineArgs) < (parseIndex + minNumReq) { - fs.Usage() - return utils.IncorrectCommandLineParameters - } - if err := fs.Parse(f.commandLineArgs[parseIndex:]); err != nil { - return utils.IncorrectCommandLineParameters - } - if len(fs.Args()) > 0 { - fmt.Printf("unhandled additional args: %v\n", fs.Args()) - fs.Usage() - return utils.IncorrectCommandLineParameters - } - return utils.Success -} - -func (f *Flags) validateUUIDOverride() utils.ReturnCode { - uuidPattern := regexp.MustCompile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$") - if matched := uuidPattern.MatchString(f.UUID); !matched { - fmt.Println("uuid provided does not follow proper uuid format") - return utils.InvalidUUID +func (f *Flags) validateUUIDOverride() error { + _, err := uuid.Parse(f.UUID) + if err != nil { + fmt.Println("uuid provided does not follow proper uuid format:", err) + return err } - return utils.Success + return nil } func (f *Flags) lookupEnvOrString(key string, defaultVal string) string { @@ -244,17 +235,18 @@ func (f *Flags) lookupEnvOrBool(key string, defaultVal bool) bool { return defaultVal } -func (f *Flags) PromptUserInput(prompt string, value *string) utils.ReturnCode { +func (f *Flags) PromptUserInput(prompt string, value *string) error { fmt.Println(prompt) _, err := fmt.Scanln(value) if err != nil { log.Error(err) return utils.InvalidUserInput } - return utils.Success + return nil } -func (f *Flags) ReadPasswordFromUser() (bool, utils.ReturnCode) { +// TODO: rework this so we can never return false +func (f *Flags) ReadPasswordFromUser() (bool, error) { fmt.Println("Please enter AMT Password: ") var password string _, err := fmt.Scanln(&password) @@ -262,13 +254,14 @@ func (f *Flags) ReadPasswordFromUser() (bool, utils.ReturnCode) { return false, utils.MissingOrIncorrectPassword } f.Password = password - return true, utils.Success + return true, nil } -func (f *Flags) handleLocalConfig() utils.ReturnCode { +func (f *Flags) handleLocalConfig() error { if f.configContent == "" { - return utils.Success + return nil } + err := utils.FailedReadingConfiguration ext := filepath.Ext(strings.ToLower(f.configContent)) isPFX := ext == ".pfx" if strings.HasPrefix(f.configContent, "smb:") { @@ -276,7 +269,7 @@ func (f *Flags) handleLocalConfig() utils.ReturnCode { isYAML := ext == ".yaml" || ext == ".yml" if !isPFX && !isJSON && !isYAML { log.Error("remote config unsupported smb file extension: ", ext) - return utils.FailedReadingConfiguration + return err } configBytes, err := f.SambaService.FetchFileContents(f.configContent) if err != nil { @@ -294,7 +287,7 @@ func (f *Flags) handleLocalConfig() utils.ReturnCode { } if err != nil { log.Error("config error: ", err) - return utils.FailedReadingConfiguration + return err } } else if isPFX { pfxBytes, err := os.ReadFile(f.configContent) @@ -307,8 +300,8 @@ func (f *Flags) handleLocalConfig() utils.ReturnCode { err := cleanenv.ReadConfig(f.configContent, &f.LocalConfig) if err != nil { log.Error("config error: ", err) - return utils.FailedReadingConfiguration + return err } } - return utils.Success + return nil } diff --git a/internal/flags/flags_test.go b/internal/flags/flags_test.go index cd5a1ae0..f8cb16ef 100644 --- a/internal/flags/flags_test.go +++ b/internal/flags/flags_test.go @@ -9,7 +9,6 @@ import ( "encoding/json" "errors" "fmt" - "gopkg.in/yaml.v3" "net" "os" "path/filepath" @@ -19,6 +18,8 @@ import ( "rpc/pkg/utils" "testing" + "gopkg.in/yaml.v3" + "github.com/stretchr/testify/assert" ) @@ -192,7 +193,7 @@ func TestParseFlagsAMTInfo(t *testing.T) { args := []string{"./rpc", "amtinfo"} flags := NewFlags(args) result := flags.ParseFlags() - assert.EqualValues(t, result, utils.Success) + assert.EqualValues(t, result, nil) assert.Equal(t, flags.Command, utils.CommandAMTInfo) assert.Equal(t, false, flags.JsonOutput) } @@ -210,7 +211,7 @@ func TestParseFlagsAMTInfoJSON(t *testing.T) { args := []string{"./rpc", "amtinfo", "-json"} flags := NewFlags(args) result := flags.ParseFlags() - assert.EqualValues(t, result, utils.Success) + assert.EqualValues(t, result, nil) assert.Equal(t, flags.Command, utils.CommandAMTInfo) assert.Equal(t, true, flags.JsonOutput) } @@ -218,7 +219,7 @@ func TestParseFlagsAMTInfoCert(t *testing.T) { args := []string{"./rpc", "amtinfo", "-cert"} flags := NewFlags(args) result := flags.ParseFlags() - assert.EqualValues(t, result, utils.Success) + assert.EqualValues(t, result, nil) assert.Equal(t, flags.Command, utils.CommandAMTInfo) assert.Equal(t, false, flags.JsonOutput) } @@ -226,7 +227,7 @@ func TestParseFlagsAMTInfoOSDNSSuffix(t *testing.T) { args := []string{"./rpc", "amtinfo", "-dns"} flags := NewFlags(args) result := flags.ParseFlags() - assert.EqualValues(t, result, utils.Success) + assert.EqualValues(t, result, nil) assert.Equal(t, flags.Command, utils.CommandAMTInfo) assert.Equal(t, false, flags.JsonOutput) } @@ -241,7 +242,7 @@ func TestParseFlagsVersion(t *testing.T) { args := []string{"./rpc", "version"} flags := NewFlags(args) result := flags.ParseFlags() - assert.EqualValues(t, result, utils.Success) + assert.EqualValues(t, result, nil) assert.Equal(t, flags.Command, utils.CommandVersion) assert.Equal(t, false, flags.JsonOutput) } @@ -274,7 +275,7 @@ func TestParseFlagsVersionJSON(t *testing.T) { args := []string{"./rpc", "version", "-json"} flags := NewFlags(args) result := flags.ParseFlags() - assert.EqualValues(t, result, utils.Success) + assert.EqualValues(t, result, nil) assert.Equal(t, flags.Command, utils.CommandVersion) assert.Equal(t, true, flags.JsonOutput) } @@ -396,7 +397,7 @@ func TestHandleLocalConfig(t *testing.T) { flags.SambaService = NewMockSambaService(nil) flags.configContent = "smb://localhost/xxx/" + cfgFilePath rc := flags.handleLocalConfig() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) if ext == "json" || ext == "yaml" { assert.Equal(t, cfg.Password, flags.LocalConfig.Password) assert.Equal(t, cfg.ACMSettings, flags.LocalConfig.ACMSettings) @@ -411,7 +412,7 @@ func TestHandleLocalConfig(t *testing.T) { flags := NewFlags(args) flags.configContent = cfgFilePath rc := flags.handleLocalConfig() - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) if ext == "json" || ext == "yaml" { assert.Equal(t, cfg.Password, flags.LocalConfig.Password) assert.Equal(t, cfg.ACMSettings, flags.LocalConfig.ACMSettings) @@ -427,8 +428,8 @@ func TestHandleLocalConfig(t *testing.T) { flags := NewFlags(args) flags.configContent = "smb://localhost/xxx/nope.html" flags.SambaService = NewMockSambaService(nil) - rc := flags.handleLocalConfig() - assert.Equal(t, utils.FailedReadingConfiguration, rc) + err := flags.handleLocalConfig() + assert.Equal(t, utils.FailedReadingConfiguration, err) }) t.Run("expect FailedReadingConfiguration for smb fetch file error", func(t *testing.T) { @@ -436,15 +437,15 @@ func TestHandleLocalConfig(t *testing.T) { flags := NewFlags(args) flags.configContent = "smb://localhost/xxx/yep.yaml" flags.SambaService = NewMockSambaService(errors.New("test error")) - rc := flags.handleLocalConfig() - assert.Equal(t, utils.FailedReadingConfiguration, rc) + err := flags.handleLocalConfig() + assert.Equal(t, utils.FailedReadingConfiguration, err) }) t.Run("expect FailedReadingConfiguration for local pfx ReadFile", func(t *testing.T) { args := []string{"./rpc"} flags := NewFlags(args) flags.configContent = "/tmp/thisfilebetterneverexist.pfx" - rc := flags.handleLocalConfig() - assert.Equal(t, utils.FailedReadingConfiguration, rc) + err := flags.handleLocalConfig() + assert.Equal(t, utils.FailedReadingConfiguration, err) }) } diff --git a/internal/flags/info.go b/internal/flags/info.go index c18054dc..462294d6 100644 --- a/internal/flags/info.go +++ b/internal/flags/info.go @@ -20,7 +20,7 @@ type AmtInfoFlags struct { OpState bool } -func (f *Flags) handleAMTInfo(amtInfoCommand *flag.FlagSet) utils.ReturnCode { +func (f *Flags) handleAMTInfo(amtInfoCommand *flag.FlagSet) error { // runs locally f.Local = true @@ -68,5 +68,5 @@ func (f *Flags) handleAMTInfo(amtInfoCommand *flag.FlagSet) utils.ReturnCode { // NOTE: UserCert and password check happen later // when provisioning mode is available - return utils.Success + return nil } diff --git a/internal/flags/info_test.go b/internal/flags/info_test.go index a5376cc1..7eb0acfd 100644 --- a/internal/flags/info_test.go +++ b/internal/flags/info_test.go @@ -1,10 +1,11 @@ package flags import ( - "github.com/stretchr/testify/assert" "rpc/pkg/utils" "strings" "testing" + + "github.com/stretchr/testify/assert" ) func TestParseFlagsAmtInfo(t *testing.T) { @@ -23,13 +24,13 @@ func TestParseFlagsAmtInfo(t *testing.T) { tests := map[string]struct { cmdLine string - wantResult utils.ReturnCode + wantResult error wantFlags AmtInfoFlags userInput string }{ "expect success for basic command": { cmdLine: "./rpc amtinfo -json", - wantResult: utils.Success, + wantResult: nil, wantFlags: defaultFlags, }, "expect IncorrectCommandLineParameters on Parse error": { @@ -39,14 +40,14 @@ func TestParseFlagsAmtInfo(t *testing.T) { }, "expect only cert flag with no password on command line": { cmdLine: "./rpc amtinfo -cert", - wantResult: utils.Success, + wantResult: nil, wantFlags: AmtInfoFlags{ Cert: true, }, }, "expect both cert flags with no password on command line": { cmdLine: "./rpc amtinfo -cert -password testPassword", - wantResult: utils.Success, + wantResult: nil, wantFlags: AmtInfoFlags{ Cert: true, UserCert: true, @@ -54,21 +55,21 @@ func TestParseFlagsAmtInfo(t *testing.T) { }, "expect success for userCert with no password": { cmdLine: "./rpc amtinfo -userCert", - wantResult: utils.Success, + wantResult: nil, wantFlags: AmtInfoFlags{ UserCert: true, }, }, "expect Success for userCert with password": { cmdLine: "./rpc amtinfo -userCert -password testPassword", - wantResult: utils.Success, + wantResult: nil, wantFlags: AmtInfoFlags{ UserCert: true, }, }, "expect Success for userCert with password input": { cmdLine: "./rpc amtinfo -userCert", - wantResult: utils.Success, + wantResult: nil, wantFlags: AmtInfoFlags{ UserCert: true, }, diff --git a/internal/flags/maintenance.go b/internal/flags/maintenance.go index 4bf740c8..485ae649 100644 --- a/internal/flags/maintenance.go +++ b/internal/flags/maintenance.go @@ -34,43 +34,42 @@ func (f *Flags) printMaintenanceUsage() string { return usage } -func (f *Flags) handleMaintenanceCommand() utils.ReturnCode { +func (f *Flags) handleMaintenanceCommand() error { //validation section if len(f.commandLineArgs) == 2 { f.printMaintenanceUsage() return utils.IncorrectCommandLineParameters } - var rc = utils.Success - + var err error f.SubCommand = f.commandLineArgs[2] switch f.SubCommand { case "syncclock": - rc = f.handleMaintenanceSyncClock() + err = f.handleMaintenanceSyncClock() break case "synchostname": - rc = f.handleMaintenanceSyncHostname() + err = f.handleMaintenanceSyncHostname() break case "syncip": - rc = f.handleMaintenanceSyncIP() + err = f.handleMaintenanceSyncIP() break case "changepassword": - rc = f.handleMaintenanceSyncChangePassword() + err = f.handleMaintenanceSyncChangePassword() break case "syncdeviceinfo": - rc = f.handleMaintenanceSyncDeviceInfo() + err = f.handleMaintenanceSyncDeviceInfo() break default: f.printMaintenanceUsage() - rc = utils.IncorrectCommandLineParameters + err = utils.IncorrectCommandLineParameters break } - if rc != utils.Success { - return rc + if err != nil { + return err } if f.Password == "" { - if _, rc := f.ReadPasswordFromUser(); rc != 0 { + if _, err := f.ReadPasswordFromUser(); err != nil { return utils.MissingOrIncorrectPassword } } @@ -82,31 +81,31 @@ func (f *Flags) handleMaintenanceCommand() utils.ReturnCode { } if f.UUID != "" { - rc = f.validateUUIDOverride() - if rc != utils.Success { + err := f.validateUUIDOverride() + if err != nil { f.printMaintenanceUsage() - return rc + return utils.InvalidUUID } } - return utils.Success + return nil } -func (f *Flags) handleMaintenanceSyncClock() utils.ReturnCode { +func (f *Flags) handleMaintenanceSyncClock() error { if err := f.amtMaintenanceSyncClockCommand.Parse(f.commandLineArgs[3:]); err != nil { return utils.IncorrectCommandLineParameters } - return utils.Success + return nil } -func (f *Flags) handleMaintenanceSyncDeviceInfo() utils.ReturnCode { +func (f *Flags) handleMaintenanceSyncDeviceInfo() error { if err := f.amtMaintenanceSyncDeviceInfoCommand.Parse(f.commandLineArgs[3:]); err != nil { return utils.IncorrectCommandLineParameters } - return utils.Success + return nil } -func (f *Flags) handleMaintenanceSyncHostname() utils.ReturnCode { +func (f *Flags) handleMaintenanceSyncHostname() error { var err error if err = f.amtMaintenanceSyncHostnameCommand.Parse(f.commandLineArgs[3:]); err != nil { f.amtMaintenanceSyncHostnameCommand.Usage() @@ -124,7 +123,7 @@ func (f *Flags) handleMaintenanceSyncHostname() utils.ReturnCode { log.Error("OS hostname is not available") return utils.OSNetworkInterfacesLookupFailed } - return utils.Success + return nil } // wrap the flag.Func method signature with the assignment value @@ -138,7 +137,7 @@ func validateIP(assignee *string) func(string) error { } } -func (f *Flags) handleMaintenanceSyncIP() utils.ReturnCode { +func (f *Flags) handleMaintenanceSyncIP() error { f.amtMaintenanceSyncIPCommand.Func( "staticip", "IP address to be assigned to AMT - if not specified, the IP Address of the active OS newtork interface is used", @@ -155,25 +154,24 @@ func (f *Flags) handleMaintenanceSyncIP() utils.ReturnCode { f.amtMaintenanceSyncIPCommand.Usage() // Parse the error message to find the problematic flag. // The problematic flag is of the following format '-' followed by flag name and then a ':' - var rc utils.ReturnCode re := regexp.MustCompile(`-.*:`) switch re.FindString(err.Error()) { case "-netmask:": - rc = utils.MissingOrIncorrectNetworkMask + err = utils.MissingOrIncorrectNetworkMask case "-staticip:": - rc = utils.MissingOrIncorrectStaticIP + err = utils.MissingOrIncorrectStaticIP case "-gateway:": - rc = utils.MissingOrIncorrectGateway + err = utils.MissingOrIncorrectGateway case "-primarydns:": - rc = utils.MissingOrIncorrectPrimaryDNS + err = utils.MissingOrIncorrectPrimaryDNS case "-secondarydns:": - rc = utils.MissingOrIncorrectSecondaryDNS + err = utils.MissingOrIncorrectSecondaryDNS default: - rc = utils.IncorrectCommandLineParameters + err = utils.IncorrectCommandLineParameters } - return rc + return err } else if len(f.IpConfiguration.IpAddress) != 0 { - return utils.Success + return nil } amtLanIfc, err := f.amtCommand.GetLANInterfaceSettings(false) @@ -213,14 +211,14 @@ func (f *Flags) handleMaintenanceSyncIP() utils.ReturnCode { log.Errorf("static ip address not found") return utils.OSNetworkInterfacesLookupFailed } - return utils.Success + return nil } -func (f *Flags) handleMaintenanceSyncChangePassword() utils.ReturnCode { +func (f *Flags) handleMaintenanceSyncChangePassword() error { f.amtMaintenanceChangePasswordCommand.StringVar(&f.StaticPassword, "static", "", "specify a new password for AMT") if err := f.amtMaintenanceChangePasswordCommand.Parse(f.commandLineArgs[3:]); err != nil { f.amtMaintenanceChangePasswordCommand.Usage() return utils.IncorrectCommandLineParameters } - return utils.Success + return nil } diff --git a/internal/flags/maintenance_test.go b/internal/flags/maintenance_test.go index 66b9199a..ef75d482 100644 --- a/internal/flags/maintenance_test.go +++ b/internal/flags/maintenance_test.go @@ -59,7 +59,7 @@ func TestParseFlagsMaintenance(t *testing.T) { } tests := map[string]struct { cmdLine string - wantResult utils.ReturnCode + wantResult error wantIPConfig IPConfiguration userInput string }{ @@ -81,7 +81,7 @@ func TestParseFlagsMaintenance(t *testing.T) { }, "should pass - syncclock": { cmdLine: cmdBase + " " + utils.SubCommandSyncClock + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should fail - syncclock bad param": { cmdLine: cmdBase + " " + utils.SubCommandSyncClock + " -nope " + argUrl + " " + argCurPw, @@ -89,11 +89,11 @@ func TestParseFlagsMaintenance(t *testing.T) { }, "should pass - synchostname no params": { cmdLine: cmdBase + " " + utils.SubCommandSyncHostname + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should pass - task force flag": { cmdLine: cmdBase + " " + utils.SubCommandSyncHostname + " -f " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should fail - synchostname bad param": { cmdLine: cmdBase + " " + utils.SubCommandSyncHostname + " -nope " + argUrl + " " + argCurPw, @@ -101,7 +101,7 @@ func TestParseFlagsMaintenance(t *testing.T) { }, "should pass - syncdeviceinfo": { cmdLine: cmdBase + " " + utils.SubCommandSyncDeviceInfo + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should fail - syncdeviceinfo bad param": { cmdLine: cmdBase + " " + utils.SubCommandSyncDeviceInfo + " -nope " + argUrl + " " + argCurPw, @@ -109,7 +109,7 @@ func TestParseFlagsMaintenance(t *testing.T) { }, "should pass - syncip no params": { cmdLine: cmdBase + " " + utils.SubCommandSyncIP + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, wantIPConfig: ipCfgNoParams, }, "should pass - syncip with params": { @@ -121,7 +121,7 @@ func TestParseFlagsMaintenance(t *testing.T) { " -primarydns " + ipCfgWithParams.PrimaryDns + " -secondarydns " + ipCfgWithParams.SecondaryDns + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, wantIPConfig: ipCfgWithParams, }, "should pass - syncip with lookup": { @@ -131,7 +131,7 @@ func TestParseFlagsMaintenance(t *testing.T) { " -primarydns " + ipCfgWithLookup.PrimaryDns + " -secondarydns " + ipCfgWithLookup.SecondaryDns + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, wantIPConfig: ipCfgWithLookup, }, "should fail - syncip bad param": { @@ -160,19 +160,19 @@ func TestParseFlagsMaintenance(t *testing.T) { }, "should pass - changepassword to random value": { cmdLine: cmdBase + " " + utils.SubCommandChangePassword + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should pass - changepassword using static value": { cmdLine: cmdBase + " " + utils.SubCommandChangePassword + " -static " + newPassword + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should pass - changepassword static value before other flags": { cmdLine: cmdBase + " " + utils.SubCommandChangePassword + " -static " + newPassword + " " + argUrl + " " + argCurPw, - wantResult: utils.Success, + wantResult: nil, }, "should pass - changepassword static value after all flags": { cmdLine: cmdBase + " " + utils.SubCommandChangePassword + " " + argUrl + " " + argCurPw + " -static " + newPassword, - wantResult: utils.Success, + wantResult: nil, }, "should fail - changepassword bad param": { cmdLine: cmdBase + " " + utils.SubCommandChangePassword + " -nope " + argUrl + " " + argCurPw, @@ -180,12 +180,12 @@ func TestParseFlagsMaintenance(t *testing.T) { }, "should pass - password user input": { cmdLine: cmdBase + " " + utils.SubCommandSyncClock + " " + argUrl, - wantResult: utils.Success, + wantResult: nil, userInput: trickyPassword, }, "should pass - UUID Override": { cmdLine: cmdBase + " " + utils.SubCommandSyncClock + " " + argUrl + " " + argCurPw + " -uuid 4c2e8db8-1c7a-00ea-279c-d17395b1f584", - wantResult: utils.Success, + wantResult: nil, }, "should fail - InvalidUUID": { cmdLine: cmdBase + " " + utils.SubCommandSyncClock + " " + argUrl + " " + argCurPw + " -uuid 4c2e8db8-1c7a-00ea-279c", diff --git a/internal/flags/version.go b/internal/flags/version.go index 08199853..480bb7f2 100644 --- a/internal/flags/version.go +++ b/internal/flags/version.go @@ -4,11 +4,11 @@ import ( "rpc/pkg/utils" ) -func (f *Flags) handleVersionCommand() utils.ReturnCode { +func (f *Flags) handleVersionCommand() error { if err := f.versionCommand.Parse(f.commandLineArgs[2:]); err != nil { return utils.IncorrectCommandLineParameters } // runs locally f.Local = true - return utils.Success + return nil } diff --git a/internal/flags/version_test.go b/internal/flags/version_test.go index 656a44b9..d005e616 100644 --- a/internal/flags/version_test.go +++ b/internal/flags/version_test.go @@ -1,9 +1,9 @@ package flags import ( - "github.com/stretchr/testify/assert" - "rpc/pkg/utils" "testing" + + "github.com/stretchr/testify/assert" ) func TestHandleVersionCommand(t *testing.T) { @@ -13,6 +13,6 @@ func TestHandleVersionCommand(t *testing.T) { }) result := f.handleVersionCommand() - assert.Equal(t, utils.Success, result) + assert.Equal(t, nil, result) assert.Equal(t, true, f.Local) } diff --git a/internal/lm/engine.go b/internal/lm/engine.go index 0cbcf3a3..7ff91327 100644 --- a/internal/lm/engine.go +++ b/internal/lm/engine.go @@ -90,6 +90,7 @@ func (lme *LMEConnection) Connect() error { // Send writes data to LMS TCP Socket func (lme *LMEConnection) Send(data []byte) error { log.Debug("sending message to LME") + log.Trace(string(data)) var bin_buf bytes.Buffer channelData := apf.ChannelData(lme.Session.SenderChannel, data) @@ -149,7 +150,6 @@ func (lme *LMEConnection) Listen() { lme.Session.Status <- true }() for { - result2, bytesRead, err2 := lme.Command.Receive() if bytesRead == 0 || err2 != nil { log.Trace("NO MORE DATA TO READ") diff --git a/internal/local/activate.go b/internal/local/activate.go index 84b9c8da..d44abcfa 100644 --- a/internal/local/activate.go +++ b/internal/local/activate.go @@ -9,22 +9,19 @@ import ( "encoding/base64" "encoding/hex" "encoding/pem" - "encoding/xml" "errors" "rpc/pkg/utils" "strings" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/general" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/ips/hostbasedsetup" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" pkcs12 "software.sslmate.com/src/go-pkcs12" ) -func (service *ProvisioningService) Activate() utils.ReturnCode { +func (service *ProvisioningService) Activate() error { controlMode, err := service.amtCommand.GetControlMode() if err != nil { - log.Error(err) return utils.AMTConnectionFailed } if controlMode != 0 { @@ -40,132 +37,78 @@ func (service *ProvisioningService) Activate() utils.ReturnCode { log.Error(err) return utils.AMTConnectionFailed } - service.setupWsmanClient(lsa.Username, lsa.Password) - - rc := utils.Success + service.interfacedWsmanMessage.SetupWsmanClient(lsa.Username, lsa.Password, logrus.GetLevel() == logrus.TraceLevel) if service.flags.UseACM { - rc = service.ActivateACM() + err = service.ActivateACM() } else if service.flags.UseCCM { - rc = service.ActivateCCM() + err = service.ActivateCCM() } - return rc + return err } -func (service *ProvisioningService) ActivateACM() utils.ReturnCode { - checkErrorAndLog := func(err error) bool { - if err != nil { - log.Error(err) - return true - } - return false - } +func (service *ProvisioningService) ActivateACM() error { + // Extract the provisioning certificate certObject, fingerPrint, err := service.GetProvisioningCertObj() - if checkErrorAndLog(err) { + if err != nil { return utils.ActivationFailed } // Check provisioning certificate is accepted by AMT - if checkErrorAndLog(service.CompareCertHashes(fingerPrint)) { + err = service.CompareCertHashes(fingerPrint) + if err != nil { return utils.ActivationFailed } - generalSettings, err := service.GetGeneralSettings() - if checkErrorAndLog(err) { + generalSettings, err := service.interfacedWsmanMessage.GetGeneralSettings() + if err != nil { return utils.ActivationFailed } - getHostBasedSetupResponse, err := service.GetHostBasedSetupService() - if checkErrorAndLog(err) { + getHostBasedSetupResponse, err := service.interfacedWsmanMessage.GetHostBasedSetupService() + if err != nil { return utils.ActivationFailed } - decodedNonce := getHostBasedSetupResponse.Body.IPS_HostBasedSetupService.ConfigurationNonce + decodedNonce := getHostBasedSetupResponse.Body.GetResponse.ConfigurationNonce fwNonce, err := base64.StdEncoding.DecodeString(decodedNonce) - if checkErrorAndLog(err) { - log.Error("Error decoding fwNonce:", err) + if err != nil { return utils.ActivationFailed } - if checkErrorAndLog(service.injectCertificate(certObject.certChain)) { + err = service.injectCertificate(certObject.certChain) + if err != nil { return utils.ActivationFailed } nonce, err := service.generateNonce() - if checkErrorAndLog(err) { + if err != nil { return utils.ActivationFailed } signedSignature, err := service.createSignedString(nonce, fwNonce, certObject.privateKey) - if checkErrorAndLog(err) { + if err != nil { return utils.ActivationFailed } - _, err = service.sendAdminSetup(generalSettings.Body.AMTGeneralSettings.DigestRealm, nonce, signedSignature) - if checkErrorAndLog(err) { + _, err = service.interfacedWsmanMessage.HostBasedSetupServiceAdmin(service.config.ACMSettings.AMTPassword, generalSettings.Body.GetResponse.DigestRealm, nonce, signedSignature) + if err != nil { return utils.ActivationFailed } - return utils.Success + return nil } -func (service *ProvisioningService) ActivateCCM() utils.ReturnCode { - generalSettings, err := service.GetGeneralSettings() +func (service *ProvisioningService) ActivateCCM() error { + generalSettings, err := service.interfacedWsmanMessage.GetGeneralSettings() if err != nil { - log.Error(err) return utils.ActivationFailed } - _, err = service.HostBasedSetup(generalSettings.Body.AMTGeneralSettings.DigestRealm, service.config.Password) + _, err = service.interfacedWsmanMessage.HostBasedSetupService(generalSettings.Body.GetResponse.DigestRealm, service.config.Password) if err != nil { - log.Error(err) return utils.ActivationFailed } log.Info("Status: Device activated in Client Control Mode") - return utils.Success -} - -func (service *ProvisioningService) GetGeneralSettings() (general.Response, error) { - message := service.amtMessages.GeneralSettings.Get() - response, err := service.client.Post(message) - if err != nil { - return general.Response{}, err - } - var generalSettings general.Response - err = xml.Unmarshal([]byte(response), &generalSettings) - if err != nil { - return general.Response{}, err - } - return generalSettings, nil -} - -func (service *ProvisioningService) HostBasedSetup(digestRealm string, password string) (utils.ReturnCode, error) { - message := service.ipsMessages.HostBasedSetupService.Setup(hostbasedsetup.AdminPassEncryptionTypeHTTPDigestMD5A1, digestRealm, password) - response, err := service.client.Post(message) - if err != nil { - return utils.AMTConnectionFailed, err - } - var hostBasedSetupResponse hostbasedsetup.Response - err = xml.Unmarshal([]byte(response), &hostBasedSetupResponse) - if err != nil { - return utils.ActivationFailed, err - } - if hostBasedSetupResponse.Body.Setup_OUTPUT.ReturnValue != 0 { - return utils.ActivationFailed, errors.New("unable to activate CCM, check to make sure the device is not alreacy activated") - } - return utils.Success, nil -} - -func (service *ProvisioningService) GetHostBasedSetupService() (hostbasedsetup.Response, error) { - message := service.ipsMessages.HostBasedSetupService.Get() - response, err := service.client.Post(message) - if err != nil { - return hostbasedsetup.Response{}, err - } - var getHostBasedSetupResponse hostbasedsetup.Response - err = xml.Unmarshal([]byte(response), &getHostBasedSetupResponse) - if err != nil { - return hostbasedsetup.Response{}, err - } - return getHostBasedSetupResponse, nil + return nil } type CertsAndKeys struct { @@ -190,6 +133,34 @@ func cleanPEM(pem string) string { return strings.Replace(pem, "\n", "", -1) } +func (service *ProvisioningService) GetProvisioningCertObj() (ProvisioningCertObj, string, error) { + config := service.config.ACMSettings + certsAndKeys, err := convertPfxToObject(config.ProvisioningCert, config.ProvisioningCertPwd) + if err != nil { + return ProvisioningCertObj{}, "", err + } + result, fingerprint, err := dumpPfx(certsAndKeys) + if err != nil { + return ProvisioningCertObj{}, "", err + } + return result, fingerprint, nil +} + +func convertPfxToObject(pfxb64 string, passphrase string) (CertsAndKeys, error) { + pfx, err := base64.StdEncoding.DecodeString(pfxb64) + if err != nil { + return CertsAndKeys{}, err + } + privateKey, certificate, extraCerts, err := pkcs12.DecodeChain(pfx, passphrase) + if err != nil { + return CertsAndKeys{}, errors.New("decrypting provisioning certificate failed") + } + certs := append([]*x509.Certificate{certificate}, extraCerts...) + pfxOut := CertsAndKeys{certs: certs, keys: []interface{}{privateKey}} + + return pfxOut, nil +} + func dumpPfx(pfxobj CertsAndKeys) (ProvisioningCertObj, string, error) { if len(pfxobj.certs) == 0 { return ProvisioningCertObj{}, "", errors.New("no certificates found") @@ -231,35 +202,6 @@ func dumpPfx(pfxobj CertsAndKeys) (ProvisioningCertObj, string, error) { return provisioningCertificateObj, fingerprint, nil } - -func convertPfxToObject(pfxb64 string, passphrase string) (CertsAndKeys, error) { - pfx, err := base64.StdEncoding.DecodeString(pfxb64) - if err != nil { - return CertsAndKeys{}, err - } - privateKey, certificate, extraCerts, err := pkcs12.DecodeChain(pfx, passphrase) - if err != nil { - return CertsAndKeys{}, errors.New("Decrypting provisioning certificate failed") - } - certs := append([]*x509.Certificate{certificate}, extraCerts...) - pfxOut := CertsAndKeys{certs: certs, keys: []interface{}{privateKey}} - - return pfxOut, nil -} - -func (service *ProvisioningService) GetProvisioningCertObj() (ProvisioningCertObj, string, error) { - config := service.config.ACMSettings - certsAndKeys, err := convertPfxToObject(config.ProvisioningCert, config.ProvisioningCertPwd) - if err != nil { - return ProvisioningCertObj{}, "", err - } - result, fingerprint, err := dumpPfx(certsAndKeys) - if err != nil { - return ProvisioningCertObj{}, "", err - } - return result, fingerprint, nil -} - func (service *ProvisioningService) CompareCertHashes(fingerPrint string) error { result, err := service.amtCommand.GetCertificateHashes() if err != nil { @@ -270,7 +212,7 @@ func (service *ProvisioningService) CompareCertHashes(fingerPrint string) error return nil } } - return errors.New("The root of the provisioning certificate does not match any of the trusted roots in AMT.") + return errors.New("the root of the provisioning certificate does not match any of the trusted roots in AMT") } func (service *ProvisioningService) injectCertificate(certChain []string) error { @@ -280,36 +222,20 @@ func (service *ProvisioningService) injectCertificate(certChain []string) error isLeaf := i == firstIndex isRoot := i == lastIndex - err := service.AddNextCertInChain(cert, isLeaf, isRoot) + _, err := service.interfacedWsmanMessage.AddNextCertInChain(cert, isLeaf, isRoot) if err != nil { log.Error(err) - return errors.New("Failed to add certificate to AMT.") + // TODO: check if this is the correct error to return + return errors.New("failed to add certificate to AMT") } } return nil } -func (service *ProvisioningService) AddNextCertInChain(cert string, isLeaf bool, isRoot bool) error { - message := service.ipsMessages.HostBasedSetupService.AddNextCertInChain(cert, isLeaf, isRoot) - response, err := service.client.Post(message) - if err != nil { - return err - } - var addCertResponse hostbasedsetup.Response - err = xml.Unmarshal([]byte(response), &addCertResponse) - if err != nil { - return err - } - if addCertResponse.Body.AdminSetup_OUTPUT.ReturnValue != 0 { - return errors.New("unable to activate ACM") - } - return nil -} - func (service *ProvisioningService) generateNonce() ([]byte, error) { nonce := make([]byte, 20) - _, err := rand.Read(nonce) - if err != nil { + // fills nonce with 20 random bytes + if _, err := rand.Read(nonce); err != nil { log.Error("Error generating nonce:", err) return nil, err } @@ -357,37 +283,3 @@ func (service *ProvisioningService) createSignedString(nonce []byte, fwNonce []b } return signature, nil } - -func (service *ProvisioningService) sendAdminSetup(digestRealm string, nonce []byte, signature string) (utils.ReturnCode, error) { - password := service.config.ACMSettings.AMTPassword - message := service.ipsMessages.HostBasedSetupService.AdminSetup(hostbasedsetup.AdminPassEncryptionTypeHTTPDigestMD5A1, digestRealm, password, base64.StdEncoding.EncodeToString(nonce), hostbasedsetup.SigningAlgorithmRSASHA2256, signature) - response, err := service.client.Post(message) - if err != nil && err.Error() != "Post \"http://localhost:16992/wsman\": EOF" { - log.Error(err) - return utils.ActivationFailed, err - } - if response != nil { - var hostBasedSetupResponse hostbasedsetup.Response - err = xml.Unmarshal([]byte(response), &hostBasedSetupResponse) - if err != nil { - log.Error(err) - return utils.ActivationFailed, err - } - if hostBasedSetupResponse.Body.AdminSetup_OUTPUT.ReturnValue != 0 { - log.Error("hostBasedSetupResponse.Body.AdminSetup_OUTPUT.ReturnValue: ", hostBasedSetupResponse.Body.AdminSetup_OUTPUT.ReturnValue) - return utils.ActivationFailed, errors.New("unable to activate in ACM") - } - } else { - controlMode, err := service.amtCommand.GetControlMode() - if err != nil { - log.Error(err) - return utils.AMTConnectionFailed, err - } - if controlMode != 2 { - log.Error("unable to activate in ACM. control mode: ", controlMode) - return utils.UnableToActivate, err - } - } - log.Info("Status: Device activated in Admin Control Mode") - return utils.Success, nil -} diff --git a/internal/local/activate_test.go b/internal/local/activate_test.go index 8e88cac6..a5048982 100644 --- a/internal/local/activate_test.go +++ b/internal/local/activate_test.go @@ -2,8 +2,6 @@ package local import ( "crypto/x509" - "errors" - "net/http" amt2 "rpc/internal/amt" "rpc/internal/certs" "rpc/internal/flags" @@ -24,197 +22,58 @@ func getTestCerts() *certs.CompositeChain { } func TestActivation(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithTestServer(&flags.Flags{}, handler) + lps := setupService(&flags.Flags{}) lps.flags.Command = utils.CommandActivate lps.flags.LocalConfig.Password = "P@ssw0rd" + t.Run("return nil activate is success", func(t *testing.T) { + err := lps.Activate() + assert.NoError(t, err) + }) t.Run("returns AMTConnectionFailed when GetControlMode fails", func(t *testing.T) { - mockControlModeErr = errors.New("yep it failed") - rc := lps.Activate() - assert.Equal(t, utils.AMTConnectionFailed, rc) + mockControlModeErr = errTestError + err := lps.Activate() + assert.Error(t, err) mockControlModeErr = nil }) t.Run("returns UnableToActivate when already activated", func(t *testing.T) { mockControlMode = 1 - rc := lps.Activate() - assert.Equal(t, utils.UnableToActivate, rc) + err := lps.Activate() + assert.Error(t, err) mockControlMode = 0 }) t.Run("returns AMTConnectionFailed when GetLocalSystemAccount fails", func(t *testing.T) { - mockLocalSystemAccountErr = errors.New("yep it failed") - rc := lps.Activate() - assert.Equal(t, utils.AMTConnectionFailed, rc) + mockLocalSystemAccountErr = errTestError + err := lps.Activate() + assert.Error(t, err) mockLocalSystemAccountErr = nil }) - t.Run("returns ActivationFailed when UseACM and responses are not mocked", func(t *testing.T) { - lps.flags.UseACM = true - rc := lps.Activate() - assert.Equal(t, utils.ActivationFailed, rc) - lps.flags.UseACM = false - }) - - t.Run("returns ActivationFailed when UseCCM and responses are not mocked", func(t *testing.T) { - lps.flags.UseCCM = true - rc := lps.Activate() - assert.Equal(t, utils.ActivationFailed, rc) - lps.flags.UseCCM = false - }) } func TestActivateCCM(t *testing.T) { - f := &flags.Flags{} - t.Run("returns ActivationFailed on GeneralSettings.Get() server error", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateCCM() - assert.Equal(t, utils.ActivationFailed, rc) - }) - - t.Run("returns ActivationFailed on GeneralSettings.Get() xml.unmarshal error", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondBadXML(t, w) - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateCCM() - assert.Equal(t, utils.ActivationFailed, rc) - }) - - t.Run("returns ActivationFailed on HostBasedSetupService.Setup server error", func(t *testing.T) { - calls := 0 - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - calls++ - if calls == 1 { - respondGeneralSettings(t, w) - } else if calls == 2 { - respondServerError(w) - } - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateCCM() - assert.Equal(t, utils.ActivationFailed, rc) - }) - - t.Run("returns ActivationFailed on HostBasedSetupService.Setup xml.unmarshal error", func(t *testing.T) { - calls := 0 - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - calls++ - if calls == 1 { - respondGeneralSettings(t, w) - } else if calls == 2 { - respondBadXML(t, w) - } - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateCCM() - assert.Equal(t, utils.ActivationFailed, rc) + lps := setupService(&flags.Flags{}) + lps.flags.Command = utils.CommandActivate + lps.flags.LocalConfig.Password = "P@ssw0rd" + t.Run("returns ActivationFailed on GetGeneralSettings error", func(t *testing.T) { + errMockGeneralSettings = errTestError + err := lps.ActivateCCM() + assert.Error(t, err) + errMockGeneralSettings = nil }) - t.Run("returns ActivationFailed on HostBasedSetupService.Setup ReturnValue is not success (0)", func(t *testing.T) { - calls := 0 - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - calls++ - if calls == 1 { - respondGeneralSettings(t, w) - } else if calls == 2 { - mockHostBasedSetupResponse.Body.Setup_OUTPUT.ReturnValue = 1 - respondHostBasedSetup(t, w) - mockHostBasedSetupResponse.Body.Setup_OUTPUT.ReturnValue = 0 - } - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateCCM() - assert.Equal(t, utils.ActivationFailed, rc) + t.Run("returns ActivationFailed on HostBasedSetupService", func(t *testing.T) { + errHostBasedSetupService = errTestError + err := lps.ActivateCCM() + assert.Error(t, err) + errHostBasedSetupService = nil }) t.Run("returns Success on happy path", func(t *testing.T) { - calls := 0 - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - calls++ - if calls == 1 { - respondGeneralSettings(t, w) - } else if calls == 2 { - respondHostBasedSetup(t, w) - } - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateCCM() - assert.Equal(t, utils.Success, rc) - }) -} - -func TestGetHostBasedSetupService(t *testing.T) { - f := &flags.Flags{} - t.Run("returns error on server error response", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithWsmanClient(f, handler) - _, err := lps.GetHostBasedSetupService() - assert.NotNil(t, err) - }) - - t.Run("returns error on xml.unmarshal error", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondBadXML(t, w) - }) - lps := setupWithWsmanClient(f, handler) - _, err := lps.GetHostBasedSetupService() - assert.NotNil(t, err) - }) - - t.Run("returns valid response on happy path", func(t *testing.T) { - expected := "test_name" - mockHostBasedSetupResponse.Body.IPS_HostBasedSetupService.SystemName = expected - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondHostBasedSetup(t, w) - }) - lps := setupWithWsmanClient(f, handler) - rsp, err := lps.GetHostBasedSetupService() - assert.Nil(t, err) - assert.Equal(t, expected, rsp.Body.IPS_HostBasedSetupService.SystemName) - mockHostBasedSetupResponse.Body.IPS_HostBasedSetupService.SystemName = "" - }) -} - -func TestGetGeneralSettings(t *testing.T) { - f := &flags.Flags{} - t.Run("returns error on server error response", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithWsmanClient(f, handler) - _, err := lps.GetGeneralSettings() - assert.NotNil(t, err) - }) - - t.Run("returns error on xml.unmarshal error", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondBadXML(t, w) - }) - lps := setupWithWsmanClient(f, handler) - _, err := lps.GetGeneralSettings() - assert.NotNil(t, err) - }) - - t.Run("returns valid response on happy path", func(t *testing.T) { - expected := "test_name" - mockGenerlSettingsResponse.Body.AMTGeneralSettings.HostName = expected - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondGeneralSettings(t, w) - }) - lps := setupWithWsmanClient(f, handler) - rsp, err := lps.GetGeneralSettings() - assert.Nil(t, err) - assert.Equal(t, expected, rsp.Body.AMTGeneralSettings.HostName) - mockGenerlSettingsResponse.Body.AMTGeneralSettings.HostName = "" + err := lps.ActivateCCM() + assert.NoError(t, err) }) } @@ -224,7 +83,9 @@ func TestActivateACM(t *testing.T) { testCerts := getTestCerts() f.LocalConfig.ACMSettings.ProvisioningCert = testCerts.Pfxb64 f.LocalConfig.ACMSettings.ProvisioningCertPwd = testCerts.PfxPassword - + lps := setupService(f) + lps.flags.Command = utils.CommandActivate + lps.flags.LocalConfig.Password = "P@ssw0rd" mockCertHashes = []amt2.CertHashEntry{ { Hash: testCerts.Root.Fingerprint, @@ -234,21 +95,8 @@ func TestActivateACM(t *testing.T) { IsDefault: true, }, } - calls := 0 - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "POST", r.Method) - var err error - calls++ - if calls == 1 { - respondGeneralSettings(t, w) - } else { - respondHostBasedSetup(t, w) - } - assert.Nil(t, err) - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.ActivateACM() - assert.Equal(t, utils.Success, rc) + err := lps.ActivateACM() + assert.NoError(t, err) } func TestInjectCertsErrors(t *testing.T) { @@ -257,22 +105,17 @@ func TestInjectCertsErrors(t *testing.T) { certs := []string{testCerts.Leaf.Pem, testCerts.Intermediate.Pem, testCerts.Root.Pem} - t.Run("returns error on server error response", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithWsmanClient(f, handler) + t.Run("returns success on injectCerts", func(t *testing.T) { + lps := setupService(f) err := lps.injectCertificate(certs) - assert.NotNil(t, err) + assert.NoError(t, err) }) - - t.Run("returns error on xml.unmarshal error", func(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondBadXML(t, w) - }) - lps := setupWithWsmanClient(f, handler) + t.Run("returns error on injectCerts", func(t *testing.T) { + errAddNextCertInChain = errTestError + lps := setupService(f) err := lps.injectCertificate(certs) - assert.NotNil(t, err) + assert.Error(t, err) + errAddNextCertInChain = nil }) } diff --git a/internal/local/amt/localTransport.go b/internal/local/amt/localTransport.go new file mode 100644 index 00000000..a48c33a8 --- /dev/null +++ b/internal/local/amt/localTransport.go @@ -0,0 +1,119 @@ +package amt + +import ( + "bufio" + "bytes" + "fmt" + "io" + "net/http" + "rpc/internal/lm" + + "github.com/sirupsen/logrus" +) + +// LocalTransport - Your custom net.Conn implementation +type LocalTransport struct { + local lm.LocalMananger + data chan []byte + errors chan error + status chan bool +} + +func NewLocalTransport() *LocalTransport { + lmDataChannel := make(chan []byte) + lmErrorChannel := make(chan error) + lmStatus := make(chan bool) + lm := &LocalTransport{ + local: lm.NewLMEConnection(lmDataChannel, lmErrorChannel, lmStatus), + data: lmDataChannel, + errors: lmErrorChannel, + status: lmStatus, + } + // defer lm.local.Close() + // defer close(lmDataChannel) + // defer close(lmErrorChannel) + // defer close(lmStatus) + + err := lm.local.Initialize() + if err != nil { + logrus.Error(err) + } + + return lm +} + +// Custom dialer function +func (l *LocalTransport) RoundTrip(r *http.Request) (*http.Response, error) { + //Something comes here...Maybe + go l.local.Listen() + + // send channel open + err := l.local.Connect() + + if err != nil { + logrus.Error(err) + return nil, err + } + // wait for channel open confirmation + <-l.status + logrus.Trace("Channel open confirmation received") + + // Serialize the HTTP request to raw form + rawRequest, err := serializeHTTPRequest(r) + if err != nil { + logrus.Error(err) + return nil, err + } + + var responseReader *bufio.Reader + // send our data to LMX + err = l.local.Send(rawRequest) + if err != nil { + logrus.Error(err) + return nil, err + } + + for dataFromLM := range l.data { + if len(dataFromLM) > 0 { + logrus.Debug("received data from LME") + logrus.Trace(string(dataFromLM)) + + // /<-l.status + responseReader = bufio.NewReader(bytes.NewReader(dataFromLM)) + break + } + } + + response, err := http.ReadResponse(responseReader, r) + if err != nil { + logrus.Error("Failed to parse response: ", err) + return nil, err + } + + return response, nil +} + +func serializeHTTPRequest(r *http.Request) ([]byte, error) { + var reqBuffer bytes.Buffer + + // Write request line + reqLine := fmt.Sprintf("%s %s %s\r\n", r.Method, r.URL.RequestURI(), r.Proto) + reqBuffer.WriteString(reqLine) + + // Write headers + r.Header.Write(&reqBuffer) + reqBuffer.WriteString("\r\n") // End of headers + + // Write body if present + if r.Body != nil { + bodyBytes, err := io.ReadAll(r.Body) + if err != nil { + return nil, err + } + // Important: Replace the body so it can be read again later if needed + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + reqBuffer.Write(bodyBytes) + } + + return reqBuffer.Bytes(), nil +} diff --git a/internal/local/amt/wsman.go b/internal/local/amt/wsman.go new file mode 100644 index 00000000..871161aa --- /dev/null +++ b/internal/local/amt/wsman.go @@ -0,0 +1,282 @@ +package amt + +import ( + "encoding/base64" + + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/general" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publicprivate" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/setupandconfiguration" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/timesynchronization" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/tls" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/wifiportconfiguration" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/concrete" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/credential" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/models" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/client" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/ips/hostbasedsetup" +) + +type WSMANer interface { + SetupWsmanClient(username string, password string, logAMTMessages bool) + Unprovision(int) (setupandconfiguration.Response, error) + GetGeneralSettings() (general.Response, error) + HostBasedSetupService(digestRealm string, password string) (hostbasedsetup.Response, error) + GetHostBasedSetupService() (hostbasedsetup.Response, error) + AddNextCertInChain(cert string, isLeaf bool, isRoot bool) (hostbasedsetup.Response, error) + HostBasedSetupServiceAdmin(password string, digestRealm string, nonce []byte, signature string) (hostbasedsetup.Response, error) + SetupMEBX(string) (response setupandconfiguration.Response, err error) + GetPublicKeyCerts() ([]publickey.PublicKeyCertificateResponse, error) + GetPublicPrivateKeyPairs() ([]publicprivate.PublicPrivateKeyPair, error) + DeletePublicPrivateKeyPair(instanceId string) error + DeletePublicCert(instanceId string) error + GetCredentialRelationships() ([]credential.CredentialContext, error) + GetConcreteDependencies() ([]concrete.ConcreteDependency, error) + AddTrustedRootCert(caCert string) (string, error) + AddClientCert(clientCert string) (string, error) + AddPrivateKey(privateKey string) (string, error) + DeleteKeyPair(instanceID string) error + GetLowAccuracyTimeSynch() (response timesynchronization.Response, err error) + SetHighAccuracyTimeSynch(ta0 int64, tm1 int64, tm2 int64) (response timesynchronization.Response, err error) + GenerateKeyPair(keyAlgorithm publickey.KeyAlgorithm, keyLength publickey.KeyLength) (response publickey.Response, err error) + // WiFi + GetWiFiSettings() ([]wifi.WiFiEndpointSettingsResponse, error) + DeleteWiFiSetting(instanceId string) error + EnableWiFi() error + AddWiFiSettings(wifiEndpointSettings wifi.WiFiEndpointSettingsRequest, ieee8021xSettings models.IEEE8021xSettings, wifiEndpoint, clientCredential, caCredential string) (wifiportconfiguration.Response, error) + // TLS + CreateTLSCredentialContext(certHandle string) (response tls.Response, err error) + EnumerateTLSSettingData() (response tls.Response, err error) + PullTLSSettingData(enumerationContext string) (response tls.Response, err error) + PUTTLSSettings(instanceID string, tlsSettingData tls.SettingDataRequest) (response tls.Response, err error) + + CommitChanges() (response setupandconfiguration.Response, err error) +} + +type GoWSMANMessages struct { + wsmanMessages wsman.Messages + target string +} + +func NewGoWSMANMessages(lmsAddress string) *GoWSMANMessages { + return &GoWSMANMessages{ + target: lmsAddress, + } +} + +func (g *GoWSMANMessages) SetupWsmanClient(username string, password string, logAMTMessages bool) { + + clientParams := client.Parameters{ + Target: g.target, + Username: username, + Password: password, + UseDigest: true, + UseTLS: false, + LogAMTMessages: logAMTMessages, + } + g.wsmanMessages = wsman.NewMessages(clientParams) +} + +func (g *GoWSMANMessages) GetGeneralSettings() (general.Response, error) { + return g.wsmanMessages.AMT.GeneralSettings.Get() +} + +func (g *GoWSMANMessages) HostBasedSetupService(digestRealm string, password string) (hostbasedsetup.Response, error) { + return g.wsmanMessages.IPS.HostBasedSetupService.Setup(hostbasedsetup.AdminPassEncryptionTypeHTTPDigestMD5A1, digestRealm, password) +} + +func (g *GoWSMANMessages) GetHostBasedSetupService() (hostbasedsetup.Response, error) { + return g.wsmanMessages.IPS.HostBasedSetupService.Get() +} + +func (g *GoWSMANMessages) AddNextCertInChain(cert string, isLeaf bool, isRoot bool) (hostbasedsetup.Response, error) { + return g.wsmanMessages.IPS.HostBasedSetupService.AddNextCertInChain(cert, isLeaf, isRoot) +} + +func (g *GoWSMANMessages) HostBasedSetupServiceAdmin(password, digestRealm string, nonce []byte, signature string) (hostbasedsetup.Response, error) { + return g.wsmanMessages.IPS.HostBasedSetupService.AdminSetup(hostbasedsetup.AdminPassEncryptionTypeHTTPDigestMD5A1, digestRealm, password, base64.StdEncoding.EncodeToString(nonce), hostbasedsetup.SigningAlgorithmRSASHA2256, signature) +} + +func (g *GoWSMANMessages) Unprovision(int) (setupandconfiguration.Response, error) { + return g.wsmanMessages.AMT.SetupAndConfigurationService.Unprovision(1) +} + +func (g *GoWSMANMessages) SetupMEBX(password string) (response setupandconfiguration.Response, err error) { + return g.wsmanMessages.AMT.SetupAndConfigurationService.SetMEBXPassword(password) +} + +func (g *GoWSMANMessages) GetPublicKeyCerts() ([]publickey.PublicKeyCertificateResponse, error) { + response, err := g.wsmanMessages.AMT.PublicKeyCertificate.Enumerate() + if err != nil { + return nil, err + } + response, err = g.wsmanMessages.AMT.PublicKeyCertificate.Pull(response.Body.EnumerateResponse.EnumerationContext) + if err != nil { + return nil, err + } + return response.Body.PullResponse.PublicKeyCertificateItems, nil +} + +func (g *GoWSMANMessages) GenerateKeyPair(keyAlgorithm publickey.KeyAlgorithm, keyLength publickey.KeyLength) (response publickey.Response, err error) { + return g.wsmanMessages.AMT.PublicKeyManagementService.GenerateKeyPair(keyAlgorithm, keyLength) +} + +func (g *GoWSMANMessages) CreateTLSCredentialContext(certHandle string) (response tls.Response, err error) { + return g.wsmanMessages.AMT.TLSCredentialContext.Create(certHandle) +} + +// GetPublicPrivateKeyPairs +// NOTE: RSA Key encoded as DES PKCS#1. The Exponent (E) is 65537 (0x010001). +// When this structure is used as an output parameter (GET or PULL method), +// only the public section of the key is exported. +func (g *GoWSMANMessages) GetPublicPrivateKeyPairs() ([]publicprivate.PublicPrivateKeyPair, error) { + response, err := g.wsmanMessages.AMT.PublicPrivateKeyPair.Enumerate() + if err != nil { + return nil, err + } + response, err = g.wsmanMessages.AMT.PublicPrivateKeyPair.Pull(response.Body.EnumerateResponse.EnumerationContext) + if err != nil { + return nil, err + } + return response.Body.PullResponse.PublicPrivateKeyPairItems, nil +} +func (g *GoWSMANMessages) GetWiFiSettings() ([]wifi.WiFiEndpointSettingsResponse, error) { + response, err := g.wsmanMessages.CIM.WiFiEndpointSettings.Enumerate() + if err != nil { + return nil, err + } + response, err = g.wsmanMessages.CIM.WiFiEndpointSettings.Pull(response.Body.EnumerateResponse.EnumerationContext) + if err != nil { + return nil, err + } + return response.Body.PullResponse.EndpointSettingsItems, nil +} +func (g *GoWSMANMessages) DeletePublicPrivateKeyPair(instanceId string) error { + _, err := g.wsmanMessages.AMT.PublicPrivateKeyPair.Delete(instanceId) + return err +} +func (g *GoWSMANMessages) DeletePublicCert(instanceId string) error { + _, err := g.wsmanMessages.AMT.PublicKeyCertificate.Delete(instanceId) + return err +} +func (g *GoWSMANMessages) GetCredentialRelationships() ([]credential.CredentialContext, error) { + response, err := g.wsmanMessages.CIM.CredentialContext.Enumerate() + if err != nil { + return nil, err + } + response, err = g.wsmanMessages.CIM.CredentialContext.Pull(response.Body.EnumerateResponse.EnumerationContext) + if err != nil { + return nil, err + } + return response.Body.PullResponse.Items, nil +} +func (g *GoWSMANMessages) GetConcreteDependencies() ([]concrete.ConcreteDependency, error) { + response, err := g.wsmanMessages.CIM.ConcreteDependency.Enumerate() + if err != nil { + return nil, err + } + response, err = g.wsmanMessages.CIM.ConcreteDependency.Pull(response.Body.EnumerateResponse.EnumerationContext) + if err != nil { + return nil, err + } + return response.Body.PullResponse.Items, nil +} +func (g *GoWSMANMessages) DeleteWiFiSetting(instanceID string) error { + _, err := g.wsmanMessages.CIM.WiFiEndpointSettings.Delete(instanceID) + return err +} +func (g *GoWSMANMessages) AddTrustedRootCert(caCert string) (handle string, err error) { + response, err := g.wsmanMessages.AMT.PublicKeyManagementService.AddTrustedRootCertificate(caCert) + if err != nil { + return "", err + } + if len(response.Body.AddTrustedRootCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selectors) > 0 { + handle = response.Body.AddTrustedRootCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selectors[0].Text + } + return handle, nil +} +func (g *GoWSMANMessages) AddClientCert(clientCert string) (handle string, err error) { + response, err := g.wsmanMessages.AMT.PublicKeyManagementService.AddCertificate(clientCert) + if err != nil { + return "", err + } + if len(response.Body.AddCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selectors) > 0 { + handle = response.Body.AddCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selectors[0].Text + } + return handle, nil +} +func (g *GoWSMANMessages) AddPrivateKey(privateKey string) (handle string, err error) { + response, err := g.wsmanMessages.AMT.PublicKeyManagementService.AddKey(privateKey) + if err != nil { + return "", err + } + if len(response.Body.AddKey_OUTPUT.CreatedKey.ReferenceParameters.SelectorSet.Selectors) > 0 { + handle = response.Body.AddKey_OUTPUT.CreatedKey.ReferenceParameters.SelectorSet.Selectors[0].Text + } + return handle, nil +} +func (g *GoWSMANMessages) DeleteKeyPair(instanceID string) error { + _, err := g.wsmanMessages.AMT.PublicKeyManagementService.Delete(instanceID) + return err +} +func (g *GoWSMANMessages) EnableWiFi() error { + response, err := g.wsmanMessages.AMT.WiFiPortConfigurationService.Get() + if err != nil { + return err + } + + // if local sync not enable, enable it + if response.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled == wifiportconfiguration.LocalSyncDisabled { + putRequest := wifiportconfiguration.WiFiPortConfigurationServiceRequest{ + RequestedState: response.Body.WiFiPortConfigurationService.RequestedState, + EnabledState: response.Body.WiFiPortConfigurationService.EnabledState, + HealthState: response.Body.WiFiPortConfigurationService.HealthState, + ElementName: response.Body.WiFiPortConfigurationService.ElementName, + SystemCreationClassName: response.Body.WiFiPortConfigurationService.SystemCreationClassName, + SystemName: response.Body.WiFiPortConfigurationService.SystemName, + CreationClassName: response.Body.WiFiPortConfigurationService.CreationClassName, + Name: response.Body.WiFiPortConfigurationService.Name, + LocalProfileSynchronizationEnabled: wifiportconfiguration.UnrestrictedSync, + LastConnectedSsidUnderMeControl: response.Body.WiFiPortConfigurationService.LastConnectedSsidUnderMeControl, + NoHostCsmeSoftwarePolicy: response.Body.WiFiPortConfigurationService.NoHostCsmeSoftwarePolicy, + UEFIWiFiProfileShareEnabled: response.Body.WiFiPortConfigurationService.UEFIWiFiProfileShareEnabled, + } + + _, err := g.wsmanMessages.AMT.WiFiPortConfigurationService.Put(putRequest) + if err != nil { + return err + } + } + + // always turn wifi on via state change request + // Enumeration 32769 - WiFi is enabled in S0 + Sx/AC + _, err = g.wsmanMessages.CIM.WiFiPort.RequestStateChange(32769) + if err != nil { + return err // utils.WSMANMessageError + } + return nil +} +func (g *GoWSMANMessages) AddWiFiSettings(wifiEndpointSettings wifi.WiFiEndpointSettingsRequest, ieee8021xSettings models.IEEE8021xSettings, wifiEndpoint, clientCredential, caCredential string) (response wifiportconfiguration.Response, err error) { + return g.wsmanMessages.AMT.WiFiPortConfigurationService.AddWiFiSettings(wifiEndpointSettings, ieee8021xSettings, wifiEndpoint, clientCredential, caCredential) +} +func (g *GoWSMANMessages) PUTTLSSettings(instanceID string, tlsSettingData tls.SettingDataRequest) (response tls.Response, err error) { + return g.wsmanMessages.AMT.TLSSettingData.Put(instanceID, tlsSettingData) +} +func (g *GoWSMANMessages) GetLowAccuracyTimeSynch() (response timesynchronization.Response, err error) { + return g.wsmanMessages.AMT.TimeSynchronizationService.GetLowAccuracyTimeSynch() +} +func (g *GoWSMANMessages) SetHighAccuracyTimeSynch(ta0 int64, tm1 int64, tm2 int64) (response timesynchronization.Response, err error) { + return g.wsmanMessages.AMT.TimeSynchronizationService.SetHighAccuracyTimeSynch(ta0, tm1, tm1) +} +func (g *GoWSMANMessages) EnumerateTLSSettingData() (response tls.Response, err error) { + return g.wsmanMessages.AMT.TLSSettingData.Enumerate() +} +func (g *GoWSMANMessages) PullTLSSettingData(enumerationContext string) (response tls.Response, err error) { + return g.wsmanMessages.AMT.TLSSettingData.Pull(enumerationContext) +} + +func (g *GoWSMANMessages) CommitChanges() (response setupandconfiguration.Response, err error) { + return g.wsmanMessages.AMT.SetupAndConfigurationService.CommitChanges() +} diff --git a/internal/local/amt/wsman_test.go b/internal/local/amt/wsman_test.go new file mode 100644 index 00000000..227baa46 --- /dev/null +++ b/internal/local/amt/wsman_test.go @@ -0,0 +1 @@ +package amt diff --git a/internal/local/configure.go b/internal/local/configure.go index 27c35034..3d0bfcb6 100644 --- a/internal/local/configure.go +++ b/internal/local/configure.go @@ -6,23 +6,21 @@ import ( "rpc/internal/config" "rpc/pkg/utils" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/wifiportconfiguration" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/models" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/wifi" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/models" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) -func (service *ProvisioningService) Configure() utils.ReturnCode { - service.setupWsmanClient("admin", service.flags.Password) +func (service *ProvisioningService) Configure() (err error) { + service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, logrus.GetLevel() == logrus.TraceLevel) switch service.flags.SubCommand { case utils.SubCommandAddWifiSettings: return service.AddWifiSettings() case utils.SubCommandEnableWifiPort: return service.EnableWifiPort() + case utils.SubCommandSetMEBx: + return service.SetMebx() case utils.SubCommandConfigureTLS: return service.ConfigureTLS() default: @@ -30,99 +28,127 @@ func (service *ProvisioningService) Configure() utils.ReturnCode { return utils.IncorrectCommandLineParameters } -func (service *ProvisioningService) EnableWifiPort() utils.ReturnCode { - rc := service.EnableWifi() - if rc != utils.Success { +func (service *ProvisioningService) SetMebx() (err error) { + // Retrieve the current control mode from the AMT command interface. + controlMode, err := service.amtCommand.GetControlMode() + if err != nil { + log.Error("Failed to get control mode:", err) + return utils.AMTConnectionFailed + } + + // Check if the control mode is ACM (Admin Control Mode) + if controlMode != 2 { // If not in ACM, return an error. + errMsg := "MEBx password can only be configured in ACM. Current device control mode: " + utils.InterpretControlMode(controlMode) + log.Error(errMsg) + return utils.SetMEBXPasswordFailed + } + + // Set up MEBx with the provided password. + response, err := service.interfacedWsmanMessage.SetupMEBX(service.flags.MEBxPassword) + // log.Info(response.JSON()) + if err != nil { + log.Error("Failed to configure MEBx Password:", err) + return err + } + + // Check the response's success status. + if response.Body.SetMEBxPassword_OUTPUT.ReturnValue != 0 { + // If ReturnValue is not 0, configuration failed. + log.Error("Failed to configure MEBx Password with return value:", response.Body.SetMEBxPassword_OUTPUT.ReturnValue) + return utils.SetMEBXPasswordFailed + } + log.Info("Successfully configured MEBx Password.") + return nil +} + +func (service *ProvisioningService) EnableWifiPort() (err error) { + err = service.interfacedWsmanMessage.EnableWiFi() + if err != nil { log.Error("Failed to enable wifi port and local profile synchronization.") - } else { - log.Info("Successfully enabled wifi port and local profile synchronization.") + return } - return rc + log.Info("Successfully enabled wifi port and local profile synchronization.") + return } -func (service *ProvisioningService) AddWifiSettings() utils.ReturnCode { +func (service *ProvisioningService) AddWifiSettings() (err error) { // start with fresh map service.handlesWithCerts = make(map[string]string) // PruneWifiConfigs is best effort // it will log error messages, but doesn't stop the configuration flow service.PruneWifiConfigs() - rc := service.EnableWifi() - if rc != utils.Success { - return rc + err = service.EnableWifiPort() + if err != nil { + return err } return service.ProcessWifiConfigs() } -func (service *ProvisioningService) PruneWifiConfigs() utils.ReturnCode { +func (service *ProvisioningService) PruneWifiConfigs() (err error) { // get these handles BEFORE deleting the wifi profiles - certHandles, keyPairHandles := service.GetWifiIeee8021xCerts() - - var pullRspEnv wifi.PullResponseEnvelope - rc := service.EnumPullUnmarshal( - service.cimMessages.WiFiEndpointSettings.Enumerate, - service.cimMessages.WiFiEndpointSettings.Pull, - &pullRspEnv, - ) - if rc != utils.Success { - return rc + certHandles, keyPairHandles, err := service.GetWifiIeee8021xCerts() + if err != nil { + return err } - var successes []string - var failures []string - for _, wifiSetting := range pullRspEnv.Body.PullResponse.Items { + wifiEndpointSettings, err := service.interfacedWsmanMessage.GetWiFiSettings() + if err != nil { + return err + } + + for _, wifiSetting := range wifiEndpointSettings { // while testing, saw some cases where the PullResponse returned items with no InstanceID? if wifiSetting.InstanceID == "" { + // Skip wifiSettings with no InstanceID continue } log.Infof("deleting wifiSetting: %s", wifiSetting.InstanceID) - xmlMsg := service.cimMessages.WiFiEndpointSettings.Delete(wifiSetting.InstanceID) - // the response does not return any additional useful information - _, err := service.client.Post(xmlMsg) + err := service.interfacedWsmanMessage.DeleteWiFiSetting(wifiSetting.InstanceID) if err != nil { log.Infof("unable to delete: %s %s", wifiSetting.InstanceID, err) - failures = append(failures, wifiSetting.InstanceID) + err = utils.DeleteWifiConfigFailed continue } - successes = append(successes, wifiSetting.InstanceID) + + log.Infof("successfully deleted wifiSetting: %s", wifiSetting.InstanceID) } - service.PruneWifiIeee8021xCerts(certHandles, keyPairHandles) + err = service.PruneWifiIeee8021xCerts(certHandles, keyPairHandles) - if len(failures) > 0 { - return utils.DeleteWifiConfigFailed - } - return utils.Success + return err } -func (service *ProvisioningService) PruneWifiIeee8021xCerts(certHandles []string, keyPairHandles []string) (failedCertHandles []string, failedKeyPairHandles []string) { +func (service *ProvisioningService) PruneWifiIeee8021xCerts(certHandles []string, keyPairHandles []string) (err error) { for _, handle := range certHandles { - rc := service.DeletePublicCert(handle) - if rc != utils.Success { - failedCertHandles = append(failedCertHandles, handle) - } else { - delete(service.handlesWithCerts, handle) + err := service.interfacedWsmanMessage.DeletePublicCert(handle) + if err != nil { + log.Infof("unable to delete: %s %s", handle, err) + err = utils.DeleteWifiConfigFailed } } for _, handle := range keyPairHandles { - rc := service.DeletePublicPrivateKeyPair(handle) - if rc != utils.Success { - failedKeyPairHandles = append(failedKeyPairHandles, handle) - } else { - delete(service.handlesWithCerts, handle) + err := service.interfacedWsmanMessage.DeletePublicPrivateKeyPair(handle) + if err != nil { + log.Infof("unable to delete: %s %s", handle, err) + err = utils.DeleteWifiConfigFailed } } - return failedCertHandles, failedKeyPairHandles + return err } -func (service *ProvisioningService) GetWifiIeee8021xCerts() (certHandles []string, keyPairHandles []string) { - - var publicCerts []publickey.PublicKeyCertificate - service.GetPublicKeyCerts(&publicCerts) - var keyPairs []publicprivate.PublicPrivateKeyPair - service.GetPublicPrivateKeyPairs(&keyPairs) - credentials, rc := service.GetCredentialRelationships() - if rc != utils.Success { - return certHandles, keyPairHandles +func (service *ProvisioningService) GetWifiIeee8021xCerts() (certHandles, keyPairHandles []string, err error) { + publicCerts, err := service.interfacedWsmanMessage.GetPublicKeyCerts() + if err != nil { + return []string{}, []string{}, err + } + // what/wjhere is this used? keyPairs + // _, err = service.interfacedWsmanMessage.GetPublicPrivateKeyPairs() + // if err != nil { + // return []string{}, []string{}, err + // } + credentials, err := service.interfacedWsmanMessage.GetCredentialRelationships() + if err != nil { + return []string{}, []string{}, err } certHandleMap := make(map[string]bool) for i := range credentials { @@ -144,11 +170,11 @@ func (service *ProvisioningService) GetWifiIeee8021xCerts() (certHandles []strin } } if len(certHandles) == 0 { - return certHandles, keyPairHandles + return certHandles, keyPairHandles, err } keyPairHandleMap := make(map[string]bool) - dependencies, _ := service.GetConcreteDependencies() + dependencies, _ := service.interfacedWsmanMessage.GetConcreteDependencies() for i := range dependencies { antecedent := &dependencies[i].Antecedent.ReferenceParameters if antecedent.ResourceURI != `http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate` { @@ -172,17 +198,17 @@ func (service *ProvisioningService) GetWifiIeee8021xCerts() (certHandles []strin } } - return certHandles, keyPairHandles + return certHandles, keyPairHandles, err } -func (service *ProvisioningService) ProcessWifiConfigs() utils.ReturnCode { +func (service *ProvisioningService) ProcessWifiConfigs() error { lc := service.flags.LocalConfig var successes []string var failures []string for _, cfg := range lc.WifiConfigs { log.Info("configuring wifi profile: ", cfg.ProfileName) - rc := service.ProcessWifiConfig(&cfg) - if rc != utils.Success { + err := service.ProcessWifiConfig(&cfg) + if err != nil { log.Error("failed configuring: ", cfg.ProfileName) failures = append(failures, cfg.ProfileName) } else { @@ -197,10 +223,10 @@ func (service *ProvisioningService) ProcessWifiConfigs() utils.ReturnCode { return utils.WiFiConfigurationFailed } } - return utils.Success + return nil } -func (service *ProvisioningService) ProcessWifiConfig(wifiCfg *config.WifiConfig) utils.ReturnCode { +func (service *ProvisioningService) ProcessWifiConfig(wifiCfg *config.WifiConfig) (err error) { // profile names can only be alphanumeric (not even dashes) var reAlphaNum = regexp.MustCompile("[^a-zA-Z0-9]+") @@ -209,132 +235,95 @@ func (service *ProvisioningService) ProcessWifiConfig(wifiCfg *config.WifiConfig return utils.MissingOrIncorrectWifiProfileName } - wiFiEndpointSettings := models.WiFiEndpointSettings{ + // Set wifiEndpointSettings properties from wifiCfg file + + wifiEndpointSettings := wifi.WiFiEndpointSettingsRequest{ ElementName: wifiCfg.ProfileName, InstanceID: fmt.Sprintf("Intel(r) AMT:WiFi Endpoint Settings %s", wifiCfg.ProfileName), SSID: wifiCfg.SSID, Priority: wifiCfg.Priority, - AuthenticationMethod: models.AuthenticationMethod(wifiCfg.AuthenticationMethod), - EncryptionMethod: models.EncryptionMethod(wifiCfg.EncryptionMethod), + AuthenticationMethod: wifi.AuthenticationMethod(wifiCfg.AuthenticationMethod), + EncryptionMethod: wifi.EncryptionMethod(wifiCfg.EncryptionMethod), } - var ieee8021xSettings *models.IEEE8021xSettings - handles := Handles{} - if wiFiEndpointSettings.AuthenticationMethod == models.AuthenticationMethod_WPA_IEEE8021x || - wiFiEndpointSettings.AuthenticationMethod == models.AuthenticationMethod_WPA2_IEEE8021x { + // Create an empty handles reference holder + handles := Handles{} - ieee8021xSettings = &models.IEEE8021xSettings{} - rc := service.ProcessIeee8012xConfig(wifiCfg.Ieee8021xProfileName, ieee8021xSettings, &handles) - if rc != utils.Success { - service.RollbackAddedItems(&handles) - return rc + // Find the correct Ieee8021xConfig from wifiCfg file + ieee8021xConfig := service.checkForIeee8021xConfig(wifiCfg) + // If we find a matching Ieee8021xConfig, populate the IEEE8021xSettings and add any required private keys and certificates + var ieee8021xSettings models.IEEE8021xSettings + if ieee8021xConfig != nil { + ieee8021xSettings, err = service.setIeee8021xConfig(ieee8021xConfig, handles) + if err != nil { + return err } - } else { - wiFiEndpointSettings.PSKPassPhrase = wifiCfg.PskPassphrase - } - xmlMsg := service.amtMessages.WiFiPortConfigurationService.AddWiFiSettings( - wiFiEndpointSettings, - ieee8021xSettings, - "WiFi Endpoint 0", - handles.clientCertHandle, - handles.rootCertHandle) - var addWifiSettingsRsp wifiportconfiguration.AddWiFiSettingsResponse - rc := service.PostAndUnmarshal(xmlMsg, &addWifiSettingsRsp) - if rc != utils.Success { - service.RollbackAddedItems(&handles) - return rc + // not using IEEE8021x, so set the wireless passphrase + wifiEndpointSettings.PSKPassPhrase = wifiCfg.PskPassphrase } - rc = utils.ReturnCode(addWifiSettingsRsp.Body.AddWiFiSettings_OUTPUT.ReturnValue) - if rc != 0 { + + _, err = service.interfacedWsmanMessage.AddWiFiSettings(wifiEndpointSettings, ieee8021xSettings, "WiFi Endpoint 0", handles.clientCertHandle, handles.rootCertHandle) + if err != nil { + // The AddWiFiSettings call failed, return error response from go-wsman-messages service.RollbackAddedItems(&handles) - log.Errorf("AddWiFiSettings_OUTPUT.ReturnValue: %d", rc) - return utils.AmtPtStatusCodeBase + rc + return utils.WiFiConfigurationFailed //should we return err? } - return utils.Success -} -func (service *ProvisioningService) ProcessIeee8012xConfig(profileName string, settings *models.IEEE8021xSettings, handles *Handles) utils.ReturnCode { + return nil +} - // find the matching configuration - var ieee8021xConfig config.Ieee8021xConfig - var found bool - for _, curCfg := range service.flags.LocalConfig.Ieee8021xConfigs { - if curCfg.ProfileName == profileName { - ieee8021xConfig = curCfg - found = true - break - } +func (service *ProvisioningService) setIeee8021xConfig(ieee8021xConfig *config.Ieee8021xConfig, handles Handles) (ieee8021xSettings models.IEEE8021xSettings, err error) { + ieee8021xSettings = models.IEEE8021xSettings{ + ElementName: ieee8021xConfig.ProfileName, + InstanceID: fmt.Sprintf("Intel(r) AMT: 8021X Settings %s", ieee8021xConfig.ProfileName), + AuthenticationProtocol: models.AuthenticationProtocol(ieee8021xConfig.AuthenticationProtocol), + Username: ieee8021xConfig.Username, } - if !found { - log.Errorf("missing Ieee8021xConfig %s", profileName) - return utils.MissingIeee8021xConfiguration + if ieee8021xSettings.AuthenticationProtocol == models.AuthenticationProtocolPEAPv0_EAPMSCHAPv2 { + ieee8021xSettings.Password = ieee8021xConfig.Password } - - // translate from configuration to settings - settings.ElementName = ieee8021xConfig.ProfileName - settings.InstanceID = fmt.Sprintf("Intel(r) AMT: 8021X Settings %s", ieee8021xConfig.ProfileName) - settings.AuthenticationProtocol = models.AuthenticationProtocol(ieee8021xConfig.AuthenticationProtocol) - settings.Username = ieee8021xConfig.Username - if settings.AuthenticationProtocol == models.AuthenticationProtocolPEAPv0_EAPMSCHAPv2 { - settings.Password = ieee8021xConfig.Password - } - - // add key and certs - var rc utils.ReturnCode if ieee8021xConfig.PrivateKey != "" { - handles.privateKeyHandle, rc = service.AddPrivateKey(ieee8021xConfig.PrivateKey) - if rc != utils.Success { - return rc + handles.privateKeyHandle = checkHandleExists(service.handlesWithCerts, ieee8021xConfig.ClientCert) + if handles.privateKeyHandle == "" { + handles.privateKeyHandle, err = service.interfacedWsmanMessage.AddPrivateKey(ieee8021xConfig.PrivateKey) + service.handlesWithCerts[handles.privateKeyHandle] = ieee8021xConfig.PrivateKey + if err != nil { + return ieee8021xSettings, err + } } } if ieee8021xConfig.ClientCert != "" { - handles.clientCertHandle, rc = service.AddClientCert(ieee8021xConfig.ClientCert) - if rc != utils.Success { - return rc + handles.clientCertHandle = checkHandleExists(service.handlesWithCerts, ieee8021xConfig.ClientCert) + if handles.clientCertHandle == "" { + handles.clientCertHandle, err = service.interfacedWsmanMessage.AddClientCert(ieee8021xConfig.ClientCert) + service.handlesWithCerts[handles.clientCertHandle] = ieee8021xConfig.ClientCert + if err != nil { + return ieee8021xSettings, err + } } } - handles.rootCertHandle, rc = service.AddTrustedRootCert(ieee8021xConfig.CACert) - return rc -} - -func (service *ProvisioningService) EnableWifi() utils.ReturnCode { - xmlMsg := service.amtMessages.WiFiPortConfigurationService.Get() - var portCfgRsp wifiportconfiguration.Response - rc := service.PostAndUnmarshal(xmlMsg, &portCfgRsp) - if rc != utils.Success { - return rc - } - - // if local sync not enable, enable it - if portCfgRsp.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled == wifiportconfiguration.LocalSyncDisabled { - - portCfgRsp.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled = wifiportconfiguration.UnrestrictedSync - xmlMsg = service.amtMessages.WiFiPortConfigurationService.Put(portCfgRsp.Body.WiFiPortConfigurationService) - rc = service.PostAndUnmarshal(xmlMsg, &portCfgRsp) - if rc != utils.Success { - return rc - } - if portCfgRsp.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled == 0 { - log.Errorf("failed to enable wifi local profile synchronization") - return utils.WiFiConfigurationFailed + if ieee8021xConfig.CACert != "" { + handles.rootCertHandle = checkHandleExists(service.handlesWithCerts, ieee8021xConfig.CACert) + if handles.rootCertHandle == "" { + handles.rootCertHandle, err = service.interfacedWsmanMessage.AddTrustedRootCert(ieee8021xConfig.CACert) + service.handlesWithCerts[handles.rootCertHandle] = ieee8021xConfig.CACert + if err != nil { + return ieee8021xSettings, err + } } } + return ieee8021xSettings, nil +} - // always turn wifi on via state change request - // Enumeration 32769 - WiFi is enabled in S0 + Sx/AC - xmlMsg = service.cimMessages.WiFiPort.RequestStateChange(32769) - var stateChangeRsp wifi.RequestStateChangeResponse - rc = service.PostAndUnmarshal(xmlMsg, &stateChangeRsp) - if rc != utils.Success { - return rc - } - rc = utils.ReturnCode(stateChangeRsp.Body.RequestStateChange_OUTPUT.ReturnValue) - if rc != utils.Success { - log.Errorf("AddWiFiSettings_OUTPUT.ReturnValue: %d", rc) - return utils.AmtPtStatusCodeBase + rc +func (service *ProvisioningService) checkForIeee8021xConfig(wifiCfg *config.WifiConfig) (ieee8021xConfig *config.Ieee8021xConfig) { + for _, curCfg := range service.flags.LocalConfig.Ieee8021xConfigs { + if curCfg.ProfileName == wifiCfg.Ieee8021xProfileName { + ieee8021xConfig = &curCfg + break + } } - return utils.Success + return ieee8021xConfig } type Handles struct { @@ -347,8 +336,7 @@ type Handles struct { func (service *ProvisioningService) RollbackAddedItems(handles *Handles) { if handles.privateKeyHandle != "" { log.Infof("rolling back private key %s", handles.privateKeyHandle) - xmlMsg := service.amtMessages.PublicPrivateKeyPair.Delete(handles.privateKeyHandle) - _, err := service.client.Post(xmlMsg) + err := service.interfacedWsmanMessage.DeletePublicPrivateKeyPair(handles.privateKeyHandle) if err != nil { log.Errorf("failed deleting private key: %s", handles.privateKeyHandle) } else { @@ -357,9 +345,7 @@ func (service *ProvisioningService) RollbackAddedItems(handles *Handles) { } if handles.keyPairHandle != "" { log.Infof("rolling back private key %s", handles.keyPairHandle) - xmlMsg := service.amtMessages.PublicKeyManagementService.Delete(handles.keyPairHandle) - log.Trace(xmlMsg) - _, err := service.client.Post(xmlMsg) + err := service.interfacedWsmanMessage.DeleteKeyPair(handles.keyPairHandle) if err != nil { log.Errorf("failed deleting keyPairHandle: %s", handles.keyPairHandle) } else { @@ -368,8 +354,7 @@ func (service *ProvisioningService) RollbackAddedItems(handles *Handles) { } if handles.clientCertHandle != "" { log.Infof("rolling back client cert %s", handles.clientCertHandle) - xmlMsg := service.amtMessages.PublicKeyCertificate.Delete(handles.clientCertHandle) - _, err := service.client.Post(xmlMsg) + err := service.interfacedWsmanMessage.DeletePublicCert(handles.clientCertHandle) if err != nil { log.Errorf("failed deleting client cert: %s", handles.clientCertHandle) } else { @@ -378,8 +363,7 @@ func (service *ProvisioningService) RollbackAddedItems(handles *Handles) { } if handles.rootCertHandle != "" { log.Infof("rolling back root cert %s", handles.rootCertHandle) - xmlMsg := service.amtMessages.PublicKeyCertificate.Delete(handles.rootCertHandle) - _, err := service.client.Post(xmlMsg) + err := service.interfacedWsmanMessage.DeletePublicCert(handles.rootCertHandle) if err != nil { log.Errorf("failed deleting root cert: %s", handles.rootCertHandle) } else { @@ -387,94 +371,3 @@ func (service *ProvisioningService) RollbackAddedItems(handles *Handles) { } } } - -func (service *ProvisioningService) AddTrustedRootCert(caCert string) (string, utils.ReturnCode) { - // check if this has been added already - for k, v := range service.handlesWithCerts { - if v == caCert { - return k, utils.Success - } - } - xmlMsg := service.amtMessages.PublicKeyManagementService.AddTrustedRootCertificate(caCert) - var rspEnv publickey.Response - rc := service.PostAndUnmarshal(xmlMsg, &rspEnv) - if rc != utils.Success { - return "", rc - } - rc = checkReturnValue(utils.ReturnCode(rspEnv.Body.AddTrustedRootCertificate_OUTPUT.ReturnValue), "root certificate") - if rc != utils.Success { - return "", rc - } - var handle string - if len(rspEnv.Body.AddTrustedRootCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selector) > 0 { - handle = rspEnv.Body.AddTrustedRootCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selector[0].Value - } - service.handlesWithCerts[handle] = caCert - return handle, utils.Success -} - -func (service *ProvisioningService) AddClientCert(clientCert string) (string, utils.ReturnCode) { - // check if this has been added already - for k, v := range service.handlesWithCerts { - if v == clientCert { - return k, utils.Success - } - } - xmlMsg := service.amtMessages.PublicKeyManagementService.AddCertificate(clientCert) - var rspEnv publickey.Response - rc := service.PostAndUnmarshal(xmlMsg, &rspEnv) - if rc != utils.Success { - return "", rc - } - rc = checkReturnValue(utils.ReturnCode(rspEnv.Body.AddTrustedCertificate_OUTPUT.ReturnValue), "client certificate") - if rc != utils.Success { - return "", rc - } - var handle string - if len(rspEnv.Body.AddTrustedCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selector) > 0 { - handle = rspEnv.Body.AddTrustedCertificate_OUTPUT.CreatedCertificate.ReferenceParameters.SelectorSet.Selector[0].Value - } - service.handlesWithCerts[handle] = clientCert - return handle, utils.Success -} - -func (service *ProvisioningService) AddPrivateKey(privateKey string) (string, utils.ReturnCode) { - // check if this has been added already, but need the publik key of the pair - for k, v := range service.handlesWithCerts { - if v == privateKey { - return k, utils.Success - } - } - xmlMsg := service.amtMessages.PublicKeyManagementService.AddKey([]byte(privateKey)) - var rspEnv publickey.Response - rc := service.PostAndUnmarshal(xmlMsg, &rspEnv) - if rc != utils.Success { - return "", rc - } - rc = checkReturnValue(utils.ReturnCode(rspEnv.Body.AddKey_OUTPUT.ReturnValue), "private key") - if rc != utils.Success { - return "", rc - } - var handle string - if len(rspEnv.Body.AddKey_OUTPUT.CreatedKey.ReferenceParameters.SelectorSet.Selector) > 0 { - handle = rspEnv.Body.AddKey_OUTPUT.CreatedKey.ReferenceParameters.SelectorSet.Selector[0].Value - } - service.handlesWithCerts[handle] = privateKey - return handle, utils.Success -} - -func checkReturnValue(rc utils.ReturnCode, item string) utils.ReturnCode { - if rc != common.PT_STATUS_SUCCESS { - if rc == common.PT_STATUS_DUPLICATE { - log.Errorf("%s already exists and must be removed before continuing", item) - return utils.AmtPtStatusCodeBase + rc - } else if rc == common.PT_STATUS_INVALID_CERT { - log.Errorf("%s is invalid", item) - return utils.AmtPtStatusCodeBase + rc - } else { - log.Errorf("%s non-zero return code: %d", item, rc) - return utils.AmtPtStatusCodeBase + rc - } - } - return utils.Success -} diff --git a/internal/local/configure_test.go b/internal/local/configure_test.go index 7150e55f..6f6138d3 100644 --- a/internal/local/configure_test.go +++ b/internal/local/configure_test.go @@ -1,38 +1,90 @@ package local import ( - "fmt" - "regexp" + "errors" "rpc/internal/config" "rpc/internal/flags" "rpc/pkg/utils" - "strings" "testing" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/credential" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/wifiportconfiguration" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/models" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/wifi" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/ips/ieee8021x" "github.com/stretchr/testify/assert" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" ) -const trustedRootXMLResponse = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous2http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementlps/AddTrustedRootCertificateResponseuuid:00000000-8086-8086-8086-00000003A988http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementlpshttp://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymoushttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificateIntel(r) AMT Certificate: Handle: 20" -const clientCertXMLResponse = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous1http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementlps/AddCertificateResponseuuid:00000000-8086-8086-8086-00000003A89Chttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementlpshttp://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymoushttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificateIntel(r) AMT Certificate: Handle: 10" -const addKeyXMLResponse = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous0http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementlps/AddKeyResponseuuid:00000000-8086-8086-8086-00000003A89Bhttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementlpshttp://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymoushttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPairIntel(r) AMT Key: Handle: 00" +type testCase struct { + name string + controlMode int + controlModeErr error + setupMEBXResp int + setupMEBXErr error + expectedErr error +} + +func TestSetMebx(t *testing.T) { + tests := []testCase{ + { + name: "GetControlModeError", + controlModeErr: assert.AnError, + expectedErr: utils.AMTConnectionFailed, + }, + { + name: "NotACM", + controlMode: 1, // Not ACM + expectedErr: utils.SetMEBXPasswordFailed, + }, + { + name: "SetupMEBXError", + controlMode: 2, + setupMEBXErr: assert.AnError, + expectedErr: assert.AnError, + }, + { + name: "SetupMEBXFailReturnValue", + controlMode: 2, + setupMEBXResp: 1, + expectedErr: utils.SetMEBXPasswordFailed, + }, + { + name: "Success", + controlMode: 2, + setupMEBXResp: 0, + expectedErr: nil, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + f := &flags.Flags{} + mockAMT := new(MockAMT) + mockWsman := new(MockWSMAN) + service := NewProvisioningService(f) // Placeholder for actual service initialization + service.amtCommand = mockAMT + service.interfacedWsmanMessage = mockWsman + + mockControlMode = tc.controlMode + mockControlModeErr = tc.controlModeErr + + mockSetupAndConfigurationValue = tc.setupMEBXResp + mockSetupAndConfigurationErr = tc.setupMEBXErr + + err := service.SetMebx() + + if tc.expectedErr != nil { + assert.ErrorIs(t, err, tc.expectedErr) + } else { + assert.NoError(t, err) + } + }) + } +} var wifiCfgWPA = config.WifiConfig{ ProfileName: "wifiWPA", SSID: "ssid", Priority: 1, - AuthenticationMethod: int(models.AuthenticationMethod_WPA_PSK), - EncryptionMethod: int(models.EncryptionMethod_CCMP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA_PSK), + EncryptionMethod: int(wifi.EncryptionMethod_CCMP), PskPassphrase: "wifiWPAPassPhrase", Ieee8021xProfileName: "", } @@ -41,8 +93,8 @@ var wifiCfgWPA2 = config.WifiConfig{ ProfileName: "wifiWPA2", SSID: "ssid", Priority: 2, - AuthenticationMethod: int(models.AuthenticationMethod_WPA2_PSK), - EncryptionMethod: int(models.EncryptionMethod_CCMP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA2_PSK), + EncryptionMethod: int(wifi.EncryptionMethod_CCMP), PskPassphrase: "wifiWPAPassPhrase", Ieee8021xProfileName: "", } @@ -51,8 +103,8 @@ var wifiCfgWPA8021xEAPTLS = config.WifiConfig{ ProfileName: "wifiWPA28021x", SSID: "ssid", Priority: 2, - AuthenticationMethod: int(models.AuthenticationMethod_WPA_IEEE8021x), - EncryptionMethod: int(models.EncryptionMethod_CCMP), + AuthenticationMethod: int(wifi.AuthenticationMethod_WPA_IEEE8021x), + EncryptionMethod: int(wifi.EncryptionMethod_CCMP), PskPassphrase: "", Ieee8021xProfileName: "ieee8021xCfgEAPTLS", } @@ -61,134 +113,99 @@ var ieee8021xCfgEAPTLS = config.Ieee8021xConfig{ ProfileName: "ieee8021xCfgEAPTLS", Username: "username", Password: "", - AuthenticationProtocol: int(models.AuthenticationProtocolEAPTLS), - ClientCert: "clientCert", - CACert: "caCert", - PrivateKey: "privateKey", -} - -var wifiCfgWPA28021xPEAPv0_EAPMSCHAPv2 = config.WifiConfig{ - ProfileName: "wifiWPA28021x", - SSID: "ssid", - Priority: 2, - AuthenticationMethod: int(models.AuthenticationMethod_WPA2_IEEE8021x), - EncryptionMethod: int(models.EncryptionMethod_CCMP), - PskPassphrase: "", - Ieee8021xProfileName: "ieee8021xCfgPEAPv0_EAPMSCHAPv2", -} - -var ieee8021xCfgPEAPv0_EAPMSCHAPv2 = config.Ieee8021xConfig{ - ProfileName: "ieee8021xCfgPEAPv0_EAPMSCHAPv2", - Username: "username", - Password: "password", - AuthenticationProtocol: int(models.AuthenticationProtocolPEAPv0_EAPMSCHAPv2), + AuthenticationProtocol: int(ieee8021x.AuthenticationProtocolEAPTLS), ClientCert: "clientCert", CACert: "caCert", PrivateKey: "privateKey", } - -func emptyPublicPrivateCertsResponsers(t *testing.T) ResponseFuncArray { - return ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, publickey.PullResponseEnvelope{}), - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, publicprivate.PullResponseEnvelope{}), - } -} - -func emptyGetWifiIeee8021xCerts(t *testing.T) ResponseFuncArray { - return append( - emptyPublicPrivateCertsResponsers(t), - ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, credential.ContextPullResponseEnvelope{}), - }..., - ) -} +var errTestError = errors.New("test error") func TestConfigure(t *testing.T) { f := &flags.Flags{} t.Run("expect error for unhandled Subcommand", func(t *testing.T) { - lps := setupWsmanResponses(t, f, ResponseFuncArray{}) - rc := lps.Configure() - assert.Equal(t, utils.IncorrectCommandLineParameters, rc) + lps := setupService(&flags.Flags{}) + err := lps.Configure() + assert.Equal(t, utils.IncorrectCommandLineParameters, err) + }) + t.Run("expect error for SubCommandAddWifiSettings", func(t *testing.T) { + f.SubCommand = utils.SubCommandAddWifiSettings + errEnableWiFi = errTestError + lps := setupService(f) + err := lps.Configure() + assert.Error(t, err) + errEnableWiFi = nil + }) + t.Run("expect success for SubCommandAddWifiSettings", func(t *testing.T) { + f.SubCommand = utils.SubCommandAddWifiSettings + lps := setupService(f) + err := lps.Configure() + assert.NoError(t, err) + }) + t.Run("expect error for SubCommandEnableWifiPort", func(t *testing.T) { + f.SubCommand = utils.SubCommandEnableWifiPort + errEnableWiFi = errTestError + lps := setupService(f) + err := lps.Configure() + assert.Error(t, err) + errEnableWiFi = nil + }) + t.Run("expect success for SubCommandEnableWifiPort", func(t *testing.T) { + f.SubCommand = utils.SubCommandEnableWifiPort + lps := setupService(f) + err := lps.Configure() + assert.NoError(t, err) + }) + t.Run("expect error for SetMebx", func(t *testing.T) { + f.SubCommand = utils.SubCommandSetMEBx + lps := setupService(f) + mockSetupAndConfigurationErr = errTestError + err := lps.Configure() + assert.Error(t, err) + mockSetupAndConfigurationErr = nil + }) + t.Run("expect success for SetMebx", func(t *testing.T) { + f.SubCommand = utils.SubCommandSetMEBx + lps := setupService(f) + mockControlMode = 2 + err := lps.Configure() + assert.NoError(t, err) }) - subCommands := []string{ - utils.SubCommandAddWifiSettings, - utils.SubCommandEnableWifiPort, - utils.SubCommandConfigureTLS, - } - for _, sc := range subCommands { - t.Run(fmt.Sprintf("expect error for %s", sc), func(t *testing.T) { - f.SubCommand = sc - rfa := ResponseFuncArray{} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.Configure() - assert.Equal(t, utils.WSMANMessageError, rc) - }) - } } func TestAddWifiSettings(t *testing.T) { f := &flags.Flags{} f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgWPA) - pcsRsp := wifiportconfiguration.Response{} - pcsRsp.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled = 1 - t.Run("expect Success on happy path", func(t *testing.T) { - rfa := append( - emptyGetWifiIeee8021xCerts(t), - ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, wifi.PullResponseEnvelope{}), - respondMsgFunc(t, pcsRsp), - respondMsgFunc(t, wifi.RequestStateChangeResponse{}), - respondMsgFunc(t, wifiportconfiguration.AddWiFiSettingsResponse{}), - }..., - ) - lps := setupWsmanResponses(t, f, rfa) - rc := lps.AddWifiSettings() - assert.Equal(t, utils.Success, rc) - }) - t.Run("expect error from PruneWifiConfigs path", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.AddWifiSettings() - assert.NotEqual(t, utils.Success, rc) + + t.Run("expect success when AddWifiSettings", func(t *testing.T) { + lps := setupService(f) + err := lps.AddWifiSettings() + assert.NoError(t, err) }) - t.Run("expect error from EnableWifi path", func(t *testing.T) { - rfa := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, wifi.PullResponseEnvelope{}), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.AddWifiSettings() - assert.NotEqual(t, utils.Success, rc) + t.Run("expect error failed wifi port", func(t *testing.T) { + errEnableWiFi = errTestError + lps := setupService(f) + err := lps.AddWifiSettings() + assert.Error(t, err) + errEnableWiFi = nil }) } func TestProcessWifiConfigs(t *testing.T) { f := &flags.Flags{} f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgWPA) - f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgWPA2) - t.Run("expect WifiConfigurationWithWarnings if some configs fail", func(t *testing.T) { - f.LocalConfig.WifiConfigs[0].ProfileName = "bad-name" - rfa := ResponseFuncArray{ - respondMsgFunc(t, wifiportconfiguration.AddWiFiSettingsResponse{}), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessWifiConfigs() - assert.Equal(t, utils.WifiConfigurationWithWarnings, rc) + + t.Run("expect success processing wifi configs", func(t *testing.T) { + lps := setupService(f) + err := lps.ProcessWifiConfigs() + assert.NoError(t, err) }) - t.Run("expect WiFiConfigurationFailed if all configs fail", func(t *testing.T) { + t.Run("expect warning processing 2 wifi configs with 1 bad-name", func(t *testing.T) { + f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, wifiCfgWPA2) f.LocalConfig.WifiConfigs[1].ProfileName = "bad-name" - rfa := ResponseFuncArray{ - respondMsgFunc(t, wifiportconfiguration.AddWiFiSettingsResponse{}), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessWifiConfigs() - assert.Equal(t, utils.WiFiConfigurationFailed, rc) + lps := setupService(f) + err := lps.ProcessWifiConfigs() + assert.Equal(t, utils.WifiConfigurationWithWarnings, err) }) } @@ -196,327 +213,71 @@ func TestProcessWifiConfig(t *testing.T) { f := &flags.Flags{} // bad name error already tested - t.Run("expect WSMANMessageError for ProcessIeee8012xConfig", func(t *testing.T) { + t.Run("expect success when handling ieee8021x config", func(t *testing.T) { orig := wifiCfgWPA8021xEAPTLS.AuthenticationMethod - wifiCfgWPA8021xEAPTLS.AuthenticationMethod = int(models.AuthenticationMethod_WPA_IEEE8021x) - f.LocalConfig.Ieee8021xConfigs = config.Ieee8021xConfigs{} - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgEAPTLS) - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessWifiConfig(&wifiCfgWPA8021xEAPTLS) - assert.Equal(t, utils.WSMANMessageError, rc) + wifiCfgWPA8021xEAPTLS.AuthenticationMethod = int(wifi.AuthenticationMethod_WPA_IEEE8021x) + f.LocalConfig.Ieee8021xConfigs = []config.Ieee8021xConfig{ + ieee8021xCfgEAPTLS, + } + lps := setupService(f) + err := lps.ProcessWifiConfig(&wifiCfgWPA8021xEAPTLS) + assert.NoError(t, err) wifiCfgWPA8021xEAPTLS.AuthenticationMethod = orig }) - t.Run("expect WSMANMessageError for AddWiFiSettings()", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessWifiConfig(&wifiCfgWPA2) - assert.Equal(t, utils.WSMANMessageError, rc) - }) - t.Run("expect UnmarshalMessageFailed for AddWiFiSettings()", func(t *testing.T) { - rfa := ResponseFuncArray{respondBadXmlFunc(t)} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessWifiConfig(&wifiCfgWPA2) - assert.Equal(t, utils.UnmarshalMessageFailed, rc) + t.Run("expect success when handling non-ieee8021x config", func(t *testing.T) { + lps := setupService(f) + err := lps.ProcessWifiConfig(&wifiCfgWPA2) + assert.NoError(t, err) }) - t.Run("expect unsuccessful return value error for AddWiFiSettings()", func(t *testing.T) { - msgRsp := wifiportconfiguration.AddWiFiSettingsResponse{} - msgRsp.Body.AddWiFiSettings_OUTPUT.ReturnValue = 1 - expected := utils.AmtPtStatusCodeBase + utils.ReturnCode(msgRsp.Body.AddWiFiSettings_OUTPUT.ReturnValue) - rfa := ResponseFuncArray{respondMsgFunc(t, msgRsp)} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessWifiConfig(&wifiCfgWPA2) - assert.Equal(t, expected, rc) - }) -} +} func TestPruneWifiConfigs(t *testing.T) { f := &flags.Flags{} t.Run("expect Success when there are no configs", func(t *testing.T) { - rfa := append( - emptyGetWifiIeee8021xCerts(t), - ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, wifi.PullResponseEnvelope{}), - }..., - ) - lps := setupWsmanResponses(t, f, rfa) - rc := lps.PruneWifiConfigs() - assert.Equal(t, utils.Success, rc) + lps := setupService(f) + tempStorage := getWiFiSettingsResponse + // empty the response + getWiFiSettingsResponse = []wifi.WiFiEndpointSettingsResponse{} + err := lps.PruneWifiConfigs() + assert.NoError(t, err) + //restore + getWiFiSettingsResponse = tempStorage }) t.Run("expect success when there are configs", func(t *testing.T) { - pullEnvelope := wifi.PullResponseEnvelope{} - pullEnvelope.Body.PullResponse.Items = append(pullEnvelope.Body.PullResponse.Items, wifi.CIMWiFiEndpointSettings{InstanceID: "Config1"}) - pullEnvelope.Body.PullResponse.Items = append(pullEnvelope.Body.PullResponse.Items, wifi.CIMWiFiEndpointSettings{InstanceID: "Config2"}) - pullEnvelope.Body.PullResponse.Items = append(pullEnvelope.Body.PullResponse.Items, wifi.CIMWiFiEndpointSettings{InstanceID: ""}) - rfa := append( - emptyGetWifiIeee8021xCerts(t), - ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, pullEnvelope), - respondMsgFunc(t, "Config1 Deleted"), - respondMsgFunc(t, "Config2 Deleted"), - respondServerErrFunc(), // this one should NOT get called - }..., - ) - lps := setupWsmanResponses(t, f, rfa) - rc := lps.PruneWifiConfigs() - assert.Equal(t, utils.Success, rc) - }) - t.Run("expect DeleteWifiConfigFailed", func(t *testing.T) { - pullEnvelope := wifi.PullResponseEnvelope{} - pullEnvelope.Body.PullResponse.Items = append(pullEnvelope.Body.PullResponse.Items, wifi.CIMWiFiEndpointSettings{InstanceID: "Config1"}) - pullEnvelope.Body.PullResponse.Items = append(pullEnvelope.Body.PullResponse.Items, wifi.CIMWiFiEndpointSettings{InstanceID: "Config2"}) - rfa := append( - emptyGetWifiIeee8021xCerts(t), - ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, pullEnvelope), - respondMsgFunc(t, "Config1 Deleted"), - respondServerErrFunc(), - }..., - ) - lps := setupWsmanResponses(t, f, rfa) - rc := lps.PruneWifiConfigs() - assert.Equal(t, utils.DeleteWifiConfigFailed, rc) + lps := setupService(f) + err := lps.PruneWifiConfigs() + assert.NoError(t, err) }) - t.Run("expect WSMANMessageError error on EnumPullUnmarshal", func(t *testing.T) { - rfa := append( - emptyGetWifiIeee8021xCerts(t), - ResponseFuncArray{ - respondServerErrFunc(), - }..., - ) - lps := setupWsmanResponses(t, f, rfa) - rc := lps.PruneWifiConfigs() - assert.Equal(t, utils.WSMANMessageError, rc) - }) -} - -func TestPruneIeee8012xConfig(t *testing.T) { - f := &flags.Flags{} - certHandles := []string{"handle 1", "handle 2"} - keyPairHandles := []string{"handle 3", "handle 4"} - rfa := ResponseFuncArray{ - respondMsgFunc(t, "Deleted"), - respondServerErrFunc(), - respondMsgFunc(t, "Deleted"), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, rfa) - failCerts, failKeyPairs := lps.PruneWifiIeee8021xCerts(certHandles, keyPairHandles) - assert.NotEmpty(t, failCerts) - assert.Equal(t, "handle 2", failCerts[0]) - assert.NotEmpty(t, failKeyPairs) - assert.Equal(t, "handle 4", failKeyPairs[0]) -} - -func TestGetWifiIeee8021xCerts(t *testing.T) { - f := &flags.Flags{} - re := regexp.MustCompile(enumCtxElement) - relationshipsEOS := re.ReplaceAllString(credCtxPullRspString, endOfSequenceElement) - dependenciesEOS := re.ReplaceAllString(concreteDependencyPullRspString, endOfSequenceElement) - // make a puclickey response to match the credCtx - instanceId := "Intel(r) AMT Certificate: Handle: 1" - x509CertString := "ThisIsJustFakeCertBytes" - pkPullRspEnv := publickey.PullResponseEnvelope{} - pkPullRspEnv.Body.PullResponse.Items = []publickey.PublicKeyCertificate{ - { - InstanceID: instanceId, - X509Certificate: x509CertString, - }, - } - rfa := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, pkPullRspEnv), - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, publicprivate.PullResponseEnvelope{}), - respondMsgFunc(t, common.EnumerationResponse{}), - respondStringFunc(t, relationshipsEOS), - respondMsgFunc(t, common.EnumerationResponse{}), - respondStringFunc(t, dependenciesEOS), - } - lps := setupWsmanResponses(t, f, rfa) - certHandles, keyPairHandles := lps.GetWifiIeee8021xCerts() - assert.Equal(t, 2, len(certHandles)) - assert.Equal(t, 1, len(keyPairHandles)) - assert.Equal(t, x509CertString, lps.handlesWithCerts[instanceId]) } -func TestProcessIeee8012xConfig(t *testing.T) { +func TestEnableWifiErrors(t *testing.T) { f := &flags.Flags{} - - t.Run("expect error on missing ieee8021x profile", func(t *testing.T) { - ieee8021xSettings := &models.IEEE8021xSettings{} - handles := Handles{} - f.LocalConfig.Ieee8021xConfigs = config.Ieee8021xConfigs{} - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgEAPTLS) - lps := setupWsmanResponses(t, f, ResponseFuncArray{}) - rc := lps.ProcessIeee8012xConfig("someothername", ieee8021xSettings, &handles) - assert.Equal(t, utils.MissingIeee8021xConfiguration, rc) - assert.Empty(t, ieee8021xSettings.ElementName) - assert.Empty(t, handles.privateKeyHandle) - assert.Empty(t, handles.clientCertHandle) - assert.Empty(t, handles.rootCertHandle) - }) - t.Run("expect error on AddPrivateKey error", func(t *testing.T) { - ieee8021xSettings := &models.IEEE8021xSettings{} - handles := Handles{} - f.LocalConfig.Ieee8021xConfigs = config.Ieee8021xConfigs{} - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgPEAPv0_EAPMSCHAPv2) - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessIeee8012xConfig(ieee8021xCfgPEAPv0_EAPMSCHAPv2.ProfileName, ieee8021xSettings, &handles) - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Equal(t, ieee8021xCfgPEAPv0_EAPMSCHAPv2.ProfileName, ieee8021xSettings.ElementName) - assert.Empty(t, handles.privateKeyHandle) - assert.Empty(t, handles.clientCertHandle) - assert.Empty(t, handles.rootCertHandle) - }) - t.Run("expect error on AddClientCert error", func(t *testing.T) { - ieee8021xSettings := &models.IEEE8021xSettings{} - handles := Handles{} - f.LocalConfig.Ieee8021xConfigs = config.Ieee8021xConfigs{} - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgEAPTLS) - rfa := ResponseFuncArray{ - respondStringFunc(t, addKeyXMLResponse), - respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessIeee8012xConfig(ieee8021xCfgEAPTLS.ProfileName, ieee8021xSettings, &handles) - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Equal(t, ieee8021xCfgEAPTLS.ProfileName, ieee8021xSettings.ElementName) - assert.NotEmpty(t, handles.privateKeyHandle) - assert.Empty(t, handles.clientCertHandle) - assert.Empty(t, handles.rootCertHandle) - }) - t.Run("expect error on AddTrustedRootCert error", func(t *testing.T) { - ieee8021xSettings := &models.IEEE8021xSettings{} - handles := Handles{} - f.LocalConfig.Ieee8021xConfigs = config.Ieee8021xConfigs{} - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgEAPTLS) - rfa := ResponseFuncArray{ - respondStringFunc(t, addKeyXMLResponse), - respondStringFunc(t, clientCertXMLResponse), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessIeee8012xConfig(ieee8021xCfgEAPTLS.ProfileName, ieee8021xSettings, &handles) - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Equal(t, ieee8021xCfgEAPTLS.ProfileName, ieee8021xSettings.ElementName) - assert.NotEmpty(t, handles.privateKeyHandle) - assert.NotEmpty(t, handles.clientCertHandle) - assert.Empty(t, handles.rootCertHandle) + t.Run("expect success for EnableWifi", func(t *testing.T) { + lps := setupService(f) + err := lps.EnableWifiPort() + assert.NoError(t, err) }) - t.Run("expect success on happy path", func(t *testing.T) { - ieee8021xSettings := &models.IEEE8021xSettings{} - handles := Handles{} - f.LocalConfig.Ieee8021xConfigs = config.Ieee8021xConfigs{} - f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfgEAPTLS) - rfa := ResponseFuncArray{ - respondStringFunc(t, addKeyXMLResponse), - respondStringFunc(t, clientCertXMLResponse), - respondStringFunc(t, trustedRootXMLResponse), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.ProcessIeee8012xConfig(ieee8021xCfgEAPTLS.ProfileName, ieee8021xSettings, &handles) - assert.Equal(t, utils.Success, rc) - assert.Equal(t, ieee8021xCfgEAPTLS.ProfileName, ieee8021xSettings.ElementName) - assert.NotEmpty(t, handles.privateKeyHandle) - assert.NotEmpty(t, handles.clientCertHandle) - assert.NotEmpty(t, handles.rootCertHandle) + t.Run("expect failure for EnableWifi", func(t *testing.T) { + errEnableWiFi = errTestError + lps := setupService(f) + err := lps.EnableWifiPort() + assert.Error(t, err) + errEnableWiFi = nil }) -} -func TestEnableWifiErrors(t *testing.T) { +} +func TestGetWifiIeee8021xCerts(t *testing.T) { f := &flags.Flags{} - t.Run("expect WSMANMessageError for WiFiPortConfigurationService.Get()", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.WSMANMessageError, rc) - }) - t.Run("expect UnmarshalMessageFailed for WiFiPortConfigurationService.Get()", func(t *testing.T) { - rfa := ResponseFuncArray{respondBadXmlFunc(t)} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.UnmarshalMessageFailed, rc) - }) - t.Run("expect WSMANMessageError for WiFiPortConfigurationService.Put()", func(t *testing.T) { - pcsResponse := wifiportconfiguration.Response{} - rfa := ResponseFuncArray{ - respondMsgFunc(t, pcsResponse), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.WSMANMessageError, rc) - }) - t.Run("expect UnmarshalMessageFailed for WiFiPortConfigurationService.Put()", func(t *testing.T) { - pcsResponse := wifiportconfiguration.Response{} - rfa := ResponseFuncArray{ - respondMsgFunc(t, pcsResponse), - respondBadXmlFunc(t), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.UnmarshalMessageFailed, rc) - }) - t.Run("expect WiFiConfigurationFailed when enable is unsuccessful", func(t *testing.T) { - pcsResponse := wifiportconfiguration.Response{} - pcsResponseFailed := wifiportconfiguration.Response{} - rfa := ResponseFuncArray{ - respondMsgFunc(t, pcsResponse), - respondMsgFunc(t, pcsResponseFailed), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.WiFiConfigurationFailed, rc) - }) - t.Run("expect WSMANMessageError for RequestStateChange()", func(t *testing.T) { - pcsResponse := wifiportconfiguration.Response{} - pcsResponseEnabled := wifiportconfiguration.Response{} - pcsResponseEnabled.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled = 1 - rfa := ResponseFuncArray{ - respondMsgFunc(t, pcsResponse), - respondMsgFunc(t, pcsResponseEnabled), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.WSMANMessageError, rc) - }) - t.Run("expect UnmarshalMessageFailed for RequestStateChange()", func(t *testing.T) { - pcsResponse := wifiportconfiguration.Response{} - pcsResponseEnabled := wifiportconfiguration.Response{} - pcsResponseEnabled.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled = 1 - rfa := ResponseFuncArray{ - respondMsgFunc(t, pcsResponse), - respondMsgFunc(t, pcsResponseEnabled), - respondBadXmlFunc(t), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, utils.UnmarshalMessageFailed, rc) - }) - t.Run("expect non-zero error for RequestStateChange()", func(t *testing.T) { - pcsResponse := wifiportconfiguration.Response{} - pcsResponseEnabled := wifiportconfiguration.Response{} - pcsResponseEnabled.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled = 1 - stateChangeResponse := wifi.RequestStateChangeResponse{} - stateChangeResponse.Body.RequestStateChange_OUTPUT.ReturnValue = 1 - expected := utils.AmtPtStatusCodeBase + utils.ReturnCode(stateChangeResponse.Body.RequestStateChange_OUTPUT.ReturnValue) - rfa := ResponseFuncArray{ - respondMsgFunc(t, pcsResponse), - respondMsgFunc(t, pcsResponseEnabled), - respondMsgFunc(t, stateChangeResponse), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifi() - assert.Equal(t, expected, rc) + t.Run("expect all error paths traversed for coverage", func(t *testing.T) { + lps := setupService(f) + certHandles, keyPairHandles, err := lps.GetWifiIeee8021xCerts() + assert.NoError(t, err) + assert.Equal(t, 2, len(certHandles)) + assert.Equal(t, 1, len(keyPairHandles)) + assert.Equal(t, caCert.X509Certificate, lps.handlesWithCerts["Intel(r) AMT Certificate: Handle: 1"]) }) } - func TestRollbackAddedItems(t *testing.T) { f := &flags.Flags{} handles := Handles{ @@ -526,173 +287,11 @@ func TestRollbackAddedItems(t *testing.T) { } t.Run("expect all error paths traversed for coverage", func(t *testing.T) { - rfa := ResponseFuncArray{ - respondServerErrFunc(), - respondServerErrFunc(), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, rfa) + lps := setupService(f) lps.RollbackAddedItems(&handles) }) t.Run("expect all happy paths traversed for coverage", func(t *testing.T) { - rfa := ResponseFuncArray{ - respondStringFunc(t, "any message works?"), - respondStringFunc(t, "any message works?"), - respondStringFunc(t, "any message works?"), - } - lps := setupWsmanResponses(t, f, rfa) + lps := setupService(f) lps.RollbackAddedItems(&handles) }) } - -func TestAddTrustedRootCert(t *testing.T) { - f := &flags.Flags{} - t.Run("expect WSMANMessageError", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddTrustedRootCert("AABBCCDD") - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Empty(t, handle) - }) - t.Run("expect UnmarshalMessageFailed", func(t *testing.T) { - rfa := ResponseFuncArray{respondBadXmlFunc(t)} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddTrustedRootCert("AABBCCDD") - assert.Equal(t, utils.UnmarshalMessageFailed, rc) - assert.Empty(t, handle) - }) - t.Run("expect non-zero error ", func(t *testing.T) { - dup := strings.Replace(trustedRootXMLResponse, `0`, `1`, 1) - expected := utils.AmtPtStatusCodeBase + 1 - rfa := ResponseFuncArray{respondStringFunc(t, dup)} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddTrustedRootCert("AABBCCDD") - assert.Equal(t, expected, rc) - assert.Empty(t, handle) - }) - t.Run("expect success when credential already added", func(t *testing.T) { - lps := setupWsmanResponses(t, f, ResponseFuncArray{}) - instanceId := `Intel® AMT XXXCertYYYkey: Handle: 1` - associatedCredential := `THISISAFAKECERTSTRING` - lps.handlesWithCerts[instanceId] = associatedCredential - handle, resultCode := lps.AddTrustedRootCert(associatedCredential) - assert.Equal(t, utils.Success, resultCode) - assert.Equal(t, instanceId, handle) - }) -} - -func TestAddClientCert(t *testing.T) { - f := &flags.Flags{} - t.Run("expect WSMANMessageError", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddClientCert("AABBCCDD") - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Empty(t, handle) - }) - t.Run("expect UnmarshalMessageFailed", func(t *testing.T) { - rfa := ResponseFuncArray{respondBadXmlFunc(t)} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddClientCert("AABBCCDD") - assert.Equal(t, utils.UnmarshalMessageFailed, rc) - assert.Empty(t, handle) - }) - t.Run("expect non-zero error ", func(t *testing.T) { - dup := strings.Replace(clientCertXMLResponse, `0`, `1`, 1) - expected := utils.AmtPtStatusCodeBase + 1 - rfa := ResponseFuncArray{respondStringFunc(t, dup)} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddClientCert("AABBCCDD") - assert.Equal(t, expected, rc) - assert.Empty(t, handle) - }) - t.Run("expect success when credential already added", func(t *testing.T) { - lps := setupWsmanResponses(t, f, ResponseFuncArray{}) - instanceId := `Intel® AMT XXXCertYYYkey: Handle: 1` - associatedCredential := `THISISAFAKECERTSTRING` - lps.handlesWithCerts[instanceId] = associatedCredential - handle, resultCode := lps.AddClientCert(associatedCredential) - assert.Equal(t, utils.Success, resultCode) - assert.Equal(t, instanceId, handle) - }) -} - -func TestAddPrivateKey(t *testing.T) { - f := &flags.Flags{} - t.Run("expect WSMANMessageError", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddPrivateKey("AABBCCDD") - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Empty(t, handle) - }) - t.Run("expect UnmarshalMessageFailed", func(t *testing.T) { - rfa := ResponseFuncArray{respondBadXmlFunc(t)} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddPrivateKey("AABBCCDD") - assert.Equal(t, utils.UnmarshalMessageFailed, rc) - assert.Empty(t, handle) - }) - t.Run("expect non-zero error ", func(t *testing.T) { - dup := strings.Replace(addKeyXMLResponse, `0`, `1`, 1) - expected := utils.AmtPtStatusCodeBase + 1 - rfa := ResponseFuncArray{respondStringFunc(t, dup)} - lps := setupWsmanResponses(t, f, rfa) - handle, rc := lps.AddPrivateKey("AABBCCDD") - assert.Equal(t, expected, rc) - assert.Empty(t, handle) - }) - t.Run("expect success when credential already added", func(t *testing.T) { - lps := setupWsmanResponses(t, f, ResponseFuncArray{}) - instanceId := `Intel® AMT XXXCertYYYkey: Handle: 1` - associatedCredential := `THISISAFAKECERTSTRING` - lps.handlesWithCerts[instanceId] = associatedCredential - handle, resultCode := lps.AddPrivateKey(associatedCredential) - assert.Equal(t, utils.Success, resultCode) - assert.Equal(t, instanceId, handle) - }) -} - -func TestCheckReturnValue(t *testing.T) { - tests := []struct { - name string - in utils.ReturnCode - item string - want utils.ReturnCode - }{ - {"TestNoError", 0, "item", utils.Success}, - {"TestAlreadyExists", common.PT_STATUS_DUPLICATE, "item", utils.AmtPtStatusCodeBase + common.PT_STATUS_DUPLICATE}, - {"TestInvalidItem", common.PT_STATUS_INVALID_CERT, "item", utils.AmtPtStatusCodeBase + common.PT_STATUS_INVALID_CERT}, - {"TestNonZeroReturnCode", 2082, "item", utils.AmtPtStatusCodeBase + 2082}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := checkReturnValue(tt.in, tt.item) - assert.Equal(t, tt.want, got) - }) - } -} -func TestEnableWifiPort(t *testing.T) { - f := &flags.Flags{} - pcsRsp := wifiportconfiguration.Response{} - pcsRsp.Body.WiFiPortConfigurationService.LocalProfileSynchronizationEnabled = 1 - pcsRsp.Body.WiFiPortConfigurationService.EnabledState = 1 - t.Run("enablewifiport: expect Success on happy path", func(t *testing.T) { - rfa := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, wifi.PullResponseEnvelope{}), - respondMsgFunc(t, pcsRsp), - respondMsgFunc(t, wifi.RequestStateChangeResponse{}), - } - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifiPort() - assert.Equal(t, utils.Success, rc) - }) - t.Run("enablewifiport: expect WSMANMessageError ", func(t *testing.T) { - rfa := ResponseFuncArray{respondServerErrFunc()} - lps := setupWsmanResponses(t, f, rfa) - rc := lps.EnableWifiPort() - assert.Equal(t, utils.WSMANMessageError, rc) - }) -} diff --git a/internal/local/deactivate.go b/internal/local/deactivate.go index 26e33c54..67795647 100644 --- a/internal/local/deactivate.go +++ b/internal/local/deactivate.go @@ -1,57 +1,49 @@ package local import ( - "encoding/xml" "rpc/pkg/utils" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/setupandconfiguration" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) -func (service *ProvisioningService) Deactivate() utils.ReturnCode { - +func (service *ProvisioningService) Deactivate() (err error) { controlMode, err := service.amtCommand.GetControlMode() if err != nil { log.Error(err) return utils.AMTConnectionFailed } if controlMode == 1 { - return service.DeactivateCCM() + err = service.DeactivateCCM() } else if controlMode == 2 { - return service.DeactivateACM() + err = service.DeactivateACM() + } + + if err == nil { + log.Info("Status: Device deactivated") + return nil } log.Error("Deactivation failed. Device control mode: " + utils.InterpretControlMode(controlMode)) return utils.UnableToDeactivate } -func (service *ProvisioningService) DeactivateACM() utils.ReturnCode { +func (service *ProvisioningService) DeactivateACM() (err error) { if service.flags.Password == "" { - if _, rc := service.flags.ReadPasswordFromUser(); rc != utils.Success { - return rc + result, rc := service.flags.ReadPasswordFromUser() + if !result || rc != nil { + return utils.MissingOrIncorrectPassword } } - service.setupWsmanClient("admin", service.flags.Password) - msg := service.amtMessages.SetupAndConfigurationService.Unprovision(1) - response, err := service.client.Post(msg) + service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, logrus.GetLevel() == logrus.TraceLevel) + _, err = service.interfacedWsmanMessage.Unprovision(1) if err != nil { log.Error("Status: Unable to deactivate ", err) return utils.UnableToDeactivate } - var setupResponse setupandconfiguration.UnprovisionResponse - err = xml.Unmarshal([]byte(response), &setupResponse) - if err != nil { - log.Error("Status: Failed to deactivate ", err) - return utils.DeactivationFailed - } - if setupResponse.Body.Unprovision_OUTPUT.ReturnValue != 0 { - log.Error("Status: Failed to deactivate. ReturnValue: ", setupResponse.Body.Unprovision_OUTPUT.ReturnValue) - return utils.DeactivationFailed - } - log.Info("Status: Device deactivated in ACM.") - return utils.Success + return nil } -func (service *ProvisioningService) DeactivateCCM() utils.ReturnCode { +func (service *ProvisioningService) DeactivateCCM() (err error) { if service.flags.Password != "" { log.Warn("Password not required for CCM deactivation") } @@ -60,6 +52,5 @@ func (service *ProvisioningService) DeactivateCCM() utils.ReturnCode { log.Error("Status: Failed to deactivate ", err) return utils.DeactivationFailed } - log.Info("Status: Device deactivated.") - return utils.Success + return nil } diff --git a/internal/local/deactivate_test.go b/internal/local/deactivate_test.go index 712145ea..275f8cc8 100644 --- a/internal/local/deactivate_test.go +++ b/internal/local/deactivate_test.go @@ -2,7 +2,6 @@ package local import ( "errors" - "net/http" "rpc/internal/flags" "rpc/pkg/utils" "testing" @@ -19,8 +18,8 @@ func TestDeactivation(t *testing.T) { t.Run("returns AMTConnectionFailed when GetControlMode fails", func(t *testing.T) { lps := setupService(f) mockControlModeErr = stdErr - rc := lps.Deactivate() - assert.Equal(t, utils.AMTConnectionFailed, rc) + err := lps.Deactivate() + assert.Equal(t, utils.AMTConnectionFailed, err) mockControlModeErr = nil }) @@ -28,8 +27,8 @@ func TestDeactivation(t *testing.T) { lps := setupService(f) // this is default mode for the mock already // mockControlMode = 0 - rc := lps.Deactivate() - assert.Equal(t, utils.UnableToDeactivate, rc) + err := lps.Deactivate() + assert.Equal(t, utils.UnableToDeactivate, err) }) } @@ -42,27 +41,27 @@ func TestDeactivateCCM(t *testing.T) { t.Run("returns Success without password", func(t *testing.T) { f.Password = "" lps := setupService(f) - resultCode := lps.Deactivate() - assert.Equal(t, utils.Success, resultCode) + err := lps.Deactivate() + assert.Equal(t, nil, err) }) t.Run("returns Success with warning, given the password", func(t *testing.T) { f.Password = "P@ssw0rd" lps := setupService(f) - rc := lps.Deactivate() - assert.Equal(t, utils.Success, rc) + err := lps.Deactivate() + assert.Equal(t, nil, err) }) t.Run("returns DeactivationFailed when unprovision fails", func(t *testing.T) { mockUnprovisionErr = errors.New("test error") lps := setupService(f) - rc := lps.Deactivate() - assert.Equal(t, utils.DeactivationFailed, rc) + err := lps.Deactivate() + assert.Equal(t, utils.DeactivationFailed, err) mockUnprovisionErr = nil }) t.Run("returns DeactivationFailed when unprovision ReturnStatus is not success (0)", func(t *testing.T) { mockUnprovisionCode = 1 lps := setupService(f) - rc := lps.Deactivate() - assert.Equal(t, utils.DeactivationFailed, rc) + err := lps.Deactivate() + assert.Equal(t, utils.DeactivationFailed, err) mockUnprovisionCode = 0 }) } @@ -75,50 +74,23 @@ func TestDeactivateACM(t *testing.T) { t.Run("returns Success for happy path", func(t *testing.T) { f.Password = "P@ssw0rd" - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondUnprovision(t, w) - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.Deactivate() - assert.Equal(t, utils.Success, rc) + lps := setupService(f) + err := lps.Deactivate() + assert.Equal(t, nil, err) }) t.Run("returns UnableToDeactivate with no password", func(t *testing.T) { f.Password = "" - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithWsmanClient(f, handler) - resultCode := lps.Deactivate() - assert.Equal(t, utils.MissingOrIncorrectPassword, resultCode) + lps := setupService(f) + err := lps.Deactivate() + assert.Equal(t, utils.MissingOrIncorrectPassword, err) }) t.Run("returns UnableToDeactivate on SetupAndConfigurationService.Unprovision server error", func(t *testing.T) { f.Password = "P@ssw0rd" - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondServerError(w) - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.Deactivate() - assert.Equal(t, utils.UnableToDeactivate, rc) - }) - t.Run("returns UnableToDeactivate on SetupAndConfigurationService.Unprovision xml error", func(t *testing.T) { - f.Password = "P@ssw0rd" - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - respondBadXML(t, w) - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.Deactivate() - assert.Equal(t, utils.DeactivationFailed, rc) - }) - t.Run("returns DeactivationFailed when unprovision ReturnStatus is not success (0)", func(t *testing.T) { - f.Password = "P@ssw0rd" - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - mockUnprovisionResponse.Body.Unprovision_OUTPUT.ReturnValue = 1 - respondUnprovision(t, w) - mockUnprovisionResponse.Body.Unprovision_OUTPUT.ReturnValue = 0 - }) - lps := setupWithWsmanClient(f, handler) - rc := lps.Deactivate() - assert.Equal(t, utils.DeactivationFailed, rc) + mockACMUnprovisionErr = errors.New("yep, it failed") + lps := setupService(f) + err := lps.Deactivate() + assert.Equal(t, utils.UnableToDeactivate, err) + mockACMUnprovisionErr = nil }) } diff --git a/internal/local/info.go b/internal/local/info.go index 172fb7c9..563860f8 100644 --- a/internal/local/info.go +++ b/internal/local/info.go @@ -3,14 +3,15 @@ package local import ( "encoding/json" "fmt" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" "os" "rpc/internal/amt" "rpc/pkg/utils" "strconv" "strings" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publicprivate" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) @@ -19,7 +20,7 @@ type PrivateKeyPairReference struct { AssociatedCerts []string } -func (service *ProvisioningService) DisplayAMTInfo() utils.ReturnCode { +func (service *ProvisioningService) DisplayAMTInfo() (err error) { dataStruct := make(map[string]interface{}) cmd := service.amtCommand @@ -34,12 +35,12 @@ func (service *ProvisioningService) DisplayAMTInfo() utils.ReturnCode { log.Error(err) service.flags.AmtInfo.UserCert = false } else if result == 0 { - fmt.Println("Device is in pre-provisioning mode. User certificates are not available") + log.Warn("Device is in pre-provisioning mode. User certificates are not available") service.flags.AmtInfo.UserCert = false } else { - if _, rc := service.flags.ReadPasswordFromUser(); rc != 0 { + if _, err := service.flags.ReadPasswordFromUser(); err != nil { fmt.Println("Invalid Entry") - return rc + return err } } } @@ -228,10 +229,9 @@ func (service *ProvisioningService) DisplayAMTInfo() utils.ReturnCode { } } if service.flags.AmtInfo.UserCert { - service.setupWsmanClient("admin", service.flags.Password) - var userCerts []publickey.PublicKeyCertificate - service.GetPublicKeyCerts(&userCerts) - userCertMap := map[string]publickey.PublicKeyCertificate{} + service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, logrus.GetLevel() == logrus.TraceLevel) + userCerts, _ := service.interfacedWsmanMessage.GetPublicKeyCerts() + userCertMap := map[string]publickey.PublicKeyCertificateResponse{} for i := range userCerts { c := userCerts[i] name := GetTokenFromKeyValuePairs(c.Subject, "CN") @@ -252,9 +252,9 @@ func (service *ProvisioningService) DisplayAMTInfo() utils.ReturnCode { } for k, c := range userCertMap { fmt.Printf("%s", k) - if c.TrustedRootCertficate && c.ReadOnlyCertificate { + if c.TrustedRootCertificate && c.ReadOnlyCertificate { fmt.Printf(" (TrustedRoot, ReadOnly)") - } else if c.TrustedRootCertficate { + } else if c.TrustedRootCertificate { fmt.Printf(" (TrustedRoot)") } else if c.ReadOnlyCertificate { fmt.Printf(" (ReadOnly)") @@ -272,7 +272,7 @@ func (service *ProvisioningService) DisplayAMTInfo() utils.ReturnCode { } println(output) } - return utils.Success + return nil } func DecodeAMT(version, SKU string) string { diff --git a/internal/local/info_test.go b/internal/local/info_test.go index 78bf7a5c..33efd89c 100644 --- a/internal/local/info_test.go +++ b/internal/local/info_test.go @@ -1,12 +1,12 @@ package local import ( - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - "github.com/stretchr/testify/assert" "rpc/internal/flags" "rpc/pkg/utils" "testing" + + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" + "github.com/stretchr/testify/assert" ) func TestDisplayAMTInfo(t *testing.T) { @@ -28,8 +28,9 @@ func TestDisplayAMTInfo(t *testing.T) { f := &flags.Flags{} f.AmtInfo = defaultFlags lps := setupService(f) - rc := lps.DisplayAMTInfo() - assert.Equal(t, utils.Success, rc) + err := lps.DisplayAMTInfo() + assert.NoError(t, err) + assert.Equal(t, nil, err) }) t.Run("returns Success with json output", func(t *testing.T) { @@ -37,8 +38,9 @@ func TestDisplayAMTInfo(t *testing.T) { f.AmtInfo = defaultFlags f.JsonOutput = true lps := setupService(f) - resultCode := lps.DisplayAMTInfo() - assert.Equal(t, utils.Success, resultCode) + err := lps.DisplayAMTInfo() + assert.NoError(t, err) + assert.Equal(t, nil, err) }) t.Run("returns Success with certs", func(t *testing.T) { @@ -47,38 +49,36 @@ func TestDisplayAMTInfo(t *testing.T) { f.AmtInfo.UserCert = true f.Password = "testPassword" mockCertHashes = mockCertHashesDefault - pullEnvelope := publickey.PullResponseEnvelope{} - pullEnvelope.Body.PullResponse.Items = []publickey.PublicKeyCertificate{ + pullEnvelope := publickey.PullResponse{} + pullEnvelope.PublicKeyCertificateItems = []publickey.PublicKeyCertificateResponse{ mpsCert, clientCert, caCert, } - rfa := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondMsgFunc(t, pullEnvelope), - } - lps := setupWsmanResponses(t, f, rfa) - resultCode := lps.DisplayAMTInfo() - assert.Equal(t, utils.Success, resultCode) + lps := setupService(f) + err := lps.DisplayAMTInfo() + assert.NoError(t, err) + assert.Equal(t, nil, err) }) t.Run("returns Success but logs errors on error conditions", func(t *testing.T) { - mockUUIDErr = mockStandardErr - mockVersionDataErr = mockStandardErr - mockControlModeErr = mockStandardErr - mockDNSSuffixErr = mockStandardErr - mockOSDNSSuffixErr = mockStandardErr - mockRemoteAcessConnectionStatusErr = mockStandardErr - mockLANInterfaceSettingsErr = mockStandardErr - mockCertHashesErr = mockStandardErr + mockUUIDErr = errMockStandard + mockVersionDataErr = errMockStandard + mockControlModeErr = errMockStandard + mockDNSSuffixErr = errMockStandard + mockOSDNSSuffixErr = errMockStandard + mockRemoteAcessConnectionStatusErr = errMockStandard + mockLANInterfaceSettingsErr = errMockStandard + mockCertHashesErr = errMockStandard f := &flags.Flags{} f.AmtInfo = defaultFlags f.JsonOutput = true lps := setupService(f) - rc := lps.DisplayAMTInfo() - assert.Equal(t, utils.Success, rc) + err := lps.DisplayAMTInfo() + assert.NoError(t, err) + assert.Equal(t, nil, err) f.JsonOutput = false mockUUIDErr = nil @@ -94,11 +94,10 @@ func TestDisplayAMTInfo(t *testing.T) { t.Run("resets UserCert on GetControlMode failure", func(t *testing.T) { f := &flags.Flags{} f.AmtInfo.UserCert = true - mockControlModeErr = mockStandardErr - rfa := ResponseFuncArray{} - lps := setupWsmanResponses(t, f, rfa) - resultCode := lps.DisplayAMTInfo() - assert.Equal(t, utils.Success, resultCode) + mockControlModeErr = errMockStandard + lps := setupService(f) + err := lps.DisplayAMTInfo() + assert.Equal(t, nil, err) assert.False(t, f.AmtInfo.UserCert) mockControlModeErr = nil }) @@ -107,10 +106,9 @@ func TestDisplayAMTInfo(t *testing.T) { f.AmtInfo.UserCert = true orig := mockControlMode mockControlMode = 0 - rfa := ResponseFuncArray{} - lps := setupWsmanResponses(t, f, rfa) - resultCode := lps.DisplayAMTInfo() - assert.Equal(t, utils.Success, resultCode) + lps := setupService(f) + err := lps.DisplayAMTInfo() + assert.Equal(t, nil, err) assert.False(t, f.AmtInfo.UserCert) mockControlMode = orig }) @@ -119,10 +117,9 @@ func TestDisplayAMTInfo(t *testing.T) { f.AmtInfo.UserCert = true orig := mockControlMode mockControlMode = 2 - rfa := ResponseFuncArray{} - lps := setupWsmanResponses(t, f, rfa) - resultCode := lps.DisplayAMTInfo() - assert.Equal(t, utils.MissingOrIncorrectPassword, resultCode) + lps := setupService(f) + err := lps.DisplayAMTInfo() + assert.Equal(t, utils.MissingOrIncorrectPassword, err) assert.True(t, f.AmtInfo.UserCert) mockControlMode = orig }) diff --git a/internal/local/linux.go b/internal/local/linux.go index af6c69dd..300e7e92 100644 --- a/internal/local/linux.go +++ b/internal/local/linux.go @@ -14,7 +14,7 @@ import ( "rpc/pkg/utils" ) -func (n *RealOSNetworker) RenewDHCPLease() utils.ReturnCode { +func (n *RealOSNetworker) RenewDHCPLease() error { log.Debug("renewing DHCP lease") cmd := exec.Command("dhclient") err := cmd.Run() @@ -22,5 +22,5 @@ func (n *RealOSNetworker) RenewDHCPLease() utils.ReturnCode { log.Error("Error renewing DHCP lease:", err) return utils.NetworkConfigurationFailed } - return utils.Success + return nil } diff --git a/internal/local/lps.go b/internal/local/lps.go index d1b479c9..a4f14a91 100644 --- a/internal/local/lps.go +++ b/internal/local/lps.go @@ -1,76 +1,67 @@ package local import ( + "net/url" internalAMT "rpc/internal/amt" "rpc/internal/config" "rpc/internal/flags" + bacon "rpc/internal/local/amt" "rpc/pkg/utils" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/ips" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/wsman" + log "github.com/sirupsen/logrus" ) type OSNetworker interface { - RenewDHCPLease() utils.ReturnCode + RenewDHCPLease() error } type RealOSNetworker struct{} type ProvisioningService struct { - flags *flags.Flags - serverURL string - client *wsman.Client - config *config.Config - amtCommand internalAMT.Interface - amtMessages amt.Messages - cimMessages cim.Messages - ipsMessages ips.Messages - handlesWithCerts map[string]string - networker OSNetworker + flags *flags.Flags + serverURL *url.URL + interfacedWsmanMessage bacon.WSMANer + config *config.Config + amtCommand internalAMT.Interface + handlesWithCerts map[string]string + networker OSNetworker } func NewProvisioningService(flags *flags.Flags) ProvisioningService { - // supports unit testing - serverURL := "http://" + utils.LMSAddress + ":" + utils.LMSPort + "/wsman" + serverURL := &url.URL{ + Scheme: "http", + Host: utils.LMSAddress + ":" + utils.LMSPort, + Path: "/wsman", + } return ProvisioningService{ - flags: flags, - client: nil, - serverURL: serverURL, - config: &flags.LocalConfig, - amtCommand: internalAMT.NewAMTCommand(), - amtMessages: amt.NewMessages(), - cimMessages: cim.NewMessages(), - ipsMessages: ips.NewMessages(), - handlesWithCerts: make(map[string]string), - networker: &RealOSNetworker{}, + flags: flags, + serverURL: serverURL, + config: &flags.LocalConfig, + amtCommand: internalAMT.NewAMTCommand(), + handlesWithCerts: make(map[string]string), + networker: &RealOSNetworker{}, + interfacedWsmanMessage: bacon.NewGoWSMANMessages(flags.LMSAddress), } + } -func ExecuteCommand(flags *flags.Flags) utils.ReturnCode { - rc := utils.Success +func ExecuteCommand(flags *flags.Flags) error { + var err error service := NewProvisioningService(flags) switch flags.Command { case utils.CommandActivate: - rc = service.Activate() - break + err = service.Activate() case utils.CommandAMTInfo: - rc = service.DisplayAMTInfo() - break + err = service.DisplayAMTInfo() case utils.CommandDeactivate: - rc = service.Deactivate() - break + err = service.Deactivate() case utils.CommandConfigure: - rc = service.Configure() - break + err = service.Configure() case utils.CommandVersion: - rc = service.DisplayVersion() - break + err = service.DisplayVersion() } - return rc -} - -func (service *ProvisioningService) setupWsmanClient(username string, password string) { - service.client = wsman.NewClient(service.serverURL, username, password, true, service.flags.Verbose) + if err != nil { + log.Error(err) + } + return err } diff --git a/internal/local/lps_test.go b/internal/local/lps_test.go index a4659069..9423bb1a 100644 --- a/internal/local/lps_test.go +++ b/internal/local/lps_test.go @@ -1,28 +1,395 @@ package local import ( - "encoding/xml" "errors" "net/http" - "net/http/httptest" amt2 "rpc/internal/amt" "rpc/internal/flags" "rpc/pkg/utils" "testing" "time" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/general" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/setupandconfiguration" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/ips/hostbasedsetup" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/general" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publicprivate" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/setupandconfiguration" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/timesynchronization" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/tls" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/wifiportconfiguration" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/concrete" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/credential" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/models" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/ips/hostbasedsetup" "github.com/stretchr/testify/assert" ) type MockOSNetworker struct{} -var mockRenewDHCPLeaseRC = utils.Success +var mockRenewDHCPLeaseerr error = nil -func (m MockOSNetworker) RenewDHCPLease() utils.ReturnCode { - return mockRenewDHCPLeaseRC +func (m MockOSNetworker) RenewDHCPLease() error { + return mockRenewDHCPLeaseerr +} + +// Mock the go-wsman-messages +type MockWSMAN struct{} + +// CommitChanges implements amt.WSMANer. +func (m MockWSMAN) CommitChanges() (response setupandconfiguration.Response, err error) { + panic("unimplemented") +} + +// CreateTLSCredentialContext implements amt.WSMANer. +func (m MockWSMAN) CreateTLSCredentialContext(certHandle string) (response tls.Response, err error) { + panic("unimplemented") +} + +// EnumerateTLSSettingData implements amt.WSMANer. +func (m MockWSMAN) EnumerateTLSSettingData() (response tls.Response, err error) { + panic("unimplemented") +} + +// GenerateKeyPair implements amt.WSMANer. +func (m MockWSMAN) GenerateKeyPair(keyAlgorithm publickey.KeyAlgorithm, keyLength publickey.KeyLength) (response publickey.Response, err error) { + panic("unimplemented") +} + +// PullTLSSettingData implements amt.WSMANer. +func (m MockWSMAN) PullTLSSettingData(enumerationContext string) (response tls.Response, err error) { + panic("unimplemented") +} + +var mockGetLowAccuracyTimeSynchRsp = timesynchronization.Response{ + Body: timesynchronization.Body{ + GetLowAccuracyTimeSynchResponse: timesynchronization.GetLowAccuracyTimeSynchResponse{ + Ta0: time.Now().Unix(), + ReturnValue: 0, + }, + }, +} +var mockGetLowAccuracyTimeSynchErr error = nil + +func (m MockWSMAN) GetLowAccuracyTimeSynch() (response timesynchronization.Response, err error) { + return mockGetLowAccuracyTimeSynchRsp, mockGetLowAccuracyTimeSynchErr +} + +var mockSetHighAccuracyTimeSynchRsp = timesynchronization.Response{ + Body: timesynchronization.Body{ + SetHighAccuracyTimeSynchResponse: timesynchronization.SetHighAccuracyTimeSynchResponse{ + ReturnValue: 0, + }, + }, +} +var mockSetHighAccuracyTimeSynchErr error = nil + +func (m MockWSMAN) SetHighAccuracyTimeSynch(ta0 int64, tm1 int64, tm2 int64) (response timesynchronization.Response, err error) { + return mockSetHighAccuracyTimeSynchRsp, mockSetHighAccuracyTimeSynchErr +} + +// DeleteKeyPair implements amt.WSMANer. +func (MockWSMAN) DeleteKeyPair(instanceID string) error { + panic("unimplemented") +} + +// PUTTLSSettings implements amt.WSMANer. +func (MockWSMAN) PUTTLSSettings(instanceID string, tlsSettingData tls.SettingDataRequest) (response tls.Response, err error) { + panic("unimplemented") +} + +var mockACMUnprovisionValue = 0 +var mockACMUnprovisionErr error = nil + +func (m MockWSMAN) Unprovision(int) (setupandconfiguration.Response, error) { + return setupandconfiguration.Response{ + Body: setupandconfiguration.Body{ + Unprovision_OUTPUT: setupandconfiguration.Unprovision_OUTPUT{ + ReturnValue: mockACMUnprovisionValue, + }, + }, + }, mockACMUnprovisionErr +} + +var mockSetupAndConfigurationValue = 0 +var mockSetupAndConfigurationErr error = nil + +func (m MockWSMAN) SetupMEBX(password string) (setupandconfiguration.Response, error) { + return setupandconfiguration.Response{ + Body: setupandconfiguration.Body{ + SetMEBxPassword_OUTPUT: setupandconfiguration.SetMEBxPassword_OUTPUT{ + ReturnValue: mockSetupAndConfigurationValue, + }, + }, + }, mockSetupAndConfigurationErr +} + +func (m MockWSMAN) SetupWsmanClient(username string, password string, logAMTMessages bool) {} + +var mockGeneralSettings = general.Response{} +var errMockGeneralSettings error = nil + +func (m MockWSMAN) GetGeneralSettings() (general.Response, error) { + return mockGeneralSettings, errMockGeneralSettings +} + +var mockHostBasedSetupService = hostbasedsetup.Response{} +var errHostBasedSetupService error = nil + +func (m MockWSMAN) HostBasedSetupService(digestRealm string, password string) (hostbasedsetup.Response, error) { + return mockHostBasedSetupService, errHostBasedSetupService +} + +var mockGetHostBasedSetupService = hostbasedsetup.Response{} +var errGetHostBasedSetupService error = nil + +func (m MockWSMAN) GetHostBasedSetupService() (hostbasedsetup.Response, error) { + return mockGetHostBasedSetupService, errGetHostBasedSetupService +} + +var mockAddNextCertInChain = hostbasedsetup.Response{} +var errAddNextCertInChain error = nil + +func (m MockWSMAN) AddNextCertInChain(cert string, isLeaf bool, isRoot bool) (hostbasedsetup.Response, error) { + return mockAddNextCertInChain, errAddNextCertInChain +} + +var mockHostBasedSetupServiceAdmin = hostbasedsetup.Response{} +var errHostBasedSetupServiceAdmin error = nil + +func (m MockWSMAN) HostBasedSetupServiceAdmin(password string, digestRealm string, nonce []byte, signature string) (hostbasedsetup.Response, error) { + return mockHostBasedSetupServiceAdmin, errHostBasedSetupServiceAdmin +} + +var errGetPublicKeyCerts error = nil + +func (m MockWSMAN) GetPublicKeyCerts() ([]publickey.PublicKeyCertificateResponse, error) { + certs := []publickey.PublicKeyCertificateResponse{ + mpsCert, + clientCert, + caCert, + } + return certs, errGetPublicKeyCerts +} + +var errGetPublicPrivateKeyPairs error = nil + +func (m MockWSMAN) GetPublicPrivateKeyPairs() ([]publicprivate.PublicPrivateKeyPair, error) { + return nil, errGetPublicPrivateKeyPairs +} + +var errDeletePublicPrivateKeyPair error = nil + +func (m MockWSMAN) DeletePublicPrivateKeyPair(instanceId string) error { + return errDeletePublicPrivateKeyPair +} + +var errDeletePublicCert error = nil + +func (m MockWSMAN) DeletePublicCert(instanceId string) error { + return errDeletePublicCert +} + +var errGetCredentialRelationships error = nil + +func (m MockWSMAN) GetCredentialRelationships() ([]credential.CredentialContext, error) { + return []credential.CredentialContext{{ + ElementInContext: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate", + SelectorSet: []models.SelectorNoNamespace{ + { + Name: "InstanceID", + Value: "Intel(r) AMT Certificate: Handle: 2", + }, + }, + }, + }, + ElementProvidingContext: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_IEEE8021xSettings", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "Intel(r) AMT:IEEE 802.1x Settings wifi8021x", + }}, + }, + }, + }, { + ElementInContext: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate", + SelectorSet: []models.SelectorNoNamespace{ + { + Name: "InstanceID", + Value: "Intel(r) AMT Certificate: Handle: 1", + }, + }, + }, + }, + ElementProvidingContext: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_IEEE8021xSettings", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "Intel(r) AMT:IEEE 802.1x Settings wifi8021x", + }}, + }, + }, + }}, errGetCredentialRelationships +} + +var errGetConcreteDependencies error = nil + +func (m MockWSMAN) GetConcreteDependencies() ([]concrete.ConcreteDependency, error) { + return []concrete.ConcreteDependency{ + { + Antecedent: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AssetTableService", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "CreationClassName", + Value: "AMT_AssetTableService", + }, { + Name: "Name", + Value: "Intel(r) AMT Asset Table Service", + }, { + Name: "SystemCreationClassName", + Value: "CIM_ComputerSystem", + }, { + Name: "SystemName", + Value: "Intel(r) AMT", + }}, + }, + }, + Dependent: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AssetTable", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "1", + }, { + Name: "TableType", + Value: "131", + }}, + }, + }, + }, + { + Antecedent: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "Intel(r) AMT Certificate: Handle: 1", + }}, + }, + }, + Dependent: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPair", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "Intel(r) AMT Key: Handle: 0", + }}, + }, + }, + }, { + Antecedent: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "Intel(r) AMT Certificate: Handle: 1", + }}, + }, + }, + Dependent: models.AssociationReference{ + Address: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous", + ReferenceParameters: models.ReferenceParmetersNoNamespace{ + ResourceURI: "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SOME_UNHANDLED_RESOURCE_FOR_TESTING", + SelectorSet: []models.SelectorNoNamespace{{ + Name: "InstanceID", + Value: "Intel(r) AMT Key: Handle: 0", + }}, + }, + }, + }, + }, errGetConcreteDependencies +} + +var errGetWiFiSettings error = nil +var getWiFiSettingsResponse = []wifi.WiFiEndpointSettingsResponse{{ + AuthenticationMethod: 0, + BSSType: 0, + ElementName: "", + EncryptionMethod: 0, + InstanceID: "Config1", + Priority: 0, + SSID: "", +}, { + AuthenticationMethod: 0, + BSSType: 0, + ElementName: "", + EncryptionMethod: 0, + InstanceID: "Config2", + Priority: 0, + SSID: "", +}, { + AuthenticationMethod: 0, + BSSType: 0, + ElementName: "", + EncryptionMethod: 0, + InstanceID: "", + Priority: 0, + SSID: "", +}} + +func (m MockWSMAN) GetWiFiSettings() ([]wifi.WiFiEndpointSettingsResponse, error) { + return getWiFiSettingsResponse, errGetWiFiSettings +} + +var errDeleteWiFiSetting error = nil + +func (m MockWSMAN) DeleteWiFiSetting(instanceId string) error { + return errDeleteWiFiSetting +} + +var errAddTrustedRootCert error = nil + +func (m MockWSMAN) AddTrustedRootCert(caCert string) (string, error) { + return "rootCertHandle", errAddTrustedRootCert +} + +var errAddClientCert error = nil + +func (m MockWSMAN) AddClientCert(clientCert string) (string, error) { + return "clientCertHandle", errAddClientCert +} + +var errAddPrivateKey error = nil + +func (m MockWSMAN) AddPrivateKey(privateKey string) (string, error) { + return "privateKeyHandle", errAddPrivateKey +} + +var errEnableWiFi error = nil + +func (m MockWSMAN) EnableWiFi() error { + return errEnableWiFi +} + +var errAddWiFiSettings error = nil + +func (m MockWSMAN) AddWiFiSettings(wifiEndpointSettings wifi.WiFiEndpointSettingsRequest, ieee8021xSettings models.IEEE8021xSettings, wifiEndpoint, clientCredential, caCredential string) (wifiportconfiguration.Response, error) { + return wifiportconfiguration.Response{}, errAddWiFiSettings } // Mock the AMT Hardware @@ -33,11 +400,11 @@ const ChangeEnabledResponseNewDisabled = 0x80 const ChangeEnabledResponseNotNew = 0x00 var mockChangeEnabledResponse = amt2.ChangeEnabledResponse(ChangeEnabledResponseNewEnabled) -var mockChangeEnabledErr error = nil -var mockStandardErr = errors.New("yep, it failed") +var errMockChangeEnabled error = nil +var errMockStandard = errors.New("failed") -func (c MockAMT) Initialize() (utils.ReturnCode, error) { - return utils.Success, nil +func (c MockAMT) Initialize() error { + return nil } var mockVersionDataErr error = nil @@ -46,7 +413,7 @@ func (c MockAMT) GetVersionDataFromME(key string, amtTimeout time.Duration) (str return "Version", mockVersionDataErr } func (c MockAMT) GetChangeEnabled() (amt2.ChangeEnabledResponse, error) { - return mockChangeEnabledResponse, mockChangeEnabledErr + return mockChangeEnabledResponse, errMockChangeEnabled } var mockEnableAMTErr error = nil @@ -132,73 +499,11 @@ func (c MockAMT) Unprovision() (int, error) { return mockUnprovisionCode, mockUn type ResponseFuncArray []func(w http.ResponseWriter, r *http.Request) -func setupWsmanResponses(t *testing.T, f *flags.Flags, responses ResponseFuncArray) ProvisioningService { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "POST", r.Method) - if len(responses) > 0 { - responses[0](w, r) - responses = responses[1:] - } else { - w.WriteHeader(http.StatusServiceUnavailable) - } - }) - return setupWithWsmanClient(f, handler) -} - -func respondServerErrFunc() func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - } -} - -func respondErrFunc(t *testing.T, errNum int, msg string) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(errNum) - _, rc := w.Write([]byte(msg)) - assert.Nil(t, rc) - } -} - -func respondBadXmlFunc(t *testing.T) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - _, rc := w.Write([]byte(`not really xml is it?`)) - assert.Nil(t, rc) - } -} - -func respondMsgFunc(t *testing.T, msg any) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - bytes, err := xml.Marshal(msg) - assert.Nil(t, err) - _, err = w.Write(bytes) - assert.Nil(t, err) - } -} - -func respondStringFunc(t *testing.T, msg string) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte(msg)) - assert.Nil(t, err) - } -} - func setupService(f *flags.Flags) ProvisioningService { service := NewProvisioningService(f) service.amtCommand = MockAMT{} service.networker = &MockOSNetworker{} - return service -} - -func setupWithTestServer(f *flags.Flags, handler http.Handler) ProvisioningService { - service := setupService(f) - server := httptest.NewServer(handler) - service.serverURL = server.URL - return service -} - -func setupWithWsmanClient(f *flags.Flags, handler http.Handler) ProvisioningService { - service := setupWithTestServer(f, handler) - service.setupWsmanClient("admin", "password") + service.interfacedWsmanMessage = MockWSMAN{} return service } @@ -208,13 +513,13 @@ func TestExecute(t *testing.T) { t.Run("execute CommandAMTInfo should succeed", func(t *testing.T) { f.Command = utils.CommandAMTInfo rc := ExecuteCommand(f) - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) }) t.Run("execute CommandVersion should succeed", func(t *testing.T) { f.Command = utils.CommandVersion rc := ExecuteCommand(f) - assert.Equal(t, utils.Success, rc) + assert.Equal(t, nil, rc) }) t.Run("execute CommandConfigure with no SubCommand fails", func(t *testing.T) { @@ -223,39 +528,3 @@ func TestExecute(t *testing.T) { assert.Equal(t, utils.IncorrectCommandLineParameters, rc) }) } - -func respondServerError(w http.ResponseWriter) { - w.WriteHeader(http.StatusInternalServerError) -} - -func respondBadXML(t *testing.T, w http.ResponseWriter) { - _, err := w.Write([]byte(`not really xml is it?`)) - assert.Nil(t, err) -} - -var mockGenerlSettingsResponse = general.Response{} - -func respondGeneralSettings(t *testing.T, w http.ResponseWriter) { - xmlString, err := xml.Marshal(mockGenerlSettingsResponse) - assert.Nil(t, err) - _, err = w.Write(xmlString) - assert.Nil(t, err) -} - -var mockHostBasedSetupResponse = hostbasedsetup.Response{} - -func respondHostBasedSetup(t *testing.T, w http.ResponseWriter) { - xmlString, err := xml.Marshal(mockHostBasedSetupResponse) - assert.Nil(t, err) - _, err = w.Write(xmlString) - assert.Nil(t, err) -} - -var mockUnprovisionResponse = setupandconfiguration.UnprovisionResponse{} - -func respondUnprovision(t *testing.T, w http.ResponseWriter) { - xmlString, err := xml.Marshal(mockUnprovisionResponse) - assert.Nil(t, err) - _, err = w.Write(xmlString) - assert.Nil(t, err) -} diff --git a/internal/local/opstate.go b/internal/local/opstate.go index 3a8b3af9..411c41ba 100644 --- a/internal/local/opstate.go +++ b/internal/local/opstate.go @@ -6,17 +6,17 @@ import ( "rpc/pkg/utils" ) -func (service *ProvisioningService) EnableAMT() utils.ReturnCode { +func (service *ProvisioningService) EnableAMT() error { log.Info("Enabling AMT") err := service.amtCommand.EnableAMT() if err != nil { log.Error("Failed to enable AMT ", err) return utils.AmtNotReady } - return utils.Success + return nil } -func (service *ProvisioningService) CheckAndEnableAMT(skipIPRenewal bool) utils.ReturnCode { +func (service *ProvisioningService) CheckAndEnableAMT(skipIPRenewal bool) error { rsp, err := service.amtCommand.GetChangeEnabled() if err != nil { log.Error(err) @@ -24,25 +24,28 @@ func (service *ProvisioningService) CheckAndEnableAMT(skipIPRenewal bool) utils. } if !rsp.IsNewInterfaceVersion() { log.Debug("this AMT version does not support SetAmtOperationalState") - return utils.Success + return nil } if rsp.IsAMTEnabled() { log.Debug("AMT is alreay enabled") - return utils.Success + return nil } - rc := service.EnableAMT() - if rc != utils.Success { - // error message is already logged - return rc + err = service.EnableAMT() + if err != nil { + return err } if !skipIPRenewal { - return service.RenewIP() + err := service.RenewIP() + return err } - return rc + return nil } -func (service *ProvisioningService) RenewIP() utils.ReturnCode { - rc := service.networker.RenewDHCPLease() +func (service *ProvisioningService) RenewIP() error { + err := service.networker.RenewDHCPLease() + if err != nil { + return err + } if log.IsLevelEnabled(log.DebugLevel) { amtInfoOrig := service.flags.AmtInfo service.flags.AmtInfo = flags.AmtInfoFlags{ @@ -52,5 +55,5 @@ func (service *ProvisioningService) RenewIP() utils.ReturnCode { service.DisplayAMTInfo() service.flags.AmtInfo = amtInfoOrig } - return rc + return nil } diff --git a/internal/local/opstate_test.go b/internal/local/opstate_test.go index 7a7eb05a..f196170f 100644 --- a/internal/local/opstate_test.go +++ b/internal/local/opstate_test.go @@ -1,12 +1,13 @@ package local import ( - log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" "rpc/internal/amt" "rpc/internal/flags" "rpc/pkg/utils" "testing" + + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" ) func TestCheckAndEnableAMT(t *testing.T) { @@ -14,42 +15,42 @@ func TestCheckAndEnableAMT(t *testing.T) { tests := []struct { name string skipIPRenewal bool - expectedRC utils.ReturnCode + expectedRC error rsp amt.ChangeEnabledResponse errChangeEnabled error errEnableAMT error errDisableAMT error - renewDHCPLeaseRC utils.ReturnCode + renewDHCPLeaseRC error }{ { name: "expect AMTConnectionFailed", expectedRC: utils.AMTConnectionFailed, - errChangeEnabled: mockStandardErr, + errChangeEnabled: errMockStandard, }, { name: "expect noop for older versions", - expectedRC: utils.Success, + expectedRC: nil, rsp: ChangeEnabledResponseNotNew, }, { name: "expect noop if already enabled", - expectedRC: utils.Success, + expectedRC: nil, rsp: ChangeEnabledResponseNewEnabled, }, { name: "expect AmtNotReady for enable if error occurs", expectedRC: utils.AmtNotReady, rsp: ChangeEnabledResponseNewDisabled, - errEnableAMT: mockStandardErr, + errEnableAMT: errMockStandard, }, { name: "expect Success for enable happy path", - expectedRC: utils.Success, + expectedRC: nil, rsp: ChangeEnabledResponseNewDisabled, }, { name: "expect Success if skipIPRenewal is true", - expectedRC: utils.Success, + expectedRC: nil, rsp: ChangeEnabledResponseNewDisabled, skipIPRenewal: true, renewDHCPLeaseRC: utils.NetworkConfigurationFailed, @@ -58,25 +59,25 @@ func TestCheckAndEnableAMT(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - origChangeEnabledErr := mockChangeEnabledErr - mockChangeEnabledErr = tc.errChangeEnabled + origChangeEnabledErr := errMockChangeEnabled + errMockChangeEnabled = tc.errChangeEnabled origDisableAMTErr := mockDisableAMTErr mockDisableAMTErr = tc.errDisableAMT origEnableAMTErr := mockEnableAMTErr mockEnableAMTErr = tc.errEnableAMT origRsp := mockChangeEnabledResponse mockChangeEnabledResponse = tc.rsp - origRenewDHCPLeaseRC := mockRenewDHCPLeaseRC - mockRenewDHCPLeaseRC = tc.renewDHCPLeaseRC + origRenewDHCPLeaseRC := mockRenewDHCPLeaseerr + mockRenewDHCPLeaseerr = tc.renewDHCPLeaseRC f := &flags.Flags{} lps := setupService(f) - rc := lps.CheckAndEnableAMT(tc.skipIPRenewal) - assert.Equal(t, tc.expectedRC, rc) + err := lps.CheckAndEnableAMT(tc.skipIPRenewal) + assert.Equal(t, tc.expectedRC, err) mockChangeEnabledResponse = origRsp - mockChangeEnabledErr = origChangeEnabledErr + errMockChangeEnabled = origChangeEnabledErr mockEnableAMTErr = origEnableAMTErr mockDisableAMTErr = origDisableAMTErr - mockRenewDHCPLeaseRC = origRenewDHCPLeaseRC + mockRenewDHCPLeaseerr = origRenewDHCPLeaseRC }) } } @@ -85,9 +86,9 @@ func TestRenewIP(t *testing.T) { f := &flags.Flags{} log.SetLevel(log.DebugLevel) lps := setupService(f) - origRC := mockRenewDHCPLeaseRC - mockRenewDHCPLeaseRC = utils.NetworkConfigurationFailed - rc := lps.RenewIP() - assert.Equal(t, mockRenewDHCPLeaseRC, rc) - mockRenewDHCPLeaseRC = origRC + origRC := mockRenewDHCPLeaseerr + mockRenewDHCPLeaseerr = utils.NetworkConfigurationFailed + err := lps.RenewIP() + assert.Equal(t, mockRenewDHCPLeaseerr, err) + mockRenewDHCPLeaseerr = origRC } diff --git a/internal/local/time.go b/internal/local/time.go index 812917b8..effabc87 100644 --- a/internal/local/time.go +++ b/internal/local/time.go @@ -1,60 +1,53 @@ package local import ( - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/timesynchronization" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - log "github.com/sirupsen/logrus" "rpc/pkg/utils" "time" + + log "github.com/sirupsen/logrus" ) -func (service *ProvisioningService) SynchronizeTime() utils.ReturnCode { +func (service *ProvisioningService) SynchronizeTime() error { log.Info("synchronizing time") - ta0, rc := service.GetLowAccuracyTimeSynch() - if rc != utils.Success { - return rc + ta0, err := service.GetLowAccuracyTimeSynch() + if err != nil { + return err } - rc = service.SetHighAccuracyTimeSynch(ta0) - if rc == utils.Success { + err = service.SetHighAccuracyTimeSynch(ta0) + if err == nil { log.Info("synchronizing time completed successfully") } - return rc + return err } -func (service *ProvisioningService) GetLowAccuracyTimeSynch() (ta0 int64, rc utils.ReturnCode) { +func (service *ProvisioningService) GetLowAccuracyTimeSynch() (ta0 int64, err error) { log.Info("getting low accuracy time") - xmlMsg := service.amtMessages.TimeSynchronizationService.GetLowAccuracyTimeSynch() - var rsp timesynchronization.Response - rc = service.PostAndUnmarshal(xmlMsg, &rsp) - if rc != utils.Success { + response, err := service.interfacedWsmanMessage.GetLowAccuracyTimeSynch() + if err != nil { log.Error("failed GetTimeOffset") - return ta0, rc + return ta0, err } - ptCode := utils.ReturnCode(rsp.Body.GetLowAccuracyTimeSynch_OUTPUT.ReturnValue) - if ptCode != common.PT_STATUS_SUCCESS { + ptCode := response.Body.GetLowAccuracyTimeSynchResponse.ReturnValue + if ptCode != 0 { log.Errorf("failed GetLowAccuracyTimeSynch with PT Code: %v", ptCode) - rc = utils.AmtPtStatusCodeBase + ptCode - return ta0, rc + err = utils.AmtPtStatusCodeBase } - ta0 = rsp.Body.GetLowAccuracyTimeSynch_OUTPUT.Ta0 - return ta0, rc + ta0 = response.Body.GetLowAccuracyTimeSynchResponse.Ta0 + return ta0, nil } -func (service *ProvisioningService) SetHighAccuracyTimeSynch(ta0 int64) utils.ReturnCode { +func (service *ProvisioningService) SetHighAccuracyTimeSynch(ta0 int64) error { log.Info("setting high accuracy time") tm1 := time.Now().Unix() - xmlMsg := service.amtMessages.TimeSynchronizationService.SetHighAccuracyTimeSynch(ta0, tm1, tm1) - rsp := timesynchronization.Response{} - rc := service.PostAndUnmarshal(xmlMsg, &rsp) - if rc != utils.Success { + rsp, err := service.interfacedWsmanMessage.SetHighAccuracyTimeSynch(ta0, tm1, tm1) + if err != nil { log.Error("failed SetHighAccuracyTimeSynch") - return rc + return err } - ptCode := utils.ReturnCode(rsp.Body.SetHighAccuracyTimeSynch_OUTPUT.ReturnValue) - if ptCode != common.PT_STATUS_SUCCESS { + ptCode := rsp.Body.SetHighAccuracyTimeSynchResponse.ReturnValue + if ptCode != 0 { log.Errorf("failed SetHighAccuracyTimeSynch with PT Code: %v", ptCode) - return utils.AmtPtStatusCodeBase + ptCode + return utils.AmtPtStatusCodeBase } - - return utils.Success + return nil } diff --git a/internal/local/time_test.go b/internal/local/time_test.go index 61587f6a..507c4f1f 100644 --- a/internal/local/time_test.go +++ b/internal/local/time_test.go @@ -1,141 +1,55 @@ package local import ( - "github.com/stretchr/testify/assert" + "errors" "rpc/internal/flags" - "rpc/pkg/utils" - "strings" "testing" - "time" + + "github.com/stretchr/testify/assert" ) func TestSynchronizeTime(t *testing.T) { - t.Run("expect success for happy path", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, getLowAccuracyTimeSynchXMLResponse), - respondStringFunc(t, setHighAccuracyTimeSynchXMLResponse), - } - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, r) - rc := lps.SynchronizeTime() - assert.Equal(t, utils.Success, rc) - }) -} - -func runGetLowAccuracyTimeSynchTest(t *testing.T, expectedRC utils.ReturnCode, expectedTa0 int64, responsers ResponseFuncArray) { - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, responsers) - ta0, rc := lps.GetLowAccuracyTimeSynch() - assert.Equal(t, expectedRC, rc) - assert.Equal(t, expectedTa0, ta0) -} - -func TestGetLowAccuracyTimeSynch(t *testing.T) { - t.Run("expect error at PostAndUnmarshal", func(t *testing.T) { - r := ResponseFuncArray{ - respondServerErrFunc(), - } - runGetLowAccuracyTimeSynchTest(t, utils.WSMANMessageError, 0, r) - }) - t.Run("expect error on bad ReturnValue", func(t *testing.T) { - rsp := strings.Replace(getLowAccuracyTimeSynchXMLResponse, - `0`, - `1`, 1) - expectRC := utils.AmtPtStatusCodeBase + utils.ReturnCode(1) - r := ResponseFuncArray{ - respondStringFunc(t, rsp), - } - runGetLowAccuracyTimeSynchTest(t, expectRC, 0, r) - }) - t.Run("expect success", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, getLowAccuracyTimeSynchXMLResponse), - } - runGetLowAccuracyTimeSynchTest(t, utils.Success, 1704394160, r) - }) + tests := []struct { + name string + mockGetLowAccuracyTimeSynchErr error + mockSetHighAccuracyTimeSynchErr error + expectedError bool + }{ + { + name: "successful synchronization", + expectedError: false, + }, + { + name: "failure on GetLowAccuracyTimeSynch", + mockGetLowAccuracyTimeSynchErr: errors.New("network error"), + expectedError: true, + }, + { + name: "failure on SetHighAccuracyTimeSynch", + mockSetHighAccuracyTimeSynchErr: errors.New("network error"), + expectedError: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + f := &flags.Flags{} + mockAMT := new(MockAMT) + mockWsman := new(MockWSMAN) + service := NewProvisioningService(f) + service.amtCommand = mockAMT + service.interfacedWsmanMessage = mockWsman + + mockGetLowAccuracyTimeSynchErr = tc.mockGetLowAccuracyTimeSynchErr + mockSetHighAccuracyTimeSynchErr = tc.mockSetHighAccuracyTimeSynchErr + + err := service.SynchronizeTime() + + if tc.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } } - -func runSetHighAccuracyTimeSynchTest(t *testing.T, expectedRC utils.ReturnCode, ta0 int64, responsers ResponseFuncArray) { - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, responsers) - rc := lps.SetHighAccuracyTimeSynch(ta0) - assert.Equal(t, expectedRC, rc) -} - -func TestSetHighAccuracyTimeSynch(t *testing.T) { - ta0 := time.Now().Unix() - t.Run("expect error at PostAndUnmarshal", func(t *testing.T) { - r := ResponseFuncArray{ - respondServerErrFunc(), - } - runSetHighAccuracyTimeSynchTest(t, utils.WSMANMessageError, ta0, r) - }) - t.Run("expect error on bad ReturnValue", func(t *testing.T) { - rsp := strings.Replace(setHighAccuracyTimeSynchXMLResponse, - `0`, - `1`, 1) - expectRC := utils.AmtPtStatusCodeBase + utils.ReturnCode(1) - r := ResponseFuncArray{ - respondStringFunc(t, rsp), - } - runSetHighAccuracyTimeSynchTest(t, expectRC, ta0, r) - }) - t.Run("expect success", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, setHighAccuracyTimeSynchXMLResponse), - } - runSetHighAccuracyTimeSynchTest(t, utils.Success, ta0, r) - }) -} - -const getLowAccuracyTimeSynchXMLResponse = ` - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 0 - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TimeSynchronizationService/GetLowAccuracyTimeSynchResponse - - uuid:00000000-8086-8086-8086-000000011E1F - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TimeSynchronizationService - - - - 1704394160 - 0 - - -` - -const setHighAccuracyTimeSynchXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 9 - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TimeSynchronizationService/SetHighAccuracyTimeSynchResponse - - uuid:00000000-8086-8086-8086-000000000061 - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TimeSynchronizationService - - - - 0 - - - -` diff --git a/internal/local/tls.go b/internal/local/tls.go index 6c756137..f9f1936d 100644 --- a/internal/local/tls.go +++ b/internal/local/tls.go @@ -1,57 +1,49 @@ package local import ( - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/setupandconfiguration" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/tls" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - log "github.com/sirupsen/logrus" "rpc/internal/certs" "rpc/internal/flags" "rpc/pkg/utils" "strings" + + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publicprivate" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/tls" + log "github.com/sirupsen/logrus" ) const RemoteTLSInstanceId = `Intel(r) AMT 802.3 TLS Settings` const LocalTLSInstanceId = `Intel(r) AMT LMS TLS Settings` -//type TLSContext struct { -// RootComp certs.Composite -// ClientComp certs.Composite -// Handles Handles -//} - -func (service *ProvisioningService) ConfigureTLS() utils.ReturnCode { +func (service *ProvisioningService) ConfigureTLS() error { log.Info("configuring TLS") var handles Handles - var rc utils.ReturnCode + var err error defer func() { - if rc != utils.Success { + if err != nil { service.RollbackAddedItems(&handles) } }() - var err error rootComposite, err := certs.NewRootComposite() if err != nil { return utils.TLSConfigurationFailed } - handles.rootCertHandle, rc = service.AddTrustedRootCert(rootComposite.StripPem()) - if rc != utils.Success { - return rc + handles.rootCertHandle, err = service.interfacedWsmanMessage.AddTrustedRootCert(rootComposite.StripPem()) + if err != nil { + return err } - handles.keyPairHandle, rc = service.GenerateKeyPair() - if rc != utils.Success { - return rc + handles.keyPairHandle, err = service.GenerateKeyPair() + if err != nil { + return err } handles.privateKeyHandle = handles.keyPairHandle var keyPairs []publicprivate.PublicPrivateKeyPair - rc = service.GetPublicPrivateKeyPairs(&keyPairs) - if rc != utils.Success { - return rc + keyPairs, err = service.interfacedWsmanMessage.GetPublicPrivateKeyPairs() + if err != nil { + return err } var derKey string for _, keyPair := range keyPairs { @@ -70,62 +62,54 @@ func (service *ProvisioningService) ConfigureTLS() utils.ReturnCode { return utils.TLSConfigurationFailed } - handles.clientCertHandle, rc = service.AddClientCert(clientComposite.StripPem()) - if rc != utils.Success { - return rc + handles.clientCertHandle, err = service.interfacedWsmanMessage.AddClientCert(clientComposite.StripPem()) + if err != nil { + return err } log.Debug("TLS rootCertHandle:", handles.rootCertHandle) log.Debug("TLS clientCertHandle:", handles.clientCertHandle) log.Debug("TLS keyPairHandle:", handles.keyPairHandle) - rc = service.CreateTLSCredentialContext(handles.clientCertHandle) - if rc != utils.Success { - return rc + err = service.CreateTLSCredentialContext(handles.clientCertHandle) + if err != nil { + return err } - rc = service.SynchronizeTime() - if rc != utils.Success { - return rc + err = service.SynchronizeTime() + if err != nil { + return err } - rc = service.EnableTLS() - if rc == utils.Success { - log.Info("configuring TLS completed successfully") + err = service.EnableTLS() + if err != nil { + log.Error("Failed to configure TLS") } - return rc + log.Info("configuring TLS completed successfully") + return nil } -func (service *ProvisioningService) GenerateKeyPair() (handle string, rc utils.ReturnCode) { +func (service *ProvisioningService) GenerateKeyPair() (handle string, err error) { log.Info("generating key pair") - keyPairInput := publickey.GenerateKeyPair_INPUT{ - KeyAlgorithm: publickey.RSA, - KeyLength: 2048, - } - xmlMsg := service.amtMessages.PublicKeyManagementService.GenerateKeyPair(keyPairInput) - var publicKeyResponse publickey.Response - rc = service.PostAndUnmarshal(xmlMsg, &publicKeyResponse) - if rc != utils.Success { - return handle, rc - } - rc = utils.ReturnCode(publicKeyResponse.Body.GeneratedKeyPair_OUTPUT.ReturnValue) - if rc != 0 { - log.Errorf("GenerateKeyPair.ReturnValue: %d", rc) - return handle, utils.AmtPtStatusCodeBase + rc - } - if len(publicKeyResponse.Body.GeneratedKeyPair_OUTPUT.KeyPair.ReferenceParameters.SelectorSet.Selector) == 0 { + response, err := service.interfacedWsmanMessage.GenerateKeyPair(publickey.RSA, 2048) + if err != nil { + return "", err + } + if response.Body.GenerateKeyPair_OUTPUT.ReturnValue != 0 { + log.Errorf("GenerateKeyPair.ReturnValue: %d", response.Body.GenerateKeyPair_OUTPUT.ReturnValue) + return "", utils.AmtPtStatusCodeBase + } + if len(response.Body.GenerateKeyPair_OUTPUT.KeyPair.ReferenceParameters.SelectorSet.Selectors) == 0 { log.Error("GenerateKeyPair did not return a valid handle") return handle, utils.TLSConfigurationFailed } - handle = publicKeyResponse.Body.GeneratedKeyPair_OUTPUT.KeyPair.ReferenceParameters.SelectorSet.Selector[0].Value - return handle, utils.Success + handle = response.Body.GenerateKeyPair_OUTPUT.KeyPair.ReferenceParameters.SelectorSet.Selectors[0].Text + return handle, nil } -func (service *ProvisioningService) CreateTLSCredentialContext(certHandle string) utils.ReturnCode { +func (service *ProvisioningService) CreateTLSCredentialContext(certHandle string) error { log.Info("creating TLS credential context") - xmlMsg := service.amtMessages.TLSCredentialContext.Create(certHandle) - - xmlRsp, err := service.client.Post(xmlMsg) - log.Trace(string(xmlRsp)) + response, err := service.interfacedWsmanMessage.CreateTLSCredentialContext(certHandle) + log.Trace(response) if err != nil { if strings.Contains(strings.ToLower(err.Error()), "alreadyexists") { log.Info("TLSCredentialContext already exists", certHandle) @@ -134,61 +118,54 @@ func (service *ProvisioningService) CreateTLSCredentialContext(certHandle string return utils.WSMANMessageError } } - return utils.Success + return nil } -func (service *ProvisioningService) EnableTLS() utils.ReturnCode { +func (service *ProvisioningService) EnableTLS() error { log.Info("enabling tls") - var pullRsp tls.Response - rc := service.EnumPullUnmarshal( - service.amtMessages.TLSSettingData.Enumerate, - service.amtMessages.TLSSettingData.Pull, - &pullRsp, - ) - if rc != utils.Success { - return rc + enumerateRsp, err := service.interfacedWsmanMessage.EnumerateTLSSettingData() + if err != nil { + return utils.WSMANMessageError } - - for _, item := range pullRsp.Body.PullResponse.TlsSettingItems { + pullRsp, err := service.interfacedWsmanMessage.PullTLSSettingData(enumerateRsp.Body.EnumerateResponse.EnumerationContext) + for _, item := range pullRsp.Body.PullResponse.SettingDataItems { if item.InstanceID == RemoteTLSInstanceId || item.InstanceID == LocalTLSInstanceId { - rc = service.ConfigureTLSSettings(&item) + err = service.ConfigureTLSSettings(item) + if err != nil { + return err + } } - if rc != utils.Success { - return rc + if err != nil { + return err } } - - service.Pause(service.flags.ConfigTLSInfo.DelayInSeconds) - - xmlMsg := service.amtMessages.SetupAndConfigurationService.CommitChanges() - var commitResponse setupandconfiguration.Response - rc = service.PostAndUnmarshal(xmlMsg, &commitResponse) - if rc != utils.Success { + // service.Pause(service.flags.ConfigTLSInfo.DelayInSeconds) + // time.Sleep(time.Duration(howManySeconds) * time.Second) + commitResponse, err := service.interfacedWsmanMessage.CommitChanges() + if err != nil { log.Error("commit changes failed") - return rc + return err } - retVal := commitResponse.Body.CommitChanges_OUTPUT.ReturnValue - if retVal != common.PT_STATUS_SUCCESS { - log.Errorf("CommitChangesResponse non-zero return code: %d", retVal) - return utils.AmtPtStatusCodeBase + utils.ReturnCode(retVal) + if commitResponse.Body.CommitChanges_OUTPUT.ReturnValue != 0 { + log.Errorf("CommitChangesResponse non-zero return code: %d", commitResponse.Body.CommitChanges_OUTPUT.ReturnValue) + return utils.AmtPtStatusCodeBase } - return utils.Success + return err } -func (service *ProvisioningService) ConfigureTLSSettings(setting *tls.TlsSetting) utils.ReturnCode { - data := getTLSSettingsPutData(setting, service.flags.ConfigTLSInfo.TLSMode) - xmlMsg := service.amtMessages.TLSSettingData.Put(data) - var putResponse tls.Response - rc := service.PostAndUnmarshal(xmlMsg, &putResponse) - if rc != utils.Success { +func (service *ProvisioningService) ConfigureTLSSettings(setting tls.SettingDataResponse) error { + data := getTLSSettings(setting, service.flags.ConfigTLSInfo.TLSMode) + putResponse, err := service.interfacedWsmanMessage.PUTTLSSettings(data.InstanceID, data) + log.Trace(putResponse) + if err != nil { log.Errorf("failed to configure remote TLS Settings (%s)\n", data.InstanceID) } - return rc + return nil } -func getTLSSettingsPutData(setting *tls.TlsSetting, tlsMode flags.TLSMode) tls.TLSSettingData { - data := tls.TLSSettingData{ +func getTLSSettings(setting tls.SettingDataResponse, tlsMode flags.TLSMode) tls.SettingDataRequest { + data := tls.SettingDataRequest{ AcceptNonSecureConnections: setting.AcceptNonSecureConnections, ElementName: setting.ElementName, Enabled: true, @@ -197,7 +174,7 @@ func getTLSSettingsPutData(setting *tls.TlsSetting, tlsMode flags.TLSMode) tls.T } if setting.InstanceID == RemoteTLSInstanceId { log.Infof("configuring remote TLS settings mode: %s", tlsMode) - if setting.NonSecureConnectionsSupported == nil || *setting.NonSecureConnectionsSupported { + if setting.NonSecureConnectionsSupported { data.AcceptNonSecureConnections = tlsMode == flags.TLSModeServerAndNonTLS || tlsMode == flags.TLSModeMutualAndNonTLS } data.MutualAuthentication = tlsMode == flags.TLSModeMutual || tlsMode == flags.TLSModeMutualAndNonTLS diff --git a/internal/local/tls_test.go b/internal/local/tls_test.go deleted file mode 100644 index 3f3edea5..00000000 --- a/internal/local/tls_test.go +++ /dev/null @@ -1,516 +0,0 @@ -package local - -import ( - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/tls" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - "github.com/stretchr/testify/assert" - "rpc/internal/flags" - "rpc/pkg/utils" - "strings" - "testing" -) - -func runConfigureTLSTest(t *testing.T, expectedCode utils.ReturnCode, responsers ResponseFuncArray) { - f := &flags.Flags{} - f.ConfigTLSInfo.DelayInSeconds = 0 - lps := setupWsmanResponses(t, f, responsers) - rc := lps.ConfigureTLS() - assert.Equal(t, expectedCode, rc) -} - -func TestConfigureTLS(t *testing.T) { - enumRsp := common.EnumerationResponse{} - - t.Run("expect error at AddTrustedRootCert", func(t *testing.T) { - r := ResponseFuncArray{} - runConfigureTLSTest(t, utils.WSMANMessageError, r) - }) - - t.Run("expect error at GenerateKeyPair", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - } - runConfigureTLSTest(t, utils.WSMANMessageError, r) - }) - - t.Run("expect error at GetPublicPrivateKeyPairs", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - respondStringFunc(t, generateKeyPairXMLResponse), - } - runConfigureTLSTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect error at der key not found after GetPublicPrivateKeyPairs", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - respondStringFunc(t, generateKeyPairXMLResponse), - respondMsgFunc(t, enumRsp), - respondMsgFunc(t, publicprivate.PullResponseEnvelope{}), - } - runConfigureTLSTest(t, utils.TLSConfigurationFailed, r) - }) - t.Run("expect error at AddClientCert", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - respondStringFunc(t, generateKeyPairXMLResponse), - respondMsgFunc(t, enumRsp), - respondStringFunc(t, publicPrivateKeyPairXMLResponse), - } - runConfigureTLSTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect error at CreateTLSCredentialContext", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - respondStringFunc(t, generateKeyPairXMLResponse), - respondMsgFunc(t, enumRsp), - respondStringFunc(t, publicPrivateKeyPairXMLResponse), - respondStringFunc(t, addClientCertXMLResponse), - } - runConfigureTLSTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect error at SyncTime", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - respondStringFunc(t, generateKeyPairXMLResponse), - respondMsgFunc(t, enumRsp), - respondStringFunc(t, publicPrivateKeyPairXMLResponse), - respondStringFunc(t, addClientCertXMLResponse), - respondStringFunc(t, credCtxPullRspString), - } - runConfigureTLSTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect success for happy path", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, trustedRootXMLResponse), - respondStringFunc(t, generateKeyPairXMLResponse), - respondMsgFunc(t, enumRsp), - respondStringFunc(t, publicPrivateKeyPairXMLResponse), - respondStringFunc(t, addClientCertXMLResponse), - respondStringFunc(t, credCtxPullRspString), - respondStringFunc(t, getLowAccuracyTimeSynchXMLResponse), - respondStringFunc(t, setHighAccuracyTimeSynchXMLResponse), - respondMsgFunc(t, enumRsp), - respondStringFunc(t, tlsSettingsXMLResponse), - respondStringFunc(t, putTLSSettingsXMLResponse), - respondStringFunc(t, putTLSSettingsXMLResponse), - respondStringFunc(t, commitChangesXMLResponse), - } - runConfigureTLSTest(t, utils.Success, r) - }) -} - -func runGenerateKeyPairTest(t *testing.T, expectedHandle string, expectedCode utils.ReturnCode, responsers ResponseFuncArray) { - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, responsers) - handle, rc := lps.GenerateKeyPair() - assert.Equal(t, expectedCode, rc) - assert.Equal(t, expectedHandle, handle) -} - -func TestGenerateKeyPair(t *testing.T) { - - t.Run("expect failure on non-success return code", func(t *testing.T) { - rsp := publickey.Response{} - rsp.Body.GeneratedKeyPair_OUTPUT.ReturnValue = 1 - expected := utils.AmtPtStatusCodeBase + utils.ReturnCode(rsp.Body.GeneratedKeyPair_OUTPUT.ReturnValue) - r := ResponseFuncArray{ - respondMsgFunc(t, rsp), - } - runGenerateKeyPairTest(t, "", expected, r) - }) - t.Run("expect failure on non-success return code", func(t *testing.T) { - rsp := publickey.Response{} - r := ResponseFuncArray{ - respondMsgFunc(t, rsp), - } - runGenerateKeyPairTest(t, "", utils.TLSConfigurationFailed, r) - }) - t.Run("expect success on non-success return code", func(t *testing.T) { - expectedHandle := "Intel(r) AMT Key: Handle: 3" - r := ResponseFuncArray{ - respondStringFunc(t, generateKeyPairXMLResponse), - } - runGenerateKeyPairTest(t, expectedHandle, utils.Success, r) - }) -} - -func TestCreateCredentialContext(t *testing.T) { - t.Run("expect success if credential already exists", func(t *testing.T) { - expectedHandle := "Intel(r) AMT Key: Handle: 3" - r := ResponseFuncArray{ - respondErrFunc(t, 403, credentialAlreadyExists), - } - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, r) - rc := lps.CreateTLSCredentialContext(expectedHandle) - assert.Equal(t, utils.Success, rc) - }) -} - -func runEnableTLSTest(t *testing.T, expectedCode utils.ReturnCode, responsers ResponseFuncArray) { - f := &flags.Flags{} - f.ConfigTLSInfo.DelayInSeconds = 1 - lps := setupWsmanResponses(t, f, responsers) - rc := lps.EnableTLS() - assert.Equal(t, expectedCode, rc) -} - -func TestEnableTLS(t *testing.T) { - enumRsp := common.EnumerationResponse{} - t.Run("expect error at EnumPullUnmarshal", func(t *testing.T) { - runEnableTLSTest(t, utils.WSMANMessageError, ResponseFuncArray{}) - }) - t.Run("expect error at ConfigureTLSSettings", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondStringFunc(t, tlsSettingsXMLResponse), - } - runEnableTLSTest(t, utils.WSMANMessageError, r) - }) - - t.Run("expect WSMANMessageError at CommitChanges", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondStringFunc(t, tlsSettingsXMLResponse), - respondStringFunc(t, putTLSSettingsXMLResponse), - respondStringFunc(t, putTLSSettingsXMLResponse), - } - runEnableTLSTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect ReturnValue error at CommitChanges", func(t *testing.T) { - var rspXML = strings.Replace(commitChangesXMLResponse, - "0", - "1", - 1) - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondStringFunc(t, tlsSettingsXMLResponse), - respondStringFunc(t, putTLSSettingsXMLResponse), - respondStringFunc(t, putTLSSettingsXMLResponse), - respondStringFunc(t, rspXML), - } - expected := utils.AmtPtStatusCodeBase + utils.ReturnCode(1) - runEnableTLSTest(t, expected, r) - }) -} - -func TestGetTLSSettingsPutData(t *testing.T) { - t.Run("expect correct local tls settings", func(t *testing.T) { - setting := tls.TlsSetting{ - AcceptNonSecureConnections: true, - ElementName: LocalTLSInstanceId, - Enabled: true, - InstanceID: LocalTLSInstanceId, - MutualAuthentication: true, - } - expected := tls.TLSSettingData{ - AcceptNonSecureConnections: true, - ElementName: LocalTLSInstanceId, - Enabled: true, - InstanceID: LocalTLSInstanceId, - MutualAuthentication: true, - } - actual := getTLSSettingsPutData(&setting, flags.TLSModeServer) - assert.Equal(t, expected, actual) - }) - t.Run("expect correct remote tls settings", func(t *testing.T) { - setting := tls.TlsSetting{ - AcceptNonSecureConnections: true, - ElementName: RemoteTLSInstanceId, - InstanceID: RemoteTLSInstanceId, - MutualAuthentication: true, - } - expected := tls.TLSSettingData{ - ElementName: RemoteTLSInstanceId, - Enabled: true, - InstanceID: RemoteTLSInstanceId, - } - - expected.AcceptNonSecureConnections = false - expected.MutualAuthentication = false - actual := getTLSSettingsPutData(&setting, flags.TLSModeServer) - assert.Equal(t, expected, actual) - - var nonSecureCnx = true - setting.NonSecureConnectionsSupported = &nonSecureCnx - expected.AcceptNonSecureConnections = true - expected.MutualAuthentication = false - actual = getTLSSettingsPutData(&setting, flags.TLSModeServerAndNonTLS) - assert.Equal(t, expected, actual) - - expected.AcceptNonSecureConnections = false - expected.MutualAuthentication = true - actual = getTLSSettingsPutData(&setting, flags.TLSModeMutual) - assert.Equal(t, expected, actual) - - expected.AcceptNonSecureConnections = true - expected.MutualAuthentication = true - actual = getTLSSettingsPutData(&setting, flags.TLSModeMutualAndNonTLS) - assert.Equal(t, expected, actual) - - }) - -} - -const generateKeyPairXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 3 - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementService/GenerateKeyPairResponse - - uuid:00000000-8086-8086-8086-0000000005C5 - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementService - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPair - - Intel(r) AMT Key: Handle: 3 - - - - 0 - - -` - -const publicPrivateKeyPairXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 5 - http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse - uuid:00000000-8086-8086-8086-000000000024 - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPair - - - - - - - MIIBCgKCAQEA3zEgE1hJ+rK2nnxMUh2/sO+4J39PsPo+97vtmdlJH86yyoP/kFTGu6MABV/ew331jHUhaKPNYczTK2ApWrewD6E5qzeyPhYevRCuA+igysYCRk9Vn59ZQpVFAgoZKtc0AYlc4nWIpZGAw4dxtef8RD7vKrY8+D597XPC+DVANbIS+OhcF7VyChTdx7qVU6xdjiXritVux7iHv0Jy2/VpMcAE9u2XJTW4nERTDhUiuWepDoZouTzR7mbDOusLhLjK348JkK2+IBjagnBmNCPTI02MP8HKAr/0Q9JsKh3ddL7C7mo1f9d385NNG7GZEN/AA1oBmzKVplwEL0uw5ITG7wIDAQAB - - Intel(r) AMT Key - Intel(r) AMT Key: Handle: 0 - - - - MIIBCgKCAQEAwX77L32ccNNmllIk9O5h+DG740iO56rzAmjo63F8KU51k7cudZB5RKcQwIiqBwHuKdzhAlWVpKPLWFLIrOwTCnMwGeSU6okUbctK1vOLg87a5Us78pA4Z8tI8GjlSIhCS7NUwxTVoQasWPCQlek+KpB8JcZOB7qRcIu8wZrXwvHphglmRfGDcONSZaWkYTFaWXaKCLFzJi+094Mp/Ucgu2szrMWqi13bUqHTf6DjXqJ+k+IMCIrEk2vx1mpbz120/ZAEo/pXcBk0hkt+g3Qg3QLHFB6tWGCJoKKyI5ySyZMppKzkgl7paCEDrUsnuew0y41jCTC5+8bPE6Mk3AzGQwIDAQAB - - Intel(r) AMT Key - Intel(r) AMT Key: Handle: 1 - - - - MIIBCgKCAQEA2qJUQXfLPBSQjAkj2YyskzcBaYe2BoE5OIDghUf7V0f29a84ulqx1alrsptf3X9cT1mIHhJ2ThBQoE2sqEE/liBpJLExj+sXB78bWPYvxjayJKZmVS95fHPy6Namse8GrYz4sN8U0EQIQ/Mt6Tg+kIharZL+znqZXGDslYLvBr+NYGy97q7JxA2Y69V8eK9D2+2leo1DWLBuLwrJaTxVnkh72q4v6OSVtP3IR3U9lDTt9rehgFLiLbE1ioaQ6eutVyg8vI2l8qr5fPpDVRB/TNa9z98DqNL/rur7y82CCDWwpLgKCBz6qMXfa+EBBNs1cLYVGHhn9+AqKxrha356PQIDAQAB - - Intel(r) AMT Key - Intel(r) AMT Key: Handle: 2 - - - - MIIBCgKCAQEArYLhHgyZXGU8rt88sSWmuy+e/Qz/arN+2DcLM8KHdJSewfD8h8Ydk4S1z00+y4AmnVUYYC8JChu+BtuNGlAdEKbo36hySH9a5BGuUn8uPnZGpkCLAD2wbXfmoSk9ReGgC5q+ScpQdtDq0C/e/eHUDc+2fUdPAri4Zx4Ot/6vyq1YSKvGr8eiO91v4IA0r8sdJETrtAtJ/hDz131JJBXadRhrOteqc30TYohqdRxN2JNOeXNAT1McNBJBnqcsRF6BSK8V4wMbA+qCvazN3byyJ1kq/GKX5W8e3cMvzWCXil58oiEvsXkMBc938omXc+TQDzl9biP3pSNhg3Wvh7AKywIDAQAB - - Intel(r) AMT Key - Intel(r) AMT Key: Handle: 3 - - - - - -` - -const addClientCertXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 6 - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementService/AddCertificateResponse - - uuid:00000000-8086-8086-8086-000000000025 - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyManagementService - - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate - - Intel(r) AMT Certificate: Handle: 7 - - - - - 0 - - -` - -const tlsSettingsXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 12 - http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse - uuid:00000000-8086-8086-8086-0000000000FC - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TLSSettingData - - - - - - false - Intel(r) AMT 802.3 TLS Settings - true - Intel(r) AMT 802.3 TLS Settings - false - false - - - true - Intel(r) AMT LMS TLS Settings - true - Intel(r) AMT LMS TLS Settings - false - true - - - - - - -` -const putTLSSettingsXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 40 - http://schemas.xmlsoap.org/ws/2004/09/transfer/PutResponse - - uuid:00000000-8086-8086-8086-00000000008E - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TLSSettingData - - - - - true - Intel(r) AMT LMS TLS Settings - false - Intel(r) AMT LMS TLS Settings - false - true - - - -` - -const commitChangesXMLResponse = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 11 - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService/CommitChangesResponse - - uuid:00000000-8086-8086-8086-00000000BE73 - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService - - - - 0 - - - -` - -const credentialAlreadyExists = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 36 - http://schemas.dmtf.org/wbem/wsman/1/wsman/fault - uuid:00000000-8086-8086-8086-000000000084 - - - - - a:Sender - - e:AlreadyExists - - - - The sender attempted to create a resource which already exists. - - - - - -` diff --git a/internal/local/utils.go b/internal/local/utils.go index 6ecdf97c..82251ca1 100644 --- a/internal/local/utils.go +++ b/internal/local/utils.go @@ -1,28 +1,10 @@ package local import ( - "encoding/xml" - "time" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/concrete" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/cim/credential" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - log "github.com/sirupsen/logrus" "reflect" - "rpc/pkg/utils" "strings" ) -func (service *ProvisioningService) Pause(howManySeconds int) { - if howManySeconds <= 0 { - return - } - log.Debugf("pausing %d seconds", howManySeconds) - time.Sleep(time.Duration(howManySeconds) * time.Second) -} - func reflectObjectName(v any) string { var vName string if t := reflect.TypeOf(v); t.Kind() == reflect.Ptr { @@ -33,38 +15,6 @@ func reflectObjectName(v any) string { return vName } -type EnumMessageFunc func() string -type PullMessageFunc func(string) string - -func (service *ProvisioningService) EnumPullUnmarshal(enumFn EnumMessageFunc, pullFn PullMessageFunc, outObj any) utils.ReturnCode { - xmlMsg := enumFn() - xmlRsp, err := service.client.Post(xmlMsg) - if err != nil { - log.Errorf("enumerate post call for %s: %s", reflectObjectName(outObj), err) - return utils.WSMANMessageError - } - var enumRsp common.EnumerationResponse - if err := xml.Unmarshal(xmlRsp, &enumRsp); err != nil { - log.Errorf("enumerate unmarshal call for %s: %s", reflectObjectName(outObj), err) - return utils.UnmarshalMessageFailed - } - xmlMsg = pullFn(enumRsp.Body.EnumerateResponse.EnumerationContext) - return service.PostAndUnmarshal(xmlMsg, outObj) -} - -func (service *ProvisioningService) PostAndUnmarshal(xmlMsg string, outObj any) utils.ReturnCode { - xmlRsp, err := service.client.Post(xmlMsg) - if err != nil { - log.Errorf("post call for %s: %s", reflectObjectName(outObj), err) - return utils.WSMANMessageError - } - if err := xml.Unmarshal(xmlRsp, outObj); err != nil { - log.Errorf("unmarshal call for %s: %s", reflectObjectName(outObj), err) - return utils.UnmarshalMessageFailed - } - return utils.Success -} - func GetTokenFromKeyValuePairs(kvList string, token string) string { attributes := strings.Split(kvList, ",") tokenMap := make(map[string]string) @@ -75,128 +25,12 @@ func GetTokenFromKeyValuePairs(kvList string, token string) string { return tokenMap[token] } -func (service *ProvisioningService) GetPublicKeyCerts(certs *[]publickey.PublicKeyCertificate) utils.ReturnCode { - - var pullRspEnv publickey.PullResponseEnvelope - rc := service.EnumPullUnmarshal( - service.amtMessages.PublicKeyCertificate.Enumerate, - service.amtMessages.PublicKeyCertificate.Pull, - &pullRspEnv, - ) - if rc != utils.Success { - return rc - } - for _, publicKeyCert := range pullRspEnv.Body.PullResponse.Items { - *certs = append(*certs, publicKeyCert) - } - return utils.Success -} - -// GetPublicPrivateKeyPairs -// NOTE: RSA Key encoded as DES PKCS#1. The Exponent (E) is 65537 (0x010001). -// When this structure is used as an output parameter (GET or PULL method), -// only the public section of the key is exported. -func (service *ProvisioningService) GetPublicPrivateKeyPairs(keyPairs *[]publicprivate.PublicPrivateKeyPair) utils.ReturnCode { - - var pullRspEnv publicprivate.PullResponseEnvelope - rc := service.EnumPullUnmarshal( - service.amtMessages.PublicPrivateKeyPair.Enumerate, - service.amtMessages.PublicPrivateKeyPair.Pull, - &pullRspEnv, - ) - if rc != utils.Success { - return rc - } - for _, keyPair := range pullRspEnv.Body.PullResponse.Items { - *keyPairs = append(*keyPairs, keyPair) - } - return utils.Success -} - -func (service *ProvisioningService) DeletePublicPrivateKeyPair(instanceId string) utils.ReturnCode { - log.Infof("deleting public private key pair instance: %s", instanceId) - xmlMsg := service.amtMessages.PublicPrivateKeyPair.Delete(instanceId) - // the response has no addiitonal information - // if post is successful, then deletion is successful - _, err := service.client.Post(xmlMsg) - if err != nil { - log.Errorf("unable to delete: %s", instanceId) - return utils.DeleteWifiConfigFailed - } - return utils.Success -} - -func (service *ProvisioningService) DeletePublicCert(instanceId string) utils.ReturnCode { - log.Infof("deleting public key certificate instance: %s", instanceId) - xmlMsg := service.amtMessages.PublicKeyCertificate.Delete(instanceId) - // the response has no addiitonal information - // if post is successful, then deletion is successful - _, err := service.client.Post(xmlMsg) - if err != nil { - log.Errorf("unable to delete: %s", instanceId) - return utils.DeleteWifiConfigFailed - } - return utils.Success -} - -func (service *ProvisioningService) GetCredentialRelationships() ([]credential.Relationship, utils.ReturnCode) { - var items []credential.Relationship - var pullRspEnv credential.ContextPullResponseEnvelope - rc := service.EnumPullUnmarshal( - service.cimMessages.CredentialContext.Enumerate, - service.cimMessages.CredentialContext.Pull, - &pullRspEnv, - ) - if rc != utils.Success { - return items, rc - } - for { - for i := range pullRspEnv.Body.PullResponse.Items { - items = append(items, pullRspEnv.Body.PullResponse.Items[i]) - } - enumContext := pullRspEnv.Body.PullResponse.EnumerationContext - if enumContext == "" { - break - } - pullRspEnv = credential.ContextPullResponseEnvelope{} - rc = service.PostAndUnmarshal( - service.cimMessages.CredentialContext.Pull(enumContext), - &pullRspEnv, - ) - if rc != utils.Success { - return items, rc - } - } - return items, utils.Success -} - -func (service *ProvisioningService) GetConcreteDependencies() ([]concrete.Relationship, utils.ReturnCode) { - var items []concrete.Relationship - var pullRspEnv concrete.DependencyPullResponseEnvelope - rc := service.EnumPullUnmarshal( - service.cimMessages.ConcreteDependency.Enumerate, - service.cimMessages.ConcreteDependency.Pull, - &pullRspEnv, - ) - if rc != utils.Success { - return items, rc - } - for { - for i := range pullRspEnv.Body.PullResponse.Items { - items = append(items, pullRspEnv.Body.PullResponse.Items[i]) - } - enumContext := pullRspEnv.Body.PullResponse.EnumerationContext - if enumContext == "" { - break - } - pullRspEnv = concrete.DependencyPullResponseEnvelope{} - rc = service.PostAndUnmarshal( - service.cimMessages.ConcreteDependency.Pull(enumContext), - &pullRspEnv, - ) - if rc != utils.Success { - return items, rc +func checkHandleExists(handles map[string]string, cert string) string { + // get the handle from the map + for k, v := range handles { + if v == cert { + return k } } - return items, utils.Success + return "" } diff --git a/internal/local/utils_test.go b/internal/local/utils_test.go index e18c1d3e..70e8c4e4 100644 --- a/internal/local/utils_test.go +++ b/internal/local/utils_test.go @@ -1,404 +1,32 @@ package local import ( - "regexp" - "rpc/internal/flags" - "rpc/pkg/utils" - "testing" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/amt/publicprivate" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/pkg/common" - "github.com/stretchr/testify/assert" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" ) -var mpsCert = publickey.PublicKeyCertificate{ - ElementName: "Intel(r) AMT Certificate", - InstanceID: "Intel(r) AMT Certificate: Handle: 0", - X509Certificate: `MIIEkzCCA3ugAwIBAgIUL3WtF7HfMKxQOHcZy65Z0tsSoLwwDQYJKoZIhvc`, - TrustedRootCertficate: true, - Issuer: "C=unknown,O=unknown,CN=MPSRoot-5bb511", - Subject: "C=unknown,O=unknown,CN=MPSRoot-5bb511", - ReadOnlyCertificate: true, -} -var caCert = publickey.PublicKeyCertificate{ - ElementName: "Intel(r) AMT Certificate", - InstanceID: "Intel(r) AMT Certificate: Handle: 1", - X509Certificate: `CERTHANDLE1MIIEkzCCA3ugAwIBAgIUL3WtF7HfMKxQOHcZy65Z0tsSoLwwDQYJKoZIhvc`, - TrustedRootCertficate: true, - Issuer: `C=US,S=Arizona,L=Chandler,CN=Unit Tests Are Us`, - Subject: `C=US,S=Arizona,L=Chandler,CN=Unit Test CA Root Certificate`, -} -var clientCert = publickey.PublicKeyCertificate{ - ElementName: "Intel(r) AMT Certificate", - InstanceID: "Intel(r) AMT Certificate: Handle: 3", - X509Certificate: `CERTHANDLE2AwIBAgIUBgF0PsmOxA/KJVDCcbW+n5IbemgwDQYJKoZIhvc`, - TrustedRootCertficate: false, - Issuer: `C=US,S=Arizona,L=Chandler,CN=Unit Tests Are Us`, - Subject: `C=US,S=Arizona,L=Chandler,CN=Unit Test Client Certificate`, - ReadOnlyCertificate: true, -} -var keyPair01 = publicprivate.PublicPrivateKeyPair{ - ElementName: "Intel(r) AMT Key", - InstanceID: "Intel(r) AMT Key: Handle: 0", - DERKey: `MIIBCgKCAQEA37Xwr/oVLFftw+2wkmwdzGaufBnLiwJCXwYrWLMld1+7Ve6DghlFPa+Mr`, -} - -func runGetPublicKeyCertTest(t *testing.T, expectedCode utils.ReturnCode, responsers ResponseFuncArray) { - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, responsers) - var certs []publickey.PublicKeyCertificate - rc := lps.GetPublicKeyCerts(&certs) - assert.Equal(t, expectedCode, rc) - assert.Empty(t, certs) -} - -func TestGetPublicKeyCerts(t *testing.T) { - enumRsp := common.EnumerationResponse{} - t.Run("expect WSMANMessageError for Enumerate call", func(t *testing.T) { - r := ResponseFuncArray{respondServerErrFunc()} - runGetPublicKeyCertTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect UnmarshalMessageFailed for Enumerate call", func(t *testing.T) { - r := ResponseFuncArray{respondBadXmlFunc(t)} - runGetPublicKeyCertTest(t, utils.UnmarshalMessageFailed, r) - }) - t.Run("expect WSMANMessageError for Pull call", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondServerErrFunc(), - } - runGetPublicKeyCertTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect UnmarshalMessageFailed for Pull call", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondBadXmlFunc(t), - } - runGetPublicKeyCertTest(t, utils.UnmarshalMessageFailed, r) - }) - t.Run("expect Success for happy path (with no certs)", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondMsgFunc(t, publickey.PullResponseEnvelope{}), - } - runGetPublicKeyCertTest(t, utils.Success, r) - }) -} - -func runGetPublicPrivateKeyPairsTest(t *testing.T, expectedCode utils.ReturnCode, responsers ResponseFuncArray) { - f := &flags.Flags{} - lps := setupWsmanResponses(t, f, responsers) - var keyPairs []publicprivate.PublicPrivateKeyPair - rc := lps.GetPublicPrivateKeyPairs(&keyPairs) - assert.Equal(t, expectedCode, rc) - assert.Empty(t, keyPairs) -} - -func TestGetPublicPrivateKeyPairs(t *testing.T) { - enumRsp := common.EnumerationResponse{} - t.Run("expect WSMANMessageError for Enumerate call", func(t *testing.T) { - r := ResponseFuncArray{respondServerErrFunc()} - runGetPublicPrivateKeyPairsTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect UnmarshalMessageFailed for Enumerate call", func(t *testing.T) { - r := ResponseFuncArray{respondBadXmlFunc(t)} - runGetPublicPrivateKeyPairsTest(t, utils.UnmarshalMessageFailed, r) - }) - t.Run("expect WSMANMessageError for Pull call", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondServerErrFunc(), - } - runGetPublicPrivateKeyPairsTest(t, utils.WSMANMessageError, r) - }) - t.Run("expect UnmarshalMessageFailed for Pull call", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondBadXmlFunc(t), - } - runGetPublicPrivateKeyPairsTest(t, utils.UnmarshalMessageFailed, r) - }) - t.Run("expect Success for happy path (with no certs)", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, enumRsp), - respondMsgFunc(t, publicprivate.PullResponseEnvelope{}), - } - runGetPublicPrivateKeyPairsTest(t, utils.Success, r) - }) +var mpsCert = publickey.PublicKeyCertificateResponse{ + ElementName: "Intel(r) AMT Certificate", + InstanceID: "Intel(r) AMT Certificate: Handle: 0", + X509Certificate: `MIIEkzCCA3ugAwIBAgIUL3WtF7HfMKxQOHcZy65Z0tsSoLwwDQYJKoZIhvc`, + TrustedRootCertificate: true, + Issuer: "C=unknown,O=unknown,CN=MPSRoot-5bb511", + Subject: "C=unknown,O=unknown,CN=MPSRoot-5bb511", + ReadOnlyCertificate: true, +} +var caCert = publickey.PublicKeyCertificateResponse{ + ElementName: "Intel(r) AMT Certificate", + InstanceID: "Intel(r) AMT Certificate: Handle: 1", + X509Certificate: `CERTHANDLE1MIIEkzCCA3ugAwIBAgIUL3WtF7HfMKxQOHcZy65Z0tsSoLwwDQYJKoZIhvc`, + TrustedRootCertificate: true, + Issuer: `C=US,S=Arizona,L=Chandler,CN=Unit Tests Are Us`, + Subject: `C=US,S=Arizona,L=Chandler,CN=Unit Test CA Root Certificate`, +} +var clientCert = publickey.PublicKeyCertificateResponse{ + ElementName: "Intel(r) AMT Certificate", + InstanceID: "Intel(r) AMT Certificate: Handle: 3", + X509Certificate: `CERTHANDLE2AwIBAgIUBgF0PsmOxA/KJVDCcbW+n5IbemgwDQYJKoZIhvc`, + TrustedRootCertificate: false, + Issuer: `C=US,S=Arizona,L=Chandler,CN=Unit Tests Are Us`, + Subject: `C=US,S=Arizona,L=Chandler,CN=Unit Test Client Certificate`, + ReadOnlyCertificate: true, } - -func TestDeletePublicPrivateKeyPair(t *testing.T) { - f := &flags.Flags{} - t.Run("expect Success for happy path", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, "response does not matter"), - } - lps := setupWsmanResponses(t, f, r) - rc := lps.DeletePublicPrivateKeyPair("some instance Id") - assert.Equal(t, utils.Success, rc) - }) - t.Run("expect DeleteWifiConfigFailed error", func(t *testing.T) { - r := ResponseFuncArray{ - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, r) - rc := lps.DeletePublicPrivateKeyPair("some instance Id") - assert.Equal(t, utils.DeleteWifiConfigFailed, rc) - }) -} - -func TestDeletePublicCert(t *testing.T) { - f := &flags.Flags{} - t.Run("expect Success for happy path", func(t *testing.T) { - r := ResponseFuncArray{ - respondStringFunc(t, "response does not matter"), - } - lps := setupWsmanResponses(t, f, r) - rc := lps.DeletePublicCert("some instance Id") - assert.Equal(t, utils.Success, rc) - }) - t.Run("expect DeleteWifiConfigFailed error", func(t *testing.T) { - r := ResponseFuncArray{ - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, r) - rc := lps.DeletePublicCert("some instance Id") - assert.Equal(t, utils.DeleteWifiConfigFailed, rc) - }) -} - -func TestGetCredentialRelationships(t *testing.T) { - f := &flags.Flags{} - t.Run("expect Success for happy path", func(t *testing.T) { - re := regexp.MustCompile(enumCtxElement) - pullRspNoEnumCtx := re.ReplaceAllString(credCtxPullRspString, endOfSequenceElement) - r := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondStringFunc(t, credCtxPullRspString), - respondStringFunc(t, pullRspNoEnumCtx), - } - lps := setupWsmanResponses(t, f, r) - credentials, rc := lps.GetCredentialRelationships() - assert.Equal(t, utils.Success, rc) - assert.Equal(t, 4, len(credentials)) - }) - t.Run("expect WSMANMessageError on second pull", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondStringFunc(t, credCtxPullRspString), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, r) - credentials, rc := lps.GetCredentialRelationships() - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Equal(t, 2, len(credentials)) - }) - t.Run("expect WSMANMessageError on EnumPullUnmarshal() error", func(t *testing.T) { - r := ResponseFuncArray{ - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, r) - credentials, rc := lps.GetCredentialRelationships() - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Empty(t, credentials) - }) -} - -func TestGetConcreteDependencies(t *testing.T) { - f := &flags.Flags{} - t.Run("expect Success for happy path", func(t *testing.T) { - re := regexp.MustCompile(enumCtxElement) - pullRspNoEnumCtx := re.ReplaceAllString(concreteDependencyPullRspString, endOfSequenceElement) - r := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondStringFunc(t, concreteDependencyPullRspString), - respondStringFunc(t, pullRspNoEnumCtx), - } - lps := setupWsmanResponses(t, f, r) - credentials, rc := lps.GetConcreteDependencies() - assert.Equal(t, utils.Success, rc) - assert.Equal(t, 6, len(credentials)) - }) - t.Run("expect WSMANMessageError on second pull", func(t *testing.T) { - r := ResponseFuncArray{ - respondMsgFunc(t, common.EnumerationResponse{}), - respondStringFunc(t, concreteDependencyPullRspString), - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, r) - credentials, rc := lps.GetConcreteDependencies() - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Equal(t, 3, len(credentials)) - }) - t.Run("expect WSMANMessageError on EnumPullUnmarshal() error", func(t *testing.T) { - r := ResponseFuncArray{ - respondServerErrFunc(), - } - lps := setupWsmanResponses(t, f, r) - credentials, rc := lps.GetConcreteDependencies() - assert.Equal(t, utils.WSMANMessageError, rc) - assert.Empty(t, credentials) - }) -} - -var enumCtxElement = `84730100-0000-0000-0000-000000000000` -var endOfSequenceElement = `` - -var credCtxPullRspString = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 3 - http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse - uuid:00000000-8086-8086-8086-0000000472D9 - http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_CredentialContext - - - ` + - enumCtxElement + - ` - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate - - Intel(r) AMT Certificate: Handle: 2 - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_IEEE8021xSettings - - Intel(r) AMT:IEEE 802.1x Settings wifi8021x - - - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate - - Intel(r) AMT Certificate: Handle: 1 - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_IEEE8021xSettings - - Intel(r) AMT:IEEE 802.1x Settings wifi8021x - - - - - - - - -` - -var concreteDependencyPullRspString = ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - 5 - http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse - uuid:00000000-8086-8086-8086-0000000473A3 - http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ConcreteDependency - - - -` + enumCtxElement + ` - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AssetTableService - - AMT_AssetTableService - Intel(r) AMT Asset Table Service - CIM_ComputerSystem - Intel(r) AMT - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AssetTable - - 1 - 131 - - - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate - - Intel(r) AMT Certificate: Handle: 1 - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPair - - Intel(r) AMT Key: Handle: 0 - - - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate - - Intel(r) AMT Certificate: Handle: 1 - - - - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SOME_UNHANDLED_RESOURCE_FOR_TESTING - - Intel(r) AMT Key: Handle: 0 - - - - - - - - -` diff --git a/internal/local/version.go b/internal/local/version.go index 825b2926..e3d9fd30 100644 --- a/internal/local/version.go +++ b/internal/local/version.go @@ -2,40 +2,34 @@ package local import ( "encoding/json" + "fmt" "rpc/pkg/utils" "strings" ) -func (service *ProvisioningService) DisplayVersion() utils.ReturnCode { - output := "" - - if !service.flags.JsonOutput { - output += strings.ToUpper(utils.ProjectName) + "\n" - output += "Version " + utils.ProjectVersion + "\n" - output += "Protocol " + utils.ProtocolVersion + "\n" - - println(output) - } +type VersionInfo struct { + App string `json:"app"` + Version string `json:"version"` + Protocol string `json:"protocol"` +} +func (service *ProvisioningService) DisplayVersion() (err error) { if service.flags.JsonOutput { - dataStruct := make(map[string]interface{}) - - projectName := strings.ToUpper(utils.ProjectName) - dataStruct["app"] = projectName - - projectVersion := utils.ProjectVersion - dataStruct["version"] = projectVersion - - protocolVersion := utils.ProtocolVersion - dataStruct["protocol"] = protocolVersion - - outBytes, err := json.MarshalIndent(dataStruct, "", " ") - output = string(outBytes) + info := VersionInfo{ + App: strings.ToUpper(utils.ProjectName), + Version: utils.ProjectVersion, + Protocol: utils.ProtocolVersion, + } + outBytes, err := json.MarshalIndent(info, "", " ") if err != nil { - output = err.Error() + return err } - println(output) + println(string(outBytes)) + } else { + fmt.Println(strings.ToUpper(utils.ProjectName)) + fmt.Println("Version", utils.ProjectVersion) + fmt.Println("Protocol", utils.ProtocolVersion) } - return utils.Success + return nil } diff --git a/internal/local/version_test.go b/internal/local/version_test.go index 42cedc80..4027240c 100644 --- a/internal/local/version_test.go +++ b/internal/local/version_test.go @@ -14,15 +14,17 @@ func TestDisplayVersion(t *testing.T) { t.Run("should return Success", func(t *testing.T) { lps := setupService(f) - rc := lps.DisplayVersion() - assert.Equal(t, utils.Success, rc) + err := lps.DisplayVersion() + assert.NoError(t, err) + assert.Equal(t, nil, err) }) t.Run("should return Success with json output", func(t *testing.T) { f.JsonOutput = true lps := setupService(f) - rc := lps.DisplayVersion() - assert.Equal(t, utils.Success, rc) + err := lps.DisplayVersion() + assert.NoError(t, err) + assert.Equal(t, nil, err) f.JsonOutput = false }) diff --git a/internal/local/windows.go b/internal/local/windows.go index c7b3e9f4..6f3cb4df 100644 --- a/internal/local/windows.go +++ b/internal/local/windows.go @@ -14,7 +14,7 @@ import ( log "github.com/sirupsen/logrus" ) -func (n *RealOSNetworker) RenewDHCPLease() utils.ReturnCode { +func (n *RealOSNetworker) RenewDHCPLease() error { log.Debug("renewing DHCP lease") cmd := exec.Command("ipconfig", "/renew") err := cmd.Run() @@ -22,5 +22,5 @@ func (n *RealOSNetworker) RenewDHCPLease() utils.ReturnCode { log.Error("Error renewing DHCP lease:", err) return utils.NetworkConfigurationFailed } - return utils.Success + return nil } diff --git a/internal/rps/message_test.go b/internal/rps/message_test.go index 6d91f894..d57981d2 100644 --- a/internal/rps/message_test.go +++ b/internal/rps/message_test.go @@ -27,8 +27,8 @@ var controlMode int = 0 var err error = nil var mode int = 0 -func (c MockAMT) Initialize() (utils.ReturnCode, error) { - return utils.Success, nil +func (c MockAMT) Initialize() error { + return nil } func (c MockAMT) GetVersionDataFromME(key string, amtTimeout time.Duration) (string, error) { return "Version", nil diff --git a/internal/rps/rps.go b/internal/rps/rps.go index 04224768..006811cd 100644 --- a/internal/rps/rps.go +++ b/internal/rps/rps.go @@ -24,8 +24,7 @@ type AMTActivationServer struct { flags *flags.Flags } -func ExecuteCommand(flags *flags.Flags) utils.ReturnCode { - rc := utils.Success +func ExecuteCommand(flags *flags.Flags) error { setCommandMethod(flags) startMessage, err := PrepareInitialMessage(flags) @@ -44,7 +43,7 @@ func ExecuteCommand(flags *flags.Flags) utils.ReturnCode { executor.MakeItSo(startMessage) - return rc + return nil } func setCommandMethod(flags *flags.Flags) { diff --git a/internal/rps/rps_test.go b/internal/rps/rps_test.go index 5872c162..c0316bd1 100644 --- a/internal/rps/rps_test.go +++ b/internal/rps/rps_test.go @@ -55,7 +55,7 @@ func TestExecuteCommand(t *testing.T) { f.Command = utils.CommandActivate f.Profile = "profile01" rc := ExecuteCommand(f) - assert.NotEqual(t, utils.Success, rc) + assert.NotEqual(t, nil, rc) } func TestSetCommandMethodActivate(t *testing.T) { diff --git a/pkg/utils/constants.go b/pkg/utils/constants.go index ff12e72b..13b619fa 100644 --- a/pkg/utils/constants.go +++ b/pkg/utils/constants.go @@ -32,6 +32,7 @@ const ( SubCommandAddWifiSettings = "addwifisettings" SubCommandEnableWifiPort = "enablewifiport" + SubCommandSetMEBx = "mebx" SubCommandConfigureTLS = "tls" SubCommandChangePassword = "changepassword" SubCommandSyncDeviceInfo = "syncdeviceinfo" @@ -41,70 +42,73 @@ const ( // Return Codes Success ReturnCode = 0 - - // (1-99) General Errors - - // (1-19) Basic errors outside of Open AMT Cloud Toolkit - IncorrectPermissions ReturnCode = 1 // (not admin or sudo) - HECIDriverNotDetected ReturnCode = 2 - AmtNotDetected ReturnCode = 3 - AmtNotReady ReturnCode = 4 - - // (20-69) Input errors to RPC - MissingOrIncorrectURL ReturnCode = 20 - MissingOrIncorrectProfile ReturnCode = 21 - ServerCerificateVerificationFailed ReturnCode = 22 - MissingOrIncorrectPassword ReturnCode = 23 - MissingDNSSuffix ReturnCode = 24 - MissingHostname ReturnCode = 25 - MissingProxyAddressAndPort ReturnCode = 26 - MissingOrIncorrectStaticIP ReturnCode = 27 - IncorrectCommandLineParameters ReturnCode = 28 - MissingOrIncorrectNetworkMask ReturnCode = 29 - MissingOrIncorrectGateway ReturnCode = 30 - MissingOrIncorrectPrimaryDNS ReturnCode = 31 - MissingOrIncorrectSecondaryDNS ReturnCode = 32 - InvalidParameterCombination ReturnCode = 33 - FailedReadingConfiguration ReturnCode = 34 - MissingOrInvalidConfiguration ReturnCode = 35 - InvalidUserInput ReturnCode = 36 - InvalidUUID ReturnCode = 37 - - // (70-99) Connection Errors - RPSAuthenticationFailed ReturnCode = 70 - AMTConnectionFailed ReturnCode = 71 - OSNetworkInterfacesLookupFailed ReturnCode = 72 - - // (100-149) Activation, and configuration errors - AMTAuthenticationFailed ReturnCode = 100 - WSMANMessageError ReturnCode = 101 - ActivationFailed ReturnCode = 102 - NetworkConfigurationFailed ReturnCode = 103 - CIRAConfigurationFailed ReturnCode = 104 - TLSConfigurationFailed ReturnCode = 105 - WiFiConfigurationFailed ReturnCode = 106 - AMTFeaturesConfigurationFailed ReturnCode = 107 - Ieee8021xConfigurationFailed ReturnCode = 108 - UnableToDeactivate ReturnCode = 109 - DeactivationFailed ReturnCode = 110 - UnableToActivate ReturnCode = 111 - WifiConfigurationWithWarnings ReturnCode = 112 - UnmarshalMessageFailed ReturnCode = 113 - DeleteWifiConfigFailed ReturnCode = 114 - MissingOrIncorrectWifiProfileName ReturnCode = 116 - MissingIeee8021xConfiguration ReturnCode = 117 - - // (150-199) Maintenance Errors - SyncClockFailed ReturnCode = 150 - SyncHostnameFailed ReturnCode = 151 - SyncIpFailed ReturnCode = 152 - ChangePasswordFailed ReturnCode = 153 - SyncDeviceInfoFailed ReturnCode = 154 - - // (200-299) KPMU - - // (300-399) Redfish - - // (1000 - 3000) Amt PT Status Code Block - AmtPtStatusCodeBase ReturnCode = 1000 ) + +// (1-99) General Errors + +// (1-19) Basic errors outside of Open AMT Cloud Toolkit +var IncorrectPermissions = CustomError{Code: 1, Message: "IncorrectPermissions"} +var HECIDriverNotDetected = CustomError{Code: 2, Message: "HECIDriverNotDetected"} +var AmtNotDetected = CustomError{Code: 3, Message: "AmtNotDetected"} +var AmtNotReady = CustomError{Code: 4, Message: "AmtNotReady"} +var GenericFailure = CustomError{Code: 10, Message: "GenericFailure"} + +// (20-69) Input errors to RPC +var MissingOrIncorrectURL = CustomError{Code: 20, Message: "MissingOrIncorrectURL"} +var MissingOrIncorrectProfile = CustomError{Code: 21, Message: "MissingOrIncorrectProfile"} +var ServerCerificateVerificationFailed = CustomError{Code: 22, Message: "ServerCerificateVerificationFailed"} +var MissingOrIncorrectPassword = CustomError{Code: 23, Message: "MissingOrIncorrectPassword"} +var MissingDNSSuffix = CustomError{Code: 24, Message: "MissingDNSSuffix"} +var MissingHostname = CustomError{Code: 25, Message: "MissingHostname"} +var MissingProxyAddressAndPort = CustomError{Code: 26, Message: "MissingProxyAddressAndPort"} +var MissingOrIncorrectStaticIP = CustomError{Code: 27, Message: "MissingOrIncorrectStaticIP"} +var IncorrectCommandLineParameters = CustomError{Code: 28, Message: "IncorrectCommandLineParameters"} +var MissingOrIncorrectNetworkMask = CustomError{Code: 29, Message: "MissingOrIncorrectNetworkMask"} +var MissingOrIncorrectGateway = CustomError{Code: 30, Message: "MissingOrIncorrectGateway"} +var MissingOrIncorrectPrimaryDNS = CustomError{Code: 31, Message: "MissingOrIncorrectPrimaryDNS"} +var MissingOrIncorrectSecondaryDNS = CustomError{Code: 32, Message: "MissingOrIncorrectSecondaryDNS"} +var InvalidParameterCombination = CustomError{Code: 33, Message: "InvalidParameterCombination"} +var FailedReadingConfiguration = CustomError{Code: 34, Message: "FailedReadingConfiguration"} +var MissingOrInvalidConfiguration = CustomError{Code: 35, Message: "MissingOrInvalidConfiguration"} + +var InvalidUserInput = CustomError{Code: 36, Message: "InvalidUserInput"} +var InvalidUUID = CustomError{Code: 37, Message: "InvalidUUID"} + +// (70-99) Connection Errors +var RPSAuthenticationFailed = CustomError{Code: 70, Message: "RPSAuthenticationFailed"} +var AMTConnectionFailed = CustomError{Code: 71, Message: "AMTConnectionFailed"} +var OSNetworkInterfacesLookupFailed = CustomError{Code: 72, Message: "OSNetworkInterfacesLookupFailed"} + +// (100-149) Activation, and configuration errors +var AMTAuthenticationFailed = CustomError{Code: 100, Message: "AMTAuthenticationFailed"} +var WSMANMessageError = CustomError{Code: 101, Message: "WSMANMessageError"} +var ActivationFailed = CustomError{Code: 102, Message: "ActivationFailed"} +var NetworkConfigurationFailed = CustomError{Code: 103, Message: "NetworkConfigurationFailed"} +var CIRAConfigurationFailed = CustomError{Code: 104, Message: "CIRAConfigurationFailed"} +var TLSConfigurationFailed = CustomError{Code: 105, Message: "TLSConfigurationFailed"} +var WiFiConfigurationFailed = CustomError{Code: 106, Message: "WiFiConfigurationFailed"} +var AMTFeaturesConfigurationFailed = CustomError{Code: 107, Message: "AMTFeaturesConfigurationFailed"} +var Ieee8021xConfigurationFailed = CustomError{Code: 108, Message: "Ieee8021xConfigurationFailed"} +var UnableToDeactivate = CustomError{Code: 109, Message: "UnableToDeactivate"} +var DeactivationFailed = CustomError{Code: 110, Message: "DeactivationFailed"} +var UnableToActivate = CustomError{Code: 111, Message: "UnableToActivate"} +var WifiConfigurationWithWarnings = CustomError{Code: 112, Message: "WifiConfigurationWithWarnings"} +var UnmarshalMessageFailed = CustomError{Code: 113, Message: "UnmarshalMessageFailed"} +var DeleteWifiConfigFailed = CustomError{Code: 114, Message: "DeleteWifiConfigFailed"} +var MissingOrIncorrectWifiProfileName = CustomError{Code: 116, Message: "MissingOrIncorrectWifiProfileName"} +var MissingIeee8021xConfiguration = CustomError{Code: 117, Message: "MissingIeee8021xConfiguration"} +var SetMEBXPasswordFailed = CustomError{Code: 118, Message: "SetMEBXPasswordFailed"} + +// (150-199) Maintenance Errors +var SyncClockFailed = CustomError{Code: 150, Message: "SyncClockFailed"} +var SyncHostnameFailed = CustomError{Code: 151, Message: "SyncHostnameFailed"} +var SyncIpFailed = CustomError{Code: 152, Message: "SyncIpFailed"} +var ChangePasswordFailed = CustomError{Code: 153, Message: "ChangePasswordFailed"} +var SyncDeviceInfoFailed = CustomError{Code: 154, Message: "SyncDeviceInfoFailed"} + +// (200-299) KPMU + +// (300-399) Redfish + +// (1000 - 3000) Amt PT Status Code Block +var AmtPtStatusCodeBase = CustomError{Code: 1000, Message: "AmtPtStatusCodeBase"} diff --git a/pkg/utils/error.go b/pkg/utils/error.go new file mode 100644 index 00000000..42cc23da --- /dev/null +++ b/pkg/utils/error.go @@ -0,0 +1,14 @@ +package utils + +import "fmt" + +// CustomError defines a custom error type with an integer code and a message. +type CustomError struct { + Code int + Message string +} + +// Error implements the error interface for CustomError. +func (e CustomError) Error() string { + return fmt.Sprintf("Error %d: %s", e.Code, e.Message) +} diff --git a/samples/dotnet/dotnet.sln b/samples/dotnet/dotnet.sln new file mode 100644 index 00000000..2f384735 --- /dev/null +++ b/samples/dotnet/dotnet.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "client", "client.csproj", "{2DC95FF2-6883-42E5-AE2F-B51D9E1AC91E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2DC95FF2-6883-42E5-AE2F-B51D9E1AC91E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DC95FF2-6883-42E5-AE2F-B51D9E1AC91E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DC95FF2-6883-42E5-AE2F-B51D9E1AC91E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DC95FF2-6883-42E5-AE2F-B51D9E1AC91E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D126AD16-B394-4366-942C-2D2A938FFAED} + EndGlobalSection +EndGlobal