PostgreSQL在SSL模式下返回”服务器不支持SSL,但需要SSL”的错误信息。

huangapple go评论138阅读模式
英文:

PostgreSQL in SSL mode returns 'server does not support SSL, but SSL was required'

问题

你好 PostgreSQL在SSL模式下返回”服务器不支持SSL,但需要SSL”的错误信息。 希望你一切都好!

我正在尝试在一个Postgres Docker容器和一个FastAPI容器之间启用SSL通信,但正如你从标题中可以看出,有些东西不起作用 :/

我阅读了文档,据说我已经按照要求设置了一切。例如:

  1. 我创建了根CA,然后使用根CA为Postgres服务器创建了密钥和签名证书。

  2. 我已经按照以下方式配置了postgresql.conf文件:

  1. ... 默认配置
  2. # - SSL -
  3. ssl = on
  4. ssl_ca_file = '/var/lib/postgresql/data/root.crt'
  5. ssl_cert_file = '/var/lib/postgresql/data/server.crt'
  6. ssl_key_file = '/var/lib/postgresql/data/server.key'
  7. #ssl_crl_file = ''
  8. #ssl_crl_dir = ''
  9. #ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
  10. #ssl_prefer_server_ciphers = on
  11. #ssl_ecdh_curve = 'prime256v1'
  12. #ssl_min_protocol_version = 'TLSv1.2'
  13. #ssl_max_protocol_version = ''
  14. #ssl_dh_params_file = ''
  15. #ssl_passphrase_command = ''
  16. #ssl_passphrase_command_supports_reload = off
  17. ... 默认配置

