minio
minio copied to clipboard
ldap just don't work
services:
minio:
container_name: minio
hostname: minio.innovanon.com
image: quay.io/minio/minio:latest # Recommended image from quay.io
ports:
- "9000:9000" # MinIO API port
#- "9001:9001" # MinIO Console UI port
environment:
MINIO_ROOT_USER: minio_admin # Change this to a strong username
MINIO_ROOT_PASSWORD: minio_password # Change this to a strong password
MINIO_SERVER_URL: http://minio.innovanon.com:9000 # Important for S3 clients
SOCKS_PROXY: socks5://tor.innovanon.com:9050
HTTPS_PROXY: socks5://tor.innovanon.com:9050
OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector.innovanon.com:4317
VIRTUAL_HOST: minio.innovanon.com
VIRTUAL_PORT: 9001
MINIO_IDENTITY_LDAP_ENABLE: true
MINIO_IDENTITY_LDAP_SERVER_ADDR: ldap:389
MINIO_IDENTITY_LDAP_SERVER_INSECURE: true
MINIO_IDENTITY_LDAP_LOOKUP_BIND_DN: cn=admin,dc=innovanon,dc=com
MINIO_IDENTITY_LDAP_LOOKUP_BIND_PASSWORD: abc123
MINIO_IDENTITY_LDAP_USER_DN_SEARCH_BASE_DN: ou=Users,dc=innovanon,dc=com
MINIO_IDENTITY_LDAP_USER_DN_SEARCH_FILTER: "(uid=%s)"
#MINIO_IDENTITY_LDAP_USER_DN_ATTRIBUTES: uid
#MINIO_IDENTITY_LDAP_GROUP_SEARCH_FILTER: # Add if you need group-based policies
#MINIO_IDENTITY_LDAP_POLICY_NAME: default-ldap-policy # Example policy mapping
volumes:
- minio-data:/data # Persistent storage for MinIO data
command: server /data --console-address ":9001" # Start server and console on specified ports
restart: unless-stopped
logging:
driver: syslog
depends_on:
nginx-proxy:
condition: service_started # FIXME
#syslog:
# condition: service_healthy
deploy:
resources:
limits:
cpus: 1.0
memory: 500M
reservations:
cpus: 0.1
memory: 100M
healthcheck:
#test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9000/minio/health/live"]
test: ["CMD", "curl", "-f", "--connect-timeout", "5", "http://localhost:9000/minio/health/live"]
interval: 10s # Check every 10 seconds
timeout: 5s # Wait up to 5 seconds for a response
retries: 5 # Retry 5 times before marking as unhealthy
start_period: 30s # Give MinIO 30 seconds to start up initially
volumes:
minio-data:
(venv) user@user-XPS-15-9550:~/src/ia$ docker compose down minio && docker compose up -d minio && docker compose logs -f minio
[+] Running 2/2
✔ Container minio Removed 0.3s
! Network ia_default Resource is still in use 0.0s
WARN[0000] Found orphan containers ([caido ia-python-run-6a51f842b87c pos cafe-pos-system ia-sqlscript-1 inventree-proxy grocy inventree homebox snipeit ia-zap-1 kimai-db ia-python-run-b9926ae74fde flink-sql-gateway ia-flink-sql-gateway-run-7ff3159a4591 ia-python-run-251ccea060f8 airbyte-webapp airbyte-server airbyte-worker ia-python-run-bb2cc22abb06 ia-python-run-3f88571de8bc ia-python-run-9fa63b6560cd ia-python-run-9542d3715a6a]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
[+] Running 2/2
✔ Container nginx-proxy Running 0.0s
✔ Container minio Started 0.4s
minio | MinIO Object Storage Server
minio | Copyright: 2015-2025 MinIO, Inc.
minio | License: GNU AGPLv3 - https://www.gnu.org/licenses/agpl-3.0.html
minio | Version: RELEASE.2025-09-07T16-13-09Z (go1.24.6 linux/amd64)
minio |
minio | API: http://minio.innovanon.com:9000
minio | WebUI: http://172.18.0.22:9001 http://127.0.0.1:9001
minio |
minio | Docs: https://docs.min.io
ldap logs:
notice the ldap logs are blank. minio does not attempt to contact the ldap server. minio logs are similarly tacit unless ldap is misconfigured:
minio | API: SYSTEM.iam
minio | Time: 20:58:40 UTC 11/23/2025
minio | DeploymentID: e23783af-a595-480f-a5ca-c3a5093f0cb0
minio | Error: Unable to load LDAP configuration (LDAP configuration will be disabled!): The following environment variables are unknown: MINIO_IDENTITY_LDAP_POLICY_NAME (*fmt.wrapError)
minio | 6: internal/logger/logger.go:271:logger.LogIf()
minio | 5: cmd/logging.go:29:cmd.iamLogIf()
minio | 4: cmd/iam.go:297:cmd.(*IAMSys).Init()
minio | 3: cmd/server-main.go:1006:cmd.serverMain.func15.1()
minio | 2: cmd/server-main.go:566:cmd.bootstrapTrace()
minio | 1: cmd/server-main.go:1005:cmd.serverMain.func15()
minio | INFO: Waiting for LDAP to be initialized.. (retrying in 1.887043323s)
ldap authentication is actually really easy to implement in python:
LDAP_SERVER_URL :str = os.getenv('LDAP_SERVER_URL', "ldap://ldap.innovanon.com:389")
BIND_DN :str = os.getenv('BIND_DN', "cn=admin,dc=innovanon,dc=com")
BIND_PASSWORD :str = os.getenv('BIND_PASSWORD', "abc123")
SEARCH_BASE :str = os.getenv('SEARCH_BASE', "dc=innovanon,dc=com")
USER_SEARCH_FILTER:str = os.getenv('USER_SEARCH_FILTER', "(uid={})") # Set to search by 'uid' as requested
@cite('https://github.com/RetributionByRevenue/LDAP3-fastapi-auth-simple/blob/main/main.py')
async def LDAP_AUTH(username:str, password:str)->bool:
"""
Authenticates a user against the LDAP server using the Search-and-Bind method.
This version avoids importing constants to bypass environment errors.
"""
try:
server = Server(LDAP_SERVER_URL, get_info=ALL)
# 1. Bind with Service Account to Search for the user's full DN
# Connection() defaults to simple authentication and sync strategy.
search_conn = Connection(
server,
user=BIND_DN,
password=BIND_PASSWORD,
auto_bind=True
)
# Check if service account bind was successful
if not search_conn.bound:
#print(f"LDAP: Service account bind failed with result: {search_conn.result}")
await logger.aerror("LDAP: Service account bind failed with result: %s", search_conn.result)
return False
# Construct the search filter for the user
search_filter = USER_SEARCH_FILTER.format(username)
search_conn.search(
search_base=SEARCH_BASE,
search_filter=search_filter,
attributes=['uid'],
size_limit=1
)
if not search_conn.entries:
#print(f"LDAP: User '{username}' not found in search base.")
await logger.aerror("LDAP: User '%s' not found in search base.", username)
return False
# Get the full DN of the user found
user_dn = search_conn.entries[0].entry_dn
# 2. Attempt User Authentication (Direct Bind)
# This connection uses the user's full DN and the password they provided.
user_conn = Connection(
server,
user=user_dn,
password=password,
auto_bind=True # Attempts simple authentication by default
)
# We only need to check if the connection was successfully bound
if user_conn.bound:
#print(f"LDAP: Authentication successful for {username}. DN: {user_dn}")
await logger.ainfo("LDAP: Authentication successful for %s. DN: %s", username, user_dn)
return True
else:
#print(f"LDAP: Authentication failed for {username}. Result: {user_conn.result}")
await logger.ainfo("LDAP: Authentication failed for %s. Result: %s", username, user_conn.result)
return False
except core.exceptions.LDAPInvalidCredentialsResult:
# Handles explicit invalid credentials error during bind attempt
#print(f"LDAP: Invalid credentials used for either service account or user.")
await logger.aerror("LDAP: Invalid credentials used for either service account or user.")
return False
except core.exceptions.LDAPSocketOpenError as e:
# Handles connection issues (e.g., server down or incorrect URL)
#print(f"LDAP: Connection error (503): {e}")
await logger.aerror("LDAP: Connection error (503): %s", e)
# Reraise as HTTP 503 so the client knows the auth service is offline
raise HTTPException(status_code=503, detail="Authentication service unavailable.")
except Exception as e:
# Catch all unexpected errors gracefully
#print(f"LDAP: Unexpected error: {e}")
await logger.aerror(f"LDAP: Unexpected error: %s", e)
return False
# Initialize FastAPI app
app :FastAPI = FastAPI()
# Define the HTTPBasic authentication scheme
security:HTTPBasic = HTTPBasic()
# Dependency to check LDAP authentication
async def check_ldap_auth(credentials: HTTPBasicCredentials = Depends(security)):
"""FastAPI dependency that attempts LDAP login."""
if not await LDAP_AUTH(credentials.username, credentials.password):
# Triggers the browser's basic auth popup
raise HTTPException(
status_code=401,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
return credentials.username
Please consider correctly implementing ldap authentication or kindly remove it from your documentation. Thanks
It's best not to use this software anymore.
It is no longer maintained