// 2020 Rackspace, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package ipaudit import ( "fmt" "log" "os" "strconv" "time" "github.rackspace.com/gorax/clients/migrationAPI" "github.com/360EntSecGroup-Skylar/excelize" "github.com/jedib0t/go-pretty/v6/table" "github.com/jokelyo/argparse" "github.com/sirupsen/logrus" "github.rackspace.com/DCM/gomigrate/core" "github.rackspace.com/DCM/gomigrate/shared" "github.rackspace.com/gorax/gokeys" ) const httpTimeout = 180 * time.Second var ( argMoveGroup *[]string argAccount *[]string csvFlag *bool ) // SubPlugin function will return a argparse.Command type back to the parent parser // nolint:typecheck func SubPlugin(p *argparse.Command) core.Plugin { // Create a command and argument for the ip audit cmd := p.NewCommand("ip_audit", "Audits migration IPs") argMoveGroup = shared.ArgMoveGroups(cmd) argAccount = shared.ArgAccounts(cmd) csvFlag = shared.ArgFlag(cmd, "csv", "Create a CSV results file") return core.Plugin{CMD: cmd, Func: pluginFunc} } // pluginFunc function will prompt for a move group, device, or account // and will run the IP Audit API call with that information // It should then run the IP audit and return audit data func pluginFunc(cfg gokeys.Settings) { // Pull an identity token from the users gokeys keychain identKey, err := cfg.Identity(false) if err != nil { log.Fatalf("gokeys.Identity:%s", err) } // Pull a core token from the users gokeys keychain coreKey, err := cfg.Core(false) if err != nil { log.Fatalf("gokeys.Core:%s", err) } if len(*argMoveGroup) == 0 && len(*argAccount) == 0 { fmt.Println("Must specify a move-group or account") } // Select which arg will be passed to the API - move group, device or account c := migrationAPI.New(identKey.Password, false) results := make([]migrationAPI.AuditResponse, 0) switch { case len(*argMoveGroup) != 0: mg := *argMoveGroup for _, val := range mg { resp, err := c.AuditMigrationIPs( shared.GetCollection(val), migrationAPI.NewOptions().SetHTTPTimeout(httpTimeout).SetMoveGroup(val), ) if err != nil { logrus.Fatal(err) } results = append(results, *resp) pPrint(resp) } case len(*argAccount) != 0: accounts := *argAccount collection := shared.GetAccountCollection(accounts[0], coreKey.Password) for _, val := range accounts { acct, err := strconv.Atoi(val) if err != nil { logrus.Fatal(err) } resp, err := c.AuditMigrationIPs( collection, migrationAPI.NewOptions().SetHTTPTimeout(httpTimeout).SetAccount(acct), ) if err != nil { logrus.Fatal(err) } results = append(results, *resp) pPrint(resp) } } if *csvFlag { if err := csv(results, "IP_Audit", "Sheet1"); err != nil { logrus.Error(err) } } } //// pPrint func will take a structured type of response data and render a table //// output to stdout. // func pPrint(data *migrationAPI.AuditResponse) { t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{"Device ID", "Account", "Team Name", "Current IP", "Migration IP", "Reason"}) for _, d := range data.Data { t.AppendRow(table.Row{d.ID, d.AccountID, d.TeamName, d.Current, d.Destination, d.Reason}) } t.SortBy([]table.SortBy{{Name: "Account", Mode: table.AscNumeric}}) t.Render() } // Function to create a CSV of data on demand func csv(results []migrationAPI.AuditResponse, fileName, sheetName string) error { file := excelize.NewFile() index := file.NewSheet(sheetName) file.SetCellValue(sheetName, "A1", "Device ID") file.SetCellValue(sheetName, "B1", "Account Number") file.SetCellValue(sheetName, "C1", "Team Name") file.SetCellValue(sheetName, "D1", "Current IP") file.SetCellValue(sheetName, "E1", "Migration IP") file.SetCellValue(sheetName, "F1", "Reason") row := 2 for _, r := range results { for _, v := range r.Data { file.SetCellValue(sheetName, fmt.Sprintf("A%d", row), v.ID) file.SetCellValue(sheetName, fmt.Sprintf("B%d", row), v.AccountID) file.SetCellValue(sheetName, fmt.Sprintf("C%d", row), v.TeamName) file.SetCellValue(sheetName, fmt.Sprintf("D%d", row), v.Current) file.SetCellValue(sheetName, fmt.Sprintf("E%d", row), v.Destination) file.SetCellValue(sheetName, fmt.Sprintf("F%d", row), v.Reason) row = row + 1 } } file.SetActiveSheet(index) if err := file.SaveAs(fmt.Sprintf("%s.xlsx", fileName)); err != nil { return err } logrus.Infof("csv file written to %s", fmt.Sprintf("%s.xlsx", fileName)) return nil }