Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gutyán Gábor
/
circlestack
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
9fb5f44b
authored
Mar 03, 2015
by
Bach Dániel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature-fw-api' into 'master'
Feature fw api
✅
See merge request !297
parents
59cb3f57
4a0abb1e
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
182 additions
and
109 deletions
+182
-109
circle/circle/settings/base.py
+3
-0
circle/circle/urls.py
+2
-7
circle/firewall/admin.py
+2
-1
circle/firewall/fw.py
+3
-6
circle/firewall/migrations/0003_auto_20150226_1927.py
+48
-0
circle/firewall/models.py
+13
-14
circle/firewall/tasks/local_tasks.py
+1
-0
circle/firewall/views.py
+71
-43
circle/network/forms.py
+3
-1
circle/network/tables.py
+6
-3
circle/network/views.py
+30
-34
No files found.
circle/circle/settings/base.py
View file @
9fb5f44b
...
@@ -564,3 +564,6 @@ MAX_NODE_RAM = get_env_variable("MAX_NODE_RAM", 1024)
...
@@ -564,3 +564,6 @@ MAX_NODE_RAM = get_env_variable("MAX_NODE_RAM", 1024)
CLIENT_DOWNLOAD_URL
=
get_env_variable
(
'CLIENT_DOWNLOAD_URL'
,
'http://circlecloud.org/client/download/'
)
CLIENT_DOWNLOAD_URL
=
get_env_variable
(
'CLIENT_DOWNLOAD_URL'
,
'http://circlecloud.org/client/download/'
)
ADMIN_ENABLED
=
False
ADMIN_ENABLED
=
False
BLACKLIST_PASSWORD
=
get_env_variable
(
"BLACKLIST_PASSWORD"
,
""
)
BLACKLIST_HOOK_URL
=
get_env_variable
(
"BLACKLIST_HOOK_URL"
,
""
)
circle/circle/urls.py
View file @
9fb5f44b
...
@@ -27,21 +27,16 @@ from django.shortcuts import redirect
...
@@ -27,21 +27,16 @@ from django.shortcuts import redirect
from
circle.settings.base
import
get_env_variable
from
circle.settings.base
import
get_env_variable
from
dashboard.views
import
circle_login
,
HelpView
from
dashboard.views
import
circle_login
,
HelpView
from
dashboard.forms
import
CirclePasswordResetForm
,
CircleSetPasswordForm
from
dashboard.forms
import
CirclePasswordResetForm
,
CircleSetPasswordForm
from
firewall.views
import
add_blacklist_item
admin
.
autodiscover
()
admin
.
autodiscover
()
urlpatterns
=
patterns
(
urlpatterns
=
patterns
(
''
,
''
,
# url(r'^$', TemplateView.as_view(template_name='base.html')),
# Examples:
# url(r'^$', 'circle.views.home', name='home'),
# url(r'^circle/', include('circle.foo.urls')),
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url
(
r'^$'
,
lambda
x
:
redirect
(
reverse
(
"dashboard.index"
))),
url
(
r'^$'
,
lambda
x
:
redirect
(
reverse
(
"dashboard.index"
))),
url
(
r'^network/'
,
include
(
'network.urls'
)),
url
(
r'^network/'
,
include
(
'network.urls'
)),
url
(
r'^blacklist-add/'
,
add_blacklist_item
),
url
(
r'^dashboard/'
,
include
(
'dashboard.urls'
)),
url
(
r'^dashboard/'
,
include
(
'dashboard.urls'
)),
# django/contrib/auth/urls.py (care when new version)
# django/contrib/auth/urls.py (care when new version)
...
...
circle/firewall/admin.py
View file @
9fb5f44b
...
@@ -132,7 +132,8 @@ class RecordAdmin(admin.ModelAdmin):
...
@@ -132,7 +132,8 @@ class RecordAdmin(admin.ModelAdmin):
class
BlacklistItemAdmin
(
admin
.
ModelAdmin
):
class
BlacklistItemAdmin
(
admin
.
ModelAdmin
):
list_display
=
(
'ipv4'
,
'type'
,
'reason'
,
'created_at'
,
'modified_at'
)
list_display
=
(
'ipv4'
,
'whitelisted'
,
'reason'
,
'expires_at'
,
'created_at'
,
'modified_at'
)
class
SwitchPortAdmin
(
admin
.
ModelAdmin
):
class
SwitchPortAdmin
(
admin
.
ModelAdmin
):
...
...
circle/firewall/fw.py
View file @
9fb5f44b
...
@@ -19,14 +19,12 @@ import re
...
@@ -19,14 +19,12 @@ import re
import
logging
import
logging
from
collections
import
OrderedDict
from
collections
import
OrderedDict
from
netaddr
import
IPAddress
,
AddrFormatError
from
netaddr
import
IPAddress
,
AddrFormatError
from
datetime
import
timedelta
from
itertools
import
product
from
itertools
import
product
from
.models
import
(
Host
,
Rule
,
Vlan
,
Domain
,
Record
,
BlacklistItem
,
from
.models
import
(
Host
,
Rule
,
Vlan
,
Domain
,
Record
,
BlacklistItem
,
SwitchPort
)
SwitchPort
)
from
.iptables
import
IptRule
,
IptChain
from
.iptables
import
IptRule
,
IptChain
import
django.conf
import
django.conf
from
django.db.models
import
Q
from
django.template
import
loader
,
Context
from
django.template
import
loader
,
Context
from
django.utils
import
timezone
from
django.utils
import
timezone
...
@@ -161,10 +159,9 @@ class BuildFirewall:
...
@@ -161,10 +159,9 @@ class BuildFirewall:
def
ipset
():
def
ipset
():
week
=
timezone
.
now
()
-
timedelta
(
days
=
2
)
now
=
timezone
.
now
()
filter_ban
=
(
Q
(
type
=
'tempban'
,
modified_at__gte
=
week
)
|
return
BlacklistItem
.
objects
.
filter
(
whitelisted
=
False
)
.
exclude
(
Q
(
type
=
'permban'
))
expires_at__lt
=
now
)
.
values
(
'ipv4'
,
'reason'
)
return
BlacklistItem
.
objects
.
filter
(
filter_ban
)
.
values
(
'ipv4'
,
'reason'
)
def
ipv6_to_octal
(
ipv6
):
def
ipv6_to_octal
(
ipv6
):
...
...
circle/firewall/migrations/0003_auto_20150226_1927.py
0 → 100644
View file @
9fb5f44b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
models
,
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'firewall'
,
'0002_auto_20150115_0021'
),
]
operations
=
[
migrations
.
RemoveField
(
model_name
=
'blacklistitem'
,
name
=
'type'
,
),
migrations
.
AddField
(
model_name
=
'blacklistitem'
,
name
=
'expires_at'
,
field
=
models
.
DateTimeField
(
default
=
None
,
null
=
True
,
verbose_name
=
'expires at'
,
blank
=
True
),
preserve_default
=
True
,
),
migrations
.
AddField
(
model_name
=
'blacklistitem'
,
name
=
'whitelisted'
,
field
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'whitelisted'
),
preserve_default
=
True
,
),
migrations
.
AlterField
(
model_name
=
'blacklistitem'
,
name
=
'ipv4'
,
field
=
models
.
GenericIPAddressField
(
protocol
=
b
'ipv4'
,
unique
=
True
,
verbose_name
=
b
'IPv4 address'
),
preserve_default
=
True
,
),
migrations
.
AlterField
(
model_name
=
'blacklistitem'
,
name
=
'reason'
,
field
=
models
.
TextField
(
null
=
True
,
verbose_name
=
'reason'
,
blank
=
True
),
preserve_default
=
True
,
),
migrations
.
AlterField
(
model_name
=
'blacklistitem'
,
name
=
'snort_message'
,
field
=
models
.
TextField
(
null
=
True
,
verbose_name
=
'short message'
,
blank
=
True
),
preserve_default
=
True
,
),
]
circle/firewall/models.py
View file @
9fb5f44b
...
@@ -1109,24 +1109,23 @@ class EthernetDevice(models.Model):
...
@@ -1109,24 +1109,23 @@ class EthernetDevice(models.Model):
class
BlacklistItem
(
models
.
Model
):
class
BlacklistItem
(
models
.
Model
):
CHOICES_type
=
((
'permban'
,
'permanent ban'
),
(
'tempban'
,
'temporary ban'
),
ipv4
=
models
.
GenericIPAddressField
(
(
'whitelist'
,
'whitelist'
),
(
'tempwhite'
,
'tempwhite'
))
protocol
=
'ipv4'
,
unique
=
True
,
verbose_name
=
(
"IPv4 address"
))
ipv4
=
models
.
GenericIPAddressField
(
protocol
=
'ipv4'
,
unique
=
True
)
host
=
models
.
ForeignKey
(
host
=
models
.
ForeignKey
(
'Host'
,
blank
=
True
,
null
=
True
,
'Host'
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'host'
))
verbose_name
=
_
(
'host'
))
reason
=
models
.
TextField
(
reason
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'reason'
))
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'reason'
))
snort_message
=
models
.
TextField
(
blank
=
True
,
snort_message
=
models
.
TextField
(
verbose_name
=
_
(
'short message'
))
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'short message'
))
type
=
models
.
CharField
(
max_length
=
10
,
whitelisted
=
models
.
BooleanField
(
choices
=
CHOICES_type
,
default
=
False
,
verbose_name
=
_
(
"whitelisted"
))
default
=
'tempban'
,
verbose_name
=
_
(
'type'
)
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'created_at'
))
verbose_name
=
_
(
'created_at'
))
modified_at
=
models
.
DateTimeField
(
auto_now
=
True
,
modified_at
=
models
.
DateTimeField
(
auto_now
=
True
,
verbose_name
=
_
(
'modified_at'
))
verbose_name
=
_
(
'modified_at'
))
expires_at
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
default
=
None
,
verbose_name
=
_
(
'expires at'
))
def
save
(
self
,
*
args
,
**
kwargs
):
def
save
(
self
,
*
args
,
**
kwargs
):
self
.
full_clean
()
self
.
full_clean
()
...
...
circle/firewall/tasks/local_tasks.py
View file @
9fb5f44b
...
@@ -102,6 +102,7 @@ def reloadtask(type='Host', timeout=15):
...
@@ -102,6 +102,7 @@ def reloadtask(type='Host', timeout=15):
'Rule'
:
[
'firewall'
],
'Rule'
:
[
'firewall'
],
'SwitchPort'
:
[
'firewall_vlan'
],
'SwitchPort'
:
[
'firewall_vlan'
],
'EthernetDevice'
:
[
'firewall_vlan'
],
'EthernetDevice'
:
[
'firewall_vlan'
],
'BlacklistItem'
:
[
'blacklist'
],
}[
type
]
}[
type
]
logger
.
info
(
"Reload
%
s on next periodic iteration applying change to
%
s."
,
logger
.
info
(
"Reload
%
s on next periodic iteration applying change to
%
s."
,
", "
.
join
(
reload
),
type
)
", "
.
join
(
reload
),
type
)
...
...
circle/firewall/views.py
View file @
9fb5f44b
...
@@ -15,69 +15,97 @@
...
@@ -15,69 +15,97 @@
# You should have received a copy of the GNU General Public License along
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import
base64
from
__future__
import
absolute_import
,
unicode_literals
import
datetime
import
json
from
django.core.exceptions
import
ValidationError
from
datetime
import
timedelta
from
django.db
import
IntegrityError
from
json
import
dumps
import
logging
from
netaddr
import
AddrFormatError
,
IPAddress
from
requests
import
post
from
requests.exceptions
import
RequestException
from
django.core.exceptions
import
PermissionDenied
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
from
django.utils
.timezone
import
utc
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.views.decorators.csrf
import
csrf_exempt
from
django.views.decorators.csrf
import
csrf_exempt
from
django.views.decorators.http
import
require_POST
from
django.views.decorators.http
import
require_POST
from
.tasks.local_tasks
import
reloadtask
from
.models
import
BlacklistItem
,
Host
from
.models
import
BlacklistItem
,
Host
from
django.conf
import
settings
def
reload_firewall
(
request
):
logger
=
logging
.
getLogger
(
__name__
)
if
request
.
user
.
is_authenticated
():
if
request
.
user
.
is_superuser
:
html
=
(
_
(
"Dear
%
s, you've signed in as administrator!<br />"
def
send_request
(
obj
):
"Reloading in 10 seconds..."
)
%
request
.
user
.
username
)
data
=
{
"ip"
:
obj
.
ipv4
,
reloadtask
.
delay
()
"msg"
:
obj
.
snort_message
,
reloadtask
.
delay
(
'Vlan'
)
"reason"
:
obj
.
reason
,
else
:
"expires_at"
:
str
(
obj
.
expires_at
)
.
split
(
'.'
)[
0
],
html
=
(
_
(
"Dear
%
s, you've signed in!"
)
%
request
.
user
.
username
)
"object_kind"
:
"ban"
}
if
obj
.
host
:
data
.
update
({
"hostname"
:
obj
.
host
.
hostname
,
"username"
:
obj
.
host
.
owner
.
username
,
"fullname"
:
obj
.
host
.
owner
.
get_full_name
()})
try
:
r
=
post
(
settings
.
BLACKLIST_HOOK_URL
,
data
=
dumps
(
data
,
indent
=
2
),
timeout
=
3
)
r
.
raise_for_status
()
except
RequestException
as
e
:
logger
.
warning
(
"Error in HTTP POST:
%
s. url:
%
s params:
%
s"
,
str
(
e
),
settings
.
BLACKLIST_HOOK_URL
,
data
)
else
:
else
:
html
=
_
(
"Dear anonymous, you've not signed in yet!"
)
logger
.
info
(
"Successful HTTP POST. url:
%
s params:
%
s"
,
return
HttpResponse
(
html
)
settings
.
BLACKLIST_HOOK_URL
,
data
)
@csrf_exempt
@csrf_exempt
@require_POST
@require_POST
def
firewall_api
(
request
):
def
add_blacklist_item
(
request
):
password
=
request
.
POST
.
get
(
'password'
)
if
(
not
settings
.
BLACKLIST_PASSWORD
or
password
!=
settings
.
BLACKLIST_PASSWORD
):
logger
.
warning
(
"Tried invalid password. Password:
%
s IP:
%
s"
,
password
,
request
.
META
[
"REMOTE_ADDR"
])
raise
PermissionDenied
()
try
:
try
:
data
=
json
.
loads
(
base64
.
b64decode
(
request
.
POST
[
"data"
]))
address
=
request
.
POST
.
get
(
'address'
)
command
=
request
.
POST
[
"command"
]
address_object
=
IPAddress
(
address
,
version
=
4
)
if
data
[
"password"
]
!=
"bdmegintelrontottaanetet"
:
except
(
AddrFormatError
,
TypeError
)
as
e
:
raise
Exception
(
_
(
"Wrong password."
))
logger
.
warning
(
"Invalid IP address:
%
s (
%
s)"
,
address
,
str
(
e
))
return
HttpResponse
(
_
(
"Invalid IP address."
))
if
command
==
"blacklist"
:
obj
,
created
=
BlacklistItem
.
objects
.
get_or_create
(
ipv4
=
data
[
"ip"
])
obj
,
created
=
BlacklistItem
.
objects
.
get_or_create
(
ipv4
=
address
)
obj
.
reason
=
data
[
"reason"
]
obj
.
snort_message
=
data
[
"snort_message"
]
if
created
:
if
created
:
try
:
try
:
obj
.
host
=
Host
.
objects
.
get
(
ipv4
=
data
[
"ip"
]
)
db_format
=
'.'
.
join
(
"
%03
d"
%
x
for
x
in
address_object
.
words
)
except
(
Host
.
DoesNotExist
,
ValidationError
,
obj
.
host
=
Host
.
objects
.
get
(
ipv4
=
db_format
)
IntegrityError
,
AttributeError
)
:
except
Host
.
DoesNotExist
:
pass
pass
modified
=
obj
.
modified_at
+
datetime
.
timedelta
(
minutes
=
1
)
now
=
timezone
.
now
()
now
=
datetime
.
dateime
.
utcnow
()
.
replace
(
tzinfo
=
utc
)
can_update
=
(
if
obj
.
type
==
'tempwhite'
and
modified
<
now
:
(
obj
.
whitelisted
and
obj
.
expires_at
and
now
>
obj
.
expires_at
)
or
obj
.
type
=
'tempban'
not
obj
.
whitelisted
)
if
obj
.
type
!=
'whitelist'
:
is_new
=
created
or
(
obj
.
expires_at
and
now
>
obj
.
expires_at
)
if
created
or
can_update
:
obj
.
reason
=
request
.
POST
.
get
(
'reason'
)
obj
.
snort_message
=
request
.
POST
.
get
(
'snort_message'
)
obj
.
whitelisted
=
False
obj
.
expires_at
=
now
+
timedelta
(
weeks
=
1
)
obj
.
full_clean
()
obj
.
save
()
obj
.
save
()
return
HttpResponse
(
unicode
(
_
(
"OK"
)))
else
:
raise
Exception
(
_
(
"Unknown command."
))
except
(
ValidationError
,
IntegrityError
,
AttributeError
,
Exception
)
as
e
:
if
created
:
return
HttpResponse
(
_
(
"Something went wrong!
\n
%
s
\n
"
)
%
e
)
logger
.
info
(
"Successfully created blacklist item
%
s."
,
address
)
except
:
elif
can_update
:
return
HttpResponse
(
_
(
"Something went wrong!
\n
"
))
logger
.
info
(
"Successfully modified blacklist item
%
s."
,
address
)
if
is_new
and
settings
.
BLACKLIST_HOOK_URL
:
send_request
(
obj
)
return
HttpResponse
(
unicode
(
_
(
"OK"
)))
return
HttpResponse
(
unicode
(
_
(
"OK"
)))
circle/network/forms.py
View file @
9fb5f44b
...
@@ -54,8 +54,10 @@ class BlacklistItemForm(ModelForm):
...
@@ -54,8 +54,10 @@ class BlacklistItemForm(ModelForm):
''
,
''
,
'ipv4'
,
'ipv4'
,
'host'
,
'host'
,
'expires_at'
,
'whitelisted'
,
'reason'
,
'reason'
,
'
typ
e'
,
'
snort_messag
e'
,
)
)
),
),
FormActions
(
FormActions
(
...
...
circle/network/tables.py
View file @
9fb5f44b
...
@@ -20,7 +20,8 @@ from django.utils.translation import ugettext_lazy as _
...
@@ -20,7 +20,8 @@ from django.utils.translation import ugettext_lazy as _
from
django.utils.html
import
format_html
from
django.utils.html
import
format_html
from
django_tables2
import
Table
,
A
from
django_tables2
import
Table
,
A
from
django_tables2.columns
import
LinkColumn
,
TemplateColumn
,
Column
from
django_tables2.columns
import
(
LinkColumn
,
TemplateColumn
,
Column
,
BooleanColumn
)
from
firewall.models
import
Host
,
Vlan
,
Domain
,
Group
,
Record
,
Rule
,
SwitchPort
from
firewall.models
import
Host
,
Vlan
,
Domain
,
Group
,
Record
,
Rule
,
SwitchPort
...
@@ -41,12 +42,14 @@ class MACColumn(Column):
...
@@ -41,12 +42,14 @@ class MACColumn(Column):
class
BlacklistItemTable
(
Table
):
class
BlacklistItemTable
(
Table
):
ipv4
=
LinkColumn
(
'network.blacklist'
,
args
=
[
A
(
'pk'
)])
ipv4
=
LinkColumn
(
'network.blacklist'
,
args
=
[
A
(
'pk'
)])
whitelisted
=
BooleanColumn
()
class
Meta
:
class
Meta
:
model
=
Domain
model
=
Domain
attrs
=
{
'class'
:
'table table-striped table-condensed'
}
attrs
=
{
'class'
:
'table table-striped table-condensed'
}
fields
=
(
'ipv4'
,
'host'
,
'reason'
,
'type'
)
fields
=
(
'ipv4'
,
'host'
,
'reason'
,
'whitelisted'
,
'expires_at'
,
order_by
=
(
'ipv4'
,
)
'created_at'
)
order_by
=
(
'-expires_at'
,
)
class
DomainTable
(
Table
):
class
DomainTable
(
Table
):
...
...
circle/network/views.py
View file @
9fb5f44b
This diff is collapsed.
Click to expand it.
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