Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# ===========================================
# Git
# ===========================================
.git
.gitignore
.gitattributes

# ===========================================
# Python
# ===========================================
__pycache__
*.py[cod]
*$py.class
*.so
.Python
.venv
venv
env
ENV
.env
.env.*
*.egg
*.egg-info
dist
build
eggs
parts
sdist
develop-eggs
.installed.cfg
lib
lib64
*.manifest
*.spec
pip-log.txt
pip-delete-this-directory.txt

# ===========================================
# Testing
# ===========================================
tests
pytest.ini
.pytest_cache
.coverage
.tox
.nox
htmlcov
coverage.xml
*.cover
.hypothesis

# ===========================================
# IDE & Editors
# ===========================================
.idea
.vscode
*.swp
*.swo
*~
.project
.pydevproject
.settings

# ===========================================
# Documentation
# ===========================================
docs
*.md
!README.md
mkdocs.yml

# ===========================================
# Docker
# ===========================================
Dockerfile*
docker-compose*.yml
.docker

# ===========================================
# CI/CD
# ===========================================
.github
.gitlab-ci.yml
.travis.yml
Jenkinsfile

# ===========================================
# Misc
# ===========================================
*.log
*.tmp
*.temp
*.bak
*.cache
.DS_Store
Thumbs.db
*.png
*.jpg
*.jpeg
*.gif
*.svg

# ===========================================
# Project specific
# ===========================================
manual_oauth_qa
examples
scripts
_typos.toml
CLAUDE.md
LICENSE

# ===========================================
# Linting
# ===========================================
.ruff_cache
.mypy_cache

# ===========================================
# Pre-commit
# ===========================================
.pre-commit-config.yaml
.pre-commit-hooks.yaml

# Note: uv.lock and pyproject.toml are REQUIRED for the build
# Note: agent-memory-client/ is REQUIRED (workspace dependency)
15 changes: 12 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ WINDOW_SIZE=12
GENERATION_MODEL=gpt-4o-mini
EMBEDDING_MODEL=text-embedding-3-small

# OpenAI API key
# API Keys
OPENAI_API_KEY=your_openai_api_key
ANTHROPIC_API_KEY=your_anthropic_api_key

# Cloud Region
REGION_NAME=your_cloud_region
# AWS Cloud Credentials
AWS_ACCESS_KEY_ID=your_aws_access_key_id
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key
AWS_SESSION_TOKEN=your_aws_session_token


# OAuth2/JWT Authentication (for production)
# OAUTH2_ISSUER_URL=https://your-auth-provider.com
# OAUTH2_AUDIENCE=your-api-audience
# OAUTH2_JWKS_URL=https://your-auth-provider.com/.well-known/jwks.json # Optional

# Development Mode (DISABLE AUTHENTICATION - DEVELOPMENT ONLY)
DISABLE_AUTH=true
# In development mode, you may disable authentication
DISABLE_AUTH=false
140 changes: 115 additions & 25 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,75 @@
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim
# ============================================
# BUILDER BASE - Build tools for compilation
# ============================================
FROM python:3.12-slim-bookworm AS builder-base

WORKDIR /app

# Copy uv binary from official image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy

