Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
R
router_services
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Code Review
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nova
router_services
Commits
166dae9c
Commit
166dae9c
authored
Nov 27, 2013
by
Sigmund Augdal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First shot at code to generate ipset/iptables commands out of security groups
parent
9ce0f34c
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
169 additions
and
0 deletions
+169
-0
iptables_configurator.py
iptables_configurator.py
+169
-0
No files found.
iptables_configurator.py
0 → 100644
View file @
166dae9c
#!/usr/bin/env python
import
etcd
import
os
import
os.path
import
subprocess
import
logging
import
logging.handlers
import
time
import
argparse
import
daemon
import
sys
try
:
from
daemon.pidfile
import
TimeoutPIDLockFile
except
ImportError
:
from
daemon.pidlockfile
import
TimeoutPIDLockFile
from
nova_router
import
security_groups
CONF_FILE
=
"/etc/haproxy/haproxy.cfg"
def
etcd_get_dict
(
etcd_client
,
prefix
):
result
=
dict
()
for
key
in
etcd_client
.
list
(
prefix
):
if
not
key
.
dir
:
result
[
key
.
key
.
split
(
'/'
)[
-
1
]]
=
key
.
value
return
result
def
etcd_get_dirs
(
etcd_client
,
prefix
):
result
=
set
()
for
key
in
etcd_client
.
list
(
prefix
):
if
key
.
dir
:
result
.
add
(
key
.
key
.
split
(
'/'
)[
-
1
])
return
result
def
escape_group_name
(
name
):
name
=
name
.
replace
(
" "
,
"_"
)
name
=
name
.
replace
(
"
\t
"
,
"_"
)
return
name
class
Generator
(
object
):
def
__init__
(
self
,
cert
,
key
,
cacert
,
logfile
=
None
):
self
.
etcd_client
=
etcd
.
Etcd
(
ssl_key
=
key
,
ssl_cert
=
cert
,
verify
=
cacert
)
if
logfile
:
handler
=
logging
.
handlers
.
RotatingFileHandler
(
logfile
,
maxBytes
=
10
*
1024
**
3
,
backupCount
=
5
)
logging
.
getLogger
(
""
).
addHandler
(
handler
)
self
.
range
=
[
150
,
200
]
self
.
prefix
=
"158.38.213."
def
output
(
self
,
line
):
self
.
output_file
.
write
(
line
)
self
.
output_file
.
write
(
"
\n
"
)
def
create_ipset
(
self
,
name
,
set_type
):
name
=
escape_group_name
(
name
)
for
family
in
(
"inet"
,
"inet6"
):
self
.
output
(
"ipset create {}_{} {} family {}"
.
format
(
name
,
family
,
set_type
,
family
))
def
add_ipset_member
(
self
,
name
,
member
,
protocol
=
"tcp"
,
port
=
None
,
net
=
None
):
name
=
escape_group_name
(
name
)
suffix
=
""
if
port
is
not
None
:
suffix
+=
",{}:{}"
.
format
(
protocol
,
port
)
if
net
is
not
None
:
suffix
+=
",{}"
.
format
(
net
)
member
=
member
.
lower
()
if
member
in
self
.
addresses_v4
and
(
net
is
None
or
"."
in
net
):
self
.
output
(
"ipset add {}_inet {}{}"
.
format
(
name
,
self
.
addresses_v4
[
member
],
suffix
))
if
member
in
self
.
addresses_v6
and
(
net
is
None
or
":"
in
net
):
self
.
output
(
"ipset add {}_inet6 {}{}"
.
format
(
name
,
self
.
addresses_v6
[
member
],
suffix
))
def
process_security_group
(
self
,
group_id
,
name
):
rules
=
security_groups
.
get_group_rules
(
self
.
etcd_client
,
group_id
)
_
,
members
=
security_groups
.
get_group_members
(
self
.
etcd_client
,
group_id
)
source_group
=
"source_{}"
.
format
(
group_id
)
self
.
create_ipset
(
source_group
,
"hash:ip"
)
for
member
in
members
:
self
.
add_ipset_member
(
source_group
,
member
)
for
rule
in
rules
:
for
member
in
members
:
if
rule
[
"source_type"
]
==
"any"
:
self
.
add_ipset_member
(
"rules_from_any"
,
member
,
rule
[
"protocol"
],
rule
[
"destination_port"
])
elif
rule
[
"source_type"
]
==
"cidr"
:
self
.
add_ipset_member
(
"rule_from_cidr"
,
member
,
rule
[
"protocol"
],
rule
[
"destination_port"
],
rule
[
"source_cidr"
])
elif
rule
[
"source_type"
]
==
"security_group"
:
source_group
=
rule
[
"source_security_group"
]
set_name
=
"rule_from_group_{}"
.
format
(
escape_group_name
(
source_group
))
if
source_group
not
in
self
.
source_sets
:
self
.
create_ipset
(
set_name
,
"hash:ip,port"
)
self
.
source_sets
[
source_group
]
=
set_name
self
.
add_ipset_member
(
set_name
,
member
,
rule
[
"protocol"
],
rule
[
"destination_port"
])
else
:
logging
.
warning
(
"Unhandled source type: %s"
,
rule
[
"source_type"
])
def
get_addresses
(
self
,
addrtype
):
addresses
=
{}
for
entry
in
self
.
etcd_client
.
list
(
"/nova/iaas/instances"
):
if
not
entry
.
dir
:
next
mac
=
entry
.
key
.
split
(
"/"
)[
-
1
]
try
:
ipaddr
=
self
.
etcd_client
.
get
(
entry
.
key
+
"/"
+
addrtype
).
value
addresses
[
mac
]
=
ipaddr
except
etcd
.
EtcdError
as
ex
:
if
ex
.
args
[
0
]
!=
100
:
raise
ex
return
addresses
def
generate_all
(
self
):
index
=
None
self
.
addresses_v4
=
self
.
get_addresses
(
"ipv4"
)
self
.
addresses_v6
=
self
.
get_addresses
(
"ipv6_public"
)
self
.
source_sets
=
{}
self
.
output_file
=
open
(
"output.sh"
,
"w"
)
self
.
create_ipset
(
"rules_from_any"
,
"hash:ip,port"
)
self
.
create_ipset
(
"rules_from_cidr"
,
"hash:ip,port,net"
)
groups
=
security_groups
.
get_security_groups
(
self
.
etcd_client
)
for
group_id
,
name
in
groups
.
items
():
self
.
process_security_group
(
group_id
,
name
)
self
.
output
(
"iptables -A FORWARD -m set --match-set rules_from_any_inet dst,dst -j ACCEPT"
)
self
.
output
(
"ip6tables -A FORWARD -m set --match-set rules_from_any_inet6 dst,dst -j ACCEPT"
)
self
.
output
(
"iptables -A FORWARD -m set --match-set rules_from_cidr_inet dst,dst,src -j ACCEPT"
)
self
.
output
(
"ip6tables -A FORWARD -m set --match-set rules_from_cidr_inet6 dst,dst,src -j ACCEPT"
)
for
source_group
,
destination_set
in
self
.
source_sets
.
items
():
self
.
output
(
"iptables -A FORWARD -m set --match-set {}_inet dst,dst --match-set source_{}_inet src -j ACCEPT"
.
format
(
destination_set
,
source_group
))
self
.
output
(
"ip6tables -A FORWARD -m set --match-set {}_inet6 dst,dst --match-set source_{}_inet6 src -j ACCEPT"
.
format
(
destination_set
,
source_group
))
return
index
def
main
(
self
):
index
=
self
.
generate_all
()
sys
.
exit
(
0
)
while
True
:
data
=
self
.
etcd_client
.
watch
(
"/nova/iaas/instances"
,
index
+
1
)
logging
.
debug
(
"new config index %d"
,
data
.
index
)
time
.
sleep
(
1
)
index
=
self
.
generate_all
()
def
parse_args
():
parser
=
argparse
.
ArgumentParser
(
description
=
"Configure haproxy based on data from etcd"
)
parser
.
add_argument
(
'-d'
,
'--daemonize'
,
default
=
False
,
action
=
'store_true'
,
help
=
"Run as daemon"
)
parser
.
add_argument
(
'--pidfile'
,
type
=
str
,
default
=
"/var/run/nova_lb_configuration.pid"
,
help
=
"pidfile when run as daemon"
)
parser
.
add_argument
(
'--cert'
,
default
=
"client.crt"
,
help
=
"client certificate to use"
)
parser
.
add_argument
(
'--key'
,
default
=
"client.key"
,
help
=
"private key to use for client certificate"
)
parser
.
add_argument
(
'--cacert'
,
default
=
"etcd_ca.crt"
,
help
=
"ca certificate to use"
)
return
parser
.
parse_args
()
if
__name__
==
'__main__'
:
logging
.
basicConfig
(
level
=
logging
.
DEBUG
)
logging
.
getLogger
(
"requests"
).
setLevel
(
logging
.
WARNING
)
args
=
parse_args
()
if
args
.
daemonize
:
logfile
=
'/var/log/nova_loadbalancer_configurator.log'
daemon_context
=
daemon
.
DaemonContext
(
pidfile
=
TimeoutPIDLockFile
(
args
.
pidfile
))
with
daemon_context
:
Generator
(
args
.
cert
,
args
.
key
,
args
.
cacert
,
logfile
=
logfile
).
main
()
else
:
Generator
(
args
.
cert
,
args
.
key
,
args
.
cacert
).
main
()
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