Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
slapos.core
Commits
7368822f
Commit
7368822f
authored
Oct 15, 2015
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'tap-nobridge' into 'master'
Tap nobridge See merge request !2
parents
0f48ce37
b8d90b26
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
566 additions
and
4 deletions
+566
-4
master/product/Vifib/Tool/SlapTool.py
master/product/Vifib/Tool/SlapTool.py
+49
-0
slapos/grid/slapgrid.py
slapos/grid/slapgrid.py
+294
-2
slapos/grid/templates/iptables-ipv4-firewall-add.in
slapos/grid/templates/iptables-ipv4-firewall-add.in
+0
-0
slapos/slap/interface/slap.py
slapos/slap/interface/slap.py
+6
-0
slapos/slap/slap.py
slapos/slap/slap.py
+9
-0
slapos/tests/slapgrid.py
slapos/tests/slapgrid.py
+208
-2
No files found.
master/product/Vifib/Tool/SlapTool.py
View file @
7368822f
...
@@ -272,6 +272,33 @@ class SlapTool(BaseTool):
...
@@ -272,6 +272,33 @@ class SlapTool(BaseTool):
self
.
_getSlapPartitionByPackingList
(
_assertACI
(
computer_partition
.
getObject
())))
self
.
_getSlapPartitionByPackingList
(
_assertACI
(
computer_partition
.
getObject
())))
return
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
)
return
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
)
@
UnrestrictedMethod
def
_getHostingSubscriptionIpList
(
self
,
computer_id
,
computer_partition_id
):
software_instance
=
self
.
_getSoftwareInstanceForComputerPartition
(
computer_id
,
computer_partition_id
)
if
software_instance
is
None
or
\
software_instance
.
getSlapState
()
==
'destroy_requested'
:
return
xml_marshaller
.
xml_marshaller
.
dumps
([])
# Search hosting subscription
hosting
=
software_instance
.
getSpecialiseValue
()
while
hosting
and
hosting
.
getPortalType
()
!=
"Hosting Subscription"
:
hosting
=
hosting
.
getSpecialiseValue
()
ip_address_list
=
[]
for
instance
in
hosting
.
getSpecialiseRelatedValueList
(
portal_type
=
"Software Instance"
):
computer_partition
=
instance
.
getAggregateValue
(
portal_type
=
"Computer Partition"
)
if
not
computer_partition
:
continue
for
internet_protocol_address
in
computer_partition
.
contentValues
(
portal_type
=
'Internet Protocol Address'
):
ip_address_list
.
append
(
(
internet_protocol_address
.
getNetworkInterface
(
''
).
decode
(
"UTF-8"
),
internet_protocol_address
.
getIpAddress
().
decode
(
"UTF-8"
))
)
return
xml_marshaller
.
xml_marshaller
.
dumps
(
ip_address_list
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getFullComputerInformation'
)
'getFullComputerInformation'
)
def
getFullComputerInformation
(
self
,
computer_id
):
def
getFullComputerInformation
(
self
,
computer_id
):
...
@@ -298,6 +325,28 @@ class SlapTool(BaseTool):
...
@@ -298,6 +325,28 @@ class SlapTool(BaseTool):
else
:
else
:
return
result
return
result
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getHostingSubscriptionIpList'
)
def
getHostingSubscriptionIpList
(
self
,
computer_id
,
computer_partition_id
):
"""
Search and return all Computer Partition IP address related to one
Hosting Subscription
"""
result
=
self
.
_getHostingSubscriptionIpList
(
computer_id
,
computer_partition_id
)
if
self
.
REQUEST
.
response
.
getStatus
()
==
200
:
# Keep in cache server for 7 days
self
.
REQUEST
.
response
.
setHeader
(
'Cache-Control'
,
'public, max-age=1, stale-if-error=604800'
)
self
.
REQUEST
.
response
.
setHeader
(
'Vary'
,
'REMOTE_USER'
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
DateTime
()))
self
.
REQUEST
.
response
.
setBody
(
result
)
return
self
.
REQUEST
.
response
else
:
return
result
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getComputerPartitionCertificate'
)
'getComputerPartitionCertificate'
)
def
getComputerPartitionCertificate
(
self
,
computer_id
,
computer_partition_id
):
def
getComputerPartitionCertificate
(
self
,
computer_id
,
computer_partition_id
):
...
...
slapos/grid/slapgrid.py
View file @
7368822f
...
@@ -40,6 +40,7 @@ import time
...
@@ -40,6 +40,7 @@ import time
import
traceback
import
traceback
import
warnings
import
warnings
import
logging
import
logging
import
json
if
sys
.
version_info
<
(
2
,
6
):
if
sys
.
version_info
<
(
2
,
6
):
warnings
.
warn
(
'Used python version (%s) is old and has problems with'
warnings
.
warn
(
'Used python version (%s) is old and has problems with'
...
@@ -56,9 +57,10 @@ from slapos.grid.svcbackend import (launchSupervisord,
...
@@ -56,9 +57,10 @@ from slapos.grid.svcbackend import (launchSupervisord,
createSupervisordConfiguration
,
createSupervisordConfiguration
,
_getSupervisordConfigurationDirectory
,
_getSupervisordConfigurationDirectory
,
_getSupervisordSocketPath
)
_getSupervisordSocketPath
)
from
slapos.grid.utils
import
(
md5digest
,
dropPrivileges
,
SlapPopen
)
from
slapos.grid.utils
import
(
md5digest
,
dropPrivileges
,
SlapPopen
,
updateFile
)
from
slapos.human
import
human2bytes
from
slapos.human
import
human2bytes
import
slapos.slap
import
slapos.slap
from
netaddr
import
valid_ipv4
,
valid_ipv6
# XXX: should be moved to SLAP library
# XXX: should be moved to SLAP library
...
@@ -166,6 +168,22 @@ def merged_options(args, configp):
...
@@ -166,6 +168,22 @@ def merged_options(args, configp):
url
.
strip
()
for
url
in
options
.
get
(
url
.
strip
()
for
url
in
options
.
get
(
"upload-to-binary-cache-url-blacklist"
,
""
).
split
(
'
\
n
'
)
if
url
]
"upload-to-binary-cache-url-blacklist"
,
""
).
split
(
'
\
n
'
)
if
url
]
options
[
'firewall'
]
=
{}
if
configp
.
has_section
(
'firewall'
):
options
[
'firewall'
]
=
dict
(
configp
.
items
(
'firewall'
))
options
[
'firewall'
][
"authorized_sources"
]
=
[
source
.
strip
()
for
source
in
options
[
'firewall'
].
get
(
"authorized_sources"
,
""
).
split
(
'
\
n
'
)
if
source
]
options
[
'firewall'
][
'firewall_cmd'
]
=
options
[
'firewall'
].
get
(
"firewall_cmd"
,
"firewall-cmd"
)
options
[
'firewall'
][
'firewall_executable'
]
=
options
[
'firewall'
].
get
(
"firewall_executable"
,
""
)
options
[
'firewall'
][
'dbus_executable'
]
=
options
[
'firewall'
].
get
(
"dbus_executable"
,
""
)
options
[
'firewall'
][
'reload_config_cmd'
]
=
options
[
'firewall'
].
get
(
"reload_config_cmd"
,
"slapos node restart firewall"
)
return
options
return
options
...
@@ -240,7 +258,8 @@ def create_slapgrid_object(options, logger):
...
@@ -240,7 +258,8 @@ def create_slapgrid_object(options, logger):
software_min_free_space
=
software_min_free_space
,
software_min_free_space
=
software_min_free_space
,
instance_min_free_space
=
instance_min_free_space
,
instance_min_free_space
=
instance_min_free_space
,
instance_storage_home
=
op
.
get
(
'instance_storage_home'
),
instance_storage_home
=
op
.
get
(
'instance_storage_home'
),
ipv4_global_network
=
op
.
get
(
'ipv4_global_network'
))
ipv4_global_network
=
op
.
get
(
'ipv4_global_network'
),
firewall_conf
=
op
.
get
(
'firewall'
))
def
check_required_only_partitions
(
existing
,
required
):
def
check_required_only_partitions
(
existing
,
required
):
...
@@ -298,6 +317,7 @@ class Slapgrid(object):
...
@@ -298,6 +317,7 @@ class Slapgrid(object):
instance_min_free_space
=
None
,
instance_min_free_space
=
None
,
instance_storage_home
=
None
,
instance_storage_home
=
None
,
ipv4_global_network
=
None
,
ipv4_global_network
=
None
,
firewall_conf
=
{},
):
):
"""Makes easy initialisation of class parameters"""
"""Makes easy initialisation of class parameters"""
# Parses arguments
# Parses arguments
...
@@ -359,6 +379,8 @@ class Slapgrid(object):
...
@@ -359,6 +379,8 @@ class Slapgrid(object):
self
.
ipv4_global_network
=
ipv4_global_network
self
.
ipv4_global_network
=
ipv4_global_network
else
:
else
:
self
.
ipv4_global_network
=
""
self
.
ipv4_global_network
=
""
self
.
firewall_conf
=
firewall_conf
def
_getWatchdogLine
(
self
):
def
_getWatchdogLine
(
self
):
invocation_list
=
[
WATCHDOG_PATH
]
invocation_list
=
[
WATCHDOG_PATH
]
...
@@ -370,6 +392,93 @@ class Slapgrid(object):
...
@@ -370,6 +392,93 @@ class Slapgrid(object):
invocation_list
.
append
(
"--instance-root '%s'"
%
self
.
instance_root
)
invocation_list
.
append
(
"--instance-root '%s'"
%
self
.
instance_root
)
return
' '
.
join
(
invocation_list
)
return
' '
.
join
(
invocation_list
)
def
_generateFirewallSupervisorConf
(
self
):
"""If firewall section is defined in slapos configuration, generate
supervisor configuration entry for firewall process.
"""
supervisord_conf_folder_path
=
os
.
path
.
join
(
self
.
instance_root
,
'etc'
,
'supervisord.conf.d'
)
supervisord_firewall_conf
=
os
.
path
.
join
(
supervisord_conf_folder_path
,
'firewall.conf'
)
if
not
self
.
firewall_conf
or
not
self
.
firewall_conf
.
get
(
'firewall_executable'
)
\
or
self
.
firewall_conf
.
get
(
'testing'
,
False
):
if
os
.
path
.
exists
(
supervisord_firewall_conf
):
os
.
unlink
(
supervisord_firewall_conf
)
return
supervisord_firewall_program_conf
=
"""
\
[program:firewall]
directory=/opt/slapos
command=%(firewall_executable)s
process_name=firewall
priority=5
autostart=true
autorestart=true
startsecs=0
startretries=0
exitcodes=0
stopsignal=TERM
stopwaitsecs=60
user=0
group=0
serverurl=AUTO
redirect_stderr=true
stdout_logfile=%(log_file)s
stdout_logfile_maxbytes=100KB
stdout_logfile_backups=1
stderr_logfile=%(log_file)s
stderr_logfile_maxbytes=100KB
stderr_logfile_backups=1
"""
%
{
'firewall_executable'
:
self
.
firewall_conf
[
'firewall_executable'
],
'log_file'
:
self
.
firewall_conf
.
get
(
'log_file'
,
'/var/log/firewall.log'
)}
if
not
os
.
path
.
exists
(
supervisord_conf_folder_path
):
os
.
makedirs
(
supervisord_conf_folder_path
)
updateFile
(
supervisord_firewall_conf
,
supervisord_firewall_program_conf
)
def
_generateDbusSupervisorConf
(
self
):
"""If dbus command is defined in slapos configuration, generate
supervisor configuration entry for dbus daemon.
"""
supervisord_conf_folder_path
=
os
.
path
.
join
(
self
.
instance_root
,
'etc'
,
'supervisord.conf.d'
)
supervisord_dbus_conf
=
os
.
path
.
join
(
supervisord_conf_folder_path
,
'dbus.conf'
)
if
not
self
.
firewall_conf
or
not
self
.
firewall_conf
.
get
(
'dbus_executable'
)
\
or
self
.
firewall_conf
.
get
(
'testing'
,
False
):
if
os
.
path
.
exists
(
supervisord_dbus_conf
):
os
.
unlink
(
supervisord_dbus_conf
)
return
supervisord_dbus_program_conf
=
"""
\
[program:dbus]
directory=/opt/slapos
command=%(dbus_executable)s
process_name=dbus
priority=1
autostart=true
autorestart=true
startsecs=0
startretries=0
exitcodes=0
stopsignal=TERM
stopwaitsecs=60
user=0
group=0
serverurl=AUTO
redirect_stderr=true
stdout_logfile=%(dbus_log_file)s
stdout_logfile_maxbytes=100KB
stdout_logfile_backups=1
stderr_logfile=%(dbus_log_file)s
stderr_logfile_maxbytes=100KB
stderr_logfile_backups=1
"""
%
{
'dbus_executable'
:
self
.
firewall_conf
[
'dbus_executable'
],
'dbus_log_file'
:
self
.
firewall_conf
.
get
(
'dbus_log_file'
,
'/var/log/dbus.log'
)}
if
not
os
.
path
.
exists
(
supervisord_conf_folder_path
):
os
.
makedirs
(
supervisord_conf_folder_path
)
updateFile
(
supervisord_dbus_conf
,
supervisord_dbus_program_conf
)
def
checkEnvironmentAndCreateStructure
(
self
):
def
checkEnvironmentAndCreateStructure
(
self
):
"""Checks for software_root and instance_root existence, then creates
"""Checks for software_root and instance_root existence, then creates
needed files and directories.
needed files and directories.
...
@@ -379,6 +488,8 @@ class Slapgrid(object):
...
@@ -379,6 +488,8 @@ class Slapgrid(object):
raise
OSError
(
'%s does not exist.'
%
self
.
software_root
)
raise
OSError
(
'%s does not exist.'
%
self
.
software_root
)
createSupervisordConfiguration
(
self
.
instance_root
,
self
.
_getWatchdogLine
())
createSupervisordConfiguration
(
self
.
instance_root
,
self
.
_getWatchdogLine
())
self
.
_generateFirewallSupervisorConf
()
self
.
_generateDbusSupervisorConf
()
def
_launchSupervisord
(
self
):
def
_launchSupervisord
(
self
):
if
not
self
.
forbid_supervisord_automatic_launch
:
if
not
self
.
forbid_supervisord_automatic_launch
:
...
@@ -543,6 +654,168 @@ class Slapgrid(object):
...
@@ -543,6 +654,168 @@ class Slapgrid(object):
if
not
promise_present
:
if
not
promise_present
:
self
.
logger
.
info
(
"No promise."
)
self
.
logger
.
info
(
"No promise."
)
def
_checkAddFirewallRules
(
self
,
partition_id
,
command_list
,
add
=
True
):
"""
"""
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
partition_id
)
firewall_rules
=
os
.
path
.
join
(
instance_path
,
'.slapos-firewalld-rules'
)
json_list
=
[]
reload_rules
=
False
if
os
.
path
.
exists
(
firewall_rules
):
with
open
(
firewall_rules
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
for
command
in
rules_list
:
skip_check
=
False
if
add
:
for
i
in
range
(
0
,
len
(
command_list
)):
new_cmd
=
command_list
[
i
]
if
command
==
new_cmd
:
json_list
.
append
(
command_list
.
pop
(
i
))
skip_check
=
True
break
# Only if add==True, do not try to remove the rule
if
skip_check
:
continue
# Check if this rule exists in iptables
check_cmd
=
command
.
replace
(
'--add-rule'
,
'--query-rule'
)
process
=
subprocess
.
Popen
(
check_cmd
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
shell
=
True
)
check_result
=
process
.
communicate
()[
0
]
self
.
logger
.
debug
(
'%s: %s'
%
(
check_cmd
,
check_result
))
if
check_result
.
strip
()
==
'yes'
:
reload_rules
=
True
command
=
command
.
replace
(
'--add-rule'
,
'--remove-rule'
)
self
.
logger
.
debug
(
command
)
cmd_process
=
subprocess
.
Popen
(
command
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
shell
=
True
)
result
=
cmd_process
.
communicate
()[
0
]
if
cmd_process
.
returncode
==
1
:
raise
Exception
(
"Failed to remove firewalld rule %s.
\
n
%s"
%
(
command
,
result
))
if
add
:
for
i
in
range
(
0
,
len
(
command_list
)):
reload_rules
=
True
command
=
command_list
.
pop
()
self
.
logger
.
debug
(
command
)
cmd_process
=
subprocess
.
Popen
(
command
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
shell
=
True
)
result
=
cmd_process
.
communicate
()[
0
]
if
cmd_process
.
returncode
==
1
:
raise
Exception
(
"Failed to add firewalld rule %s.
\
n
%s"
%
(
command
,
result
))
json_list
.
append
(
command
)
if
reload_rules
:
# Apply changes: reload configuration
# XXX - need to check firewalld reload instead of restart
self
.
logger
.
info
(
"Reloading firewall configuration..."
)
reload_cmd
=
self
.
firewall_conf
[
'reload_config_cmd'
]
reload_process
=
subprocess
.
Popen
(
reload_cmd
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
shell
=
True
)
result
=
reload_process
.
communicate
()[
0
]
if
reload_process
.
returncode
==
1
:
self
.
logger
.
error
(
'FirewallD Reload: %s'
%
result
)
raise
Exception
(
"Failed to load firewalld rules with command %s"
%
reload_cmd
)
with
open
(
firewall_rules
,
'w'
)
as
frules
:
frules
.
write
(
json
.
dumps
(
json_list
))
def
_getFirewallRules
(
self
,
ip
,
ip_list
,
ip_type
=
'ipv4'
):
"""
"""
if
ip_type
not
in
[
'ipv4'
,
'ipv6'
,
'eb'
]:
raise
NotImplementedError
(
"firewall-cmd has not rules with tables %s."
%
ip_type
)
fw_cmd
=
self
.
firewall_conf
[
'firewall_cmd'
]
command
=
'%s --permanent --direct --add-rule %s filter'
%
(
fw_cmd
,
ip_type
)
cmd_list
=
[]
for
other_ip
in
ip_list
:
# Configure INPUT rules
cmd_list
.
append
(
'%s INPUT 0 -s %s -d %s -j ACCEPT'
%
(
command
,
other_ip
,
ip
))
# Configure FORWARD rules
cmd_list
.
append
(
'%s FORWARD 0 -s %s -d %s -j ACCEPT'
%
(
command
,
other_ip
,
ip
))
# Drop all other requests
cmd_list
.
append
(
'%s INPUT 1000 -d %s -j DROP'
%
(
command
,
ip
))
cmd_list
.
append
(
'%s FORWARD 1000 -d %s -j DROP'
%
(
command
,
ip
))
cmd_list
.
append
(
'%s INPUT 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP'
%
(
command
,
ip
))
cmd_list
.
append
(
'%s FORWARD 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP'
%
(
command
,
ip
))
return
cmd_list
def
_setupComputerPartitionFirewall
(
self
,
computer_partition
,
ip_list
,
authorized_ip_list
,
drop_entries
=
False
):
"""
Using linux iptables, limit access to IP of this partition to all
others partitions of the same Hosting Subscription
"""
ipv4_list
=
[]
ipv6_list
=
[]
authorized_ipv4_list
=
[]
authorized_ipv6_list
=
[]
for
net_ip
in
ip_list
:
iface
,
ip
=
(
net_ip
[
0
],
net_ip
[
1
])
if
not
iface
.
startswith
(
'route_'
):
continue
if
valid_ipv4
(
ip
):
ipv4_list
.
append
(
ip
)
elif
valid_ipv6
(
ip
):
ipv6_list
.
append
(
ip
)
for
iface
,
ip
in
authorized_ip_list
:
if
valid_ipv4
(
ip
):
if
not
ip
in
ipv4_list
:
authorized_ipv4_list
.
append
(
ip
)
elif
valid_ipv6
(
ip
):
if
not
ip
in
ipv6_list
:
authorized_ipv6_list
.
append
(
ip
)
filter_dict
=
getattr
(
computer_partition
,
'_filter_dict'
,
None
)
extra_list
=
[]
if
filter_dict
is
not
None
:
extra_list
=
filter_dict
.
get
(
'authorized_sources'
,
''
).
split
(
' '
)
extra_list
.
extend
(
self
.
firewall_conf
.
get
(
'authorized_sources'
,
[]))
for
ip
in
extra_list
:
if
not
ip
:
continue
the_ip
=
ip
.
split
(
'/'
)[
0
]
if
valid_ipv4
(
the_ip
):
authorized_ipv4_list
.
append
(
ip
)
elif
valid_ipv6
(
the_ip
):
authorized_ipv6_list
.
append
(
ip
)
if
not
drop_entries
:
self
.
logger
.
info
(
"Configuring firewall..."
)
add_rules
=
True
else
:
add_rules
=
False
self
.
logger
.
info
(
"Removing firewall configuration..."
)
for
ip
in
ipv4_list
:
cmd_list
=
self
.
_getFirewallRules
(
ip
,
authorized_ipv4_list
,
ip_type
=
'ipv4'
)
self
.
_checkAddFirewallRules
(
computer_partition
.
getId
(),
cmd_list
,
add
=
add_rules
)
def
processComputerPartition
(
self
,
computer_partition
):
def
processComputerPartition
(
self
,
computer_partition
):
"""
"""
Process a Computer Partition, depending on its state
Process a Computer Partition, depending on its state
...
@@ -677,10 +950,20 @@ class Slapgrid(object):
...
@@ -677,10 +950,20 @@ class Slapgrid(object):
# self.logger.info(' Instance type: %s' % computer_partition.getType())
# self.logger.info(' Instance type: %s' % computer_partition.getType())
self
.
logger
.
info
(
' Instance status: %s'
%
computer_partition_state
)
self
.
logger
.
info
(
' Instance status: %s'
%
computer_partition_state
)
partition_ip_list
=
full_hosting_ip_list
=
[]
if
self
.
firewall_conf
:
partition_ip_list
=
parameter_dict
[
'ip_list'
]
+
parameter_dict
.
get
(
'full_ip_list'
,
[])
full_hosting_ip_list
=
computer_partition
.
getFullHostingIpAddressList
()
if
computer_partition_state
==
COMPUTER_PARTITION_STARTED_STATE
:
if
computer_partition_state
==
COMPUTER_PARTITION_STARTED_STATE
:
local_partition
.
install
()
local_partition
.
install
()
computer_partition
.
available
()
computer_partition
.
available
()
local_partition
.
start
()
local_partition
.
start
()
if
self
.
firewall_conf
:
self
.
_setupComputerPartitionFirewall
(
computer_partition
,
partition_ip_list
,
full_hosting_ip_list
)
self
.
_checkPromises
(
computer_partition
)
self
.
_checkPromises
(
computer_partition
)
computer_partition
.
started
()
computer_partition
.
started
()
elif
computer_partition_state
==
COMPUTER_PARTITION_STOPPED_STATE
:
elif
computer_partition_state
==
COMPUTER_PARTITION_STOPPED_STATE
:
...
@@ -689,12 +972,21 @@ class Slapgrid(object):
...
@@ -689,12 +972,21 @@ class Slapgrid(object):
# propagate the state to children if any.
# propagate the state to children if any.
local_partition
.
install
()
local_partition
.
install
()
computer_partition
.
available
()
computer_partition
.
available
()
if
self
.
firewall_conf
:
self
.
_setupComputerPartitionFirewall
(
computer_partition
,
partition_ip_list
,
full_hosting_ip_list
)
finally
:
finally
:
# Instance has to be stopped even if buildout/reporting is wrong.
# Instance has to be stopped even if buildout/reporting is wrong.
local_partition
.
stop
()
local_partition
.
stop
()
computer_partition
.
stopped
()
computer_partition
.
stopped
()
elif
computer_partition_state
==
COMPUTER_PARTITION_DESTROYED_STATE
:
elif
computer_partition_state
==
COMPUTER_PARTITION_DESTROYED_STATE
:
local_partition
.
stop
()
local_partition
.
stop
()
if
self
.
firewall_conf
:
self
.
_setupComputerPartitionFirewall
(
computer_partition
,
partition_ip_list
,
full_hosting_ip_list
,
drop_entries
=
True
)
try
:
try
:
computer_partition
.
stopped
()
computer_partition
.
stopped
()
except
(
SystemExit
,
KeyboardInterrupt
):
except
(
SystemExit
,
KeyboardInterrupt
):
...
...
slapos/grid/templates/iptables-ipv4-firewall-add.in
0 → 100644
View file @
7368822f
slapos/slap/interface/slap.py
View file @
7368822f
...
@@ -331,6 +331,12 @@ class IComputerPartition(IBuildoutController, IRequester):
...
@@ -331,6 +331,12 @@ class IComputerPartition(IBuildoutController, IRequester):
text -- message log of the status
text -- message log of the status
"""
"""
def
getFullHostingIpAddressList
():
"""
Returns a dictionnary containing the latest status of the
computer partition.
"""
class
IComputer
(
Interface
):
class
IComputer
(
Interface
):
"""
"""
Computer interface specification
Computer interface specification
...
...
slapos/slap/slap.py
View file @
7368822f
...
@@ -606,6 +606,15 @@ class ComputerPartition(SlapRequester):
...
@@ -606,6 +606,15 @@ class ComputerPartition(SlapRequester):
}
}
)
)
return
xml_marshaller
.
loads
(
xml
)
return
xml_marshaller
.
loads
(
xml
)
def
getFullHostingIpAddressList
(
self
):
xml
=
self
.
_connection_helper
.
GET
(
'getHostingSubscriptionIpList'
,
params
=
{
'computer_id'
:
self
.
_computer_id
,
'computer_partition_id'
:
self
.
_partition_id
,
}
)
return
xml_marshaller
.
loads
(
xml
)
def
_addIpv6Brackets
(
url
):
def
_addIpv6Brackets
(
url
):
# if master_url contains an ipv6 without bracket, add it
# if master_url contains an ipv6 without bracket, add it
...
...
slapos/tests/slapgrid.py
View file @
7368822f
...
@@ -39,6 +39,7 @@ import textwrap
...
@@ -39,6 +39,7 @@ import textwrap
import
time
import
time
import
unittest
import
unittest
import
urlparse
import
urlparse
import
json
import
xml_marshaller
import
xml_marshaller
from
mock
import
patch
from
mock
import
patch
...
@@ -283,6 +284,11 @@ class ComputerForTest(object):
...
@@ -283,6 +284,11 @@ class ComputerForTest(object):
self
.
software_amount
=
software_amount
self
.
software_amount
=
software_amount
self
.
software_root
=
software_root
self
.
software_root
=
software_root
self
.
instance_root
=
instance_root
self
.
instance_root
=
instance_root
self
.
ip_address_list
=
[
(
'interface1'
,
'10.0.8.3'
),
(
'interface2'
,
'10.0.8.4'
),
(
'route_interface1'
,
'10.10.8.4'
)
]
if
not
os
.
path
.
isdir
(
self
.
instance_root
):
if
not
os
.
path
.
isdir
(
self
.
instance_root
):
os
.
mkdir
(
self
.
instance_root
)
os
.
mkdir
(
self
.
instance_root
)
if
not
os
.
path
.
isdir
(
self
.
software_root
):
if
not
os
.
path
.
isdir
(
self
.
software_root
):
...
@@ -309,6 +315,12 @@ class ComputerForTest(object):
...
@@ -309,6 +315,12 @@ class ComputerForTest(object):
'status_code'
:
200
,
'status_code'
:
200
,
'content'
:
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
)
'content'
:
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
)
}
}
elif
url
.
path
==
'/getHostingSubscriptionIpList'
:
ip_address_list
=
self
.
ip_address_list
return
{
'status_code'
:
200
,
'content'
:
xml_marshaller
.
xml_marshaller
.
dumps
(
ip_address_list
)
}
if
req
.
method
==
'POST'
and
'computer_partition_id'
in
qs
:
if
req
.
method
==
'POST'
and
'computer_partition_id'
in
qs
:
instance
=
self
.
instance_list
[
int
(
qs
[
'computer_partition_id'
][
0
])]
instance
=
self
.
instance_list
[
int
(
qs
[
'computer_partition_id'
][
0
])]
instance
.
sequence
.
append
(
url
.
path
)
instance
.
sequence
.
append
(
url
.
path
)
...
@@ -417,8 +429,11 @@ class InstanceForTest(object):
...
@@ -417,8 +429,11 @@ class InstanceForTest(object):
self
.
partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
self
.
name
)
self
.
partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
self
.
name
)
os
.
mkdir
(
self
.
partition_path
,
0o750
)
os
.
mkdir
(
self
.
partition_path
,
0o750
)
self
.
timestamp
=
None
self
.
timestamp
=
None
self
.
ip_list
=
[(
'interface0'
,
'10.0.8.2'
)]
self
.
full_ip_list
=
[(
'route_interface0'
,
'10.10.2.3'
,
'10.10.0.1'
,
'255.0.0.0'
,
'10.0.0.0'
)]
def
getInstance
(
self
,
computer_id
):
def
getInstance
(
self
,
computer_id
,
):
"""
"""
Will return current requested state of instance
Will return current requested state of instance
"""
"""
...
@@ -427,9 +442,13 @@ class InstanceForTest(object):
...
@@ -427,9 +442,13 @@ class InstanceForTest(object):
partition
.
_requested_state
=
self
.
requested_state
partition
.
_requested_state
=
self
.
requested_state
if
getattr
(
self
,
'filter_dict'
,
None
):
if
getattr
(
self
,
'filter_dict'
,
None
):
partition
.
_filter_dict
=
self
.
filter_dict
partition
.
_filter_dict
=
self
.
filter_dict
partition
.
_parameter_dict
=
{
'ip_list'
:
self
.
ip_list
,
'full_ip_list'
:
self
.
full_ip_list
}
if
self
.
software
is
not
None
:
if
self
.
software
is
not
None
:
if
self
.
timestamp
is
not
None
:
if
self
.
timestamp
is
not
None
:
partition
.
_parameter_dict
=
{
'timestamp'
:
self
.
timestamp
}
partition
.
_parameter_dict
[
'timestamp'
]
=
self
.
timestamp
return
partition
return
partition
def
getSoftwareRelease
(
self
):
def
getSoftwareRelease
(
self
):
...
@@ -1952,3 +1971,190 @@ class TestSlapgridDestructionLock(MasterMixin, unittest.TestCase):
...
@@ -1952,3 +1971,190 @@ class TestSlapgridDestructionLock(MasterMixin, unittest.TestCase):
self
.
grid
.
agregateAndSendUsage
()
self
.
grid
.
agregateAndSendUsage
()
self
.
assertFalse
(
os
.
path
.
exists
(
dummy_instance_file_path
))
self
.
assertFalse
(
os
.
path
.
exists
(
dummy_instance_file_path
))
class
TestSlapgridCPWithFirewall
(
MasterMixin
,
unittest
.
TestCase
):
def
setFirewallConfig
(
self
,
source_ip
=
""
):
firewall_conf
=
dict
(
authorized_sources
=
source_ip
,
firewall_cmd
=
'/bin/echo'
,
firewall_executable
=
'/bin/echo "service firewall started"'
,
reload_config_cmd
=
'/bin/echo "Config reloaded."'
,
log_file
=
'fw-log.log'
,
testing
=
True
,
)
self
.
grid
.
firewall_conf
=
firewall_conf
def
checkRuleFromIpSource
(
self
,
ip
,
cmd_list
):
# XXX - rules for one ip contain 2*len(ip_address_list) rules ACCEPT and 4 rules DROP
num_rules
=
len
(
self
.
ip_address_list
)
*
2
+
4
self
.
assertEqual
(
len
(
cmd_list
),
num_rules
)
base_cmd
=
'%s --permanent --direct --add-rule ipv4 filter'
%
self
.
grid
.
firewall_conf
[
'firewall_cmd'
]
# Check that there is DROP rule on INPUT
rule
=
'%s INPUT 1000 -d %s -j DROP'
%
(
base_cmd
,
ip
)
self
.
assertIn
(
rule
,
cmd_list
)
# Check that there is DROP rule on FORWARD
rule
=
'%s FORWARD 1000 -d %s -j DROP'
%
(
base_cmd
,
ip
)
self
.
assertIn
(
rule
,
cmd_list
)
# Check that there is DROP rule on INPUT, ESTABLISHED,RELATED
rule
=
'%s INPUT 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP'
%
(
base_cmd
,
ip
)
self
.
assertIn
(
rule
,
cmd_list
)
# Check that there is DROP rule on FORWARD, ESTABLISHED,RELATED
rule
=
'%s FORWARD 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP'
%
(
base_cmd
,
ip
)
self
.
assertIn
(
rule
,
cmd_list
)
# Check that there is INPUT ACCEPT on ip_list
for
_
,
other_ip
in
self
.
ip_address_list
:
rule
=
'%s INPUT 0 -s %s -d %s -j ACCEPT'
%
(
base_cmd
,
other_ip
,
ip
)
self
.
assertIn
(
rule
,
cmd_list
)
# Check that there is FORWARD ACCEPT on ip_list
for
_
,
other_ip
in
self
.
ip_address_list
:
rule
=
'%s FORWARD 0 -s %s -d %s -j ACCEPT'
%
(
base_cmd
,
other_ip
,
ip
)
self
.
assertIn
(
rule
,
cmd_list
)
def
test_getFirewallRules
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
)
self
.
setFirewallConfig
()
self
.
ip_address_list
=
computer
.
ip_address_list
ip
=
computer
.
instance_list
[
0
].
full_ip_list
[
0
][
1
]
cmd_list
=
self
.
grid
.
_getFirewallRules
(
ip
,
[
elt
[
1
]
for
elt
in
self
.
ip_address_list
],
ip_type
=
'ipv4'
)
self
.
checkRuleFromIpSource
(
ip
,
cmd_list
)
def
test_checkAddFirewallRules
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
)
self
.
setFirewallConfig
()
self
.
grid
.
firewall_conf
[
'firewall_cmd'
]
=
'/bin/echo "yes" #'
self
.
ip_address_list
=
computer
.
ip_address_list
instance
=
computer
.
instance_list
[
0
]
ip
=
instance
.
full_ip_list
[
0
][
1
]
name
=
computer
.
instance_list
[
0
].
name
cmd_list
=
self
.
grid
.
_getFirewallRules
(
ip
,
[
elt
[
1
]
for
elt
in
self
.
ip_address_list
],
ip_type
=
'ipv4'
)
self
.
grid
.
_checkAddFirewallRules
(
name
,
cmd_list
,
add
=
True
)
rules_path
=
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)
with
open
(
rules_path
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
self
.
checkRuleFromIpSource
(
ip
,
rules_list
)
# Remove all rules
self
.
grid
.
_checkAddFirewallRules
(
name
,
cmd_list
,
add
=
False
)
with
open
(
rules_path
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
self
.
assertEqual
(
rules_list
,
[])
# Add one more ip in the authorized list
self
.
ip_address_list
.
append
((
'interface1'
,
'10.0.8.7'
))
cmd_list
=
self
.
grid
.
_getFirewallRules
(
ip
,
[
elt
[
1
]
for
elt
in
self
.
ip_address_list
],
ip_type
=
'ipv4'
)
self
.
grid
.
_checkAddFirewallRules
(
name
,
cmd_list
,
add
=
True
)
with
open
(
rules_path
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
self
.
checkRuleFromIpSource
(
ip
,
rules_list
)
def
test_partition_no_firewall
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
)
with
httmock
.
HTTMock
(
computer
.
request_handler
):
instance
=
computer
.
instance_list
[
0
]
self
.
assertEqual
(
self
.
grid
.
processComputerPartitionList
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertFalse
(
os
.
path
.
exists
(
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)))
def
test_partition_firewall
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
)
self
.
setFirewallConfig
()
with
httmock
.
HTTMock
(
computer
.
request_handler
):
instance
=
computer
.
instance_list
[
0
]
self
.
assertEqual
(
self
.
grid
.
processComputerPartitionList
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertTrue
(
os
.
path
.
exists
(
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)))
rules_path
=
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)
self
.
ip_address_list
=
computer
.
ip_address_list
with
open
(
rules_path
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
self
.
assertEqual
(
len
(
rules_list
),
len
(
self
.
ip_address_list
)
*
2
+
4
)
ip
=
instance
.
full_ip_list
[
0
][
1
]
self
.
checkRuleFromIpSource
(
ip
,
rules_list
)
def
test_partition_firewall_ipsource
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
)
self
.
setFirewallConfig
()
source_ip
=
[
'10.0.8.10'
]
self
.
grid
.
firewall_conf
[
'authorized_sources'
]
=
source_ip
with
httmock
.
HTTMock
(
computer
.
request_handler
):
instance
=
computer
.
instance_list
[
0
]
self
.
assertEqual
(
self
.
grid
.
processComputerPartitionList
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertTrue
(
os
.
path
.
exists
(
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)))
rules_path
=
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)
rules_list
=
[]
self
.
ip_address_list
=
computer
.
ip_address_list
+
[(
'iface'
,
ip
)
for
ip
in
source_ip
]
ip
=
instance
.
full_ip_list
[
0
][
1
]
base_cmd
=
'%s --permanent --direct --add-rule ipv4 filter'
%
self
.
grid
.
firewall_conf
[
'firewall_cmd'
]
with
open
(
rules_path
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
self
.
assertEqual
(
len
(
rules_list
),
len
(
self
.
ip_address_list
)
*
2
+
4
)
rule_input
=
'%s INPUT 0 -s %s -d %s -j ACCEPT'
%
(
base_cmd
,
source_ip
[
0
],
ip
)
self
.
assertIn
(
rule_input
,
rules_list
)
rule_fwd
=
'%s FORWARD 0 -s %s -d %s -j ACCEPT'
%
(
base_cmd
,
source_ip
[
0
],
ip
)
self
.
assertIn
(
rule_fwd
,
rules_list
)
self
.
checkRuleFromIpSource
(
ip
,
rules_list
)
def
test_partition_firewall_ip_parameter
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
)
self
.
setFirewallConfig
()
source_ip
=
'10.0.8.10'
with
httmock
.
HTTMock
(
computer
.
request_handler
):
instance
=
computer
.
instance_list
[
0
]
instance
.
filter_dict
=
{
'authorized_sources'
:
source_ip
}
self
.
assertEqual
(
self
.
grid
.
processComputerPartitionList
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertTrue
(
os
.
path
.
exists
(
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)))
rules_path
=
os
.
path
.
join
(
instance
.
partition_path
,
'.slapos-firewalld-rules'
)
rules_list
=
[]
self
.
ip_address_list
=
computer
.
ip_address_list
+
[(
'iface'
,
ip
)
for
ip
in
source_ip
.
split
(
' '
)]
ip
=
instance
.
full_ip_list
[
0
][
1
]
base_cmd
=
'%s --permanent --direct --add-rule ipv4 filter'
%
self
.
grid
.
firewall_conf
[
'firewall_cmd'
]
with
open
(
rules_path
,
'r'
)
as
frules
:
rules_list
=
json
.
loads
(
frules
.
read
())
self
.
assertEqual
(
len
(
rules_list
),
len
(
self
.
ip_address_list
)
*
2
+
4
)
rule_input
=
'%s INPUT 0 -s %s -d %s -j ACCEPT'
%
(
base_cmd
,
source_ip
,
ip
)
self
.
assertIn
(
rule_input
,
rules_list
)
rule_fwd
=
'%s FORWARD 0 -s %s -d %s -j ACCEPT'
%
(
base_cmd
,
source_ip
,
ip
)
self
.
assertIn
(
rule_fwd
,
rules_list
)
self
.
checkRuleFromIpSource
(
ip
,
rules_list
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment