Configuring CORS with NGINX and AWS Elastic Beanstalk - amazon-web-services

My app is an AWS EC2 instance, I have some problems with a CORS error.
It works great on a local server but not on a production server. My app is an angular 11 app in the frontend. Its a Spring Boot API. It is deployed in aws elastic beanstalk, I understand that aws uses nginx and this is what is generating the cors error for me
Then I tried a solution I found around: file path .ebextensions\nginx file nginx.conf
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 33282;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80;
server_name dominio.com;
root /var/app/current/public;
location / {
# Simple requests
if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}
# Preflighted requests
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}
}
location /api {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_max_body_size 10M;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/01_static.conf;
include conf.d/elasticbeanstalk/healthd.conf;
}
}
Nginx has a configuration file by default located in /etc/nginx/nginx.conf. This file has a lot of default properties for all requests and one of these is client_max_body_size. The default value for that property is 1MB.
in the file I am updating the client_max_body_size to 10MB, but the cors error when I send a file larger than 1 MB still persists:
Access to XMLHttpRequest at 'https://dominio.com/api' from origin 'https://www.dominio.frontend.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS configuration in spring:
enter image description here
The application works fine in production except when I use a field to add files larger than 1MB, at which point it generates the CORS error.
None of this has solved the problem. What am I missing here?
Thanks so much for any help!

you should configure CORS in your Spring application.
Create a #Configuration class implementing WebMvConfigurer interface
Override method addCorsMappings(), like sample below, which allow all methods, all origins and apply to all API, aka: Global CORS configuration.
#Configuration
public class CorsConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}
See the guide below if you want to apply selectively to specific APIs
Ref:
https://spring.io/guides/gs/rest-service-cors/

Related

NGINX Reverse Proxy WSS to Amazon API Gateaway