# Install build tools (only needed for compilation)
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
gcc \
g++ \
&& rm -rf /var/lib/apt/lists/*

# ============================================
# BUILDER STANDARD - Compile standard deps
# ============================================
FROM builder-base AS builder-standard

# Create virtual environment explicitly
RUN uv venv .venv

# Copy dependency files first for better layer caching
COPY pyproject.toml uv.lock ./
COPY agent-memory-client ./agent-memory-client

# Install dependencies into the venv (without the project)
RUN --mount=type=cache,target=/root/.cache/uv \
VIRTUAL_ENV=/app/.venv uv sync --frozen --no-install-project --no-dev

# Copy source code
COPY . /app

# Install the project itself
RUN --mount=type=cache,target=/root/.cache/uv \
. .venv/bin/activate && \
uv pip install --no-deps .

# ============================================
# BUILDER AWS - Compile AWS deps
# ============================================
FROM builder-base AS builder-aws

# Create virtual environment explicitly
RUN uv venv .venv

# Copy dependency files first for better layer caching
COPY pyproject.toml uv.lock ./
COPY agent-memory-client ./agent-memory-client

# Install dependencies into the venv (without the project)
RUN --mount=type=cache,target=/root/.cache/uv \
VIRTUAL_ENV=/app/.venv uv sync --frozen --no-install-project --no-dev --extra aws

# Copy source code
COPY . /app

# Install the project itself
RUN --mount=type=cache,target=/root/.cache/uv \
. .venv/bin/activate && \
uv pip install --no-deps .

# ============================================
# RUNTIME BASE - Slim image without build tools
# ============================================
FROM python:3.12-slim-bookworm AS runtime-base

# OCI labels for Docker Hub and container registries
LABEL org.opencontainers.image.title="Redis Agent Memory Server"
Expand All @@ -11,46 +82,35 @@ LABEL org.opencontainers.image.licenses="Apache-2.0"

WORKDIR /app

ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy

# Install system dependencies including build tools
RUN apt-get update && apt-get install -y \
# Install only runtime dependencies (curl for healthcheck)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
build-essential \
gcc \
g++ \
&& rm -rf /var/lib/apt/lists/*

RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
--mount=type=bind,source=agent-memory-client,target=agent-memory-client \
uv sync --frozen --no-install-project --no-dev
# Create non-root user for security
RUN groupadd -r agentmemory && useradd -r -g agentmemory agentmemory

ADD . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# ============================================
# STANDARD VARIANT - OpenAI/Anthropic only
# ============================================
FROM runtime-base AS standard

# Create non-root user for security
RUN groupadd -r agentmemory && useradd -r -g agentmemory agentmemory && \
chown -R agentmemory:agentmemory /app
# Copy the virtual environment and app from builder
COPY --chown=agentmemory:agentmemory --from=builder-standard /app /app

ENV PATH="/app/.venv/bin:$PATH"

# Switch to non-root user
USER agentmemory

ENTRYPOINT []

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/v1/health || exit 1

# Disable auth by default for easier local development.
# Override with DISABLE_AUTH=false in production.
ENV DISABLE_AUTH=true
# Enable authentication by default.
# You may override with DISABLE_AUTH=true in development.
ENV DISABLE_AUTH=false

# Default to development mode (no separate worker needed).
# For production, override the command to remove --no-worker and run a separate task-worker container.
Expand All @@ -59,3 +119,33 @@ ENV DISABLE_AUTH=true
# Production API: docker run -p 8000:8000 redislabs/agent-memory-server agent-memory api --host 0.0.0.0 --port 8000
# Production Worker: docker run redislabs/agent-memory-server agent-memory task-worker --concurrency 10
CMD ["agent-memory", "api", "--host", "0.0.0.0", "--port", "8000", "--no-worker"]

# ============================================
# AWS VARIANT - Includes AWS Bedrock support
# ============================================
FROM runtime-base AS aws

# Copy the virtual environment and app from builder
COPY --chown=agentmemory:agentmemory --from=builder-aws /app /app

ENV PATH="/app/.venv/bin:$PATH"

# Switch to non-root user
USER agentmemory

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/v1/health || exit 1

# Enable authentication by default.
# You may override with DISABLE_AUTH=true in development.
ENV DISABLE_AUTH=false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security control: Docker Scan

Secrets Passed Via Build-Args Or Envs Or Copied Secret Files

Passing secrets via build-args or envs or copying secret files can leak them out

Severity: CRITICAL

Learn more about this issue


Why should you fix this issue?
This Dockerfile introduces a container vulnerability. In a production environment, using insecure container configurations or outdated base images can lead to significant security risks. If an attacker exploits a vulnerability in the container, it could compromise the entire application or lead to unauthorized access.


Jit Bot commands and options (e.g., ignore issue)

You can trigger Jit actions by commenting on this PR review:

  • #jit_ignore_fp Ignore and mark this specific single instance of finding as “False Positive”
  • #jit_ignore_accept Ignore and mark this specific single instance of finding as “Accept Risk”
  • #jit_ignore_type_in_file Ignore any finding of type "Secrets passed via build-args or envs or copied secret files" in Dockerfile; future occurrences will also be ignored.
  • #jit_undo_ignore Undo ignore command

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#jit_ignore_fp


# Default to development mode (no separate worker needed).
# For production, override the command to remove --no-worker and run a separate task-worker container.
# Examples:
# Development: docker run -p 8000:8000 redislabs/agent-memory-server:aws
# Production API: docker run -p 8000:8000 redislabs/agent-memory-server:aws agent-memory api --host 0.0.0.0 --port 8000
# Production Worker: docker run redislabs/agent-memory-server:aws agent-memory task-worker --concurrency 10
CMD ["agent-memory", "api", "--host", "0.0.0.0", "--port", "8000", "--no-worker"]
Empty file.
74 changes: 74 additions & 0 deletions agent_memory_server/_aws/clients.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""AWS clients for the Agent Memory Server.

This module contains utilities for creating and managing AWS clients.
"""

from typing import TYPE_CHECKING

from boto3 import Session

from agent_memory_server.config import settings


if TYPE_CHECKING:
from mypy_boto3_bedrock import BedrockClient
from mypy_boto3_bedrock_runtime import BedrockRuntimeClient


def create_aws_session(
region_name: str | None = None, credentials: dict[str, str] | None = None
) -> Session:
"""Create an AWS session.

Args:
credentials (dict[str, str | None]): The AWS credentials to use.

Returns:
An AWS session.
"""
if credentials is None:
credentials = settings.aws_credentials
if region_name is None:
region_name = settings.aws_region
return Session(region_name=region_name, **credentials)


def create_bedrock_client(
region_name: str | None = None,
session: Session | None = None,
) -> "BedrockClient":
"""Create a Bedrock client.

Args:
region_name (str | None): The AWS region to use.\
If not provided, it will be picked up from the environment.
session (Session | None): The AWS session to use.\
If not provided, a new session will be created based on the environment.
"""
if session is None:
session = create_aws_session(region_name=region_name)
if region_name is None:
region_name = settings.aws_region
return session.client("bedrock", region_name=region_name)


def create_bedrock_runtime_client(
region_name: str | None = None,
session: Session | None = None,
) -> "BedrockRuntimeClient":
"""Create a Bedrock runtime client.

Args:
region_name (str | None): The AWS region to use.\
If not provided, it will be picked up from the environment.
session (Session | None): The AWS session to use.\
If not provided, a new session will be created based on the environment.

Returns:
A Bedrock runtime client.
"""
if session is None:
session = create_aws_session(region_name=region_name)
if region_name is None:
region_name = settings.aws_region
return session.client("bedrock-runtime", region_name=region_name)
Loading
Loading