-
Notifications
You must be signed in to change notification settings - Fork 0
CORS Best Practices
This document aims to clarify how CORS (Cross-Origin Resource Sharing) is handled between SPAR Client (frontend) and SPAR REST services (backend).
In simple words:
It enables JavaScripts running in browsers to connect to APIs and other web resources like fonts, and stylesheets from multiple different providers. [1]
CORS best practices says only allowed origins should have access to services. This is exactly what SPAR has currently implemented.
- Frontend: can receive requests from the public internet, from anywhere.
-
Backend services (Postgres and Oracle): can receive requests as follows:
- Locally: From
http://localhost:3000
only - DEV namespace: From both
http://localhost:3000
and OpenShift athttps://*.apps.silver.devops.gov.bc.ca
- TEST and PROD namespaces: From OpenShift only, at
https://apps.silver.devops.gov.bc.ca
- Locally: From
All these applications are being deployed on OpenShift. This means a NetworkPolicy is required to manage communication between them. Currently, there's an Ingress policy in place along with a second policy allowing communication from a specific namespace (namespace selector). This setup is sufficient to cover the running application. Take a look at this piece of code to learn more.
Each application holds its own configuration, which allow external communication with the public internet. They are:
- Frontend: The client-side application is served through Caddy with static HTML, JavaScript and styling assets. For this app, all the rules can be found in the Caddyfile, which allows incoming requests from the public internet.
- Postgres Backend: This is one of the REST API services responsible for providing Postgres database access and storage for the frontend client, written in Java on top of Spring Boot. For this application, there's a configuration allowing incoming requests from specifics origins, set previously. If the origin is not in the whitelist, the request will be blocked, resulting in CORS errors. The config file can be found here.
- Oracle Backend: This is another one of the REST API services responsible for providing Oracle database access and storage for the client, also written in Java with Spring Boot. The configuration is the same as the Postgres backend, meaning that both backend services can receive requests from the same origins. The config file for this one can be found here.
When working with CORS, there's must be a whitelist in place of all allowed origins. For new SPAR, with new URLs in place, before making the proper configuration, here's how the issue ca be seeing:
Kubernetes Network Policy template
- apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-openshift-ingress
labels:
template: openshift-name
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
network.openshift.io/policy-group: ingress
policyTypes:
- Ingress
- apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
labels:
template: nr-spar-backend-network-security-policy
spec:
policyTypes:
- Ingress
Caddyfile header configuration for the client app
header {
X-Frame-Options "SAMEORIGIN"
X-XSS-Protection "1;mode=block"
Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate"
X-Content-Type-Options "nosniff"
Strict-Transport-Security "max-age=111"
Content-Security-Policy "base-uri 'self'; ...
Referrer-Policy "same-origin"
}
Class configuration in Java to handle CORS
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Value("${server.allowed.cors.origins}")
private String[] allowedOrigins;
@Override
public void addCorsMappings(@NonNull CorsRegistry registry) {
if (allowedOrigins != null && allowedOrigins.length != 0) {
SparLog.info("allowedOrigins: {}", Arrays.asList(allowedOrigins));
registry
.addMapping("/**")
.allowedOriginPatterns(allowedOrigins)
.allowedMethods("GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS", "HEAD");
}
WebMvcConfigurer.super.addCorsMappings(registry);
}
}
- Kubernetes Network Policies: https://kubernetes.io/docs/concepts/services-networking/network-policies/
- Caddyfile Quick-start: https://caddyserver.com/docs/quick-starts/caddyfile
- WebMvcConfigurer Spring Docs API: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.html
- Spring Boot CORS Configuration Examples: https://howtodoinjava.com/spring-boot2/spring-cors-configuration/
- What is CORS? - https://aws.amazon.com/what-is/cross-origin-resource-sharing/
- Cross-Origin Resource Sharing (CORS): https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
- [1] Complete Guide do CORS: https://reflectoring.io/complete-guide-to-cors/
Welcome to Evergreen Team Wiki page.
- Problem Statement and Goals
- Architecture
- Pull Request Guideline
- Cypress testing Documentation
- Sysdig integration