Ocelot gateway unable to obtain configuration from identityserver in docker compose - asp.net-core

I have an error that I can't seem to understand why this is happening.
I have a microservice architecture running in a docker network. I'm trying to set up an identity server with the framework Identityserver4.
There is a proxy forwarding to an Ocelot gateway. The client is an angular application.
The login and logout and retrieving the access token and the identity token is successful, but when I try to set up authentication in Ocelot, I get the following error.
DX20803: Unable to obtain configuration from: 'http://identityservice:5010/.well-
known/openid-configuration'.
gateway_1 | System.InvalidOperationException: IDX20803: Unable to obtain
configuration from: 'http://identityservice:5010/.well-known/openid-configuration'.
gateway_1 | ---> System.IO.IOException: IDX20804: Unable to retrieve document
from: 'http://localhost/auth/.well-known/openid-configuration/jwks'.
gateway_1 | ---> System.Net.Http.HttpRequestException: Cannot assign
requested address
The docker-compose is set up in this way
version: '3.0'
services:
pricecalendarservice:
build:
context: ./PriceCalendarService
environment:
- ASPNETCORE_URLS=http://+:5002
- RedisConnection=redis
gateway:
build:
context: ./Gateway/
environment:
- ASPNETCORE_URLS=http://+:5000
- ID_URL=http://identityservice
frontend:
build:
context: ./SPA
dockerfile: staging.dockerfile
itemmanagerservice:
build:
./ItemManagerService
environment:
- ASPNETCORE_URLS=http://+:5003
- IdentityUrl=http://identityservice
identityservice:
build:
context: ./IdentityServer/IdentityServer
environment:
- DEV_URL=http://localhost
- ASPNETCORE_ENVIRONMENT=Developmnet
- ASPNETCORE_URLS=http://+:5010
- IDENTITY_ISSUER=http://localhost/auth
- RedisConnection=redis
ports:
- 5010:5010
proxy:
build:
context: ./proxy
ports:
- 80:80
redis:
image: redis
ports:
- 6379:6379
The Identityserver is configured in the following way
string redisConnectionString = Environment.GetEnvironmentVariable("RedisConnection",
EnvironmentVariableTarget.Process);
string prodEnv = Environment.GetEnvironmentVariable("PROD_URL");
string devEnv = Environment.GetEnvironmentVariable("DEV_URL");
string env = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
string issuer = Environment.GetEnvironmentVariable("IDENTITY_ISSUER");
var redis = ConnectionMultiplexer.Connect( redisConnectionString + ":6379");
services.AddDataProtection()
.PersistKeysToStackExchangeRedis( redis , "DataProtection-Keys")
.SetApplicationName("product");
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder
.WithOrigins("https:localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader();
}));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is
needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
var config = new Config();
config.setEnvironemnt(devEnv);
services.AddIdentityServer(options => {
options.PublicOrigin = issuer;
})
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(config.GetIdentityResources())
.AddInMemoryApiResources(config.GetApis())
.AddInMemoryClients(config.GetClients())
.AddTestUsers(config.GetUsers());
NB. the issuer is set to "http://localhost/auth"
The Nginx proxy server is set with the following settings
server {
listen 80;
location / {
proxy_pass http://frontend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location /api/hub {
proxy_pass http://gateway:5000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api {
proxy_pass http://gateway:5000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Upgrade $http_upgrade;
proxy_cache_bypass $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /auth {
proxy_pass http://gateway:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
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_cache_bypass $http_upgrade;
}
}
The gateway configuration is, as read in the documentation at Ocelot Documentation
var authenticationProviderKey = "TestKey";
s.AddAuthentication()
.AddIdentityServerAuthentication(authenticationProviderKey, x =>
{
x.Authority = "http://identityservice:5010";
x.RequireHttpsMetadata=false;
});
/*
options.TokenValidationParameters = new
Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudiences = new[] {"item"}
};
*/
s.AddOcelot();
s.AddSwaggerGen(swagger =>
{
swagger.SwaggerDoc("v1", new OpenApiInfo { Title = "PriceCalendarService" });
});
It seems that the gateway, which is running inside the docker network cant get access to the identity server. But I have tried both the URL which the angular is calling which is
"http://localhost/auth"
And also the name of the service running in docker, in multiple ways.
"http://identityservice:5010"
"http://identityservice"
But somehow, the gateway can't get access to the identity server to load the discovery document.
Can anyone point me in any direction on how to get this right.

Related

ASPNET does not run under ssl behing nginx

My setup is the following
location / {
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Url-Scheme https;
proxy_set_header Front-End-Https on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Accel-Internal /internal-nginx-static-location;
access_log off;
proxy_pass http://127.0.0.1:5000;
}
Behind nginx i am running a docker container with an aspnet core application. But this application thinks it runs using schema http instead of https.
The aspnet core application has been setup using
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
and
app.UseForwardedHeaders
So the application is available via ssl but as soon as i try to login, the secured cookies are not transfered to client and the proxy ends in an incorrect state (bad gateway). The login in the application itself was successful (in the logs the result is fine) but the nginx seems unable to bring the response to the client.
Some faced a similar issue?

Point subdomain to node express custom route with Nginx Proxy

I have a domain configured with nginx proxy to route like this:
mydomain.com -> localhost:3000
But now, I want a particular subdomain, to point to something like this:
subdomain.mydomain.com -> localhost:3000/mypage
Tried several things but I can't make it work:
server {
listen 80;
server_name subdomain.mydomain.com;
server_tokens off;
proxy_hide_header X-Powered-By;
location /healthcheck {
access_log off;
proxy_pass http://localhost:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
# NGINX will reject anything not matching /
location ~ /(?<section>.+)/ {
# Reject requests with unsupported HTTP method
if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)$) {
return 405;
}
# Only requests matching the whitelist expectations will
# get sent to the application server
proxy_pass http://localhost:3000/mypage/$section;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
}

Loadbalancing with Nginx error not redirecting properly

I was able to get the load balancer to work only on inception. It seems that when I do any clicks on the page, it renders http://backend , and not the actual web address.
here is my config on the downstream
upstream backend {
server unix:///var/www/my_app/shared/tmp/sockets/puma.sock;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

ActionCable 404 error for wss with ELB and nginx

I'm getting this error for actioncable when I switched my site to https:
WebSocket connection to 'wss://domain.com/cable' failed: Error during
WebSocket handshake: Unexpected response code: 404
The https site works fine, but I get a 404 for the websocket address. My current setup has the SSL terminate at the ELB and nginx redirect http to https. I run actioncable together with my rail server, not as a standalone.
How would I set up secure websockets in ?
Here is my nginx conf file
upstream puma {
server unix://var/run/server.sock;
}
server {
listen 80;
server_name default_server;
root /var/www/apps/server/public;
location /cable {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_pass http://puma;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_next_upstream error;
if ($http_x_forwarded_proto != "https") {
rewrite ^(.*)$ https://$host$1 permanent;
}
proxy_pass http://puma;
...
}
And here is the configuration on ELB:
ELB Listeners
Fixed similar error (404 in actioncable /cable) in my setup like this
location /cable {
proxy_pass http://unix:/home/app/shared/tmp/puma/socket;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
so add same proxy_set_header as you have in the other location (X-Real-IP etc)

Ratchet + nginx + SSL/secure websocket

I've been trying to run Ratchet.io over SSL (this problem: php ratchet websocket SSL connect?).
My webserver is running at myhost.mobi, and I have created a separate virtual host for websocket service "wws.myhost.mobi".
My web socket:
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0');
$webServer = new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
)
)
),
$webSock
);
My nginx config (I'm on nginx 1.5.8):
upstream websocketserver {
server localhost:8080;
}
server {
server_name wss.myapp.mobi;
listen 443;
ssl on;
ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
ssl_certificate_key /etc/ssl/myapp-mobi.key;
access_log /var/log/wss-access-ssl.log;
error_log /var/log/wss-error-ssl.log;
location / {
proxy_pass http://websocketserver;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "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;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
proxy_redirect off;
}
}
My client-side script:
var conn = new ab.Session('wss://wss.myapp.mobi', function(o) {
// ...
}, function() {
console.warn('WebSocket connection closed');
}, {
skipSubprotocolCheck: true
});
So, when I load the page in Firefox, I see an outgoing connection to wss://wss.myapp.mobi:8080/, which is hanging (the spinner) and never completes or dies. I do not see any trace of request arriving on the backend in the logs.
What am I missing there?
Thanks!
EDIT I have realized that I should be connecting to wss://wss.myapp.mobi, but now I am getting "101 Switching Protocols" status.
EDIT 2 Everything is working now with the config above. "101 Switching Protocols" status turns out to be a normal message. PROBLEM SOLVED!
By checking question edit history, it is clear that, the configuration in the question was correct, temuri was trying to connect from client with port set in,
upstream websocketserver {
server localhost:8080;
}
but this code block tells Nginx there is a tcp server running on port 8080, represents it as websocketserver alias, but the running server is not accessible to public.
Check the below configuration,
server {
server_name wss.myapp.mobi;
listen 443;
ssl on;
ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
ssl_certificate_key /etc/ssl/myapp-mobi.key;
access_log /var/log/wss-access-ssl.log;
error_log /var/log/wss-error-ssl.log;
location / {
proxy_pass http://websocketserver;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "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;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
proxy_redirect off;
}
}
this configuration binds the domain wss.myapp.mobi to port 443 enabling ssl and proxying the requests to the local websocket server via proxy_pass directive, rest directives are for connection upgrades handling.
So the websocket server can be accessed from browser client with
// connect through binded domain
// instead of wss.myapp.mobi:8080 which will not work
var url = 'wss://wss.myapp.mobi';