Im trying to set up a reverse wss proxy with nginx to an amazon api gateaway websocket api but I have had no luck with the configuration of nginx so i would be glad if you helped me sort this out.
Let me give you some details:
I have an EC2 instance running nginx that has attached to it an elastic ip address.
I also have dns records to point traffic from connect.example.com to that ip address.
I have set up nginx as a reverse proxy to proxy the traffic from connect.example.com to app.example.com on port 443 with ssl(I have generated the relevant certificates).
On app.example.com lies a websockets api on amazon's api gateaway service.
I can see from nginx's access logs that my requests reach the ec2 instance but I always get error responses no matter how i change the nginx config file(400,403,500,502 etc).
I dont seem to understand where the problem lies even though I have searched around and tried various configurations.
Im attaching my config files below for reference:
nginx.conf
# Based on https://www.nginx.com/resources/wiki/start/topics/examples/full/#nginx-conf
user daemon daemon;
worker_processes auto;
error_log "/opt/bitnami/nginx/logs/error.log";
pid "/opt/bitnami/nginx/tmp/nginx.pid";
events {
worker_connections 1024;
}
http {
#include mime.types;
#default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log "/opt/bitnami/nginx/logs/access.log";
#add_header X-Frame-Options SAMEORIGIN;
client_body_temp_path "/opt/bitnami/nginx/tmp/client_body" 1 2;
proxy_temp_path "/opt/bitnami/nginx/tmp/proxy" 1 2;
fastcgi_temp_path "/opt/bitnami/nginx/tmp/fastcgi" 1 2;
scgi_temp_path "/opt/bitnami/nginx/tmp/scgi" 1 2;
uwsgi_temp_path "/opt/bitnami/nginx/tmp/uwsgi" 1 2;
#connection_pool_size 112;
#sendfile on;
#tcp_nopush on;
#tcp_nodelay on;
#gzip on;
#gzip_http_version 1.0;
#gzip_comp_level 2;
#gzip_proxied any;
#gzip_types text/plain text/css application/javascript text/xml application/xml+rss;
#keepalive_timeout 65;
#ssl_protocols TLSv1.2 TLSv1.3;
#ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 80M;
#server_tokens on;
#include "/opt/bitnami/nginx/conf/server_blocks/*.conf";
# HTTP Server
#server {
# Port to listen on, can also be set in IP:PORT format
# listen 80;
# include "/opt/bitnami/nginx/conf/bitnami/*.conf";
# include "/opt/bitnami/nginx/conf/ssl/ssl-redirect.conf";
# location /status {
# stub_status on;
# access_log off;
# allow 127.0.0.1;
# deny all;
# }
# }
include "/opt/bitnami/nginx/conf/ssl/ssl.conf";
}
ssl.conf
resolver app.example.com;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
#listen [::]:443 ssl;
server_name connect.example.com;
#ssl on;
ssl_certificate /opt/bitnami/nginx/conf/bitnami/certs/server.crt;
ssl_certificate_key /opt/bitnami/nginx/conf/bitnami/certs/server.key;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
root /usr/share/nginx/html;
underscores_in_headers on;
location / {
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_pass https://ws-backend$uri$is_args$args;
proxy_read_timeout 9000;
proxy_pass_request_headers on;
#Websocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol;
proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
proxy_set_header Sec-WebSocket-Accept $http_sec_websocket_accept;
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
upstream ws-backend {
server app.example.com:443;
}
When i connect directly to app.example.com i have no problem and the response is the following:
expected response
But when i connect though connect.example.com i get the following response:
actual response

Specified location path on NGINX not working

I have an AWS EMR and I have been trying to configure a path (/hbase) to access HBase in EMR through NGINX. To achieve my goal I have created a configuration file /etc/nginx/conf.d/hbase.conf.
server {
charset utf-8;
listen 80;
#Hbase works when location /hbase/ is replaced with location /.
It does not work like below.
location /hbase/
{
proxy_pass http://localhost:16010;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Here is my /etc/nginx/nginx.confon EMR
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
log_format main '$remote_addr - [$time_local] "$request" '
'$status "$http_referer" '
'"$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
# HTTPS server
server {
listen 18888 ssl;
ssl_certificate /etc/ssl/certs/nginx.crt;
ssl_certificate_key /etc/ssl/certs/nginx.key;
server_name localhost;
location /webhdfs/v1/user {
proxy_pass http://localhost:14000;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
location /sessions {
proxy_pass http://localhost:8998;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
location /batches {
proxy_pass http://localhost:8998;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
location /proxy {
proxy_pass http://ip-10-100-0-4.ec2.internal:20888;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
} #end server tag
} #end http tag
The problem is when I hit the http://tempmyserverurl/hbase it gives me 404 Not Found error. But when I update the location /hbase to / in my hbase.conf it redirects to master_status and HBase UI is accessable.
I simply want NGINX to load HBase with location /hbase. I have tried using a different server and mentioned proxy pass to this EMR server but it did not work.
Can anyone help me put in the right direction? Help me figure out what I am missing here.
Thanks in advance.
Given
location /hbase
{
proxy_pass http://localhost:16010;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
A request to http://example.com/hbase/some/path would be proxied to http://localhost:16010 like http://localhost:16010/hbase/some/path which most likely does not exist because the hbase is in the URL thus the 404 error.
From https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
If the URI is specified along with the address, it replaces the part of the request URI that matches the location parameter.
location /hbase
{
proxy_pass http://localhost:16010/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
With this example, a request to http://example.com/hbase/some/path would be proxied to http://localhost:16010 like http://localhost:16010/some/path thus removing the hbase from the URL which most likely fixes the issue.

How to edit nginx configuration of an AWS ELB environment for larger payload limit?

I need to edit nginx configuration of an AWS ELB environment so that it accepts payload(post request body) up to 50MB.
The default nginx payload limit is 1MB.
I researched many questions and answers, and found this:
https://stackoverflow.com/a/40745569
But I'm not sure how to access the nginx configuration file behind the ELB environment.
I also tried with this AWS doc:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/java-se-nginx.html
But I still couldn't get responses from post requests with larger payload than 1M. (The server is a Node.js server)
So, please let me know how to change the max payload size of nginx from the default 1M to 50MB. Please note that the nginx is working on an AWS ELB environment.
Appendix 1: Here's the .ebextensions/nginx/nginx.conf file code I used:
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 33282;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
root /var/app/current/public;
location / {
}
location /api {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/01_static.conf;
include conf.d/elasticbeanstalk/healthd.conf;
client_max_body_size 100M; #100mb
}
client_max_body_size 100M; #100mb
}
Appendix 2. I already added these 2 lines to the Node.js Express app:
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: "50mb", extended: true, parameterLimit:50000}));

Redirect Elastic Beanstalk HTTP requests to HTTPS with nginx

I want a redirect from HTTP request to HTTPS on Elastic Beanstalk with nginx as proxy system.
I've found a lot of advices on Google but no one helped, it doesn't redirect.
That is my current test.config file in .ebexentions directory:
files:
"/etc/nginx/conf.d/proxy.conf" :
mode: "000644"
owner: root
group: root
content: |
server{
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
}
I've also tried countless other settings, none of them worked.
That are my load balancer settings:
I hope you can help me. :)
Some considerations:
1 - New Amazon Elastic Beanstalk platform versions running Amazon Linux 2 have a different path of reverse proxy configuration:
~/workspace/my-app/
|-- .platform
| `-- nginx
| `-- conf.d
| `-- elasticbeanstalk
| `-- 00_application.conf
`-- other source files
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.html
2 - The AWS ELB Health Checker appears to be unable to check HTTPS endpoints.
Surely, if you are using a custom certificate for your domain, is unable to act a check in what he considers an "untrusted site".
https://your-eb-app.eu-west-3.elasticbeanstalk.com published with a certificate registered for your organization with this DNS alias https://your-eb-app.your-organization.com causes ELB Health Checker error (certificate domain mismatch).
3 - The configuration suggested exposes all locations to ANY client which shows up with "ELB-HealthChecker*" user-agent on the standard HTTP port (80); not quite what we want :-)
You can configure ELB Health Checker to accept the HTTP 301 status, but it doesn't have much use; a simple redirect response does not mean that our web application is in good health :-)
A more secure solution is a dedicated health check endpoint configuration:
location / {
set $redirect 0;
if ($http_x_forwarded_proto != "https") {
set $redirect 1;
}
if ($redirect = 1) {
return 301 https://$host$request_uri;
}
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location = /health-check.html {
set $redirect 0;
if ($http_x_forwarded_proto != "https") {
set $redirect 1;
}
if ($http_user_agent ~* "ELB-HealthChecker") {
set $redirect 0;
}
if ($redirect = 1) {
return 301 https://$host$request_uri;
}
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
This is the only solution that worked.
It's necessary to overwrite the default nginx file after AWS created it. So there has to be two more files:
Write the nginx file.
Create a script that overwrites the default nginx file.
Run the script after AWS created the default file.
I faced a similar problem when I was trying to redirect all HTTP traffic to HTTPS in my AWS Elastic Beanstalk Go environment using Nginx. This is the solution, I was provided by the AWS Support team:
Create a file in the below directory structure at the root of the application code.
.ebextensions/nginx/conf.d/elasticbeanstalk/00_application.conf
with the content
location / {
set $redirect 0;
if ($http_x_forwarded_proto != "https") {
set $redirect 1;
}
if ($http_user_agent ~* "ELB-HealthChecker") {
set $redirect 0;
}
if ($redirect = 1) {
return 301 https://$host$request_uri;
}
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
For a complete list of AWS provided config files, you should check out this link.
What I did to achieve , I completely override original nginx.conf with my custom given nginx.conf along with some custom configuration for location directives
.plateform
-- nginx
-- nginx.conf
-- conf.d
-- elasticbeanstalk
--custom.conf
Here is my nginx.conf
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 32153;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
}
}
Following line will helped me to safely over-ride the configuration
include conf.d/elasticbeanstalk/*.conf;
AWS Beanstalk environment Load balancer
Make sure that under the load balancer settings of Beanstalk environment both the ports(80,443) enable. If the port 80 is disable you will get the error of 503 "Service Temporarily Unavailable"

site cannot reached after nginx restart - AWS EC2

I am following the tutorial and completed it without any error, when I start nginx it showed me welcome page but after I restart nginx chrome is showing
This site can’t be reached.
I am accessing it by my public IP.
Here is my security group of instance (Inbound)
(Outbound)
Here is my nginx conf file:
upstream sample_project_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/home/ubuntu/django_env/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name <my public ip>;
client_max_body_size 4G;
access_log /home/ubuntu/logs/nginx-access.log;
error_log /home/ubuntu/logs/nginx-error.log;
location /static/ {
alias /home/ubuntu/static/;
}
location /media/ {
alias /home/ubuntu/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://sample_project_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/ubuntu/static/;
}
}
any suggestions ? I am really frustrated, because every thing done perfectly but after restarting nginx, site is not reachable.