def get_host_keytab(request, hostname): """Register a computer: - create Kerberos principal - create private key - create public SSH key - create x509 certificate - create PTR DNS record - create A or AAAA DNS record - create SSHFP DNS record - return keytab :param request: :type request: :param hostname: :type hostname: :return: :rtype: """ admin_ip_address = request.GET.get('ip_address') hostname = hostname.lower() main_ip_address = request.META.get('HTTP_X_FORWARDED_FOR') short_hostname = hostname.partition('.')[0] fqdn = '%s.%s%s' % (short_hostname, settings.PDNS_INFRA_PREFIX, settings.PENATES_DOMAIN) # valid FQDN # create Kerberos principal principal = principal_from_hostname(fqdn, settings.PENATES_REALM) if principal_exists(principal): return HttpResponse('Hostname %s is already registered.' % hostname, status=403) principal = Host.register_host(short_hostname, main_ip_address, admin_ip_address) if settings.OFFER_HOST_KEYTABS: return KeytabResponse(principal) return HttpResponse('', content_type='text/plain', status=201)
def request(self, client_address=None, client_fqdn=None, request_body='', **kwargs): request = HttpRequest() principal = principal_from_hostname(client_fqdn, settings.PDNS_INFRA_PREFIX + settings.PENATES_REALM) request.GET = kwargs request.META = {'HTTP_X_FORWARDED_FOR': client_address} user, c = DjangoUser.objects.get_or_create(username=principal) request.user = user request._body = request_body return request
def delete_host(sender, instance=None, **kwargs): if sender != Host: return assert isinstance(instance, Host) # noinspection PyUnusedLocal kwargs = kwargs # kwargs is required by Django fqdn = instance.fqdn Service.objects.filter(fqdn=fqdn).delete() ShinkenService.objects.filter(host_name=fqdn).delete() delete_principal(principal_from_hostname(fqdn, settings.PENATES_REALM)) Record.objects.filter(Q(name=fqdn) | Q(content=fqdn)).delete()
def delete_host(sender, instance=None, **kwargs): if sender != Host: return assert isinstance(instance, Host) # noinspection PyUnusedLocal kwargs = kwargs # kwargs is required by Django principals = [principal_from_hostname(instance.fqdn, settings.PENATES_REALM)] for fqdn in instance.fqdn, instance.admin_fqdn: principals += [service.principal_name for service in Service.objects.filter(fqdn=fqdn)] Service.objects.filter(fqdn=fqdn).delete() Record.objects.filter(Q(name=fqdn) | Q(content=fqdn)).delete() for principal in principals: delete_principal(principal)
def request(self, client_address=None, client_fqdn=None, request_body='', **kwargs): request = HttpRequest() principal = principal_from_hostname( client_fqdn, settings.PDNS_INFRA_PREFIX + settings.PENATES_REALM) request.GET = kwargs request.META = {'HTTP_X_FORWARDED_FOR': client_address} user, c = DjangoUser.objects.get_or_create(username=principal) request.user = user request._body = request_body return request
def get_host_keytab(request, hostname): """Register a computer: - create Kerberos principal - create private key - create public SSH key - create x509 certificate - create PTR DNS record - create A or AAAA DNS record - create SSHFP DNS record - return keytab :param request: :type request: :param hostname: :type hostname: :return: :rtype: """ admin_ip_address = request.GET.get('ip_address') ip_address = request.META.get('HTTP_X_FORWARDED_FOR') short_hostname = hostname.partition('.')[0] domain_name = settings.PENATES_DOMAIN fqdn = '%s.%s%s' % (short_hostname, settings.PDNS_INFRA_PREFIX, domain_name) # valid FQDN # create Kerberos principal principal = principal_from_hostname(fqdn, settings.PENATES_REALM) if principal_exists(principal): return HttpResponse('', status=403) else: add_principal(principal) Host.objects.get_or_create(fqdn=fqdn) # create private key, public key, public certificate, public SSH key entry = entry_from_hostname(fqdn) pki = PKI() pki.ensure_certificate(entry) # create DNS records if ip_address: Domain.ensure_auto_record(ip_address, fqdn, unique=True, override_reverse=True) Host.objects.filter(fqdn=fqdn).update(main_ip_address=ip_address) if admin_ip_address: admin_fqdn = '%s.%s%s' % (short_hostname, settings.PDNS_ADMIN_PREFIX, domain_name) Domain.ensure_auto_record(admin_ip_address, admin_fqdn, unique=True, override_reverse=False) Host.objects.filter(fqdn=fqdn).update(admin_ip_address=admin_ip_address) if settings.OFFER_HOST_KEYTABS: return KeytabResponse(principal) return HttpResponse('', content_type='text/plain', status=201)
def register_host(short_hostname, main_ip_address=None, admin_ip_address=None): fqdn = '%s.%s%s' % (short_hostname, settings.PDNS_INFRA_PREFIX, settings.PENATES_DOMAIN) principal = principal_from_hostname(fqdn, settings.PENATES_REALM) add_principal(principal) Host.objects.get_or_create(fqdn=fqdn) # create private key, public key, public certificate, public SSH key entry = entry_from_hostname(fqdn) pki = PKI() pki.ensure_certificate(entry) # create DNS records if main_ip_address: Domain.ensure_auto_record(main_ip_address, fqdn, unique=True, override_reverse=True) Host.objects.filter(fqdn=fqdn).update(main_ip_address=main_ip_address) if admin_ip_address: admin_fqdn = '%s.%s%s' % (short_hostname, settings.PDNS_ADMIN_PREFIX, settings.PENATES_DOMAIN) Domain.ensure_auto_record(admin_ip_address, admin_fqdn, unique=True, override_reverse=False) Host.objects.filter(fqdn=fqdn).update(admin_ip_address=admin_ip_address) return principal
def principal(self): return principal_from_hostname(self.fqdn, settings.PENATES_REALM)
def test_complete_scenario(self): cmd = EnsureDomain() cmd.handle(domain=self.domain_name) hostname = 'directory01.%s' % self.domain_name self.call_service(scheme='ldaps', hostname=hostname, port=636, fqdn=self.infra_fqdn_1, encryption='tls') self.call_service(scheme='krb', hostname=hostname, port=88, fqdn=self.infra_fqdn_1, srv='tcp/kerberos') self.call_service(scheme='krb', hostname=hostname, port=88, fqdn=self.infra_fqdn_1, srv='tcp/kerberos', protocol='udp') self.call_service(scheme='http', hostname=hostname, port=443, fqdn=self.infra_fqdn_1, encryption='tls') self.call_service(scheme='dns', hostname=hostname, port=53, fqdn=self.infra_fqdn_1, protocol='udp') self.assertEqual( 1, Record.objects.filter(name='_636._tcp.%s' % hostname, type='TLSA').count()) self.assertEqual( 1, Record.objects.filter(name='_88._tcp.%s' % hostname, type='TLSA').count()) self.assertEqual( 1, Record.objects.filter(name='_88._udp.%s' % hostname, type='TLSA').count()) self.assertEqual( 1, Record.objects.filter(name='_443._tcp.%s' % hostname, type='TLSA').count()) response = get_host_keytab( self.request_1(ip_address=self.admin_ip_address_1), self.infra_fqdn_1) principal = principal_from_hostname(self.infra_fqdn_1, settings.PENATES_REALM) self.assertTrue(principal in text_type(response.content)) response = get_host_keytab( self.request_2(ip_address=self.admin_ip_address_2), self.infra_fqdn_2) principal = principal_from_hostname(self.infra_fqdn_2, settings.PENATES_REALM) self.assertTrue(principal in text_type(response.content)) domain_names = {x.name for x in Domain.objects.all()} for domain_name in [ self.domain_name, '%s%s' % (settings.PDNS_ADMIN_PREFIX, self.domain_name), '%s%s' % (settings.PDNS_INFRA_PREFIX, self.domain_name), '1.19.10.in-addr.arpa', '0.8.10.in-addr.arpa', ]: self.assertTrue(domain_name in domain_names) set_dhcp( self.request_1(ip_address=self.admin_ip_address_1, mac_address='5E:FF:56:A2:AF:15'), '5E:FF:56:A2:AF:15') self.assertEqual( Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_1, type='A', content=self.admin_ip_address_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) set_dhcp( self.request_2(ip_address=self.admin_ip_address_2, mac_address='88:FF:56:A2:AF:15'), '90:FF:56:A2:AF:15') self.assertEqual( Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_1, type='A', content=self.admin_ip_address_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) response = set_service(self.request_1(keytab='host', srv='tcp/ssh'), 'ssh', self.admin_fqdn_1, '22') self.assertEqual('ssh://%s:22/ created' % self.admin_fqdn_1, response.content) self.assertEqual( Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_1, type='CNAME', content=self.infra_fqdn_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) response = set_service(self.request_2(keytab='host', srv='tcp/ssh'), 'ssh', self.admin_fqdn_2, '22') self.assertEqual('ssh://%s:22/ created' % self.admin_fqdn_2, response.content) self.assertEqual( Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_1, type='CNAME', content=self.infra_fqdn_1).count(), 1) self.assertEqual( Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual( Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) response = get_service_keytab(self.request_1(protocol='tcp'), 'ssh', self.admin_fqdn_1, '22') self.assertTrue( 'host/%s@%s' % (self.infra_fqdn_1, settings.PENATES_REALM) in text_type(response.content)) response = get_service_keytab(self.request_2(protocol='tcp'), 'ssh', self.admin_fqdn_2, '22') self.assertTrue( 'host/%s@%s' % (self.admin_fqdn_2, settings.PENATES_REALM) in text_type(response.content)) body = "ssh-rsa QkJCQnozcVZRSTlNYTFIYw== flanker@%s" % self.infra_fqdn_1 response = set_ssh_pub(self.request_1(request_body=body)) self.assertEqual(201, response.status_code) body = "ssh-rsa RkJCQnozcVZRSTlNYTFIYw== flanker@%s" % self.infra_fqdn_2 response = set_ssh_pub(self.request_2(request_body=body)) self.assertEqual(201, response.status_code) self.assertEqual( 1, Record.objects.filter( name=self.admin_fqdn_1, type='SSHFP', content='1 1 915984d4f71be43b49154b61c786d1a092e49a4d').count( )) self.assertEqual(4, Record.objects.filter(type='SSHFP').count()) response = get_host_certificate(self.request_1()) self.assertTrue( '-----BEGIN RSA PRIVATE KEY-----' in text_type(response.content)) self.check_certificate(response.content, self.infra_fqdn_1, 'Computers') response = get_host_certificate(self.request_2()) self.assertTrue( '-----BEGIN RSA PRIVATE KEY-----' in text_type(response.content)) self.check_certificate(response.content, self.infra_fqdn_2, 'Computers') get_dhcpd_conf(self.request_1()) response = set_service(self.request_1(encryption='tls'), 'syslog', self.service_1_fqdn, '514') self.assertEqual('syslog://%s:514/ created' % self.service_1_fqdn, response.content) self.assertEqual( 1, Record.objects.filter(name=self.service_1_fqdn, content=self.infra_fqdn_1, type='CNAME').count()) response = get_service_certificate(self.request_1(), 'syslog', self.service_1_fqdn, '514') self.check_certificate(response.content, self.service_1_fqdn, 'Services') response = set_service(self.request_2(encryption='tls'), 'syslog', self.service_2_fqdn, '514') self.assertEqual('syslog://%s:514/ created' % self.service_2_fqdn, response.content) self.assertEqual( 1, Record.objects.filter(name=self.service_2_fqdn, content=self.infra_fqdn_2, type='CNAME').count()) response = get_service_certificate(self.request_2(), 'syslog', self.service_2_fqdn, '514') self.check_certificate(response.content, self.service_2_fqdn, 'Services') response = set_service( self.request_1(role='Service1024', encryption='tls'), 'dkim', self.service_3_fqdn, '10026') self.assertEqual('dkim://%s:10026/ created' % self.service_3_fqdn, response.content) self.assertEqual( 1, Record.objects.filter(name=self.service_3_fqdn, content=self.infra_fqdn_1, type='CNAME').count()) self.assertEqual( 1, Record.objects.filter(name='%s._domainkey.%s' % (self.service_3_fqdn.partition('.')[0], settings.PENATES_DOMAIN), type='TXT').count()) response = set_service(self.request_1(keytab='smtp', srv='smtp'), 'smtp', self.service_3_fqdn, '25') self.assertEqual('smtp://%s:25/ created' % self.service_3_fqdn, response.content) self.assertEqual( 1, Record.objects.filter(name=settings.PENATES_DOMAIN, type='MX', content=self.service_3_fqdn).count()) response = set_service(self.request_2(keytab='smtp', srv='smtp'), 'smtp', self.service_4_fqdn, '25') self.assertEqual('smtp://%s:25/ created' % self.service_4_fqdn, response.content) self.assertEqual( 1, Record.objects.filter(name=self.service_4_fqdn, content=self.infra_fqdn_2, type='CNAME').count()) self.assertEqual( 1, Record.objects.filter(name=settings.PENATES_DOMAIN, type='MX', content=self.service_3_fqdn).count()) response = set_service( self.request_2(role='Service1024', encryption='tls'), 'dkim', self.service_4_fqdn, '10026') self.assertEqual('dkim://%s:10026/ created' % self.service_4_fqdn, response.content) self.assertEqual( 1, Record.objects.filter(name=self.service_4_fqdn, content=self.infra_fqdn_2, type='CNAME').count()) self.assertEqual( 1, Record.objects.filter(name='%s._domainkey.%s' % (self.service_4_fqdn.partition('.')[0], settings.PENATES_DOMAIN), type='TXT').count()) for record in Record.objects.all(): print((repr(record)))
def test_complete_scenario(self): cmd = EnsureDomain() cmd.handle(domain=self.domain_name) hostname = 'directory01.%s' % self.domain_name self.call_service(scheme='ldaps', hostname=hostname, port=636, fqdn=self.infra_fqdn_1, encryption='tls') self.call_service(scheme='krb', hostname=hostname, port=88, fqdn=self.infra_fqdn_1, srv='tcp/kerberos') self.call_service(scheme='krb', hostname=hostname, port=88, fqdn=self.infra_fqdn_1, srv='tcp/kerberos', protocol='udp') self.call_service(scheme='http', hostname=hostname, port=443, fqdn=self.infra_fqdn_1, encryption='tls') self.call_service(scheme='dns', hostname=hostname, port=53, fqdn=self.infra_fqdn_1, protocol='udp') self.assertEqual(1, Record.objects.filter(name='_636._tcp.%s' % hostname, type='TLSA').count()) self.assertEqual(1, Record.objects.filter(name='_88._tcp.%s' % hostname, type='TLSA').count()) self.assertEqual(1, Record.objects.filter(name='_88._udp.%s' % hostname, type='TLSA').count()) self.assertEqual(1, Record.objects.filter(name='_443._tcp.%s' % hostname, type='TLSA').count()) response = get_host_keytab(self.request_1(ip_address=self.admin_ip_address_1), self.infra_fqdn_1) principal = principal_from_hostname(self.infra_fqdn_1, settings.PENATES_REALM) self.assertTrue(principal in text_type(response.content)) response = get_host_keytab(self.request_2(ip_address=self.admin_ip_address_2), self.infra_fqdn_2) principal = principal_from_hostname(self.infra_fqdn_2, settings.PENATES_REALM) self.assertTrue(principal in text_type(response.content)) domain_names = {x.name for x in Domain.objects.all()} for domain_name in [self.domain_name, '%s%s' % (settings.PDNS_ADMIN_PREFIX, self.domain_name), '%s%s' % (settings.PDNS_INFRA_PREFIX, self.domain_name), '1.19.10.in-addr.arpa', '0.8.10.in-addr.arpa', ]: self.assertTrue(domain_name in domain_names) set_dhcp(self.request_1(ip_address=self.admin_ip_address_1, mac_address='5E:FF:56:A2:AF:15'), '5E:FF:56:A2:AF:15') self.assertEqual(Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_1, type='A', content=self.admin_ip_address_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) set_dhcp(self.request_2(ip_address=self.admin_ip_address_2, mac_address='88:FF:56:A2:AF:15'), '90:FF:56:A2:AF:15') self.assertEqual(Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_1, type='A', content=self.admin_ip_address_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) response = set_service(self.request_1(keytab='host', srv='tcp/ssh'), 'ssh', self.admin_fqdn_1, '22') self.assertEqual('ssh://%s:22/ created' % self.admin_fqdn_1, response.content) self.assertEqual(Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_1, type='CNAME', content=self.infra_fqdn_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) response = set_service(self.request_2(keytab='host', srv='tcp/ssh'), 'ssh', self.admin_fqdn_2, '22') self.assertEqual('ssh://%s:22/ created' % self.admin_fqdn_2, response.content) self.assertEqual(Record.objects.filter(name=self.infra_fqdn_1, type='A', content=self.infra_ip_address_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_1, type='CNAME', content=self.infra_fqdn_1).count(), 1) self.assertEqual(Record.objects.filter(name=self.infra_fqdn_2, type='A', content=self.infra_ip_address_2).count(), 1) self.assertEqual(Record.objects.filter(name=self.admin_fqdn_2, type='A', content=self.admin_ip_address_2).count(), 1) response = get_service_keytab(self.request_1(protocol='tcp'), 'ssh', self.admin_fqdn_1, '22') self.assertTrue('host/%s@%s' % (self.infra_fqdn_1, settings.PENATES_REALM) in text_type(response.content)) response = get_service_keytab(self.request_2(protocol='tcp'), 'ssh', self.admin_fqdn_2, '22') self.assertTrue('host/%s@%s' % (self.admin_fqdn_2, settings.PENATES_REALM) in text_type(response.content)) body = "ssh-rsa QkJCQnozcVZRSTlNYTFIYw== flanker@%s" % self.infra_fqdn_1 response = set_ssh_pub(self.request_1(request_body=body)) self.assertEqual(201, response.status_code) body = "ssh-rsa RkJCQnozcVZRSTlNYTFIYw== flanker@%s" % self.infra_fqdn_2 response = set_ssh_pub(self.request_2(request_body=body)) self.assertEqual(201, response.status_code) self.assertEqual(1, Record.objects.filter(name=self.admin_fqdn_1, type='SSHFP', content='1 1 915984d4f71be43b49154b61c786d1a092e49a4d').count()) self.assertEqual(4, Record.objects.filter(type='SSHFP').count()) response = get_host_certificate(self.request_1()) self.assertTrue('-----BEGIN RSA PRIVATE KEY-----' in text_type(response.content)) self.check_certificate(response.content, self.infra_fqdn_1, 'Computers') response = get_host_certificate(self.request_2()) self.assertTrue('-----BEGIN RSA PRIVATE KEY-----' in text_type(response.content)) self.check_certificate(response.content, self.infra_fqdn_2, 'Computers') get_dhcpd_conf(self.request_1()) response = set_service(self.request_1(encryption='tls'), 'syslog', self.service_1_fqdn, '514') self.assertEqual('syslog://%s:514/ created' % self.service_1_fqdn, response.content) self.assertEqual(1, Record.objects.filter(name=self.service_1_fqdn, content=self.infra_fqdn_1, type='CNAME').count()) response = get_service_certificate(self.request_1(), 'syslog', self.service_1_fqdn, '514') self.check_certificate(response.content, self.service_1_fqdn, 'Services') response = set_service(self.request_2(encryption='tls'), 'syslog', self.service_2_fqdn, '514') self.assertEqual('syslog://%s:514/ created' % self.service_2_fqdn, response.content) self.assertEqual(1, Record.objects.filter(name=self.service_2_fqdn, content=self.infra_fqdn_2, type='CNAME').count()) response = get_service_certificate(self.request_2(), 'syslog', self.service_2_fqdn, '514') self.check_certificate(response.content, self.service_2_fqdn, 'Services') response = set_service(self.request_1(role='Service1024', encryption='tls'), 'dkim', self.service_3_fqdn, '10026') self.assertEqual('dkim://%s:10026/ created' % self.service_3_fqdn, response.content) self.assertEqual(1, Record.objects.filter(name=self.service_3_fqdn, content=self.infra_fqdn_1, type='CNAME').count()) self.assertEqual(1, Record.objects.filter(name='%s._domainkey.%s' % (self.service_3_fqdn.partition('.')[0], settings.PENATES_DOMAIN), type='TXT').count()) response = set_service(self.request_1(keytab='smtp', srv='smtp'), 'smtp', self.service_3_fqdn, '25') self.assertEqual('smtp://%s:25/ created' % self.service_3_fqdn, response.content) self.assertEqual(1, Record.objects.filter(name=settings.PENATES_DOMAIN, type='MX', content=self.service_3_fqdn).count()) response = set_service(self.request_2(keytab='smtp', srv='smtp'), 'smtp', self.service_4_fqdn, '25') self.assertEqual('smtp://%s:25/ created' % self.service_4_fqdn, response.content) self.assertEqual(1, Record.objects.filter(name=self.service_4_fqdn, content=self.infra_fqdn_2, type='CNAME').count()) self.assertEqual(1, Record.objects.filter(name=settings.PENATES_DOMAIN, type='MX', content=self.service_3_fqdn).count()) response = set_service(self.request_2(role='Service1024', encryption='tls'), 'dkim', self.service_4_fqdn, '10026') self.assertEqual('dkim://%s:10026/ created' % self.service_4_fqdn, response.content) self.assertEqual(1, Record.objects.filter(name=self.service_4_fqdn, content=self.infra_fqdn_2, type='CNAME').count()) self.assertEqual(1, Record.objects.filter(name='%s._domainkey.%s' % (self.service_4_fqdn.partition('.')[0], settings.PENATES_DOMAIN), type='TXT').count()) for record in Record.objects.all(): print(repr(record))