Skip to content

Commit

Permalink
fix: creating firewall with rules not working correctly (#412)
Browse files Browse the repository at this point in the history
Because the Firewall API expects a different JSON formatting than it
responds with (some fields must be omitted even though they are included
in the response) we have to create another struct to marshal rules
properly.

This should be reverted once the Firewall API has consistent response
and request schemas.

See hetznercloud/cli#725

(cherry picked from commit 43b2bab)
  • Loading branch information
phm07 committed Apr 19, 2024
1 parent 50a3b97 commit 39ad80d
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 41 deletions.
29 changes: 1 addition & 28 deletions hcloud/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,34 +298,7 @@ type FirewallSetRulesOpts struct {

// SetRules sets the rules of a Firewall.
func (c *FirewallClient) SetRules(ctx context.Context, firewall *Firewall, opts FirewallSetRulesOpts) ([]*Action, *Response, error) {
s := firewallSetRulesOptsToSchema(opts)

// We can't use the FirewallRule struct here, because unlike in the response some fields must be omitted when empty.
type firewallRule struct {
Direction string `json:"direction"`
SourceIPs []string `json:"source_ips,omitempty"`
DestinationIPs []string `json:"destination_ips,omitempty"`
Protocol string `json:"protocol"`
Port *string `json:"port,omitempty"`
Description *string `json:"description,omitempty"`
}

rules := make([]firewallRule, 0, len(s.Rules))
for _, r := range s.Rules {
rules = append(rules, firewallRule{
Direction: r.Direction,
SourceIPs: r.SourceIPs,
DestinationIPs: r.DestinationIPs,
Protocol: r.Protocol,
Port: r.Port,
Description: r.Description,
})
}
reqBody := struct {
Rules []firewallRule `json:"rules"`
}{
Rules: rules,
}
reqBody := firewallSetRulesOptsToSchema(opts)

reqBodyData, err := json.Marshal(reqBody)
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions hcloud/firewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ func TestFirewallSetRules(t *testing.T) {
{
name: "direction in",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{
Rules: []schema.FirewallRuleRequest{
{
Direction: "in",
SourceIPs: []string{"10.0.0.5/32", "10.0.0.6/32"},
Expand Down Expand Up @@ -358,7 +358,7 @@ func TestFirewallSetRules(t *testing.T) {
{
name: "direction out",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{
Rules: []schema.FirewallRuleRequest{
{
Direction: "out",
DestinationIPs: []string{"10.0.0.5/32", "10.0.0.6/32"},
Expand Down Expand Up @@ -388,7 +388,7 @@ func TestFirewallSetRules(t *testing.T) {
{
name: "empty",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{},
Rules: []schema.FirewallRuleRequest{},
},
opts: FirewallSetRulesOpts{
Rules: []FirewallRule{},
Expand All @@ -397,7 +397,7 @@ func TestFirewallSetRules(t *testing.T) {
{
name: "description",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{
Rules: []schema.FirewallRuleRequest{
{
Direction: "out",
DestinationIPs: []string{"10.0.0.5/32", "10.0.0.6/32"},
Expand Down
6 changes: 3 additions & 3 deletions hcloud/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ func firewallCreateOptsToSchema(opts FirewallCreateOpts) schema.FirewallCreateRe
req.Labels = &opts.Labels
}
for _, rule := range opts.Rules {
schemaRule := schema.FirewallRule{
schemaRule := schema.FirewallRuleRequest{
Direction: string(rule.Direction),
Protocol: string(rule.Protocol),
Port: rule.Port,
Expand Down Expand Up @@ -1136,9 +1136,9 @@ func firewallCreateOptsToSchema(opts FirewallCreateOpts) schema.FirewallCreateRe
}

func firewallSetRulesOptsToSchema(opts FirewallSetRulesOpts) schema.FirewallActionSetRulesRequest {
req := schema.FirewallActionSetRulesRequest{Rules: []schema.FirewallRule{}}
req := schema.FirewallActionSetRulesRequest{Rules: []schema.FirewallRuleRequest{}}
for _, rule := range opts.Rules {
schemaRule := schema.FirewallRule{
schemaRule := schema.FirewallRuleRequest{
Direction: string(rule.Direction),
Protocol: string(rule.Protocol),
Port: rule.Port,
Expand Down
22 changes: 16 additions & 6 deletions hcloud/schema/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Firewall struct {
AppliedTo []FirewallResource `json:"applied_to"`
}

// FirewallRule defines the schema of a Firewall rule.
// FirewallRule defines the schema of a Firewall rule in responses.
type FirewallRule struct {
Direction string `json:"direction"`
SourceIPs []string `json:"source_ips"`
Expand All @@ -22,6 +22,16 @@ type FirewallRule struct {
Description *string `json:"description"`
}

// FirewallRuleRequest defines the schema of a Firewall rule in requests.
type FirewallRuleRequest struct {
Direction string `json:"direction"`
SourceIPs []string `json:"source_ips,omitempty"`
DestinationIPs []string `json:"destination_ips,omitempty"`
Protocol string `json:"protocol"`
Port *string `json:"port,omitempty"`
Description *string `json:"description,omitempty"`
}

// FirewallListResponse defines the schema of the response when listing Firewalls.
type FirewallListResponse struct {
Firewalls []Firewall `json:"firewalls"`
Expand All @@ -34,10 +44,10 @@ type FirewallGetResponse struct {

// FirewallCreateRequest defines the schema of the request to create a Firewall.
type FirewallCreateRequest struct {
Name string `json:"name"`
Labels *map[string]string `json:"labels,omitempty"`
Rules []FirewallRule `json:"rules,omitempty"`
ApplyTo []FirewallResource `json:"apply_to,omitempty"`
Name string `json:"name"`
Labels *map[string]string `json:"labels,omitempty"`
Rules []FirewallRuleRequest `json:"rules,omitempty"`
ApplyTo []FirewallResource `json:"apply_to,omitempty"`
}

// FirewallResource defines the schema of a resource to apply the new Firewall on.
Expand Down Expand Up @@ -76,7 +86,7 @@ type FirewallUpdateResponse struct {

// FirewallActionSetRulesRequest defines the schema of the request when setting Firewall rules.
type FirewallActionSetRulesRequest struct {
Rules []FirewallRule `json:"rules"`
Rules []FirewallRuleRequest `json:"rules"`
}

// FirewallActionSetRulesResponse defines the schema of the response when setting Firewall rules.
Expand Down

0 comments on commit 39ad80d

Please sign in to comment.