package asa import ( "encoding/json" "errors" "fmt" "regexp" "strings" "github.com/sirupsen/logrus" "github.rackspace.com/gorax/asaapi/pkg/asaModels" "github.rackspace.com/gorax/asaapi/pkg/asaModels/captures" "github.rackspace.com/gorax/asaapi/pkg/asaModels/modules" ) type sshError struct { Error string `json:"error"` } // GatherMode : Alias for ShowMode to provide a similar name to the other father functions. func (a *ASA) GatherMode(ssh bool) error { return a.ShowMode(ssh) } func (a *ASA) ShowCap(ssh bool) (caps captures.Captures, err error) { var res string if ssh { resp, err := a.sshClient.PostCommand("show cap", "# ", 15) if err != nil { return caps, err } res = *resp.Response } else { res, err = a.httpClient.GetCommand("show cap") if err != nil { return caps, err } } if err := caps.Parse(res); err != nil { return caps, err } return caps, nil } // ShowMode : Performs a 'show mode' command on the device and populates the ASA.Mode variable func (a *ASA) ShowMode(ssh bool) error { cmd := "show mode" var res string var err error if ssh { resp, err := a.sshClient.PostCommand(cmd, "# ", 15) if err != nil { return fmt.Errorf("error sending ssh command to device: %v", err) } res = *resp.Response } else { res, err = a.httpClient.GetCommand(cmd) if err != nil { return err } } r, err := regexp.Compile(`Security context mode: (\S+)`) if err != nil { return err } f := r.FindStringSubmatch(res) if len(f) < 1 { return fmt.Errorf("unable to find expected output from show mode command; raw response: %s", res) } a.Mode = f[1] return nil } // GatherModules : Executes a 'show module all' command on the device and populates the ASA structure with the parsed results func (a *ASA) GatherModules(mod string, ssh bool) error { cmd := "show module all" if mod != "" { cmd = fmt.Sprintf("show module %s", mod) } var res string var err error if ssh { resp, err := a.sshClient.PostCommand(cmd, "# ", 15) if err != nil { return fmt.Errorf("error sending ssh command to device: %v", err) } res = *resp.Response } else { res, err = a.httpClient.GetCommand(cmd) if err != nil { return err } } dm, err := modules.Parse(res, a.log) if err != nil { return err } a.Modules = dm return nil } func (a *ASA) BackupStartup_HTTP(destination string) error { cmd, err := a.httpClient.GetCommand(fmt.Sprintf("copy /noconfirm startup-config disk0:/%s", destination)) if err != nil { return err } if !copyFileRE.MatchString(cmd) { return fmt.Errorf("Unable to match copy success string, found: %s", cmd) } return nil } func (a *ASA) BootList_HTTP() error { cmd, err := a.httpClient.GetCommand("show run boot") if err != nil { return err } var bs asaModels.BootSystem bs.Parse(cmd) a.Config.BootList = bs.BootFiles return nil } func (a *ASA) DiskInfo_HTTP(disk string) (*asaModels.Disk, error) { cmd, err := a.httpClient.GetCommand(fmt.Sprintf("dir %s", disk)) if err != nil { return nil, err } var d asaModels.Disk d.Parse(cmd) return &d, nil } func (a *ASA) GetAAAConfig_HTTP() error { cmd, err := a.httpClient.GetCommand("show run aaa") if err != nil { return err } var ac asaModels.AAAConfig ac.Parse(cmd) a.Config.AAAConfig = &ac return nil } func (a *ASA) GetAAAServers_HTTP() error { cmd, err := a.httpClient.GetCommand("show run aaa-server") if err != nil { return err } var aaa asaModels.AAAGroups aaa.Parse(cmd) a.Config.AAAServers = &aaa cmd, err = a.httpClient.GetCommand("more system:running") if err != nil { return err } if err := aaa.ParseACSKeys(cmd); err != nil { return err } return nil } func (a *ASA) GetAccessGroups_HTTP() error { cmd, err := a.httpClient.GetCommand("show run access-group") if err != nil { return err } ag := asaModels.ParseAccessGroups(cmd) a.Config.AccessGroups = ag.AccessGroups return nil } func (a *ASA) GetAccessList_HTTP(ac string) error { cmd, err := a.httpClient.GetCommand(fmt.Sprintf("show run access-list %s", ac)) if err != nil { return err } a.log.WithFields(logrus.Fields{ "Response": cmd, }).Debug() var acl asaModels.AccessLists acl.Parse(cmd) a.Config.AccessLists = acl.AccessLists return nil } func (a *ASA) GetAccessLists_HTTP() error { cmd, err := a.httpClient.GetCommand("show run access-list") if err != nil { return err } a.log.WithFields(logrus.Fields{ "Response": cmd, }).Debug() var acl asaModels.AccessLists acl.Parse(cmd) a.Config.AccessLists = acl.AccessLists return nil } func (a *ASA) GetArp_HTTP() error { cmd, err := a.httpClient.GetCommand("show arp") if err != nil { return err } var arp asaModels.ARPCache arp.Parse(cmd) a.Status.ARP = arp.ARPList return nil } func (a *ASA) GetBanner_HTTP() error { var blank []string a.Config.Banner = blank cmd, err := a.httpClient.GetCommand("show run banner") if err != nil { return err } banner := regexp.MustCompile(`banner motd (.*)\n`).FindAllStringSubmatch(cmd, -1) if len(banner) > 0 { for _, line := range banner { a.Config.Banner = append(a.Config.Banner, line[1]) } } if a.Config.Banner == nil { a.Config.Banner = []string{} } return nil } // GetBootVarHTTP method will parse and return a type of BootVar that contains the data from the // 'show bootvar' command on a Cisco ASA func (a *ASA) GetBootVarHTTP() (bv asaModels.BootVar, err error) { cmd, err := a.httpClient.GetCommand("show bootvar") if err != nil { return } bv = asaModels.ParseBootVar(cmd) return } func (a *ASA) GetCertPkcs12_HTTP() error { if a.Config.SSLConfig == nil { if err := a.GetSSLConfig(); err != nil { return err } } if len(a.Config.SSLConfig.Trustpoints) == 0 { return nil } var res []string for _, tp := range a.Config.SSLConfig.Trustpoints { cmd, err := a.httpClient.GetCommand(fmt.Sprintf("crypto ca export %s pkcs12 rack", *tp.Name)) if err != nil { return err } res = append(res, cmd) } for _, tp := range a.Config.SSLConfig.Trustpoints { for _, cmd := range res { if strings.Contains(cmd, *tp.Name) { tp.PKCS12 = &cmd } } } return nil } func (a *ASA) GetCheckSum_HTTP() error { cmd, err := a.httpClient.GetCommand("show checksum") if err != nil { return err } if err := a.Status.CheckSum.Parse(cmd); err != nil { return err } return nil } func (a *ASA) GetClock_HTTP() error { cmd, err := a.httpClient.GetCommand("show run clock") if err != nil { return err } a.Config.Clock.Parse(cmd) return a.GetNTP() } func (a *ASA) GetConfigFailover_HTTP() error { cmd, err := a.httpClient.GetCommand("show run failover") if err != nil { return err } var f asaModels.Failoverconfig f.Parse(cmd) a.Config.Failover = &f return nil } func (a *ASA) GetConn_HTTP() error { cmd, err := a.httpClient.GetCommand("show conn") if err != nil { return err } var conns asaModels.Conns conns.Parse(cmd) a.Status.Conns = conns.ConnTable return nil } func (a *ASA) GetContext_HTTP() error { cmd, err := a.httpClient.GetCommand("show mode") if err != nil { return err } a.Status.Context.Parse(cmd) return nil } func (a *ASA) GetCrypto_HTTP() error { cmd, err := a.httpClient.GetCommand("show run crypto") if err != nil { return err } a.Config.Crypto.Parse(cmd) return nil } func (a *ASA) GetCryptoKeys_HTTP() error { cmd, err := a.httpClient.GetCommand("show crypto key mypubkey rsa") if err != nil { return err } if err := a.Config.Crypto.Keys.ParseRSA(cmd); err != nil { return err } cmd, err = a.httpClient.GetCommand("show crypto key mypubkey ecdsa") if err != nil { return err } if err := a.Config.Crypto.Keys.ParseECDSA(cmd); err != nil { return err } return nil } func (a *ASA) GetDHCPD_HTTP() error { cmd, err := a.httpClient.GetCommand("show run dhcpd") if err != nil { return err } return a.Config.DHCPServer.Parse(cmd) } func (a *ASA) GetDHCPServer_HTTP() error { cmd, err := a.httpClient.GetCommand("show run dhcpd") if err != nil { return err } return a.Config.DHCPServer.Parse(cmd) } func (a *ASA) GetDomainName_HTTP() error { cmd, err := a.httpClient.GetCommand("show run domain-name") if err != nil { return err } m := regexp.MustCompile(`(.*)\n`).FindStringSubmatch(cmd) if len(m) != 2 { return fmt.Errorf("Error parsing domain-name. Raw input: %v", cmd) } a.Config.DomainName = m[1] return nil } func (a *ASA) GetEnablePassword_HTTP() error { cmd, err := a.httpClient.GetCommand("show run enable") if err != nil { return err } m := regexp.MustCompile(`(enable.*)\n`).FindStringSubmatch(cmd) if len(m) != 2 { return fmt.Errorf("Error parsing enable password. Raw input: %v", cmd) } a.Config.EnablePassword = m[1] return nil } func (a *ASA) GetFailover_HTTP() error { if err := a.GetContext_HTTP(); err != nil { return err } cmd, cmdErr := a.httpClient.GetCommand("show failover") if cmdErr != nil { return cmdErr } if strings.Contains(a.Info.PlatformModel, "Cisco ASA 5505") { var fo asaModels.FailoverStatus fo.Parse(cmd, "single") a.Status.Failover = &fo return nil } var fo asaModels.FailoverStatus fo.Parse(cmd, a.Status.Context.Mode) a.Status.Failover = &fo return nil } func (a *ASA) GetGroupPolicies_HTTP() error { cmd, err := a.httpClient.GetCommand("show run group-policy") if err != nil { return err } var gp asaModels.GroupPolicies gp.Parse(cmd) a.Config.GroupPolicies = gp.GroupPolicies return nil } func (a *ASA) GetHostname_HTTP() error { cmd, err := a.httpClient.GetCommand("show hostname") if err != nil { return err } // "response": "show hostname\ntFW1-asa5510\ntFW1-asa5510/pri/act# ", resp := strings.Split(cmd, "\n") a.Config.Hostname = resp[1] return nil } func (a *ASA) GetHTTP_HTTP() error { cmd, err := a.httpClient.GetCommand("show run http") if err != nil { return err } if err := a.Config.HTTP.Parse(cmd); err != nil { return err } return nil } func (a *ASA) GetInterfaces_HTTP() error { cmd, err := a.httpClient.GetCommand("show run interface") if err != nil { return err } var ic asaModels.InterfacesConfig ic.Parse(cmd) a.Config.Interfaces = ic.Interfaces return nil } func (a *ASA) GetInventory_HTTP() error { cmd, err := a.httpClient.GetCommand("show inventory") if err != nil { return err } if err := a.Status.Inventory.Parse(cmd); err != nil { return err } return nil } // GetStartupErrorsHTTP method will take an ASA type and execute/parse the // show startup-config errors data on the target device. func (a *ASA) GetStartupErrorsHTTP() error { cmd, err := a.httpClient.GetCommand("show startup-config errors") if err != nil { return err } if err := a.Status.Startup.Parse(cmd); err != nil { return err } return nil } func (a *ASA) GetIPReversePath_HTTP() error { cmd, err := a.httpClient.GetCommand("show run ip verify reverse-path") if err != nil { return err } m := regexp.MustCompile(`ip verify reverse-path interface (\S+)`).FindAllStringSubmatch(cmd, -1) for _, l := range m { a.Config.IPReversePathInts = append(a.Config.IPReversePathInts, l[1]) } return nil } func (a *ASA) GetLogging_HTTP() error { cmd, err := a.httpClient.GetCommand("sh run logging") if err != nil { return err } var l asaModels.Logging if err := l.Parse(cmd); err != nil { return err } l.Populated = true a.Config.Logging = l return nil } func (a *ASA) GetNames_HTTP() error { cmd, err := a.httpClient.GetCommand("show run | in names|^name") if err != nil { return err } a.Config.Names.Parse(cmd) return nil } func (a *ASA) GetNat_HTTP() error { // If version isn't populated, populate it if a.Status.Version == nil { if err := a.GetVersion(); err != nil { return err } } var cmdToSend string switch { case a.Status.Version.SoftwareVer.Major <= 8 && a.Status.Version.SoftwareVer.Minor < 3: cmdToSend = "show run static" default: cmdToSend = "show run nat" } cmd, err := a.httpClient.GetCommand(cmdToSend) if err != nil { return err } a.Config.Nat = asaModels.ParseNat(cmd) return nil } func (a *ASA) GetNTP_HTTP() error { cmd, err := a.httpClient.GetCommand("show run ntp") if err != nil { return err } a.Config.Clock.NTP.Parse(cmd) return nil } func (a *ASA) GetObjectGroups_HTTP() error { cmd, err := a.httpClient.GetCommand("show run object-group") if err != nil { return err } // a.Config.ObjectGroups.Parse(cmd) og := asaModels.ParseObjectGroups(cmd) a.Config.ObjectGroups = *og return nil } func (a *ASA) GetObjects_HTTP() error { cmd, err := a.httpClient.GetCommand("show run object") if err != nil { return err } a.Config.Objects.Parse(cmd) return nil } func (a *ASA) GetPasswordPolicy_HTTP() error { cmd, err := a.httpClient.GetCommand("show run password-policy") if err != nil { return err } return a.Config.PasswordPolicy.Parse(cmd) } func (a *ASA) GetPolicyMaps_HTTP() error { cmd, err := a.httpClient.GetCommand("show run policy-map") if err != nil { return err } if err := a.Config.PolicyMaps.Parse(cmd); err != nil { return err } return nil } func (a *ASA) GetPrompt_HTTP() error { cmd, err := a.httpClient.GetCommand("show run prompt") if err != nil { return err } m := regexp.MustCompile(`(?i)prompt (\S+)`).FindStringSubmatch(cmd) if len(m) != 2 { return fmt.Errorf("Error parsing prompt. Raw input: %v", cmd) } a.Config.Prompt = m[1] return nil } func (a *ASA) GetProxyARP_HTTP() error { cmd, err := a.httpClient.GetCommand("show run all sysopt") if err != nil { return err } a.Config.ProxyARP = asaModels.ParseProxyARP(cmd) return nil } func (a *ASA) GetRoutes_HTTP() error { cmd, err := a.httpClient.GetCommand("show route") if err != nil { return err } rt := asaModels.ParseRouteTable(cmd) a.Status.Routes = rt.Routes return nil } func (a *ASA) GetServicePolicy_HTTP() error { cmd, err := a.httpClient.GetCommand("show run service-policy") if err != nil { return err } if err := a.Config.ServicePolicies.Parse(cmd); err != nil { return err } return nil } func (a *ASA) GetSNMP_HTTP() error { cmd, err := a.httpClient.GetCommand("show run all snmp-server") if err != nil { return err } if err := a.Config.SNMP.Parse(cmd); err != nil { return err } return nil } func (a *ASA) GetSSHConfig_HTTP() error { cmd, err := a.httpClient.GetCommand("show run ssh") if err != nil { return err } return a.Config.SSHConfig.Parse(cmd) } func (a *ASA) GetSSLConfig_HTTP() error { cmd, err := a.httpClient.GetCommand("show run ssl") if err != nil { return err } var sc asaModels.SSLConfig sc.Parse(cmd) a.Config.SSLConfig = &sc return nil } func (a *ASA) GetStatics_HTTP() error { cmd, err := a.httpClient.GetCommand("show run static") if err != nil { return err } s := asaModels.ParseStatics(cmd) a.Config.Statics = s.Statics return nil } func (a *ASA) GetTelnet_HTTP() error { cmd, err := a.httpClient.GetCommand("show run telnet") if err != nil { return err } var t asaModels.Telnet t.Parse(cmd) a.Config.Telnet = t return nil } func (a *ASA) GetTunnelGroups_HTTP() error { cmd, err := a.httpClient.GetCommand("show run tunnel-group") if err != nil { return err } var tg asaModels.TunnelGroups tg.Parse(cmd) a.Config.TunnelGroups = tg.TunnelGroups return nil } func (a *ASA) GetUsernames_HTTP() error { cmd, err := a.httpClient.GetCommand("show run username") if err != nil { return err } var u asaModels.UserNames u.Parse(cmd) a.Config.UserNames = u.UserNames return nil } func (a *ASA) GetVersion_HTTP() error { cmd, err := a.httpClient.GetCommand("show version") if err != nil { return err } a.Status.Version = asaModels.VersionParse(cmd) return nil } func (a *ASA) GetWebVPN_HTTP() error { res, err := a.RunCommand("show run webvpn") if err != nil { // Attempt to unmarshal for a cleaner error e := new(sshError) if err := json.Unmarshal([]byte(err.Error()), e); err != nil { // return raw error, unmarshal failed return err } return errors.New(e.Error) } return a.Config.WebVPN.Parse(*res) } func (a *ASA) HTTPToFlash_HTTP(source string) (string, error) { var errorCheckRE = regexp.MustCompile(`(?i)%(.*?)\n+`) cmd, err := a.httpClient.GetCommand(fmt.Sprintf("copy /noconfirm http://%s flash:", source)) if err != nil { return "", err } if strings.Contains(cmd, "Unspecified Error") == true { copyerr := errorCheckRE.FindStringSubmatch(cmd) return cmd, errors.New(copyerr[1]) } return cmd, nil } func (a *ASA) ListDisk_HTTP() error { if a.Status.Disk != nil { return nil } d, err := a.DiskInfo("disk0:") if err != nil { return err } a.Status.Disk = d return nil } func (a *ASA) MoreSystem_HTTP() (string, error) { cmd, err := a.httpClient.GetCommand("more system:running-config") if err != nil { return "", err } return cmd, nil } func (a *ASA) Ping_HTTP(ip string) (bool, string, error) { ping := fmt.Sprintf("ping %s repeat 2", ip) cmd, err := a.httpClient.GetCommand(ping) if err != nil { return false, "", err } if pingSuccessRE.MatchString(cmd) { return false, cmd, nil } return true, cmd, nil } func (a *ASA) RunCommand_HTTP(command string) (*string, error) { cmd, err := a.httpClient.GetCommand(command) if err != nil { return nil, err } return &cmd, nil } func (a *ASA) SetConfReg_HTTP(confReg string) (string, error) { cmd, err := a.httpClient.GetCommand("config-register " + confReg) if err != nil { return "", err } return cmd, nil } func (a *ASA) ShowAccessList_HTTP(acl string) (*asaModels.ShowAccessList, error) { cmd, err := a.httpClient.GetCommand("show access-list " + acl) if err != nil { return nil, err } var sa asaModels.ShowAccessLists sa.Parse(cmd) return sa.FindACL(acl), nil } func (a *ASA) ShowAccessLists_HTTP() error { cmd, err := a.httpClient.GetCommand("show access-list") if err != nil { return err } var sa asaModels.ShowAccessLists sa.Parse(cmd) a.Status.ACL = sa.AccessLists return nil } func (a *ASA) ShowInterfaces_HTTP() error { cmd, err := a.httpClient.GetCommand("show interface") if err != nil { return err } is := asaModels.ParseShowInterfaces(cmd) a.Status.Interfaces = is.Interfaces return nil } func (a *ASA) ShowRun_HTTP() (string, error) { cmd, err := a.httpClient.GetCommand("show run") if err != nil { return "", err } return cmd, nil } func (a *ASA) TFTPToFlash_HTTP(source string) (string, error) { var errorCheckRE = regexp.MustCompile(`(?i)%(.*?)\n+`) cmd, err := a.httpClient.GetCommand(fmt.Sprintf("copy /noconfirm tftp://%s flash:", source)) if err != nil { return "", err } if strings.Contains(cmd, "Unspecified Error") == true { copyerr := errorCheckRE.FindStringSubmatch(cmd) return cmd, errors.New(copyerr[1]) } // a.log.Println(cmd) return cmd, nil } func (a *ASA) VPNSessionL2L_HTTP() ([]*asaModels.Lan2Lan, error) { cmd, err := a.httpClient.GetCommand("show vpn-sessiondb l2l") if err != nil { return nil, err } var l2l asaModels.Lan2Lans l2l.Parse(cmd) return l2l.Lan2Lans, nil } func (a *ASA) VPNSessionRemote_HTTP(legacy bool) ([]*asaModels.RATunnel, error) { command := "show vpn-sessiondb ra-ikev1-ipsec" if legacy { command = "show vpn-sessiondb remote" } cmd, err := a.httpClient.GetCommand(command) if err != nil { return nil, err } var ra asaModels.RATunnels ra.Parse(cmd) return ra.RATunnels, nil } func (a *ASA) WriteMem_HTTP() error { cmd, err := a.httpClient.GetCommand("write mem") if err != nil { return err } if !writeRE.MatchString(cmd) { return fmt.Errorf("Unable to match write mem prompt: %s", cmd) } return nil }