1/*
2Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package object
18
19import (
20	"context"
21	"errors"
22	"fmt"
23	"strings"
24
25	"github.com/vmware/govmomi/vim25"
26	"github.com/vmware/govmomi/vim25/methods"
27	"github.com/vmware/govmomi/vim25/mo"
28	"github.com/vmware/govmomi/vim25/types"
29)
30
31type HostFirewallSystem struct {
32	Common
33}
34
35func NewHostFirewallSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostFirewallSystem {
36	return &HostFirewallSystem{
37		Common: NewCommon(c, ref),
38	}
39}
40
41func (s HostFirewallSystem) DisableRuleset(ctx context.Context, id string) error {
42	req := types.DisableRuleset{
43		This: s.Reference(),
44		Id:   id,
45	}
46
47	_, err := methods.DisableRuleset(ctx, s.c, &req)
48	return err
49}
50
51func (s HostFirewallSystem) EnableRuleset(ctx context.Context, id string) error {
52	req := types.EnableRuleset{
53		This: s.Reference(),
54		Id:   id,
55	}
56
57	_, err := methods.EnableRuleset(ctx, s.c, &req)
58	return err
59}
60
61func (s HostFirewallSystem) Refresh(ctx context.Context) error {
62	req := types.RefreshFirewall{
63		This: s.Reference(),
64	}
65
66	_, err := methods.RefreshFirewall(ctx, s.c, &req)
67	return err
68}
69
70func (s HostFirewallSystem) Info(ctx context.Context) (*types.HostFirewallInfo, error) {
71	var fs mo.HostFirewallSystem
72
73	err := s.Properties(ctx, s.Reference(), []string{"firewallInfo"}, &fs)
74	if err != nil {
75		return nil, err
76	}
77
78	return fs.FirewallInfo, nil
79}
80
81// HostFirewallRulesetList provides helpers for a slice of types.HostFirewallRuleset
82type HostFirewallRulesetList []types.HostFirewallRuleset
83
84// ByRule returns a HostFirewallRulesetList where Direction, PortType and Protocol are equal and Port is within range
85func (l HostFirewallRulesetList) ByRule(rule types.HostFirewallRule) HostFirewallRulesetList {
86	var matches HostFirewallRulesetList
87
88	for _, rs := range l {
89		for _, r := range rs.Rule {
90			if r.PortType != rule.PortType ||
91				r.Protocol != rule.Protocol ||
92				r.Direction != rule.Direction {
93				continue
94			}
95
96			if r.EndPort == 0 && rule.Port == r.Port ||
97				rule.Port >= r.Port && rule.Port <= r.EndPort {
98				matches = append(matches, rs)
99				break
100			}
101		}
102	}
103
104	return matches
105}
106
107// EnabledByRule returns a HostFirewallRulesetList with Match(rule) applied and filtered via Enabled()
108// if enabled param is true, otherwise filtered via Disabled().
109// An error is returned if the resulting list is empty.
110func (l HostFirewallRulesetList) EnabledByRule(rule types.HostFirewallRule, enabled bool) (HostFirewallRulesetList, error) {
111	var matched, skipped HostFirewallRulesetList
112	var matchedKind, skippedKind string
113
114	l = l.ByRule(rule)
115
116	if enabled {
117		matched = l.Enabled()
118		matchedKind = "enabled"
119
120		skipped = l.Disabled()
121		skippedKind = "disabled"
122	} else {
123		matched = l.Disabled()
124		matchedKind = "disabled"
125
126		skipped = l.Enabled()
127		skippedKind = "enabled"
128	}
129
130	if len(matched) == 0 {
131		msg := fmt.Sprintf("%d %s firewall rulesets match %s %s %s %d, %d %s rulesets match",
132			len(matched), matchedKind,
133			rule.Direction, rule.Protocol, rule.PortType, rule.Port,
134			len(skipped), skippedKind)
135
136		if len(skipped) != 0 {
137			msg += fmt.Sprintf(": %s", strings.Join(skipped.Keys(), ", "))
138		}
139
140		return nil, errors.New(msg)
141	}
142
143	return matched, nil
144}
145
146// Enabled returns a HostFirewallRulesetList with enabled rules
147func (l HostFirewallRulesetList) Enabled() HostFirewallRulesetList {
148	var matches HostFirewallRulesetList
149
150	for _, rs := range l {
151		if rs.Enabled {
152			matches = append(matches, rs)
153		}
154	}
155
156	return matches
157}
158
159// Disabled returns a HostFirewallRulesetList with disabled rules
160func (l HostFirewallRulesetList) Disabled() HostFirewallRulesetList {
161	var matches HostFirewallRulesetList
162
163	for _, rs := range l {
164		if !rs.Enabled {
165			matches = append(matches, rs)
166		}
167	}
168
169	return matches
170}
171
172// Keys returns the HostFirewallRuleset.Key for each ruleset in the list
173func (l HostFirewallRulesetList) Keys() []string {
174	var keys []string
175
176	for _, rs := range l {
177		keys = append(keys, rs.Key)
178	}
179
180	return keys
181}
182