Can't fetch user info from Keycloak using Python on docker compose - python-3.x

I need to run, from docker compose, three containers: a fastapi server, a keycloack server and a postgres database.
This works well if I run the uvicorn command from my local bash instead of from docker-compose service. I also noted that if I run the code from outside docker-compose, I get the authorization option OpenIdConnect (OAuth2, authorization_code) and from docker-compose: OpenIdConnect (OAuth2, authorization_code with PKCE).
My docker-compose.yaml:
version: '3.9'
services:
web:
build: ./foo
command: uvicorn main:app --reload --workers 1 --host 0.0.0.0 --port 8000
volumes:
- ./foo:/usr/src
ports:
- 8000:8000
depends_on:
- db
- kc
environment:
BAR_ENV: local
LOGGER_NAME: local
BAR_DB_LOCAL_USERPASS: bar:bar
BAR_DB_LOCAL_DB_NAME: bar
BAR_DB_LOCAL_HOST: localhost:5438
BAR_HOSTNAME: bar.local
BAR_AUTH_URL: http://auth.bar.local:8087
BAR_FRONT_URL: bar.local:3000
kc:
image: quay.io/keycloak/keycloak-x:latest
command: start-dev --db=postgres --db-url-host=$$DB_HOST --db-url-database=$$DB_DATABASE --db-username=$$DB_USER --db-password=$$DB_PASS --http-port=8087
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
DB_HOST: db
DB_DATABASE: &KC_DB_DB keycloak
DB_USER: &KC_DB_USER keycloak
DB_PASS: &KC_DB_PASS keycloak
domainname: auth.bar.local
ports:
- 8087:8087
depends_on:
- db
volumes:
- ./resources/keycloak-themes:/opt/keycloak/themes/theme
db:
image: postgres:14
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
KC_DB_DB: *KC_DB_DB
KC_DB_USER: *KC_DB_USER
KC_DB_PASS: *KC_DB_PASS
BAR_DB_DB: bar
BAR_DB_USER: bar
BAR_DB_PASS: bar
ports:
- 5438:5432
volumes:
- ./data/pg-data:/var/lib/postgresql/data
- ./resources/init-kc-db.sh:/docker-entrypoint-initdb.d/init-kc-db.sh
- ./resources/init-bar-db.sh:/docker-entrypoint-initdb.d/init-bar-db.sh
I'm able to access http://<realm>.bar.local:8000/docs from the browser and to authenticate on OpenIdConnect (OAuth2, authorization_code with PKCE). It redirects me to keycloak login page and, then, back to swagger. But, if I try one of my endpoints in swagger, for example, /whoami, I get a 500 internal server error.
Logs from web_1 service:
web_1 | keycloak.exceptions.KeycloakConnectionError: Can't connect to server (HTTPConnectionPool(host='auth.bar.local', port=8087): Max retries exceeded with url: /realms/<realm>/protocol/openid-connect/userinfo (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fd38041a6b0>: Failed to establish a new connection: [Errno 111] Connection refused')))
web_1 | {"asctime": "2022-04-26 11:31:54,929", "threadName": "MainThread", "filename": "httptools_impl.py", "lineno": 437, "message": "172.18.0.1:63454 - \"GET /api/v1_0/whoami HTTP/1.1\" 500", "severity": "INFO"}
the error above occurs in my keycloak_auth.py, when it tries to fetch user info from self.kc_clients[org]:
class OpenIdConnectMultipleViaKeycloak(SecurityBase):
def __init__(
self, *, internal_well_known_url: str, server_url: str,
client_template: str, realm_template: str):
self.model = OpenIdConnectModel(
openIdConnectUrl=internal_well_known_url)
self.scheme_name = 'OpenIdConnect'
self.auto_error = True
self.server_url = server_url
self.client_template = client_template
self.realm_template = realm_template
self.kc_clients = {}
async def __call__(self, request: Request) -> Optional[str]:
org = get_org_from_host(request.base_url.hostname)
if org not in self.kc_clients:
self.kc_clients[org] = KeycloakOpenID(
server_url=self.server_url,
client_id=self.client_template.format(org=org),
realm_name=self.realm_template.format(org=org))
authorization: str = request.headers.get("Authorization")
if not authorization:
raise HTTPException(
status_code=HTTP_403_FORBIDDEN, detail="Not authenticated")
try:
userinfo = self.kc_clients[org].userinfo(
authorization.replace('Bearer ', ''))
userinfo['keycloak_realm'] = org
except KeycloakGetError as e:
raise HTTPException(
status_code=HTTP_403_FORBIDDEN, detail=str(e))
return userinfo
Inspecting kc_1 service from inside container:
[root#e3e5d33ce08b /]# nmap -O localhost
Starting Nmap 7.70 ( https://nmap.org ) at 2022-04-26 17:01 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000080s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 999 closed ports
PORT STATE SERVICE
8087/tcp open simplifymedia
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6.32
OS details: Linux 2.6.32
Network Distance: 0 hops
OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 4.21 seconds
and
root#e3e5d33ce08b /]# netstat -nlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8087 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.11:41567 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:37927 0.0.0.0:* LISTEN -
udp 0 0 127.0.0.11:57222 0.0.0.0:* -
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node PID/Program name Path
Active Bluetooth connections (only servers)
Proto Destination Source State PSM DCID SCID IMTU OMTU Security
Proto Destination Source State Channel
[root#e3e5d33ce08b /]#
Inspecting domain auth.bar.local from web_1 container:
root#0cf70e1cef7f:/usr/src/barz# nmap -p 8087 auth.bar.local
Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-26 17:02 UTC
Nmap scan report for auth.bar.local (127.0.0.1)
Host is up (0.000068s latency).
rDNS record for 127.0.0.1: localhost
PORT STATE SERVICE
8087/tcp closed simplifymedia
Nmap done: 1 IP address (1 host up) scanned in 15.06 seconds
It seems that domainname is reachable from other containers and from outside, but requests made to port 8087 from outside don't work. I've tried to ps aux | grep start-dev and it is running under PID 1. I can even wget it inside kc_1 container and receive a response. I also tried code proposed in https://stackoverflow.com/a/50355857/6328506 , but the behavior did not change.
What am I supposed to do to successfully get http://auth.bar.local:8087/realms/<realm>/protocol/openid-connect/userinfo using docker compose?

Changing localhost for host.docker.internal and adopting solution proposed in https://stackoverflow.com/a/60026589/6328506 for service kc solved the problem. It worth mention that ping/nmap <service_name>, localhost and <network_alias> has different effects.

Related

Problems Connecting to Remote PSQL on Linux Server

I have a linux server with PSQL installed (psql (15.2 (Ubuntu 15.2-1.pgdg22.04+1))). This is installed on Oracle Cloud.
I am trying to connect using the command
psql -h 129.213.17.88 -p 5432 -d breedingdb -U postgres
Where 129.213.17.88 is the public IP of the server in Oracle.
Error message:
psql: error: connection to server at "129.213.17.88", port 5432 failed: No route to host
Is the server running on that host and accepting TCP/IP connections?
sudo ufw status
5432 ALLOW Anywhere
5432/tcp ALLOW Anywhere
5432 (v6) ALLOW Anywhere (v6)
5432/tcp (v6) ALLOW Anywhere (v6)
sudo systemctl status postgresql
I have changed postgresql.conf to include:
listen_addresses = '*'
port = 5432
I have changed pg_hba.conf to include:
host all all 0.0.0.0/0 md5
host all all ::1/128 md5
After that sudo systemctl restart postgresql
inbound rules on Oracle cloud
sudo netstat -plunt |grep postgres
tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN 41326/postgres
tcp6 0 0 :::5432 :::* LISTEN 41326/postgres
I have no problems connecting
locally
sudo nmap -sS 129.213.17.88 -p 5432
Starting Nmap 7.80 ( https://nmap.org ) at 2023-02-18 00:14 UTC
Nmap scan report for 129.213.17.88
Host is up (0.00045s latency).
PORT STATE SERVICE
5432/tcp filtered postgresql
Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds

Open a port of a docker zookeeper container

I'm installing zookeeper on my container.
What I've done is:
root#46966b33c3a1:/opt:> wget https://downloads.apache.org/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz
root#46966b33c3a1:/opt:> tar zxf apache-zookeeper-3.6.2-bin.tar.gz
root#46966b33c3a1:/opt:> cd apache-zookeeper-3.6.2-bin
root#46966b33c3a1:/opt/apache-zookeeper-3.6.2-bin:> cp conf/zoo_sample.cfg conf/zoo.cfg
root#46966b33c3a1:/opt/apache-zookeeper-3.6.2-bin:> vi conf/zoo.cfg
root#46966b33c3a1:/opt/apache-zookeeper-3.6.2-bin:> ./bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.6.2-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
zoo.cfg
tickTime=2000
dataDir=/opt/apache-zookeeper-3.6.2-bin/data
clientPort=2181
initLimit=5
syncLimit=2
It looked like zk sever started without a problem.
However, when I try to connect to zk CLI, an error occurs:
2021-02-09 22:59:16,920 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread#1167] - Opening socket connection to server localhost/127.0.0.1:2181.
2021-02-09 22:59:16,921 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread#1169] - SASL config status: Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2021-02-09 22:59:17,001 [myid:localhost:2181] - WARN [main-SendThread(localhost:2181):ClientCnxn$SendThread#1285] - Session 0x0 for sever localhost/127.0.0.1:2181, Closing socket connection. Attempting reconnect except it is a SessionExpiredException.
java.net.ConnectException: Connection refused
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:344)
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1275)
So, I checked a connection to 2181 port.
root#46966b33c3a1:/opt/apache-zookeeper-3.6.2-bin:> telnet localhost 2181
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
Trying ::1...
telnet: connect to address ::1: Network is unreachable
root#46966b33c3a1:/opt/apache-zookeeper-3.6.2-bin:> hostname -i
172.17.0.2
root#46966b33c3a1:/opt/apache-zookeeper-3.6.2-bin:> telnet 172.17.0.2 2181
Trying 172.17.0.2...
telnet: connect to address 172.17.0.2: Connection refused
Connection is refused.
How can I resolve this?
You can use the zookeeper official docker image. You can use docker-compose instead of doing manual zookeeper installation inside a docker.
Here is a sample docker-compose file. You can modify other configs from documentation based on your requirement.
version: '3.9'
services:
zoo1:
image: zookeeper
restart: always
hostname: zoo1
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
ZOO_TICK_TIME: 2000
ZOO_INIT_LIMIT: 5
ZOO_SYNC_LIMIT: 2
zoo2:
image: zookeeper
restart: always
hostname: zoo2
ports:
- 2182:2181
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181
ZOO_TICK_TIME: 2000
ZOO_INIT_LIMIT: 5
ZOO_SYNC_LIMIT: 2
zoo3:
image: zookeeper
restart: always
hostname: zoo3
ports:
- 2183:2181
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181
ZOO_TICK_TIME: 2000
ZOO_INIT_LIMIT: 5
ZOO_SYNC_LIMIT: 2

Unable to remotely connect to docker container

I am new to docker, this is my first attempt at using it.
I have setup a docker container on a AWS DEBIAN 9 host and started it:
#docker-compose up -d
This is the section related to the web app:
waweb:
image: docker.whatsapp.biz/web:v${WA_API_VERSION:?Run docker-compose with env var WA_API_VERSION (ex. WA_API_VERSION=2.29.2 docker-compose <command> <options>)}
command: ["/opt/whatsapp/bin/wait_on_mysql.sh", "/opt/whatsapp/bin/launch_within_docker.sh"]
ports:
- "9090:443"
volumes:
- whatsappMedia:/usr/local/wamedia
env_file:
- db.env
environment:
WACORE_HOSTNAME: wacore
# This is the version of the docker templates being used to run WhatsApp Business API
WA_RUNNING_ENV_VERSION: v2.2.3
ORCHESTRATION: DOCKER-COMPOSE
depends_on:
- "db"
- "wacore"
links:
- db
- wacore
network_mode: bridge
When I test this it shows that all appears to be correct and it is listening on 9090:
# docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------
wabiz_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:33060->3306/tcp, 33060/tcp
wabiz_wacore_1 /opt/whatsapp/bin/wait_on_ ... Up 6250/tcp, 6251/tcp, 6252/tcp, 6253/tcp
wabiz_waweb_1 /opt/whatsapp/bin/wait_on_ ... Up 0.0.0.0:9090->443/tcp
and:
# netstat -tulpn | grep LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 18818/sshd
tcp6 0 0 :::22 :::* LISTEN 18818/sshd
tcp6 0 0 :::9090 :::* LISTEN 32144/docker-proxy
tcp6 0 0 :::33060 :::* LISTEN 32361/docker-proxy
I can test-connect to this locally:
# telnet localhost 9090
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
Yet when I attempt connect to it remotely, the connection is refused.
The firewall ports are all open to my IP (1-65535), I can remotely telnet to port 22 and also create a python simple-http-server and connect to that remotely too.
I thought that maybe IPV6 was being forced, but it is not:
# sysctl net.ipv6.bindv6only
net.ipv6.bindv6only = 0
Any suggestions on what the issue may be ?

Connection to MongoDb server hosted on CentOS is failing

Mongo up and running on CentOs Machine
All IPs enabled, no authorization
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
# security: none
# authorization: 'enabled
Port enabled
netstat -tulnp
(No info could be read for "-p": geteuid()=1001 but you should be root.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN -
Connection from the server itself using the IP works fine
mongo --host 10.X.X.16
MongoDB shell version v4.2.2
connecting to: mongodb://10.X.X.16:27017/?compressors=disabled&gssapiServiceName=mongodb
MongoDB server version: 4.2.2
Server has startup warnings:
2020-01-21T15:48:26.297-0800 I CONTROL [initandlisten]
Doing the same thing from a remote Windows Machine
mongo --host 10.X.X.16
MongoDB shell version v4.2.1
connecting to: mongodb://10.X.X.16:27017/?compressors=disabled&gssapiServiceName=mongodb
2020-01-21T15:59:07.563-0800 E QUERY [js] Error: couldn't connect to server 10.65.5.16:27017, connection attempt failed: NetworkTimeout: Error connecting to 10.X.X.16:27017 :: caused by :: Socket operation timed out :
connect#src/mongo/shell/mongo.js:341:17
#(connect):2:6
2020-01-21T15:59:07.571-0800 F - [main] exception: connect failed
2020-01-21T15:59:07.571-0800 E - [main] exiting with code 1
Thanks!
Problem fixed:
I had to disable the firewall for the mongo port
sudo firewall-cmd --zone=public --add-port=27017/tcp --permanent
sudo firewall-cmd --reload

Why isn't my port exposed? netstat output included

This is my problem
# docker exec -ti root_web_1 bash
[root#ca32f79bdc14]# curl couchdb:5984
curl: (7) Failed to connect to couchdb port 5984: Connection refused
[root#ca32f79bdc14]# curl redis:6379
-ERR wrong number of arguments for 'get' command
-ERR unknown command 'Host:'
-ERR unknown command 'User-Agent:'
-ERR unknown command 'Accept:'
^C
Question
Why can't I access couchdb:5984 ?
Background
When I am in my couchdb container I can curl localhost:5984 and it responds and netstat -nl gives me
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:5984 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.11:35300 0.0.0.0:* LISTEN
udp 0 0 127.0.0.11:51267 0.0.0.0:*
and the Dockerfile contains EXPOSE 5984, but I get connection refused when doing curl couchdb:5984 from the web container.
When I do the same with redis, curl redis:6379 it responds and netstat -nl gives
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.11:46665 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN
tcp6 0 0 :::6379 :::* LISTEN
udp 0 0 127.0.0.11:49518 0.0.0.0:*
This is the couchdb Dockerfile
FROM fedora:25
RUN dnf -y update
RUN dnf -y install couchdb
EXPOSE 5984
CMD ["/usr/bin/couchdb"]
This is the docker-compose.yml.
version: '2'
networks:
revproxynet:
external: true
services:
web:
images: nginx
networks:
- revproxynet
redis:
image: redis
networks:
- revproxynet
couchdb:
build: /docker/couchdb/
networks:
- revproxynet
The network is created with docker network create revproxynet.
In /etc/couchdb/local.ini you need to have
[httpd]
bind_address = 0.0.0.0
and it will work.

Resources