这是我的目录结构:

  1. .
  2. ├── docker-compose.yaml
  3. ├── Dockerfile
  4. ├── main.py
  5. ├── postgresql.conf
  6. ├── README.md
  7. ├── ssl-client
  8. ├── root.crt
  9. ├── root.csr
  10. ├── root.key
  11. ├── server.crt
  12. ├── server.csr
  13. └── server.key
  14. └── ssl-server
  15. ├── pgdata [error opening dir] -> 因为它使用了自己的用户(999
  16. ├── root.crt
  17. ├── root.csr
  18. ├── root.key
  19. ├── server.crt
  20. ├── server.csr
  21. └── server.key

这是我如何将所有内容传递给容器的方式:

  1. version: '3.8'
  2. services:
  3. app:
  4. container_name: python-app
  5. build:
  6. context: .
  7. dockerfile: Dockerfile
  8. ports:
  9. - '8000:80'
  10. depends_on:
  11. - postgres
  12. networks:
  13. - postgres-ssl
  14. postgres:
  15. container_name: postgres
  16. image: postgres:latest
  17. environment:
  18. POSTGRES_USER: username
  19. POSTGRES_PASSWORD: password
  20. POSTGRES_DB: database
  21. PGDATA: /var/lib/postgresql/data/pgdata
  22. volumes:
  23. - ./postgresql.conf:/etc/postgresql/postgresql.conf
  24. - ./ssl-server:/var/lib/postgresql/data/
  25. ports:
  26. - '5432:5432'
  27. networks:
  28. - postgres-ssl
  29. networks:
  30. postgres-ssl:
  31. name: postgres-ssl

最后,这是我的Python代码,尽管这里的一切都按预期工作,因为我得到了上面的错误:

  1. from fastapi import FastAPI, HTTPException
  2. from pydantic import BaseModel
  3. from sqlalchemy import create_engine
  4. from sqlalchemy.orm import sessionmaker
  5. from sqlalchemy.ext.declarative import declarative_base
  6. from sqlalchemy import Column, Integer, String
  7. from typing import List
  8. app = FastAPI()
  9. DATABASE_URL = "postgresql+psycopg2://username:password@postgres/database?sslmode=require"
  10. engine = create_engine(DATABASE_URL)
  11. SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  12. Base = declarative_base()
  13. def get_db():
  14. db = SessionLocal()
  15. try:
  16. yield db
  17. finally:
  18. db.close()
  19. class Student(Base):
  20. __tablename__ = 'students'
  21. id = Column(Integer, primary_key=True, nullable=False)
  22. name = Column(String, nullable=False)
  23. class StudentRequest(BaseModel):
  24. name: str
  25. class Config:
  26. orm_mode = True
  27. class StudentCreate(BaseModel):
  28. name :str
  29. @app.post("/items/", response_model=StudentRequest)
  30. def create_item(item: StudentCreate):
  31. db = SessionLocal()
  32. db_item = Student(**item.dict())
  33. db.add(db_item)
  34. db.commit()
  35. db.refresh(db_item)
  36. db.close()
  37. return db_item
  38. @app.get("/items/", response_model=List[StudentRequest])
  39. def get_items():
  40. db = SessionLocal()
  41. items = db.query(Student).all()
  42. db.close()
  43. return items
  44. @app.get("/")
  45. async def read_root():
  46. return {"message": "Hello, FastAPI with PostgreSQL using SSL!"}

如果我尝试通过将其挂载到相同的PGDATA路径来“覆盖”默认配置文件,我会得到一个错误:

这是这种情况下的docker-compose:

  1. version: '3.8'
  2. services:
  3. app:
  4. container_name: python-app
  5. build:
  6. context: .
  7. dockerfile: Dockerfile
  8. ports:
  9. - '8000:80'
  10. depends_on:
  11. - postgres
  12. networks:
  13. - postgres-ssl
  14. postgres:
  15. container_name: postgres
  16. image: postgres:latest
  17. environment:
  18. POSTGRES_USER: username
  19. POSTGRES_PASSWORD: password
  20. POSTGRES_DB: database
  21. PGDATA: /etc/postgresql/data
  22. volumes:
  23. - ./postgresql.conf:/etc/postgresql/data/postgresql.conf
  24. - ./ssl-server:/etc/postgresql/data/ssl-server
  25. ports:
  26. - '5432:5432'
  27. networks:
  28. - postgres-ssl
  29. networks:
  30. postgres-ssl:
  31. name: postgres-ssl

以及我在启动时收到的错误:

  1. postgres | The files belonging to this database system will be owned by user "postgres".
  2. postgres | This user must also own the server process.
  3. postgres |
  4. postgres |
  5. postgres | The database cluster will be initialized with locale "en_US.utf8".
  6. postgres | The default database encoding has accordingly been set to "UTF8".
  7. postgres | The default text search configuration will be set to "english".
  8. postgres |
  9. postgres | Data page checksums are disabled.
  10. postgres |
  11. postgres |
  12. postgres | initdb: error: directory "/etc/postgresql/data" exists but is not empty
  13. postgres | initdb: hint: If you want to create a new database system, either remove or empty the directory "/etc/postgresql/data" or run initdb with an argument other than "/etc/postgresql/data".
  14. postgres exited with code 1

我在这里漏掉了什么吗?为什么这不会设置SSL连接? :/

我非常困惑,如果你能在这里帮助我,我将非常非常感激!

提前谢谢你,祝你有美好的一天!

英文:

Hi PostgreSQL在SSL模式下返回”服务器不支持SSL,但需要SSL”的错误信息。 Hope you're doing great!

I a trying to enable SSL communications between a Postgres docker container and a FastAPI container, however as you can tell from the title, something is not working :/

I read the documentation and supposedly I have set up everything accordingly. For instance:

  1. I created the root CA, and then a key and signed cert for the postgres server with the root CA.

  2. I have configured the postgresql.conf file in this manner:

  1. ... defaults
  2. # - SSL -
  3. ssl = on
  4. ssl_ca_file = '/var/lib/postgresql/data/root.crt'
  5. ssl_cert_file = '/var/lib/postgresql/data/server.crt'
  6. ssl_key_file = '/var/lib/postgresql/data/server.key'
  7. #ssl_crl_file = ''
  8. #ssl_crl_dir = ''
  9. #ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
  10. #ssl_prefer_server_ciphers = on
  11. #ssl_ecdh_curve = 'prime256v1'
  12. #ssl_min_protocol_version = 'TLSv1.2'
  13. #ssl_max_protocol_version = ''
  14. #ssl_dh_params_file = ''
  15. #ssl_passphrase_command = ''
  16. #ssl_passphrase_command_supports_reload = off
  17. ... defaults

This is what my tree looks like:

  1. .
  2. ├── docker-compose.yaml
  3. ├── Dockerfile
  4. ├── main.py
  5. ├── postgresql.conf
  6. ├── README.md
  7. ├── ssl-client
  8. │   ├── root.crt
  9. │   ├── root.csr
  10. │   ├── root.key
  11. │   ├── server.crt
  12. │   ├── server.csr
  13. │   └── server.key
  14. └── ssl-server
  15. ├── pgdata [error opening dir] -> because it is using its own user (999)
  16. ├── root.crt
  17. ├── root.csr
  18. ├── root.key
  19. ├── server.crt
  20. ├── server.csr
  21. └── server.key

and this is how I am passing everything to the container:

  1. version: '3.8'
  2. services:
  3. app:
  4. container_name: python-app
  5. build:
  6. context: .
  7. dockerfile: Dockerfile
  8. ports:
  9. - '8000:80'
  10. depends_on:
  11. - postgres
  12. networks:
  13. - postgres-ssl
  14. postgres:
  15. container_name: postgres
  16. image: postgres:latest
  17. environment:
  18. POSTGRES_USER: username
  19. POSTGRES_PASSWORD: password
  20. POSTGRES_DB: database
  21. PGDATA: /var/lib/postgresql/data/pgdata
  22. volumes:
  23. - ./postgresql.conf:/etc/postgresql/postgresql.conf
  24. - ./ssl-server:/var/lib/postgresql/data/
  25. ports:
  26. - '5432:5432'
  27. networks:
  28. - postgres-ssl
  29. networks:
  30. postgres-ssl:
  31. name: postgres-ssl

Lastly, here is my python code, although everything is working as expected here, as I am getting the error above:

  1. from fastapi import FastAPI, HTTPException
  2. from pydantic import BaseModel
  3. from sqlalchemy import create_engine
  4. from sqlalchemy.orm import sessionmaker
  5. from sqlalchemy.ext.declarative import declarative_base
  6. from sqlalchemy import Column, Integer, String
  7. from typing import List
  8. app = FastAPI()
  9. DATABASE_URL = "postgresql+psycopg2://username:password@postgres/database?sslmode=require"
  10. engine = create_engine(DATABASE_URL)
  11. SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  12. Base = declarative_base()
  13. def get_db():
  14. db = SessionLocal()
  15. try:
  16. yield db
  17. finally:
  18. db.close()
  19. class Student(Base):
  20. __tablename__ = 'students'
  21. id = Column(Integer, primary_key=True, nullable=False)
  22. name = Column(String, nullable=False)
  23. class StudentRequest(BaseModel):
  24. name: str
  25. class Config:
  26. orm_mode = True
  27. class StudentCreate(BaseModel):
  28. name :str
  29. @app.post("/items/", response_model=StudentRequest)
  30. def create_item(item: StudentCreate):
  31. db = SessionLocal()
  32. db_item = Student(**item.dict())
  33. db.add(db_item)
  34. db.commit()
  35. db.refresh(db_item)
  36. db.close()
  37. return db_item
  38. @app.get("/items/", response_model=List[StudentRequest])
  39. def get_items():
  40. db = SessionLocal()
  41. items = db.query(Student).all()
  42. db.close()
  43. return items
  44. @app.get("/")
  45. async def read_root():
  46. return {"message": "Hello, FastAPI with PostgreSQL using SSL!"}

If I try to 'override' the default configuration file by mounting it in the same PGDATA path, I get an error:

Here is the docker-compose for this case:

  1. version: '3.8'
  2. services:
  3. app:
  4. container_name: python-app
  5. build:
  6. context: .
  7. dockerfile: Dockerfile
  8. ports:
  9. - '8000:80'
  10. depends_on:
  11. - postgres
  12. networks:
  13. - postgres-ssl
  14. postgres:
  15. container_name: postgres
  16. image: postgres:latest
  17. environment:
  18. POSTGRES_USER: username
  19. POSTGRES_PASSWORD: password
  20. POSTGRES_DB: database
  21. PGDATA: /etc/postgresql/data
  22. volumes:
  23. - ./postgresql.conf:/etc/postgresql/data/postgresql.conf
  24. - ./ssl-server:/etc/postgresql/data/ssl-server
  25. ports:
  26. - '5432:5432'
  27. networks:
  28. - postgres-ssl
  29. networks:
  30. postgres-ssl:
  31. name: postgres-ssl

And the error I get at startup:

  1. postgres | The files belonging to this database system will be owned by user "postgres".
  2. postgres | This user must also own the server process.
  3. postgres |
  4. postgres |
  5. postgres | The database cluster will be initialized with locale "en_US.utf8".
  6. postgres | The default database encoding has accordingly been set to "UTF8".
  7. postgres | The default text search configuration will be set to "english".
  8. postgres |
  9. postgres | Data page checksums are disabled.
  10. postgres |
  11. postgres |
  12. postgres | initdb: error: directory "/etc/postgresql/data" exists but is not empty
  13. postgres | initdb: hint: If you want to create a new database system, either remove or empty the directory "/etc/postgresql/data" or run initdb with an argument other than "/etc/postgresql/data".
  14. postgres exited with code 1

Am I missing something here? How come this is not setting up SSL connections? :/

I am very confused honestly, if you could help me out here, it would be very, very much appreciated!

Thank you in advance and have a wonderful day!

答案1

得分: 1

如果PGDATA设置为/var/lib/postgresql/data/pgdata,那么将自定义配置文件放在/etc/postgresql/中是没有任何作用的。它只会忽略该文件并使用默认配置。

此外,证书和其他内容需要放在PGDATA目录内,而不是与其同级。

英文:

If PGDATA is set to /var/lib/postgresql/data/pgdata, then putting your custom config file in /etc/postgresql/ isn't going to do anything. It will just ignore it and use the default.

Furthermore, the certs and stuff need to be inside PGDATA, not siblings to it.

huangapple
  • 本文由 发表于 2023年8月9日 01:56:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862093.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定