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
Xiaowu Zhang
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
Show 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
...
@@ -607,6 +607,15 @@ class ComputerPartition(SlapRequester):
...
@@ -607,6 +607,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
# Note that this is mostly to limit specific issues with
# Note that this is mostly to limit specific issues with
...
...
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