itamae-plugin-resource-firewalld 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -3
- data/examples/README.md +18 -4
- data/examples/recipe.rb +21 -1
- data/lib/itamae/plugin/resource/firewalld.rb +1 -0
- data/lib/itamae/plugin/resource/firewalld/version.rb +1 -1
- data/lib/itamae/plugin/resource/firewalld_service.rb +141 -0
- data/test/itamae/plugin/resource/test_firewalld_service.rb +121 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9148fc06b7117db587f794bebaf7b9999273753f
|
4
|
+
data.tar.gz: 909b1ce328e9f8f441bd5cc5597a7aee93164a0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87a0bc3bc89069dc0a46d074e4ffadb1513d8a25f42c5784acd5268759d30d909a41bc00271e8c8fb13093dff67c54f76ab38e34b69d929b4cd5d46547151b83
|
7
|
+
data.tar.gz: a12d69af2f8119a41f8e65093e0b1ef023234a30164f8952dc89c42fb8b329904597f6cdadc738e7c60608f4becc06b2d8250d8837177463de1b4247ff32f2b3
|
data/README.md
CHANGED
@@ -82,6 +82,8 @@ Or install it yourself as:
|
|
82
82
|
|
83
83
|
## Features
|
84
84
|
|
85
|
+
### firewalld_zone
|
86
|
+
|
85
87
|
Provides a `firewalld_zone` resource that operation of `Zone`:
|
86
88
|
|
87
89
|
```ruby
|
@@ -101,15 +103,35 @@ firewalld_zone 'zone_name' do
|
|
101
103
|
end
|
102
104
|
```
|
103
105
|
|
104
|
-
|
106
|
+
### firewalld_service
|
107
|
+
|
108
|
+
Provides a `firewalld_service` resource that can create or delete of `Service`:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
firewalld_service 'my-service' do
|
112
|
+
action # [:create or :delete]
|
113
|
+
|
114
|
+
short # [String]
|
115
|
+
description # [String]
|
116
|
+
port # [String]
|
117
|
+
protocol # [String]
|
118
|
+
module_name # [String]
|
119
|
+
to_ipv4 # [String]
|
120
|
+
to_ipv6 # [String]
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
After `itamae` execute, `/etc/firewalld/service/my-service.xml` is created.
|
125
|
+
|
126
|
+
## IMPORTANT
|
105
127
|
|
106
|
-
`
|
128
|
+
`itamae-plugin-resource-firewalld`'s resource performs the processing `firewall-cmd` with [--permanent](http://fedoraproject.org/wiki/FirewallD#Permanent_zone_handling) .
|
107
129
|
|
108
130
|
## TODO
|
109
131
|
|
110
132
|
Unimplemented:
|
111
133
|
|
112
|
-
- Add a new `zone
|
134
|
+
- Add a new `zone` and `icmptype` resource
|
113
135
|
- Operation of `Direct`, `Lockdown`
|
114
136
|
- Etc...
|
115
137
|
|
data/examples/README.md
CHANGED
@@ -23,6 +23,11 @@ $ bundle exec itamae ssh -h default --vagrant recipe.rb
|
|
23
23
|
INFO : running will change from 'false' to 'true'
|
24
24
|
INFO : action: enable
|
25
25
|
INFO : enabled will change from 'false' to 'true'
|
26
|
+
INFO : firewalld_service[my-ssh]
|
27
|
+
INFO : action: create
|
28
|
+
INFO : Notifying restart to service resource 'firewalld-add-service' (delayed)
|
29
|
+
INFO : service[firewalld-add-service]
|
30
|
+
INFO : action: restart
|
26
31
|
INFO : firewalld_zone[home]
|
27
32
|
INFO : action: update
|
28
33
|
INFO : services will change from '["dhcpv6-client", "ipp-client", "mdns", "samba-client", "ssh"]' to '["samba", "ssh", "vnc-server"]'
|
@@ -30,11 +35,12 @@ $ bundle exec itamae ssh -h default --vagrant recipe.rb
|
|
30
35
|
INFO : Notifying restart to service resource 'firewalld' (delayed)
|
31
36
|
INFO : firewalld_zone[public]
|
32
37
|
INFO : action: update
|
33
|
-
INFO : services will change from '["dhcpv6-client", "ssh"]' to '["https", "mysql", "ssh"]'
|
38
|
+
INFO : services will change from '["dhcpv6-client", "ssh"]' to '["https", "my-ssh", "mysql", "ssh"]'
|
34
39
|
INFO : Notifying restart to service resource 'firewalld' (delayed)
|
35
|
-
INFO : service[firewalld]
|
40
|
+
INFO : service[firewalld-add-service]
|
36
41
|
INFO : action: restart
|
37
|
-
|
42
|
+
INFO : service[firewalld]
|
43
|
+
INFO : action: restart```
|
38
44
|
|
39
45
|
### Confirmation
|
40
46
|
|
@@ -58,10 +64,18 @@ home
|
|
58
64
|
public (default, active)
|
59
65
|
interfaces: enp0s3
|
60
66
|
sources:
|
61
|
-
services: https mysql ssh
|
67
|
+
services: https my-ssh mysql ssh
|
62
68
|
ports:
|
63
69
|
masquerade: no
|
64
70
|
forward-ports:
|
65
71
|
icmp-blocks:
|
66
72
|
rich rules:
|
73
|
+
|
74
|
+
[vagrant@localhost ~]$ sudo cat /etc/firewalld/services/my-ssh.xml # formatting
|
75
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
76
|
+
<service>
|
77
|
+
<short>my-ssh</short>
|
78
|
+
<description>My perfect ssh!!</description>
|
79
|
+
<port port='2222' protocol='tcp'/>
|
80
|
+
</service>
|
67
81
|
```
|
data/examples/recipe.rb
CHANGED
@@ -4,6 +4,26 @@ service 'firewalld' do
|
|
4
4
|
action [:start, :enable]
|
5
5
|
end
|
6
6
|
|
7
|
+
firewalld_service 'my-ssh' do
|
8
|
+
short 'my-ssh'
|
9
|
+
description 'My perfect ssh!!'
|
10
|
+
port '2222'
|
11
|
+
protocol 'tcp'
|
12
|
+
|
13
|
+
#
|
14
|
+
# Necessary to restart before use added service.
|
15
|
+
# Because `firewald_serivce` is permanent configuration.
|
16
|
+
#
|
17
|
+
notifies :restart, 'service[firewalld-add-service]'
|
18
|
+
end
|
19
|
+
|
20
|
+
service 'firewalld-add-service' do
|
21
|
+
name 'firewalld'
|
22
|
+
action :restart
|
23
|
+
|
24
|
+
notifies :update, 'firewalld_zone[public]'
|
25
|
+
end
|
26
|
+
|
7
27
|
firewalld_zone 'home' do
|
8
28
|
services %w(samba ssh vnc-server)
|
9
29
|
ports %w(1900/udp 5353/udp 32469/tcp)
|
@@ -12,7 +32,7 @@ firewalld_zone 'home' do
|
|
12
32
|
end
|
13
33
|
|
14
34
|
firewalld_zone 'public' do
|
15
|
-
services %w(ssh https mysql)
|
35
|
+
services %w(ssh https mysql my-ssh)
|
16
36
|
default_zone true
|
17
37
|
|
18
38
|
notifies :restart, 'service[firewalld]'
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'itamae/resource/base'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
module Itamae
|
5
|
+
module Plugin
|
6
|
+
module Resource
|
7
|
+
class FirewalldService < ::Itamae::Resource::Base
|
8
|
+
|
9
|
+
define_attribute :action, default: :create
|
10
|
+
define_attribute :name, type: String, default_name: true
|
11
|
+
|
12
|
+
define_attribute :short, type: String, default: ''
|
13
|
+
define_attribute :description, type: String, default: ''
|
14
|
+
define_attribute :protocol, type: String, default: ''
|
15
|
+
define_attribute :port, type: String, default: ''
|
16
|
+
define_attribute :module_name, type: String, default: ''
|
17
|
+
define_attribute :to_ipv4, type: String, default: ''
|
18
|
+
define_attribute :to_ipv6, type: String, default: ''
|
19
|
+
|
20
|
+
def pre_action
|
21
|
+
current.status = current_status
|
22
|
+
|
23
|
+
return if (@current_action != :create) || (current.status == :undefined)
|
24
|
+
|
25
|
+
xml = run_specinfra(:get_file_content, service_xmlfile_path).stdout
|
26
|
+
return if xml.empty?
|
27
|
+
|
28
|
+
service = REXML::Document.new(xml).elements['/service'].elements
|
29
|
+
|
30
|
+
if service['short']
|
31
|
+
current.short = service['short'].text
|
32
|
+
end
|
33
|
+
|
34
|
+
if service['description']
|
35
|
+
current.description = service['description'].text
|
36
|
+
end
|
37
|
+
|
38
|
+
if service['port']
|
39
|
+
current.protocol = service['port'].attributes['protocol']
|
40
|
+
current.port = service['port'].attributes['port']
|
41
|
+
end
|
42
|
+
|
43
|
+
if service['module']
|
44
|
+
current.module_name = service['module'].attributes['name']
|
45
|
+
end
|
46
|
+
|
47
|
+
if service['destination']
|
48
|
+
current.to_ipv4 = service['destination'].attributes['ipv4']
|
49
|
+
current.to_ipv6 = service['destination'].attributes['ipv6']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def action_create(options)
|
54
|
+
run_specinfra(:move_file, build_xmlfile_on_remote, service_xmlfile_path)
|
55
|
+
attributes.status = :defined
|
56
|
+
end
|
57
|
+
|
58
|
+
def action_delete(options)
|
59
|
+
return if current.status == :undefined
|
60
|
+
|
61
|
+
run_command(['firewall-cmd', '--permanent', '--delete-service', attributes.name])
|
62
|
+
attributes.status = :undefined
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def build_xmlfile_on_remote
|
68
|
+
local_path = build_xmlfile_on_local
|
69
|
+
remote_path = ::File.join(runner.tmpdir, Time.now.to_f.to_s)
|
70
|
+
|
71
|
+
send_file(local_path, remote_path)
|
72
|
+
remote_path
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_xmlfile_on_local
|
76
|
+
root_document = ::REXML::Document.new
|
77
|
+
root_document << ::REXML::XMLDecl.new('1.0', 'utf-8')
|
78
|
+
@service_document = root_document.add_element('service')
|
79
|
+
|
80
|
+
add_short_tag
|
81
|
+
add_description_tag
|
82
|
+
add_port_tag
|
83
|
+
add_module_tag
|
84
|
+
add_destination_tag
|
85
|
+
|
86
|
+
f = Tempfile.open('itamae_firewalld_service')
|
87
|
+
root_document.write(f)
|
88
|
+
f.close
|
89
|
+
f.path
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_short_tag
|
93
|
+
return if attributes.short.empty?
|
94
|
+
|
95
|
+
short = @service_document.add_element('short')
|
96
|
+
short.text = attributes.short unless attributes.short.empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_description_tag
|
100
|
+
return if attributes.description.empty?
|
101
|
+
|
102
|
+
description = @service_document.add_element('description')
|
103
|
+
description.text = attributes.description unless attributes.description.empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_port_tag
|
107
|
+
return if (attributes.protocol.empty? && attributes.port.empty?)
|
108
|
+
|
109
|
+
node = @service_document.add_element('port')
|
110
|
+
node.add_attribute('protocol', attributes.protocol) unless attributes.protocol.empty?
|
111
|
+
node.add_attribute('port', attributes.port) unless attributes.port.empty?
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_module_tag
|
115
|
+
return if attributes.module_name.empty?
|
116
|
+
|
117
|
+
node = @service_document.add_element('module')
|
118
|
+
node.add_attribute('name', attributes.module_name) unless attributes.module_name.empty?
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_destination_tag
|
122
|
+
return if (attributes.to_ipv4.empty? && attributes.to_ipv6.empty?)
|
123
|
+
|
124
|
+
node = @service_document.add_element('destination')
|
125
|
+
node.add_attribute('ipv4', attributes.to_ipv4) unless attributes.to_ipv4.empty?
|
126
|
+
node.add_attribute('ipv6', attributes.to_ipv6) unless attributes.to_ipv6.empty?
|
127
|
+
end
|
128
|
+
|
129
|
+
def service_xmlfile_path
|
130
|
+
"/etc/firewalld/services/#{attributes.name}.xml"
|
131
|
+
end
|
132
|
+
|
133
|
+
def current_status
|
134
|
+
command = ['firewall-cmd', '--permanent', '--list-services']
|
135
|
+
services = run_command(command).stdout.strip.split
|
136
|
+
services.include?(attributes.name) ? :defined : :undefined
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'itamae/plugin/resource/firewalld_service'
|
3
|
+
|
4
|
+
module Itamae
|
5
|
+
module Plugin
|
6
|
+
module Resource
|
7
|
+
# Stub
|
8
|
+
class FirewalldService
|
9
|
+
def send_file(from, to)
|
10
|
+
@local_path = from
|
11
|
+
end
|
12
|
+
|
13
|
+
def local_path
|
14
|
+
@local_path
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class TestFirewalldService < Test::Unit::TestCase
|
19
|
+
setup do
|
20
|
+
@resource = FirewalldService.new(stub, 'test-service')
|
21
|
+
end
|
22
|
+
|
23
|
+
sub_test_case '#action_delete' do
|
24
|
+
setup do
|
25
|
+
@resource.attributes.action = :delete
|
26
|
+
end
|
27
|
+
|
28
|
+
sub_test_case 'predefined service' do
|
29
|
+
setup do
|
30
|
+
@resource.expects(:run_command)
|
31
|
+
.with(['firewall-cmd', '--permanent', '--list-services'])
|
32
|
+
.returns(stub(stdout: 'service1 service2 test-service'))
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'delete service' do
|
36
|
+
@resource.expects(:run_command).with(['firewall-cmd', '--permanent', '--delete-service', 'test-service'])
|
37
|
+
@resource.expects(:notify)
|
38
|
+
@resource.run
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
sub_test_case 'undefined service' do
|
43
|
+
setup do
|
44
|
+
@resource.expects(:run_command)
|
45
|
+
.with(['firewall-cmd', '--permanent', '--list-services'])
|
46
|
+
.returns(stub(stdout: 'service1 service2'))
|
47
|
+
end
|
48
|
+
|
49
|
+
test 'delete service (noop)' do
|
50
|
+
@resource.expects(:notify).never
|
51
|
+
@resource.run
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
sub_test_case '#action_create' do
|
57
|
+
setup do
|
58
|
+
@resource.attributes.action = :create
|
59
|
+
@resource.stubs(:runner).returns(stub(tmpdir: ::Dir.tmpdir))
|
60
|
+
@resource.stubs(:move_file)
|
61
|
+
@resource.stubs(:run_specinfra).with(:move_file, is_a(String), is_a(String))
|
62
|
+
|
63
|
+
@resource.expects(:notify)
|
64
|
+
end
|
65
|
+
|
66
|
+
sub_test_case 'undefined service' do
|
67
|
+
setup do
|
68
|
+
@resource.stubs(:current_status).returns(:undefined)
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'create service' do
|
72
|
+
@resource.run
|
73
|
+
|
74
|
+
assert ::File.exists?(@resource.local_path )
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
sub_test_case 'predefined service' do
|
79
|
+
setup do
|
80
|
+
@resource.stubs(:current_status).returns(:defined)
|
81
|
+
@resource.stubs(:run_specinfra)
|
82
|
+
.with(:get_file_content, '/etc/firewalld/services/test-service.xml')
|
83
|
+
.returns(stub(stdout: <<-EOS))
|
84
|
+
<?xml version="1.0" encoding="utf-8"?>
|
85
|
+
<service>
|
86
|
+
<short>test-service</short>
|
87
|
+
<description>test-service description</description>
|
88
|
+
<port protocol="tcp" port="2222"/>
|
89
|
+
<module name="test-module"/>
|
90
|
+
<destination ipv4="224.0.0.251" ipv6="ff02::fb"/>
|
91
|
+
</service>
|
92
|
+
EOS
|
93
|
+
end
|
94
|
+
|
95
|
+
test 'update service' do
|
96
|
+
@resource.attributes.short = 'test-service!!'
|
97
|
+
@resource.attributes.description = 'test-service update description'
|
98
|
+
@resource.attributes.protocol = 'udp'
|
99
|
+
@resource.attributes.port = '2222-2224'
|
100
|
+
@resource.attributes.module_name = 'new-test-module'
|
101
|
+
@resource.attributes.to_ipv4 = '172.17.0.1'
|
102
|
+
@resource.attributes.to_ipv6 = 'ffff::fc'
|
103
|
+
@resource.run
|
104
|
+
|
105
|
+
root = REXML::Document.new(File.read(@resource.local_path))
|
106
|
+
service = root.elements['/service'].elements
|
107
|
+
|
108
|
+
assert_equal @resource.attributes.short, service['short'].text
|
109
|
+
assert_equal @resource.attributes.description, service['description'].text
|
110
|
+
assert_equal @resource.attributes.protocol, service['port'].attributes['protocol']
|
111
|
+
assert_equal @resource.attributes.port, service['port'].attributes['port']
|
112
|
+
assert_equal @resource.attributes.module_name, service['module'].attributes['name']
|
113
|
+
assert_equal @resource.attributes.to_ipv4, service['destination'].attributes['ipv4']
|
114
|
+
assert_equal @resource.attributes.to_ipv6, service['destination'].attributes['ipv6']
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itamae-plugin-resource-firewalld
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wataru MIYAGUNI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -113,8 +113,10 @@ files:
|
|
113
113
|
- itamae-plugin-resource-firewalld.gemspec
|
114
114
|
- lib/itamae/plugin/resource/firewalld.rb
|
115
115
|
- lib/itamae/plugin/resource/firewalld/version.rb
|
116
|
+
- lib/itamae/plugin/resource/firewalld_service.rb
|
116
117
|
- lib/itamae/plugin/resource/firewalld_zone.rb
|
117
118
|
- test/helper.rb
|
119
|
+
- test/itamae/plugin/resource/test_firewalld_service.rb
|
118
120
|
- test/itamae/plugin/resource/test_firewalld_zone.rb
|
119
121
|
homepage: https://github.com/gongo/itamae-plugin-resource-firewalld
|
120
122
|
licenses:
|
@@ -142,4 +144,5 @@ specification_version: 4
|
|
142
144
|
summary: Itamae resource plugin to manage firewalld.
|
143
145
|
test_files:
|
144
146
|
- test/helper.rb
|
147
|
+
- test/itamae/plugin/resource/test_firewalld_service.rb
|
145
148
|
- test/itamae/plugin/resource/test_firewalld_zone.rb
|