Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: optional CORS #92

Merged
merged 5 commits into from
Feb 18, 2021
Merged
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
7 changes: 5 additions & 2 deletions foca/foca.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ def foca(config: Optional[str] = None) -> App:
logger.info(f"Error handler registered.")

# Enable cross-origin resource sharing
enable_cors(cnx_app.app)
logger.info(f"CORS enabled.")
if(conf.security.cors.enabled is True):
enable_cors(cnx_app.app)
logger.info(f"CORS enabled.")
else:
logger.info(f"CORS not enabled.")

# Register OpenAPI specs
if conf.api.specs:
Expand Down
34 changes: 27 additions & 7 deletions foca/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,24 @@ class AuthConfig(FOCABaseConfig):
validation_checks: ValidationChecksEnum = ValidationChecksEnum.all


class CORSConfig(FOCABaseConfig):
"""Model for Cross Origin Resource Sharing (CORS) configuration.

Args:
enabled: Enable/disable the CORS for the application.

Attributes:
enabled: Enable/disable the CORS for the application.

Example:
>>> CORSConfig(
... enabled=True,
... )
CORSConfig(enabled=True)
"""
enabled: bool = True


class SecurityConfig(FOCABaseConfig):
"""Model for list the Security configuration.

Expand All @@ -730,9 +748,10 @@ class SecurityConfig(FOCABaseConfig):
allow_expired=False, audience=None, claim_identity='sub', claim_issuer='iss',\
algorithms=['RS256'], validation_methods=[<ValidationMethodsEnum.userinfo: 'u\
serinfo'>, <ValidationMethodsEnum.public_key: 'public_key'>], validation_check\
s=<ValidationChecksEnum.all: 'all'>))
s=<ValidationChecksEnum.all: 'all'>), cors=CORSConfig(enabled=True))
"""
auth: AuthConfig = AuthConfig()
cors: CORSConfig = CORSConfig()


class IndexConfig(FOCABaseConfig):
Expand Down Expand Up @@ -1123,12 +1142,13 @@ class 'werkzeug.exceptions.BadGateway'>: {'title': 'Bad Gateway', 'status': 50\
ed=False, audience=None, claim_identity='sub', claim_issuer='iss', algorithms=\
['RS256'], validation_methods=[<ValidationMethodsEnum.userinfo: 'userinfo'>, <\
ValidationMethodsEnum.public_key: 'public_key'>], validation_checks=<Validatio\
nChecksEnum.all: 'all'>)), db=None, jobs=None, log=LogConfig(version=1, disabl\
e_existing_loggers=False, formatters={'standard': LogFormatterConfig(class_for\
matter='logging.Formatter', style='{', format='[{asctime}: {levelname:<8}] {me\
ssage} [{name}]')}, handlers={'console': LogHandlerConfig(class_handler='loggi\
ng.StreamHandler', level=20, formatter='standard', stream='ext://sys.stderr')}\
, root=LogRootConfig(level=10, handlers=['console'])))
nChecksEnum.all: 'all'>), cors=CORSConfig(enabled=True)), db=None, jobs=None, \
log=LogConfig(version=1, disable_existing_loggers=False, formatters={'standard\
': LogFormatterConfig(class_formatter='logging.Formatter', style='{', format='\
[{asctime}: {levelname:<8}] {message} [{name}]')}, handlers={'console': LogHan\
dlerConfig(class_handler='logging.StreamHandler', level=20, formatter='standar\
d', stream='ext://sys.stderr')}, root=LogRootConfig(level=10, handlers=['conso\
le'])))
"""
server: ServerConfig = ServerConfig()
exceptions: ExceptionConfig = ExceptionConfig()
Expand Down
15 changes: 15 additions & 0 deletions tests/test_files/conf_valid_cors_disabled.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
security:
auth:
add_key_to_claims: True
algorithms:
- RS256
allow_expired: False
audience: null
claim_identity: sub
claim_issuer: iss
validation_methods:
- userinfo
- public_key
validation_checks: all
cors:
enabled: False
15 changes: 15 additions & 0 deletions tests/test_files/conf_valid_cors_enabled.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
security:
auth:
add_key_to_claims: True
algorithms:
- RS256
allow_expired: False
audience: null
claim_identity: sub
claim_issuer: iss
validation_methods:
- userinfo
- public_key
validation_checks: all
cors:
enabled: True
14 changes: 14 additions & 0 deletions tests/test_foca.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
JOBS_CONF = str(DIR / "conf_jobs.yaml")
INVALID_JOBS_CONF = str(DIR / "conf_invalid_jobs.yaml")
API_CONF = str(DIR / "conf_api.yaml")
VALID_CORS_DIS_CONF = str(DIR / "conf_valid_cors_disabled.yaml")
VALID_CORS_ENA_CONF = str(DIR / "conf_valid_cors_enabled.yaml")


def create_temporary_copy(path, CONF):
Expand Down Expand Up @@ -104,3 +106,15 @@ def test_foca_invalid_db():
"""Test foca(); invalid db field"""
with pytest.raises(ValidationError):
foca(INVALID_DB_CONF)


def test_foca_CORS_enabled():
"""Ensures CORS is enabled for Microservice"""
app = foca(VALID_CORS_ENA_CONF)
assert app.app.config['FOCA'].security.cors.enabled is True


def test_foca_CORS_disabled():
"""Ensures CORS is disabled if user explicitly mentions"""
app = foca(VALID_CORS_DIS_CONF)
assert app.app.config['FOCA'].security.cors.enabled is False