2013-10-03 21:52:35 +02:00
|
|
|
"""
|
|
|
|
Tests for api package.
|
|
|
|
"""
|
|
|
|
|
2014-09-02 00:14:24 +02:00
|
|
|
import pytest
|
|
|
|
|
2014-09-29 13:44:21 +02:00
|
|
|
import base64
|
2014-11-18 00:14:23 +01:00
|
|
|
from netaddr import IPSet, IPAddress, IPNetwork
|
2014-09-29 13:44:21 +02:00
|
|
|
|
2017-12-28 17:12:34 +01:00
|
|
|
from django.urls import reverse
|
2013-11-15 12:14:36 +01:00
|
|
|
|
2014-08-30 18:27:21 +02:00
|
|
|
from nsupdate.main.dnstools import query_ns, FQDN
|
2013-12-18 04:08:18 +01:00
|
|
|
from nsupdate.main.models import Domain
|
2014-09-29 13:44:21 +02:00
|
|
|
from nsupdate.api.views import basic_authenticate
|
2013-11-26 08:10:05 +01:00
|
|
|
|
2014-09-22 23:41:35 +02:00
|
|
|
from conftest import TESTDOMAIN, TEST_HOST, TEST_HOST_RELATED, TEST_HOST2, TEST_SECRET, TEST_SECRET2
|
2013-11-16 01:25:05 +01:00
|
|
|
|
2013-11-16 07:23:44 +01:00
|
|
|
USERNAME = 'test'
|
|
|
|
PASSWORD = 'pass'
|
|
|
|
|
2013-11-26 08:10:05 +01:00
|
|
|
BASEDOMAIN = "nsupdate.info"
|
2014-08-30 18:27:21 +02:00
|
|
|
TEST_HOST_OTHER = FQDN('nsupdate-ddns-client-unittest', BASEDOMAIN)
|
2013-11-26 08:10:05 +01:00
|
|
|
|
2013-11-16 01:25:05 +01:00
|
|
|
|
2013-10-03 21:52:35 +02:00
|
|
|
def test_myip(client):
|
2013-11-15 12:14:36 +01:00
|
|
|
response = client.get(reverse('myip'))
|
2013-10-03 21:52:35 +02:00
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content in [b'127.0.0.1', b'::1']
|
2013-10-03 21:52:35 +02:00
|
|
|
|
|
|
|
|
2013-11-16 06:09:56 +01:00
|
|
|
def test_nic_update_noauth(client):
|
2013-11-15 13:00:57 +01:00
|
|
|
response = client.get(reverse('nic_update'))
|
2013-10-03 21:52:35 +02:00
|
|
|
assert response.status_code == 401
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'badauth'
|
2013-11-15 13:00:57 +01:00
|
|
|
|
|
|
|
|
2013-11-16 01:25:05 +01:00
|
|
|
def make_basic_auth_header(username, password):
|
2014-09-29 13:44:21 +02:00
|
|
|
"""
|
|
|
|
create a basic authentication header
|
|
|
|
|
|
|
|
:param username: user name [unicode on py2, str on py3]
|
|
|
|
:param password: password [unicode on py2, str on py3]
|
|
|
|
:return: basic auth header [str on py2, str on py3]
|
|
|
|
"""
|
|
|
|
# note: the coding dance in the next lines is to make sure we get str type
|
|
|
|
# on python 2 as well as on python 3 as str is the type we get in the auth
|
|
|
|
# object when practically running with a real web server.
|
|
|
|
user_pass = u'%s:%s' % (username, password)
|
|
|
|
return 'Basic ' + str(base64.b64encode(user_pass.encode('utf-8')).decode('ascii'))
|
|
|
|
|
|
|
|
|
|
|
|
def test_basic_auth():
|
|
|
|
user_pass = "username", "secret"
|
|
|
|
h = make_basic_auth_header(*user_pass)
|
|
|
|
assert isinstance(h, str) # must be str on py2, must be str on py3!
|
|
|
|
assert basic_authenticate(h) == user_pass
|
2013-11-16 01:25:05 +01:00
|
|
|
|
|
|
|
|
2013-11-16 06:09:56 +01:00
|
|
|
def test_nic_update_badauth(client):
|
|
|
|
response = client.get(reverse('nic_update'),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, "wrong"))
|
|
|
|
assert response.status_code == 401
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'badauth'
|
2013-11-16 06:09:56 +01:00
|
|
|
|
|
|
|
|
2013-11-16 07:51:04 +01:00
|
|
|
def test_nic_update_authorized_nonexistent_host(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?hostname=nonexistent.nsupdate.info',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# we must not get this updated, it doesn't exist in the database:
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'nohost'
|
2013-11-16 07:51:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
def test_nic_update_authorized_foreign_host(client):
|
2014-09-22 23:39:23 +02:00
|
|
|
response = client.get(reverse('nic_update') + '?hostname=%s' % (TEST_HOST2, ),
|
2013-11-16 07:51:04 +01:00
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# we must not get this updated, this is a host of some other user!
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'nohost'
|
2013-11-16 07:51:04 +01:00
|
|
|
|
|
|
|
|
2013-11-24 06:42:55 +01:00
|
|
|
def test_nic_update_authorized_not_fqdn_hostname(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?hostname=test',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'notfqdn'
|
2013-11-24 06:42:55 +01:00
|
|
|
|
|
|
|
|
|
|
|
def test_nic_update_authorized_not_fqdn_username(client):
|
|
|
|
response = client.get(reverse('nic_update'),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header('test', TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'notfqdn'
|
2013-11-24 06:42:55 +01:00
|
|
|
|
|
|
|
|
2014-09-02 23:50:39 +02:00
|
|
|
def test_nic_update_authorized_invalid_ip1(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=1234',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'dnserr'
|
|
|
|
|
|
|
|
|
|
|
|
def test_nic_update_authorized_invalid_ip2(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=%C3%A4%C3%BC%C3%B6',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'dnserr'
|
|
|
|
|
|
|
|
|
2013-11-16 01:25:05 +01:00
|
|
|
def test_nic_update_authorized(client):
|
|
|
|
response = client.get(reverse('nic_update'),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# we don't care whether it is nochg or good, but should be one of them:
|
2013-12-14 00:35:29 +01:00
|
|
|
content = response.content.decode('utf-8')
|
|
|
|
assert content.startswith('good ') or content.startswith('nochg ')
|
2013-11-16 01:25:05 +01:00
|
|
|
|
|
|
|
|
2013-12-18 04:08:18 +01:00
|
|
|
def test_nic_update_authorized_ns_unavailable(client):
|
2014-09-21 22:31:26 +02:00
|
|
|
d = Domain.objects.get(name=TESTDOMAIN)
|
2013-12-18 04:08:18 +01:00
|
|
|
d.available = False # simulate DNS unavailability
|
|
|
|
d.save()
|
2014-08-27 16:45:05 +02:00
|
|
|
# prepare: we must make sure the real test is not a nochg update
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=1.2.3.4',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# now do the real test: ip changed, but we can't update DNS as it is unavailable
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=4.3.2.1',
|
2013-12-18 04:08:18 +01:00
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
2013-12-24 21:44:11 +01:00
|
|
|
assert response.content == b'dnserr'
|
2013-12-18 04:08:18 +01:00
|
|
|
|
|
|
|
|
2014-09-23 00:48:54 +02:00
|
|
|
def test_nic_update_authorized_myip_v4(client):
|
2013-11-16 07:51:04 +01:00
|
|
|
response = client.get(reverse('nic_update') + '?myip=4.3.2.1',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# we don't care whether it is nochg or good, but should be the ip from myip=...:
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content in [b'good 4.3.2.1', b'nochg 4.3.2.1']
|
2013-11-21 04:02:16 +01:00
|
|
|
response = client.get(reverse('nic_update') + '?myip=1.2.3.4',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# must be good (was different IP)
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'good 1.2.3.4'
|
2013-11-21 04:02:16 +01:00
|
|
|
response = client.get(reverse('nic_update') + '?myip=1.2.3.4',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# must be nochg (was same IP)
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'nochg 1.2.3.4'
|
2014-09-23 00:48:54 +02:00
|
|
|
# now check if it updated the ipv4 related hosts also:
|
|
|
|
assert query_ns(TEST_HOST_RELATED, 'A') == '1.2.3.1' # 1.2.3.4/29 + 0.0.0.1
|
|
|
|
|
|
|
|
|
|
|
|
def test_nic_update_authorized_myip_v6(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=2000::2',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# we don't care whether it is nochg or good, but should be the ip from myip=...:
|
|
|
|
assert response.content in [b'good 2000::2', b'nochg 2000::2']
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=2000::3',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# must be good (was different IP)
|
|
|
|
assert response.content == b'good 2000::3'
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=2000::3',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# must be nochg (was same IP)
|
|
|
|
assert response.content == b'nochg 2000::3'
|
|
|
|
# now check if it updated the ipv4 related hosts also:
|
|
|
|
assert query_ns(TEST_HOST_RELATED, 'AAAA') == '2000::1' # 2000::3/64 + ::1
|
2013-11-21 04:02:16 +01:00
|
|
|
|
|
|
|
|
2014-09-02 00:14:24 +02:00
|
|
|
@pytest.mark.requires_sequential
|
2013-11-26 08:10:05 +01:00
|
|
|
def test_nic_update_authorized_update_other_services(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=4.3.2.1',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# we don't care whether it is nochg or good, but should be the ip from myip=...:
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content in [b'good 4.3.2.1', b'nochg 4.3.2.1']
|
2013-11-26 08:10:05 +01:00
|
|
|
response = client.get(reverse('nic_update') + '?myip=1.2.3.4',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# must be good (was different IP)
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'good 1.2.3.4'
|
2014-08-31 18:31:03 +02:00
|
|
|
# XXX test below can not run in parallel (like on travis-ci.org) if updating same
|
|
|
|
# "other service" target host
|
2013-11-26 08:10:05 +01:00
|
|
|
# now check if it updated the other service also:
|
2014-08-30 18:27:21 +02:00
|
|
|
assert query_ns(TEST_HOST_OTHER, 'A') == '1.2.3.4'
|
2013-11-26 08:10:05 +01:00
|
|
|
response = client.get(reverse('nic_update') + '?myip=2.3.4.5',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
# must be good (was different IP)
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'good 2.3.4.5'
|
2013-11-26 08:10:05 +01:00
|
|
|
# now check if it updated the other service also:
|
2014-08-30 18:27:21 +02:00
|
|
|
assert query_ns(TEST_HOST_OTHER, 'A') == '2.3.4.5'
|
2013-11-26 08:10:05 +01:00
|
|
|
|
|
|
|
|
2013-11-21 04:02:16 +01:00
|
|
|
def test_nic_update_authorized_badagent(client, settings):
|
|
|
|
settings.BAD_AGENTS = ['foo', 'bad_agent', 'bar', ]
|
|
|
|
response = client.get(reverse('nic_update'),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET),
|
|
|
|
HTTP_USER_AGENT='bad_agent')
|
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'badagent'
|
2013-11-16 07:51:04 +01:00
|
|
|
|
|
|
|
|
2014-11-18 00:14:23 +01:00
|
|
|
def test_nic_update_authorized_badip(client, settings):
|
|
|
|
settings.BAD_IPS_HOST = IPSet([IPAddress('7.7.7.7'), ])
|
|
|
|
# normal update, not on blacklist
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=1.2.3.4',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
content = response.content.decode('utf-8')
|
|
|
|
assert content.startswith('good ') or content.startswith('nochg ')
|
|
|
|
# abusive update, ip on blacklist
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=7.7.7.7',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'abuse'
|
|
|
|
|
|
|
|
|
2013-11-16 07:23:44 +01:00
|
|
|
def test_nic_update_session_nosession(client):
|
2013-11-15 13:00:57 +01:00
|
|
|
response = client.get(reverse('nic_update_authorized'))
|
|
|
|
assert response.status_code == 302 # redirects to login view
|
|
|
|
|
|
|
|
|
2013-11-21 04:02:16 +01:00
|
|
|
def test_nic_update_session_no_hostname(client):
|
2013-11-16 07:23:44 +01:00
|
|
|
client.login(username=USERNAME, password=PASSWORD)
|
|
|
|
response = client.get(reverse('nic_update_authorized'))
|
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'nohost' # we did not tell which host
|
2013-11-21 04:02:16 +01:00
|
|
|
|
|
|
|
|
|
|
|
def test_nic_update_session(client):
|
|
|
|
client.login(username=USERNAME, password=PASSWORD)
|
|
|
|
response = client.get(reverse('nic_update_authorized') + '?hostname=%s' % (TEST_HOST, ))
|
2013-11-16 07:23:44 +01:00
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
content = response.content.decode('utf-8')
|
|
|
|
assert content.startswith('good ') or content.startswith('nochg ')
|
2013-11-16 07:23:44 +01:00
|
|
|
|
|
|
|
|
2013-11-21 04:02:16 +01:00
|
|
|
def test_nic_update_session_myip(client):
|
|
|
|
client.login(username=USERNAME, password=PASSWORD)
|
|
|
|
response = client.get(reverse('nic_update_authorized') + '?hostname=%s&myip=%s' % (TEST_HOST, '1.2.3.4'))
|
|
|
|
assert response.status_code == 200
|
2013-12-14 00:35:29 +01:00
|
|
|
content = response.content.decode('utf-8')
|
|
|
|
assert content.startswith('good 1.2.3.4') or content.startswith('nochg 1.2.3.4')
|
2013-11-21 04:02:16 +01:00
|
|
|
|
|
|
|
|
2013-11-16 07:51:04 +01:00
|
|
|
def test_nic_update_session_foreign_host(client):
|
|
|
|
client.login(username=USERNAME, password=PASSWORD)
|
2014-09-22 23:39:23 +02:00
|
|
|
response = client.get(reverse('nic_update_authorized') + '?hostname=%s' % (TEST_HOST2, ))
|
2013-11-16 07:51:04 +01:00
|
|
|
assert response.status_code == 200
|
|
|
|
# we must not get this updated, this is a host of some other user!
|
2013-12-14 00:35:29 +01:00
|
|
|
assert response.content == b'nohost'
|
2013-11-16 07:51:04 +01:00
|
|
|
|
|
|
|
|
2014-09-02 23:50:39 +02:00
|
|
|
def test_nic_delete_authorized_invalid_ip1(client):
|
|
|
|
response = client.get(reverse('nic_delete') + '?myip=1234',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'dnserr'
|
|
|
|
|
|
|
|
|
|
|
|
def test_nic_delete_authorized_invalid_ip2(client):
|
|
|
|
response = client.get(reverse('nic_delete') + '?myip=%C3%A4%C3%BC%C3%B6',
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'dnserr'
|
|
|
|
|
|
|
|
|
2014-01-21 17:50:01 +01:00
|
|
|
def test_nic_delete_authorized(client):
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=%s' % ('1.2.3.4', ),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
response = client.get(reverse('nic_update') + '?myip=%s' % ('::1', ),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
response = client.get(reverse('nic_delete') + '?myip=%s' % ('0.0.0.0', ),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'deleted A'
|
|
|
|
response = client.get(reverse('nic_delete') + '?myip=%s' % ('::', ),
|
|
|
|
HTTP_AUTHORIZATION=make_basic_auth_header(TEST_HOST, TEST_SECRET))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'deleted AAAA'
|
|
|
|
|
|
|
|
|
|
|
|
def test_nic_delete_session(client):
|
|
|
|
client.login(username=USERNAME, password=PASSWORD)
|
|
|
|
response = client.get(reverse('nic_update_authorized') + '?hostname=%s&myip=%s' % (TEST_HOST, '1.2.3.4'))
|
|
|
|
assert response.status_code == 200
|
|
|
|
response = client.get(reverse('nic_update_authorized') + '?hostname=%s&myip=%s' % (TEST_HOST, '::1'))
|
|
|
|
assert response.status_code == 200
|
|
|
|
response = client.get(reverse('nic_delete_authorized') + '?hostname=%s&myip=%s' % (TEST_HOST, '0.0.0.0'))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'deleted A'
|
|
|
|
response = client.get(reverse('nic_delete_authorized') + '?hostname=%s&myip=%s' % (TEST_HOST, '::'))
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert response.content == b'deleted AAAA'
|
|
|
|
|
|
|
|
|
2013-11-16 07:51:04 +01:00
|
|
|
def test_detect_ip_invalid_session(client):
|
2013-11-15 13:00:57 +01:00
|
|
|
response = client.get(reverse('detectip', args=('invalid_session_id', )))
|
|
|
|
assert response.status_code == 204
|
|
|
|
|
|
|
|
|
|
|
|
def test_ajax_get_ips(client):
|
|
|
|
response = client.get(reverse('ajax_get_ips'))
|
|
|
|
assert response.status_code == 200
|