Esempio n. 1
0
// getFwCmds return commands for firewall subsection
func getSpamCmds(client *govh.OvhClient) (spamCmds []cli.Command) {
	ipr, err := ip.New(client)
	if err != nil {
		return
	}

	spamCmds = []cli.Command{
		{
			Name:        "listIp",
			Usage:       "List IP which send (or have sent) spam.",
			Description: "ovh spam listIp IPBLOCK [--state ]" + NLTAB + "Example: ovh spam listIp 91.121.228.135/32 --state unblocked",
			Flags: []cli.Flag{
				cli.StringFlag{"state", "", "The state of the IP (blockedForSpam|unblocked|unblocking).", ""},
			},
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 1)
				var state string
				if c.IsSet("state") {
					state = c.String("state")
					if !inSliceStr(state, []string{"blockedForSpam", "unblocked", "unblocking"}) {
						dieBadArgs()
					}
				}
				ips, err := ipr.SpamGetSpammingIps(ip.IpBlock{c.Args().First(), ""}, state)
				handleErrFromOvh(err)
				for _, ip := range ips {
					fmt.Println(ip)
				}
				dieOk()
			},
		}, {
			Name:        "getProperties",
			Usage:       "Get properties of a spamming IP.",
			Description: "ovh spam getProperties IPBLOCK IP" + NLTAB + "Example: ovh spam listIp 91.121.228.135/32 91.121.228.135",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				p, err := ipr.SpamGetIp(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1))
				handleErrFromOvh(err)
				dieOk(fmt.Sprintf("Blocked since (duration sec):%d%sLast time: %s%sIP: %s%sState: %s", p.Time, NL, p.Date, NL, p.IpSpamming, NL, p.State))
			},
		}, {
			Name:        "getStats",
			Usage:       "Get spam stats about a spamming IP.",
			Description: "ovh spam getStats IPBLOCK IP --from TIMESTAMP_START --to TIMESTAMP_STOP" + NLTAB + "Example: ovh spam getStats 178.33.223.32/28 178.33.223.42 --from 1385251200 --to 1387882630",
			Flags: []cli.Flag{
				cli.StringFlag{"from", "", "Unix timestamp representing the begining of the peiod (required).", ""},
				cli.StringFlag{"to", "", "Unix timestamp representing the end of the peiod (required).", ""},
			},
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				if !c.IsSet("from") || !c.IsSet("to") {
					dieBadArgs()
				}
				from := c.Int("from")
				to := c.Int("to")
				if from >= to {
					dieBadArgs()
				}
				stats, err := ipr.SpamGetIpStats(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1), time.Unix(int64(from), 0), time.Unix(int64(to), 0))
				handleErrFromOvh(err)
				if stats == nil {
					dieOk("No spam stats for this period")
				}
				fmt.Printf("Blocked for the last time: %s%s", time.Unix(stats.Timestamp, 0).Format(time.RFC822Z), NL)
				fmt.Printf("Number of emails sent: %d%s", stats.Total, NL)
				fmt.Printf("Number of spams sent: %d%s", stats.NumberOfSpams, NL)
				fmt.Printf("Average score: %d%s%s", stats.AverageSpamScore, NL, NL)
				if len(stats.DetectedSpams) > 0 {
					fmt.Println("Detected Spams : ", NL)
				}
				for _, ds := range stats.DetectedSpams {
					fmt.Println("")
					fmt.Printf("\tDate: %s%s", time.Unix(ds.Date, 0).Format(time.RFC822Z), NL)
					fmt.Printf("\tMessage ID: %s%s", ds.MessageId, NL)
					fmt.Printf("\tDestination IP: %s%s", ds.DestinationIp, NL)
					fmt.Printf("\tScore: %d%s", ds.Spamscore, NL)
				}
				dieOk()
			},
		},
		{
			Name:        "unblock",
			Usage:       "Unblock a locked IP.",
			Description: "ovh spam unblock IPBLOCK IP" + NLTAB + "Example: ovh spam unblock 91.121.228.135/32 91.121.228.135",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				handleErrFromOvh(ipr.SpamUnblockSpamIp(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1)))
				dieDone()
			},
		},
		{
			Name:        "getBlocked",
			Usage:       "Retuns IPs which are currently blocked.",
			Description: "ovh spam getBlocked" + NLTAB + "Example: ovh spam getBlocked",
			Action: func(c *cli.Context) {
				//dieIfArgsMiss(len(c.Args()), 2)
				ips, err := ipr.GetBlockedForSpam()
				handleErrFromOvh(err)
				for _, ip := range ips {
					fmt.Println(ip)
				}
				dieOk()
			},
		},
	}
	return
}
Esempio n. 2
0
// getIpCmds return commands for Ip section
func getIpCmds(client *govh.OvhClient) (ipCmds []cli.Command) {
	ipr, err := ip.New(client)
	if err != nil {
		return
	}

	// Ip commands
	ipCmds = []cli.Command{
		// list
		{
			Name:        "list",
			Usage:       "List your IP blocks.",
			Description: "ovh ip list [flag...]" + NLTAB + "Example: ovh ip list --type vps",
			Flags: []cli.Flag{
				cli.StringFlag{"desc", "", "Filter: by description (like).", ""},
				cli.StringFlag{"ip", "", "Filter: by IP (contains or equals).", ""},
				cli.StringFlag{"routedTo", "", "Filter: by routing.", ""},
				cli.StringFlag{"type", "all", "Filter: by IP block type: all|cdn|dedicated|failover|hosted_ssl|housing|loadBalancing|mail|pcc|pci|private|vps|vpn|vrack|xdsl", ""},
			},
			Action: func(c *cli.Context) {
				fDesc := strings.ToLower(c.String("desc"))
				fIp := strings.ToLower(c.String("ip"))
				fRoutedTo := strings.ToLower(c.String("routedto"))
				fType := strings.ToLower(c.String("type"))
				if fType == "all" {
					fType = ""
				}

				ips, err := ipr.List(fDesc, fIp, fRoutedTo, fType)
				handleErrFromOvh(err)
				for _, i := range ips {
					fmt.Println(i.IP, i.Type)
				}
				dieOk()
			},
		},
		// getProperties
		{
			Name:        "getProperties",
			Usage:       "Get properties of an IP.",
			Description: "ovh ip getProperties IPBLOCK" + NLTAB + "Example: ovh ip getProperties 91.121.228.135/32",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 1)
				properties, err := ipr.GetIpProperties(c.Args().First())
				handleErrFromOvh(err)
				dieOk(fmt.Sprintf("IP: %s%sType: %s%sDescription: %s%sRouted to: %s", properties.Ip, NL, properties.Type, NL, properties.Description, NL, properties.RoutedTo.ServiceName))
			},
		},

		// Update properties
		{
			Name:        "updateProperties",
			Usage:       "Update properties of an IP",
			Description: `ovh ip updateProperties IPBLOCK --desc "description"` + NLTAB + `Example: ovh ip updateProperties 37.187.0.144/32 --desc "IP routed to lunar base server"`,
			Flags: []cli.Flag{
				cli.StringFlag{"desc", "", "Update description", ""},
			},
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 1)
				fDesc := c.String("desc")
				// check if there is something to update
				if len(fDesc) == 0 {
					dieDone()
				}
				err := ipr.UpdateProperties(c.Args().First(), fDesc)
				if err != nil {
					dieError(err)
				}
				dieDone()
			},
		},
	}
	return

}
Esempio n. 3
0
File: ip.go Progetto: jleroy/ovh-cli
func ipHandler(cmd *Cmd) (err error) {
	// New govh client
	client := govh.NewClient(OVH_APP_KEY, OVH_APP_SECRET, ck)
	// New ip ressource
	ipr, err := ip.New(client)
	if err != nil {
		return
	}

	var resp string

	switch cmd.Action {
	// List
	case "list":
		ipType := "all"
		if len(cmd.Args) > 2 {
			ipType = cmd.Args[2]
		}
		ips, err := ipr.List(ipType)
		if err != nil {
			dieError(err)
		}
		for _, i := range ips {
			resp = fmt.Sprintf("%s%s\r\n", resp, i.IP)
		}
		if len(resp) > 2 {
			resp = resp[0 : len(resp)-2]
		}
		dieOk(resp)
		break
	case "lb":
		if len(cmd.Args) < 3 {
			dieError("\"ip lb\" needs an argument see doc at https://github.com/Toorop/govh/blob/master/cli/README.md")
		}
		var t []byte
		t, err = ipr.LbList()
		resp = string(t)
		dieOk(resp)
		break

	case "fw":
		// ip fw ipBlock.IP list
		// ip fw x.x.x.x/y
		// Return IP V4 list of this block which is under firewall
		if len(cmd.Args) == 4 && cmd.Args[3] == "list" {
			block := ip.IpBlock{cmd.Args[2], ""}
			ips, err := ipr.FwListIpOfBlock(block)
			if err != nil {
				dieError(err)
			}
			for _, i := range ips {
				resp = fmt.Sprintf("%s%s\r\n", resp, i)
			}
			if len(resp) > 2 {
				resp = resp[0 : len(resp)-2]
			}
			dieOk(resp)
			break
		}

		// Add IP to firewall
		// cmd : ip fw ibBlock.IP ipV4 add
		if len(cmd.Args) == 5 && cmd.Args[4] == "add" {
			block := ip.IpBlock{cmd.Args[2], ""}
			if err = ipr.FwAddIp(block, cmd.Args[3]); err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("%s added to firewall", cmd.Args[3]))
		}

		// Get properties of a firewalled IP
		// ip fw ipBlock.IP ipV4 prop
		if len(cmd.Args) == 5 && cmd.Args[4] == "prop" {
			block := ip.IpBlock{cmd.Args[2], ""}
			i, err := ipr.FwGetIpProperties(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("ipOnFirewall: %s%sEnabled: %t%sState: %s", i.IpOnFirewall, NL, i.Enabled, NL, i.State))
			break
		}

		// Enable firewalll for IP ipv4
		// ip fw ipVlock ipV4 enable
		if len(cmd.Args) == 5 && cmd.Args[4] == "enable" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.FwSetFirewallEnable(block, cmd.Args[3], true)
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
			break
		}

		// Disable firewalll for IP ipv4
		// ip fw ipVlock ipV4 disable
		if len(cmd.Args) == 5 && cmd.Args[4] == "disable" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.FwSetFirewallEnable(block, cmd.Args[3], false)
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
			break
		}

		// Remove IPv4 from firewall
		// cmd : ip fw ipBlock.IP ipV4 remove
		if len(cmd.Args) == 5 && cmd.Args[4] == "remove" {
			block := ip.IpBlock{cmd.Args[2], ""}
			if err = ipr.FwRemoveIp(block, cmd.Args[3]); err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("%s removed from firewall", cmd.Args[3]))
		}

		// Get rules sequences
		// ip fw ipBlock.IP ipV4 listRules all
		if len(cmd.Args) >= 5 && cmd.Args[4] == "listRules" {
			block := ip.IpBlock{cmd.Args[2], ""}
			state := ""
			if len(cmd.Args) == 6 {
				state = cmd.Args[6]
			}
			t, err := ipr.FwGetRulesSequences(block, cmd.Args[3], state)
			if err != nil {
				dieError(err)
			}
			var r string
			if len(t) > 0 {
				r = fmt.Sprintf("%d", t[0])
				for _, s := range t[1:] {
					r = fmt.Sprintf("%s%s%d", r, NL, s)
				}
			}
			dieOk(r)
		}

		// Add rule
		// ip fw ipBlock.IP ipV4 addRule rule (as Json)
		if len(cmd.Args) == 6 && cmd.Args[4] == "addRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			// Check json
			var rule ip.FirewallRule2Add
			err := json.Unmarshal([]byte(cmd.Args[5]), &rule)
			if err != nil {
				dieError("Rule error. See doc at : https://github.com/Toorop/ovh-cli", err)
			}
			err = ipr.FwAddRule(block, cmd.Args[3], rule)
			if err != nil {
				dieError(err)
			}
			dieOk("OK")
		}

		// Remove rule
		// ip fw ipBlock.IP ipV4 remRule ruleSequence
		if len(cmd.Args) == 6 && cmd.Args[4] == "remRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			sequence, err := strconv.Atoi(cmd.Args[5])
			if err != nil {
				dieError(err)
			}
			err = ipr.FwRemoveRule(block, cmd.Args[3], sequence)
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("Rule %d removed", sequence))

		}

		// Get rule
		// ip fw ipBlock.IP ipV4 getRule sequence
		if len(cmd.Args) == 6 && cmd.Args[4] == "getRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			sequence, err := strconv.Atoi(cmd.Args[5])
			if err != nil {
				dieError(err)
			}
			rule, err := ipr.FwGetRule(block, cmd.Args[3], sequence)
			if err != nil {
				dieError(err)
			}
			out := ""
			if len(rule.Protocol) > 0 {
				out = fmt.Sprintf("%sProtocol: %s%s", out, rule.Protocol, NL)
			}
			if len(rule.Source) > 0 {
				out = fmt.Sprintf("%sSource: %s%s", out, rule.Source, NL)
			}
			if len(rule.DestinationPort) > 0 {
				out = fmt.Sprintf("%sDestinationPort: %s%s", out, rule.DestinationPort, NL)
			}

			out = fmt.Sprintf("%sSequence: %d%s", out, rule.Sequence, NL)

			if len(rule.Options) > 0 {
				out = fmt.Sprintf("%sOptions: %s%s", out, strings.Join(rule.Options, " "), NL)
			}
			if len(rule.Destination) > 0 {
				out = fmt.Sprintf("%sDestination: %s%s", out, rule.Destination, NL)
			}
			if len(rule.Rule) > 0 {
				out = fmt.Sprintf("%sRule: %s%s", out, rule.Rule, NL)
			}
			if len(rule.SourcePort) > 0 {
				out = fmt.Sprintf("%sSourcePort: %s%s", out, rule.SourcePort, NL)
			}
			if len(rule.State) > 0 {
				out = fmt.Sprintf("%sState: %s%s", out, rule.State, NL)
			}
			if len(rule.CreationDate) > 0 {
				out = fmt.Sprintf("%sCreationDate: %s%s", out, rule.CreationDate, NL)
			}
			if len(rule.Action) > 0 {
				out = fmt.Sprintf("%sAction: %s%s", out, rule.Action, NL)
			}
			dieOk(out[0 : len(out)-2])

		}
		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
		break

	case "spam":
		// List of spamming IP
		// ip spam ipBlock.IP listSpammingIp STATE
		if len(cmd.Args) >= 4 && cmd.Args[3] == "listSpammingIp" {
			block := ip.IpBlock{cmd.Args[2], ""}
			state := ""
			if len(cmd.Args) == 5 {
				state = cmd.Args[4]
			}
			ips, err := ipr.SpamGetSpammingIps(block, state)
			if err != nil {
				dieError(err)
			}
			for _, ip := range ips {
				fmt.Println(ip)
			}
			dieOk("")
		}

		// detailed info about a spamming IP
		// ip spam ipBlock.IP ipv4 details
		if len(cmd.Args) == 5 && cmd.Args[4] == "details" {
			block := ip.IpBlock{cmd.Args[2], ""}
			spamIp, err := ipr.SpamGetSpamIp(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("Time: %d%sDate: %s%sIpSpamming: %s%sState: %s", spamIp.Time, NL, spamIp.Date, NL, spamIp.IpSpamming, NL, spamIp.State))
		}

		// Stats about a spamming IP
		// ip spam ipBlock.IP ipv4 stats FROM TO
		if len(cmd.Args) == 7 && cmd.Args[4] == "stats" {
			block := ip.IpBlock{cmd.Args[2], ""}

			from, err := strconv.ParseInt(cmd.Args[5], 10, 64)
			if err != nil {
				dieError(err)
			}

			to, err := strconv.ParseInt(cmd.Args[6], 10, 64)
			if err != nil {
				dieError(err)
			}
			spamStats, err := ipr.SpamGetIpStats(block, cmd.Args[3], time.Unix(from, 0), time.Unix(to, 0))
			if err != nil {
				dieError(err)
			}
			if spamStats == nil {
				dieOk("No spam stats for this period")
			}
			fmt.Printf("Blocked for the last time: %s%s", time.Unix(spamStats.Timestamp, 0).Format(time.RFC822Z), NL)
			fmt.Printf("Number of emails sent: %d%s", spamStats.Total, NL)
			fmt.Printf("Number of spams sent: %d%s", spamStats.NumberOfSpams, NL)
			fmt.Printf("Average score: %d%s%s", spamStats.AverageSpamScore, NL, NL)
			if len(spamStats.DetectedSpams) > 0 {
				fmt.Println("Detected Spams : ", NL)
			}
			for _, ds := range spamStats.DetectedSpams {
				fmt.Println("")
				fmt.Printf("\tDate: %s%s", time.Unix(ds.Date, 0).Format(time.RFC822Z), NL)
				fmt.Printf("\tMessage ID: %s%s", ds.MessageId, NL)
				fmt.Printf("\tDestination IP: %s%s", ds.DestinationIp, NL)
				fmt.Printf("\tScore: %d%s", ds.Spamscore, NL)
			}
			dieOk("")
		}

		// Unblock
		// ip spam ipBlock.IP ipv4 unblock
		if len(cmd.Args) == 5 && cmd.Args[4] == "unblock" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.SpamUnblockSpamIp(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
		}

		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
		break
	case "getBlockedForSpam":
		// On va chercher les blocks
		ips, err := ipr.GetBlockedForSpam()
		if err != nil {
			dieError(err)
		}
		if len(ips) == 0 {
			dieOk("")
		}
		for _, i := range ips {
			fmt.Println(i)
		}
		dieOk("")

		// On les tests
		break

	default:
		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
	}
	return

}
Esempio n. 4
0
// getFwCmds return commands for firewall subsection
func getFwCmds(client *govh.OvhClient) (fwCmds []cli.Command) {
	ipr, err := ip.New(client)
	if err != nil {
		return
	}

	fwCmds = []cli.Command{
		{
			Name:        "list",
			Usage:       "List IPs, of a given block, that are under firewall.",
			Description: "ovh fw list IPBLOCK" + NLTAB + "Example: ovh fw list 91.121.228.135/32 ",

			Action: func(c *cli.Context) {
				if len(c.Args()) == 0 {
					dieBadArgs()
				}
				ips, err := ipr.FwListIpOfBlock(ip.IpBlock{c.Args().First(), ""})
				handleErrFromOvh(err)
				for _, ip := range ips {
					fmt.Println(ip)
				}
				dieOk()
			},
		},
		{
			Name:        "add",
			Usage:       "Add an IP of IPBLOCK on firewall.",
			Description: "ovh fw add IPBLOCK IP" + NLTAB + "Example: ovh fw add 92.222.14.249/32 92.222.14.249",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				err := ipr.FwAddIp(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1))
				handleErrFromOvh(err)
				dieDone()
			},
		},
		{
			Name:        "remove",
			Usage:       "Remove an IP of IPBLOCK from firewall.",
			Description: "ovh fw remove IPBLOCK IP" + NLTAB + "Example: ovh fw remove 92.222.14.249/32 92.222.14.249",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				err := ipr.FwRemoveIp(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1))
				handleErrFromOvh(err)
				dieDone()
			},
		},
		{
			Name:        "getProperties",
			Usage:       "Get properties of an IP on the firewall.",
			Description: "ovh fw getProperties IPBLOCK IP " + NLTAB + "Example: ovh fw getProperties 92.222.14.249/32 92.222.14.249",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				p, err := ipr.FwGetIpProperties(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1))
				handleErrFromOvh(err)
				dieOk(fmt.Sprintf("Ip: %s%sEnabled: %t%sState: %s", p.Ip, NL, p.Enabled, NL, p.State))
			},
		},
		{
			Name:        "update",
			Usage:       "Update an IP on the firewall.",
			Description: "ovh fw update IPBLOCK IP [--flag...]" + NLTAB + "Example: ovh fw update 92.222.14.249/32 92.222.14.249 --enable true",
			Flags: []cli.Flag{
				cli.StringFlag{"enabled", "", "Set enabled state of the IP (true|false).", ""},
			},
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				fEnabled := c.Bool("enabled")
				err := ipr.FwUpdateIp(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1), fEnabled)
				handleErrFromOvh(err)
				dieDone()
			},
		},
		{
			Name:        "listRules",
			Usage:       "Return a list ao rule sequences.",
			Description: "ovh fw listRule IPBLOCK IP [--state]" + NLTAB + "Example: ovh fw listRule 92.222.14.249/32 92.222.14.249 --state ok",
			Flags: []cli.Flag{
				cli.StringFlag{"state", "", "Filter on state (creationPending|ok|removalPending).", ""},
			},
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				var sequences []int
				if c.IsSet("state") {
					fState := c.String("state")
					sequences, err = ipr.FwListRules(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1), fState)
				} else {
					sequences, err = ipr.FwListRules(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1))
				}
				handleErrFromOvh(err)
				for _, seq := range sequences {
					fmt.Println(seq)
				}
				dieOk()
			},
		},
		{
			Name:        "addRule",
			Usage:       "Add a new rule on an IP.",
			Description: "ovh fw addRule [--flag...] IPBLOCK IP  " + NLTAB + "Example: ovh fw addRule --action deny --protocol tcp --toPort 22 --sequence 0 92.222.14.249/32 92.222.14.249",
			Flags: []cli.Flag{
				cli.StringFlag{"action", "", "Action on this rule (deny|permit). Required.", ""},
				cli.StringFlag{"sequence", "", "Sequence number of your rule. Required.", ""},
				cli.StringFlag{"protocol", "", "Network protocol (ah|esp|gre|icmp|ipv4|tcp|udp). Requiered.", ""},
				cli.StringFlag{"fromPort", "", "Source port for your rule. Only with TCP/UDP protocol", ""},
				cli.StringFlag{"fromIp", "", "Source ip for your rule. Any if not set.", ""},
				cli.StringFlag{"toPort", "", "Destination port for your rule. Only with TCP/UDP protocol.", ""},
				cli.StringFlag{"tcpFragments", "", "Can only be used with TCP protocol (true|false)", ""},
				cli.StringFlag{"tcpOption", "", "Can only be used with TCP protocol (established|syn)", ""},
			},
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 2)
				rule := ip.FwRule2Add{}

				// action
				if !c.IsSet("action") {
					dieBadArgs()
				}
				action := strings.ToLower(c.String("action"))
				if !inSliceStr(action, []string{"deny", "permit"}) {
					dieBadArgs()
				}
				rule.Action = action

				// sequence
				if !c.IsSet("sequence") {
					dieBadArgs()
				}
				sequence := c.Int("sequence")
				rule.Sequence = sequence

				// protocol
				if !c.IsSet("protocol") {
					dieBadArgs()
				}
				protocol := strings.ToLower(c.String("protocol"))
				if !inSliceStr(protocol, []string{"ah", "esp", "gre", "icmp", "ipv4", "tcp", "udp"}) {
					dieBadArgs()
				}
				rule.Protocol = protocol

				// fromPort
				if c.IsSet("fromPort") {
					rule.FromPort = c.Int("fromPort")
				}

				// fromIP
				if c.IsSet("fromIp") {
					rule.FromIp = c.String("fromIp")
				}

				// toPort
				if c.IsSet("toPort") {
					rule.ToPort = c.Int("toPort")
				}

				// fwTcpOption
				fwTcpOption := ip.FwTcpOption{}
				flagFwTcpOption := false

				// tcpOptionFragment
				if c.IsSet("tcpFragments") {
					fwTcpOption.Fragments = c.Bool("tcpFragments")
					flagFwTcpOption = true
				}

				// tcpOption
				if c.IsSet("tcpOption") {
					tcpOption := c.String("tcpOption")
					if !inSliceStr(tcpOption, []string{"established", "syn"}) {
						dieBadArgs()
					}
					fwTcpOption.Option = tcpOption
					flagFwTcpOption = true

				}
				if flagFwTcpOption {
					rule.TcpOption = &fwTcpOption
				}
				handleErrFromOvh(ipr.FwAddRule(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1), rule))
				dieDone()
			},
		},
		{
			Name:        "removeRule",
			Usage:       "Remove a firwall rule.",
			Description: "ovh fw removeRule IPBLOCK IP SEQUENCE" + NLTAB + "Example: ovh fw removeRule 92.222.14.249/32 92.222.14.249 0",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 3)
				sequence, err := strconv.ParseInt(c.Args().Get(2), 10, 16)
				if err != nil {
					dieError(err)
				}
				handleErrFromOvh(ipr.FwRemoveRule(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1), int(sequence)))
				dieDone()
			},
		},
		{
			Name:        "getRuleProperties",
			Usage:       "Get properties of firewall rule.",
			Description: "ovh fw getRuleProperties IPBLOCK IP SEQUENCE " + NLTAB + "Example: ovh fw getRuleProperties 92.222.14.249/32 92.222.14.249 0",
			Action: func(c *cli.Context) {
				dieIfArgsMiss(len(c.Args()), 3)
				sequence, err := strconv.ParseInt(c.Args().Get(2), 10, 16)
				if err != nil {
					dieError(err)
				}
				p, err := ipr.FwGetRuleProperties(ip.IpBlock{c.Args().First(), ""}, c.Args().Get(1), int(sequence))
				handleErrFromOvh(err)
				dieOk(fmt.Sprintf("Sequence: %d%sCreated: %s%sProtocol: %s%sFromIp: %s%sFromPort: %s%sToIP: %s%sToPort: %s%sAction: %s%sRule:%s%sState: %s%sTcpOption: %s%sFragments: %t", p.Sequence, NL, p.CreationDate, NL, p.Protocol, NL, p.FromIp, NL, p.FromPort, NL, p.ToIp, NL, p.ToPort, NL, p.Action, NL, p.Rule, NL, p.State, NL, p.TcpOption, NL, p.Fragments))
			},
		},
	}
	return
}