1

I am currently running my Django application on an Apache v2.4.5.2 server. When the user hits initial page (i.e. www.djangoApp.com) they are prompted to insert their CAC and PIN. Once complete, the PIN entry pop-up goes away and the user is directed to the landing page. The issue I'm having is figuring out how to identify the user based on the HTTP response received from the external source (GCDS). In the server logs, I can see the request information, but I am unsure how to view that request in Django views. I tried to comment out all middleware so that the request would make it through, but that doesn't work. Does Apache block certain HTTP Requests? Is there somewhere I need to allow external requests? The only request I'm getting is:

{'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PROTOCOL': 'HTTP/1.1', 'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'REQUEST_URI': '/', 'SCRIPT_NAME': '', 'PATH_INFO': '/', 'PATH_TRANSLATED': '\DjangoWebProject1\\wsgi.py\\', 'HTTP_HOST': 'glen', 'HTTP_CACHE_CONTROL': 'max-age=0', 'HTTP_SEC_CH_UA': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"', 'HTTP_SEC_CH_UA_MOBILE': '?0', 'HTTP_SEC_CH_UA_PLATFORM': '"Windows"', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'HTTP_SEC_FETCH_SITE': 'none', 'HTTP_SEC_FETCH_MODE': 'navigate', 'HTTP_SEC_FETCH_USER': '?1', 'HTTP_SEC_FETCH_DEST': 'document', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.9', 'HTTP_COOKIE': 'csrftoken=Nd3ggEPk0vqYJwZKOVZZoZtUqZWXs155Y6V1q', 'HTTP_X_FORWARDED_FOR': '128.202.106.24', 'HTTP_X_FORWARDED_HOST': 'glen', 'HTTP_X_FORWARDED_SERVER': 'glen', 'HTTP_CONNECTION': 'Keep-Alive', 'SystemRoot': 'C:\\Windows', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'WINDIR': 'C:\\Windows', 'SERVER_SIGNATURE': '', 'SERVER_SOFTWARE': 'Apache/2.4.52 (Win64) OpenSSL/1.1.1m mod_wsgi/4.9.0 Python/3.9', 'SERVER_NAME': 'glen', 'SERVER_ADDR': 'fe80::ed01:effd:2360:544a', 'SERVER_PORT': '81', 'REMOTE_ADDR': 'fe80::ed01:effd::544a', 'DOCUMENT_ROOT': 'webdart/DjangoWebProject1/webdart/templates/webdart', 'REQUEST_SCHEME': 'http', 'CONTEXT_PREFIX': '', 'CONTEXT_DOCUMENT_ROOT': 'webdart/DjangoWebProject1/webdart/templates/webdart', 'SERVER_ADMIN': 'admin@example.com', 'SCRIPT_FILENAME': 'webdart/DjangoWebProject1/DjangoWebProject1/wsgi.py', 'REMOTE_PORT': '6307', 'mod_wsgi.script_name': '', 'mod_wsgi.path_info': '/', 'mod_wsgi.process_group': '', 'mod_wsgi.application_group': 'GLEN:81|', 'mod_wsgi.callable_object': 'application', 'mod_wsgi.request_handler': 'wsgi-script', 'mod_wsgi.handler_script': '', 'mod_wsgi.script_reloading': '1', 'mod_wsgi.enable_sendfile': '0', 'mod_wsgi.ignore_activity': '0', 'mod_wsgi.request_start': '17490697', 'mod_wsgi.request_id': 'iT3r3Lez7vM', 'mod_wsgi.connection_id': 'iT3r3Lez7vM', 'mod_wsgi.script_start': '1069256341', 'wsgi.version': (1, 0), 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.errors': <_io.TextIOWrapper name='<wsgi.errors>' encoding='utf-8'>, 'wsgi.input': <mod_wsgi.Input object at 0x00000286F4E619D0>, 'wsgi.input_terminated': True, 'wsgi.file_wrapper': <class 'mod_wsgi.FileWrapper'>, 'apache.version': (2, 4, 52), 'mod_wsgi.version': (4, 9, 0), 'mod_wsgi.total_requests': 0, 'mod_wsgi.thread_id': 1, 'mod_wsgi.thread_requests': 0, 'CSRF_COOKIE': 'N2kUXzZUXThFW1w52r4ZKOVZZoZtUqZWXs155Y6V1q'}

