Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gelencsér Szabolcs
/
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)
CLIENT_DOWNLOAD_URL
=
get_env_variable
(
'CLIENT_DOWNLOAD_URL'
,
'http://circlecloud.org/client/download/'
)
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
from
circle.settings.base
import
get_env_variable
from
dashboard.views
import
circle_login
,
HelpView
from
dashboard.forms
import
CirclePasswordResetForm
,
CircleSetPasswordForm
from
firewall.views
import
add_blacklist_item
admin
.
autodiscover
()
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'^network/'
,
include
(
'network.urls'
)),
url
(
r'^blacklist-add/'
,
add_blacklist_item
),
url
(
r'^dashboard/'
,
include
(
'dashboard.urls'
)),
# django/contrib/auth/urls.py (care when new version)
...
...
circle/firewall/admin.py
View file @
9fb5f44b
...
...
@@ -132,7 +132,8 @@ class RecordAdmin(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
):
...
...
circle/firewall/fw.py
View file @
9fb5f44b
...
...
@@ -19,14 +19,12 @@ import re
import
logging
from
collections
import
OrderedDict
from
netaddr
import
IPAddress
,
AddrFormatError
from
datetime
import
timedelta
from
itertools
import
product
from
.models
import
(
Host
,
Rule
,
Vlan
,
Domain
,
Record
,
BlacklistItem
,
SwitchPort
)
from
.iptables
import
IptRule
,
IptChain
import
django.conf
from
django.db.models
import
Q
from
django.template
import
loader
,
Context
from
django.utils
import
timezone
...
...
@@ -161,10 +159,9 @@ class BuildFirewall:
def
ipset
():
week
=
timezone
.
now
()
-
timedelta
(
days
=
2
)
filter_ban
=
(
Q
(
type
=
'tempban'
,
modified_at__gte
=
week
)
|
Q
(
type
=
'permban'
))
return
BlacklistItem
.
objects
.
filter
(
filter_ban
)
.
values
(
'ipv4'
,
'reason'
)
now
=
timezone
.
now
()
return
BlacklistItem
.
objects
.
filter
(
whitelisted
=
False
)
.
exclude
(
expires_at__lt
=
now
)
.
values
(
'ipv4'
,
'reason'
)
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):
class
BlacklistItem
(
models
.
Model
):
CHOICES_type
=
((
'permban'
,
'permanent ban'
),
(
'tempban'
,
'temporary ban'
),
(
'whitelist'
,
'whitelist'
),
(
'tempwhite'
,
'tempwhite'
))
ipv4
=
models
.
GenericIPAddressField
(
protocol
=
'ipv4'
,
unique
=
True
)
host
=
models
.
ForeignKey
(
'Host'
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'host'
))
reason
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'reason'
))
snort_message
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'short message'
))
type
=
models
.
CharField
(
max_length
=
10
,
choices
=
CHOICES_type
,
default
=
'tempban'
,
verbose_name
=
_
(
'type'
)
)
ipv4
=
models
.
GenericIPAddressField
(
protocol
=
'ipv4'
,
unique
=
True
,
verbose_name
=
(
"IPv4 address"
))
host
=
models
.
ForeignKey
(
'Host'
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'host'
))
reason
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'reason'
))
snort_message
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'short message'
))
whitelisted
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
"whitelisted"
))
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'created_at'
))
modified_at
=
models
.
DateTimeField
(
auto_now
=
True
,
verbose_name
=
_
(
'modified_at'
))
expires_at
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
default
=
None
,
verbose_name
=
_
(
'expires at'
))
def
save
(
self
,
*
args
,
**
kwargs
):
self
.
full_clean
()
...
...
circle/firewall/tasks/local_tasks.py
View file @
9fb5f44b
...
...
@@ -102,6 +102,7 @@ def reloadtask(type='Host', timeout=15):
'Rule'
:
[
'firewall'
],
'SwitchPort'
:
[
'firewall_vlan'
],
'EthernetDevice'
:
[
'firewall_vlan'
],
'BlacklistItem'
:
[
'blacklist'
],
}[
type
]
logger
.
info
(
"Reload
%
s on next periodic iteration applying change to
%
s."
,
", "
.
join
(
reload
),
type
)
...
...
circle/firewall/views.py
View file @
9fb5f44b
...
...
@@ -15,69 +15,97 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import
base64
import
datetime
import
json
from
__future__
import
absolute_import
,
unicode_literals
from
django.core.exceptions
import
ValidationError
from
django.db
import
IntegrityError
from
datetime
import
timedelta
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.utils
.timezone
import
utc
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.views.decorators.csrf
import
csrf_exempt
from
django.views.decorators.http
import
require_POST
from
.tasks.local_tasks
import
reloadtask
from
.models
import
BlacklistItem
,
Host
from
django.conf
import
settings
def
reload_firewall
(
request
):
if
request
.
user
.
is_authenticated
():
if
request
.
user
.
is_superuser
:
html
=
(
_
(
"Dear
%
s, you've signed in as administrator!<br />"
"Reloading in 10 seconds..."
)
%
request
.
user
.
username
)
reloadtask
.
delay
()
reloadtask
.
delay
(
'Vlan'
)
else
:
html
=
(
_
(
"Dear
%
s, you've signed in!"
)
%
request
.
user
.
username
)
logger
=
logging
.
getLogger
(
__name__
)
def
send_request
(
obj
):
data
=
{
"ip"
:
obj
.
ipv4
,
"msg"
:
obj
.
snort_message
,
"reason"
:
obj
.
reason
,
"expires_at"
:
str
(
obj
.
expires_at
)
.
split
(
'.'
)[
0
],
"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
:
html
=
_
(
"Dear anonymous, you've not signed in yet!"
)
return
HttpResponse
(
html
)
logger
.
info
(
"Successful HTTP POST. url:
%
s params:
%
s"
,
settings
.
BLACKLIST_HOOK_URL
,
data
)
@csrf_exempt
@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
:
data
=
json
.
loads
(
base64
.
b64decode
(
request
.
POST
[
"data"
]))
command
=
request
.
POST
[
"command"
]
if
data
[
"password"
]
!=
"bdmegintelrontottaanetet"
:
raise
Exception
(
_
(
"Wrong password."
))
if
command
==
"blacklist"
:
obj
,
created
=
BlacklistItem
.
objects
.
get_or_create
(
ipv4
=
data
[
"ip"
])
obj
.
reason
=
data
[
"reason"
]
obj
.
snort_message
=
data
[
"snort_message"
]
address
=
request
.
POST
.
get
(
'address'
)
address_object
=
IPAddress
(
address
,
version
=
4
)
except
(
AddrFormatError
,
TypeError
)
as
e
:
logger
.
warning
(
"Invalid IP address:
%
s (
%
s)"
,
address
,
str
(
e
))
return
HttpResponse
(
_
(
"Invalid IP address."
))
obj
,
created
=
BlacklistItem
.
objects
.
get_or_create
(
ipv4
=
address
)
if
created
:
try
:
obj
.
host
=
Host
.
objects
.
get
(
ipv4
=
data
[
"ip"
]
)
except
(
Host
.
DoesNotExist
,
ValidationError
,
IntegrityError
,
AttributeError
)
:
db_format
=
'.'
.
join
(
"
%03
d"
%
x
for
x
in
address_object
.
words
)
obj
.
host
=
Host
.
objects
.
get
(
ipv4
=
db_format
)
except
Host
.
DoesNotExist
:
pass
modified
=
obj
.
modified_at
+
datetime
.
timedelta
(
minutes
=
1
)
now
=
datetime
.
dateime
.
utcnow
()
.
replace
(
tzinfo
=
utc
)
if
obj
.
type
==
'tempwhite'
and
modified
<
now
:
obj
.
type
=
'tempban'
if
obj
.
type
!=
'whitelist'
:
now
=
timezone
.
now
()
can_update
=
(
(
obj
.
whitelisted
and
obj
.
expires_at
and
now
>
obj
.
expires_at
)
or
not
obj
.
whitelisted
)
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
()
return
HttpResponse
(
unicode
(
_
(
"OK"
)))
else
:
raise
Exception
(
_
(
"Unknown command."
))
except
(
ValidationError
,
IntegrityError
,
AttributeError
,
Exception
)
as
e
:
return
HttpResponse
(
_
(
"Something went wrong!
\n
%
s
\n
"
)
%
e
)
except
:
return
HttpResponse
(
_
(
"Something went wrong!
\n
"
))
if
created
:
logger
.
info
(
"Successfully created blacklist item
%
s."
,
address
)
elif
can_update
:
logger
.
info
(
"Successfully modified blacklist item
%
s."
,
address
)
if
is_new
and
settings
.
BLACKLIST_HOOK_URL
:
send_request
(
obj
)
return
HttpResponse
(
unicode
(
_
(
"OK"
)))
circle/network/forms.py
View file @
9fb5f44b
...
...
@@ -54,8 +54,10 @@ class BlacklistItemForm(ModelForm):
''
,
'ipv4'
,
'host'
,
'expires_at'
,
'whitelisted'
,
'reason'
,
'
typ
e'
,
'
snort_messag
e'
,
)
),
FormActions
(
...
...
circle/network/tables.py
View file @
9fb5f44b
...
...
@@ -20,7 +20,8 @@ from django.utils.translation import ugettext_lazy as _
from
django.utils.html
import
format_html
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
...
...
@@ -41,12 +42,14 @@ class MACColumn(Column):
class
BlacklistItemTable
(
Table
):
ipv4
=
LinkColumn
(
'network.blacklist'
,
args
=
[
A
(
'pk'
)])
whitelisted
=
BooleanColumn
()
class
Meta
:
model
=
Domain
attrs
=
{
'class'
:
'table table-striped table-condensed'
}
fields
=
(
'ipv4'
,
'host'
,
'reason'
,
'type'
)
order_by
=
(
'ipv4'
,
)
fields
=
(
'ipv4'
,
'host'
,
'reason'
,
'whitelisted'
,
'expires_at'
,
'created_at'
)
order_by
=
(
'-expires_at'
,
)
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