1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
package firewall
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"os"
"github.com/spf13/cobra"
"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/cmd/cmpl"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/hcloud-go/v2/hcloud"
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
)
var ReplaceRulesCommand = base.Cmd{
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
cmd := &cobra.Command{
Use: "replace-rules FIREWALL FLAGS",
Short: "Replaces all rules from a Firewall from a file",
Args: cobra.ExactArgs(1),
ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Firewall().Names)),
TraverseChildren: true,
DisableFlagsInUseLine: true,
}
cmd.Flags().String("rules-file", "", "JSON file containing your routes (use - to read from stdin). The structure of the file needs to be the same as within the API: https://docs.hetzner.cloud/#firewalls-get-a-firewall")
cmd.MarkFlagRequired("rules-file")
return cmd
},
Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error {
idOrName := args[0]
firewall, _, err := client.Firewall().Get(ctx, idOrName)
if err != nil {
return err
}
if firewall == nil {
return fmt.Errorf("Firewall not found: %v", idOrName)
}
opts := hcloud.FirewallSetRulesOpts{}
rulesFile, _ := cmd.Flags().GetString("rules-file")
var data []byte
if rulesFile == "-" {
data, err = ioutil.ReadAll(os.Stdin)
} else {
data, err = ioutil.ReadFile(rulesFile)
}
if err != nil {
return err
}
var rules []schema.FirewallRule
err = json.Unmarshal(data, &rules)
if err != nil {
return err
}
for _, rule := range rules {
d := hcloud.FirewallRuleDirection(rule.Direction)
r := hcloud.FirewallRule{
Direction: d,
Protocol: hcloud.FirewallRuleProtocol(rule.Protocol),
Port: rule.Port,
Description: rule.Description,
}
switch d {
case hcloud.FirewallRuleDirectionOut:
r.DestinationIPs = make([]net.IPNet, len(rule.DestinationIPs))
for i, ip := range rule.DestinationIPs {
_, n, err := net.ParseCIDR(ip)
if err != nil {
return fmt.Errorf("invalid CIDR on index %d : %s", i, err)
}
r.DestinationIPs[i] = *n
}
case hcloud.FirewallRuleDirectionIn:
r.SourceIPs = make([]net.IPNet, len(rule.SourceIPs))
for i, ip := range rule.SourceIPs {
_, n, err := net.ParseCIDR(ip)
if err != nil {
return fmt.Errorf("invalid CIDR on index %d : %s", i, err)
}
r.SourceIPs[i] = *n
}
}
opts.Rules = append(opts.Rules, r)
}
actions, _, err := client.Firewall().SetRules(ctx, firewall, opts)
if err != nil {
return err
}
if err := waiter.WaitForActions(ctx, actions); err != nil {
return err
}
fmt.Printf("Firewall Rules for Firewall %d updated\n", firewall.ID)
return nil
},
}
|