My settings.py looks like this:

Django settings for DjangoWebProject1 project.

Based on 'django-admin startproject' using Django 2.1.2.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os
import posixpath

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'd050e2cb-bfba-4ff7-adc1-9c1c8e8d952b'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application references
# https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-INSTALLED_APPS
INSTALLED_APPS = [
    'app',
    # Add your apps here to enable them
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'webdart.apps.WebdartConfig',
    'DjangoWebProject1',
    'django_filters',
    'vertical_multi_columns',
    'el_pagination',


]

# Middleware framework
# https://docs.djangoproject.com/en/2.1/topics/http/middleware/
MIDDLEWARE = [
    #'django.middleware.authenticate.printHeader',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    
]
X_FRAME_OPTIONS = 'SAMEORIGIN';

ROOT_URLCONF = 'DjangoWebProject1.urls'

# Template configuration
# https://docs.djangoproject.com/en/2.1/topics/templates/
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.csrf',
                'django.template.context_processors.request', ## For EL-pagination
                'webdart.context_processors.add_doc_types_to_context',
                'webdart.context_processors.add_dynamic_stations_to_context',
            ],
            'libraries':{
                'webdart_extras':'webdart.templateTags.webdart_extras',
            }
        },
    },
]

WSGI_APPLICATION = 'DjangoWebProject1.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'ORCL',
        'USER': 'wd',
        'PASSWORD': 'password1',
        'HOST':'127.0.0.1',
        'PORT': '1521',
    }
}

# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]




# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = posixpath.join(*(BASE_DIR.split(os.path.sep) + ['static']))
print("00011111111111111111111000000000")
print(STATIC_ROOT)

I've tried building my own middleware, commenting out all middleware... I'm stuck. How can I view the GCDS request containing the CAC information? Does Apache block certain HTTP Requests? Is there somewhere I need to allow external requests?

Here is the landing page from views.py:

def landing(request):
    test = request.META
    print(test)
    dodNum = "101010101"
    people = Person.objects.all()
    for person in people:
        if dodNum in person.authentication_name:
       
            return render(request, 'webdart/landing.html', {'person': person})
            break
    return render(request, 'webdart/accountRequest.html')

Again, when I am printing the "test" variable, all I am seeing are requests for the landing page/accountRequest page. No authentication info in the request

Daniel Johnson
  • 193
  • 2
  • 14
  • Can you please add more code. Having views at least would be very helpful to understand what is going on. Especially, the part regarding authentication. Also, I found another related problem on SO, does this help: https://stackoverflow.com/questions/3745291/django-and-common-access-cards-cac – vinkomlacic Mar 16 '22 at 09:10
  • Thank you for the reply, I've posted my views code. I did investigate that SO code, but my current issue is tracing the route of the GET request from GCDS. My understanding of the documentation is that without any middleware, all requests should be forwarded to urls.py and then to views.py based on the urls routing. When I comment out all middleware, I still do not receive an external request (from GCDS). If you could help me understand the data flow, that would be very appreciated. – Daniel Johnson Mar 16 '22 at 16:56
  • I am also seeing the GET requests in the Apache logs, but I can't see them coming into django anywhere. How could I trace the flow? – Daniel Johnson Mar 16 '22 at 17:23

1 Answers1

1

The issue has to do with naming headers on the Apache side. Django drops all headers that are named with an underscore ("_"). However, if you use a dash ("-"), django will accept the header and convert the dash to an underscore.

We changed this in the httpd-ssl.conf file:

RequestHeader set REMOTE_USER "%{SSL_CLIENT_S_DN_CN}s"

to:

RequestHeader set REMOTE-USER "%{SSL_CLIENT_S_DN_CN}s"

Now in our views.py we can call request.META and get all authentication info. Even with the middleware, the request makes it though with all data.

Daniel Johnson
  • 193
  • 2
  • 14