Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
}
],
"security": {
"cors": true,
"cors": false,
"service": [
{
"text": "OAuth",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
}
],
"security": {
"cors": true,
"cors": false,
"service": [
{
"text": "OAuth",
Expand Down
8 changes: 4 additions & 4 deletions apps/fhir/bluebutton/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def test_oauth_resource_empty(self):

result = build_oauth_resource(request, version=Versions.V1)

expected = True
expected = False

self.assertEqual(result['cors'], expected)

Expand All @@ -427,7 +427,7 @@ def test_oauth_resource_json(self):

result = build_oauth_resource(request, Versions.V1, 'json')

expected = True
expected = False

self.assertEqual(result['cors'], expected)

Expand All @@ -439,9 +439,9 @@ def test_oauth_resource_xml(self):

result = build_oauth_resource(request, Versions.V1, 'xml')

expected = '<cors>true</cors>'
expected = '<cors>false</cors>'

self.assertEqual(result[16:33], expected)
self.assertIn(expected, result)


class PatientMatchResponseJsonTestCase(BaseApiTest):
Expand Down
4 changes: 2 additions & 2 deletions apps/fhir/bluebutton/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ def build_oauth_resource(request, version=Versions.NOT_AN_API_VERSION, format_ty
if format_type.lower() == 'xml':
security = """
<security>
<cors>true</cors>
<cors>false</cors>
<service>
<text>OAuth</text>
<coding>
Expand Down Expand Up @@ -652,7 +652,7 @@ def build_oauth_resource(request, version=Versions.NOT_AN_API_VERSION, format_ty
else: # json
security = {}

security['cors'] = True
security['cors'] = False
security['service'] = [
{
'text': 'OAuth',
Expand Down
5 changes: 0 additions & 5 deletions docker-compose/web-env-vars.env
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,3 @@ DJANGO_USER_ID_SALT=${DJANGO_USER_ID_SALT}
DJANGO_USER_ID_ITERATIONS=${DJANGO_USER_ID_ITERATIONS}
FHIR_URL="https://prod-sbx.fhir.bfd.cmscloud.local"
DJANGO_FHIR_CERTSTORE=/code/docker-compose/certstore/
# CORS configuration for local docker-based development
# Allow all origins by default in local dev; override with environment if needed
CORS_ORIGIN_ALLOW_ALL=True
# Comma-separated list of allowed origins when CORS_ORIGIN_ALLOW_ALL is False
# Example: CORS_ALLOWED_ORIGINS=https://localhost:3000, https://sandbox.bluebutton.cms.gov
28 changes: 0 additions & 28 deletions hhs_oauth_server/settings/base_ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@
'apps.authorization',
'apps.bb2_tools',
# 3rd Party ---------------------
'corsheaders',
'django_bootstrap5',
'waffle',
# dot (django-oauth-toolkit) must be installed after apps.dot_ext in order to override templates
Expand Down Expand Up @@ -261,7 +260,6 @@
'hhs_oauth_server.middleware.SecurityHeadersMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'hhs_oauth_server.request_logging.RequestTimeLoggingMiddleware',
'corsheaders.middleware.CorsMiddleware',
# Must be before CommonMiddleware but after SessionMiddleware
'django.middleware.locale.LocaleMiddleware',
# Middleware that can send a response must be below this line
Expand Down Expand Up @@ -291,32 +289,6 @@
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
X_FRAME_OPTIONS = 'DENY'

CORS_ORIGIN_ALLOW_ALL = bool_env(env('CORS_ORIGIN_ALLOW_ALL', True))
# TODO: Uncomment once Fargate migration is complete and we would have a better sense of what allowed origins would be.
# Once a Fargate post migration ticket is created, this should be addressed then.
# It is a possible security hardening that can be decided upon later.
# _CORS_ALLOWED = env("CORS_ALLOWED_ORIGINS", "")
# CORS_ALLOWED_ORIGINS = [o.strip() for o in _CORS_ALLOWED.split(",") if o.strip()]

# # Restrict allowed HTTP methods and headers for CORS
# CORS_ALLOW_METHODS = [
# "GET",
# "POST",
# "PUT",
# "PATCH",
# "DELETE",
# "OPTIONS",
# ]

# CORS_ALLOW_HEADERS = (
# "accept",
# "authorization",
# "content-type",
# "user-agent",
# "x-csrftoken",
# "x-requested-with",
# )

ROOT_URLCONF = 'hhs_oauth_server.urls'

TEMPLATES = [
Expand Down
30 changes: 0 additions & 30 deletions hhs_oauth_server/settings/base_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'hhs_oauth_server.request_logging.RequestTimeLoggingMiddleware',
'corsheaders.middleware.CorsMiddleware',
# Must be before CommonMiddleware but after SessionMiddleware
'django.middleware.locale.LocaleMiddleware',
# Middleware that can send a response must be below this line
Expand Down Expand Up @@ -150,7 +149,6 @@
'apps.authorization',
'apps.bb2_tools',
# 3rd Party ---------------------
'corsheaders',
'django_bootstrap5',
'waffle',
# DOT must be installed after apps.dot_ext in order to override templates
Expand Down Expand Up @@ -420,34 +418,6 @@
},
}

# CORS settings
# In local development we default to allowing all origins for convenience.
CORS_ORIGIN_ALLOW_ALL = env.bool('CORS_ORIGIN_ALLOW_ALL', default=True)
# TODO: Uncomment once Fargate migration is complete and we would have a better sense of what allowed origins would be.
# Once a Fargate post migration ticket is created, this should be addressed then.
# It is a possible security hardening that can be decided upon later.
# _CORS_ALLOWED = env("CORS_ALLOWED_ORIGINS", "")
# CORS_ALLOWED_ORIGINS = [o.strip() for o in _CORS_ALLOWED.split(",") if o.strip()]

# # Restrict allowed HTTP methods and headers for CORS
# CORS_ALLOW_METHODS = [
# "GET",
# "POST",
# "PUT",
# "PATCH",
# "DELETE",
# "OPTIONS",
# ]

# CORS_ALLOW_HEADERS = (
# "accept",
# "authorization",
# "content-type",
# "user-agent",
# "x-csrftoken",
# "x-requested-with",
# )

# Failed Login Attempt Module: AXES
# Either integer or timedelta.
# If integer interpreted, as hours
Expand Down
22 changes: 22 additions & 0 deletions hhs_oauth_server/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import json

from django.conf import settings
from django.test import TestCase
from django.test.client import Client
from django.urls import reverse
Expand Down Expand Up @@ -310,3 +311,24 @@ def test_valid_smart_config_response(self):
self.assertEqual(type(json.loads(response_content)), type({}))
self.assertCountEqual(response_json['capabilities'], CAPABILITIES)
self.assertCountEqual(response_json['scopes_supported'], SCOPES_SUPPORTED)


class CorsPolicyTestCase(TestCase):
def test_cors_middleware_is_not_installed(self):
self.assertNotIn('corsheaders', settings.INSTALLED_APPS)
self.assertNotIn('corsheaders.middleware.CorsMiddleware', settings.MIDDLEWARE)

def test_cross_origin_response_has_no_cors_headers(self):
response = self.client.get(reverse('openid-configuration'), HTTP_ORIGIN='https://example.com')
self.assertEqual(response.status_code, 200)
self.assertNotIn('Access-Control-Allow-Origin', response)
self.assertNotIn('Access-Control-Allow-Credentials', response)

def test_preflight_does_not_allow_cross_origin_requests(self):
response = self.client.options(
reverse('openid-configuration'),
HTTP_ORIGIN='https://example.com',
HTTP_ACCESS_CONTROL_REQUEST_METHOD='GET',
)
self.assertNotIn('Access-Control-Allow-Origin', response)
self.assertNotIn('Access-Control-Allow-Methods', response)
1 change: 0 additions & 1 deletion ops/services/01-config/values/prod.sopsw.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
/bb/prod/app/nonsensitive/target_env: prod
/bb/prod/app/nonsensitive/django_application_title: Blue Button API
/bb/prod/app/nonsensitive/signup_timeout_days: "7"
/bb/prod/app/nonsensitive/cors_origin_allow_all: "True"
#ENC[AES256_GCM,data:cjxYrqg/L58XyzZNVBl/xzq6OkIsxhtHe/gyDGvbSnUMuEmBybfd4e+JzGhG49ztVDIUP1btyokUy6mF5BOW53npkRsJrqJoPzLpGeQ=,iv:qaDWHiwa+TT+2/uBMtdSIm7EpbwgeTsMx8XUhBcDh48=,tag:FsvNuBIpoRdn1KWTaIM7iA==,type:comment]
#ENC[AES256_GCM,data:dI8KK9uBMTe93U/s,iv:Y8grfxtOYQCgPlclkmaAbcHA3oKSLY1PutJivUU7Lks=,tag:FeEUBDFEfyWGhivSyw6iAQ==,type:comment]
#ENC[AES256_GCM,data:cjxYrqg/L58XyzZNVBl/xzq6OkIsxhtHe/gyDGvbSnUMuEmBybfd4e+JzGhG49ztVDIUP1btyokUy6mF5BOW53npkRsJrqJoPzLpGeQ=,iv:qaDWHiwa+TT+2/uBMtdSIm7EpbwgeTsMx8XUhBcDh48=,tag:FsvNuBIpoRdn1KWTaIM7iA==,type:comment]
Expand Down
1 change: 0 additions & 1 deletion ops/services/01-config/values/sandbox.sopsw.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
/bb/sandbox/app/nonsensitive/target_env: impl
/bb/sandbox/app/nonsensitive/django_application_title: Blue Button API Sandbox
/bb/sandbox/app/nonsensitive/signup_timeout_days: "7"
/bb/sandbox/app/nonsensitive/cors_origin_allow_all: "True"
#ENC[AES256_GCM,data:etJuMbKWQ0eVN2BYCoqNPOCysTgkaSkJlDAhs4q7QcdoMf8EN+xJ4RwNOf+xCRGcOZeHkzUJlCETeZ179TWzfB3N49R8p3LU2ZrSF54=,iv:ZwQ7c8FbeCF4jQKXALyxcK+WXwV5o6X2/QFGqAeo2tI=,tag:4Utwk/gsCx+eMXSo5L9SCw==,type:comment]
#ENC[AES256_GCM,data:9xyjWpwegeETsHi5d5brcIZ93Kwm,iv:rL3iOjQWeoK02FEtxmvk8M6Zm5bB+hrjDvtVR+0h1FA=,tag:U+NbU+F0if2Rs/c+qBnK5w==,type:comment]
#ENC[AES256_GCM,data:etJuMbKWQ0eVN2BYCoqNPOCysTgkaSkJlDAhs4q7QcdoMf8EN+xJ4RwNOf+xCRGcOZeHkzUJlCETeZ179TWzfB3N49R8p3LU2ZrSF54=,iv:ZwQ7c8FbeCF4jQKXALyxcK+WXwV5o6X2/QFGqAeo2tI=,tag:4Utwk/gsCx+eMXSo5L9SCw==,type:comment]
Expand Down
1 change: 0 additions & 1 deletion ops/services/01-config/values/test.sopsw.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
/bb/test/app/nonsensitive/target_env: test
/bb/test/app/nonsensitive/django_application_title: Blue Button API [TEST]
/bb/test/app/nonsensitive/signup_timeout_days: "7"
/bb/test/app/nonsensitive/cors_origin_allow_all: "True"
#ENC[AES256_GCM,data:NEJYqpcJLWvsdG8PYRiAeGCrFpURmucrKzWdyMaq6WEstOCPfJS6JfMTFhthqBzBu8CVXGDcQlvlnlXpNH1SjOGpTA7vsBFt2shvegI=,iv:H9c/gKlV7taXi3VeOGys7O2XBdZ/EQvd0NSBsY6I48g=,tag:qS6CR1nX3w+jUcGPLAyWgg==,type:comment]
#ENC[AES256_GCM,data:spJgnncvZi3qyraZgJC82sJghYiA,iv:ipn+nvndjFEoFw51PQTStyz5oplo1ULQXExWbsKidCQ=,tag:bthqEYK9+fJk5XC5vz0iAA==,type:comment]
#ENC[AES256_GCM,data:NEJYqpcJLWvsdG8PYRiAeGCrFpURmucrKzWdyMaq6WEstOCPfJS6JfMTFhthqBzBu8CVXGDcQlvlnlXpNH1SjOGpTA7vsBFt2shvegI=,iv:H9c/gKlV7taXi3VeOGys7O2XBdZ/EQvd0NSBsY6I48g=,tag:qS6CR1nX3w+jUcGPLAyWgg==,type:comment]
Expand Down
7 changes: 1 addition & 6 deletions requirements/requirements.dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,6 @@ django==6.0.8 \
# dj-database-url
# django-axes
# django-bootstrap5
# django-cors-headers
# django-filter
# django-ipware
# django-oauth-toolkit
Expand All @@ -670,11 +669,7 @@ django-axes==5.41.1 \
django-bootstrap5==25.3 \
--hash=sha256:3d381a5329a1439ac3237456c28cc8170c62b4c56ad3564d57876ffc3d4c5e78 \
--hash=sha256:cc36f1a19d3200c0f5628c703320edb5c4e39e19bf17607fadf58ddb11828912
# via -r /code/requirements/requirements.in
django-cors-headers==4.0.0 \
--hash=sha256:a971cd4c75b29974068cc36b5c595698822f1e0edd5f1b32ea42ea37326ad4aa \
--hash=sha256:e3cbd247a1a835da4cf71a70d4214378813ea7e08337778b82cb2c1bc19d28d6
# via -r /code/requirements/requirements.in
# via -r requirements.in
django-environ==0.12.0 \
--hash=sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a \
--hash=sha256:92fb346a158abda07ffe6eb23135ce92843af06ecf8753f43adf9d2366dcc0ca
Expand Down
1 change: 0 additions & 1 deletion requirements/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ dj-database-url == 2.0.0
django == 6.0.8
django-axes == 5.41.1
django-bootstrap5 == 25.3 # used in our templates
django-cors-headers == 4.0.0 # used in our settings
django-environ == 0.12.0
django-filter == 25.2
django-getenv == 1.3.2
Expand Down
7 changes: 1 addition & 6 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,6 @@ django==6.0.8 \
# dj-database-url
# django-axes
# django-bootstrap5
# django-cors-headers
# django-filter
# django-ipware
# django-oauth-toolkit
Expand All @@ -463,11 +462,7 @@ django-axes==5.41.1 \
django-bootstrap5==25.3 \
--hash=sha256:3d381a5329a1439ac3237456c28cc8170c62b4c56ad3564d57876ffc3d4c5e78 \
--hash=sha256:cc36f1a19d3200c0f5628c703320edb5c4e39e19bf17607fadf58ddb11828912
# via -r /code/requirements/requirements.in
django-cors-headers==4.0.0 \
--hash=sha256:a971cd4c75b29974068cc36b5c595698822f1e0edd5f1b32ea42ea37326ad4aa \
--hash=sha256:e3cbd247a1a835da4cf71a70d4214378813ea7e08337778b82cb2c1bc19d28d6
# via -r /code/requirements/requirements.in
# via -r requirements.in
django-environ==0.12.0 \
--hash=sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a \
--hash=sha256:92fb346a158abda07ffe6eb23135ce92843af06ecf8753f43adf9d2366dcc0ca
Expand Down
6 changes: 3 additions & 3 deletions static/api-docs/connectathon_openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,7 @@ components:
- `cursor=200` the first record is the 201st record
- `cursor=1000` the first record is the 1001st record
security:
cors: true
cors: false
service:
- text: OAuth
coding:
Expand Down Expand Up @@ -2131,7 +2131,7 @@ components:
- `cursor=200` the first record is the 201st record
- `cursor=1000` the first record is the 1001st record
security:
cors: true
cors: false
service:
- text: OAuth
coding:
Expand Down Expand Up @@ -2538,7 +2538,7 @@ components:
- `cursor=200` the first record is the 201st record
- `cursor=1000` the first record is the 1001st record
security:
cors: true
cors: false
service:
- text: OAuth
coding:
Expand Down
6 changes: 3 additions & 3 deletions static/api-docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1994,7 +1994,7 @@ components:
type: string
documentation: The offset used for result pagination
security:
cors: true
cors: false
service:
- text: OAuth
coding:
Expand Down Expand Up @@ -2376,7 +2376,7 @@ components:
- `identifier=https://bluebutton.cms.gov/resources/identifier/hicn-hash|<your hicn hash>`
- `identifier=https://bluebutton.cms.gov/resources/identifier/mbi-hash|<your mbi hash>`
security:
cors: true
cors: false
service:
- text: OAuth
coding:
Expand Down Expand Up @@ -2499,7 +2499,7 @@ components:
type: token
documentation: A patient identifier
security:
cors: true
cors: false
service:
- text: OAuth
coding:
Expand Down
Loading