diff --git a/backend/auth_middleware.py b/backend/auth_middleware.py index 2d12003..8040a95 100644 --- a/backend/auth_middleware.py +++ b/backend/auth_middleware.py @@ -53,7 +53,7 @@ async def get_current_user_from_token(authorization: Optional[str] = None) -> Op # Get user from database conn = await get_database_connection() user = await conn.fetchrow(""" - SELECT id, username, email, full_name, role, is_active + SELECT id, username, email, full_name, role, is_active, is_admin FROM users WHERE id = $1 AND is_active = TRUE """, int(user_id)) @@ -70,7 +70,8 @@ async def get_current_user_from_token(authorization: Optional[str] = None) -> Op "username": user["username"], "email": user["email"], "full_name": user["full_name"], - "role": user["role"] + "role": user["role"], + "is_admin": user.get("is_admin", False) } except jwt.ExpiredSignatureError: @@ -123,7 +124,7 @@ async def get_current_user_from_token_no_exception(authorization: Optional[str] # Get user from database conn = await get_database_connection() user = await conn.fetchrow(""" - SELECT id, username, email, full_name, is_active + SELECT id, username, email, full_name, is_active, is_admin FROM users WHERE id = $1 AND is_active = TRUE """, int(user_id)) @@ -136,7 +137,8 @@ async def get_current_user_from_token_no_exception(authorization: Optional[str] "id": user["id"], "username": user["username"], "email": user["email"], - "full_name": user["full_name"] + "full_name": user["full_name"], + "is_admin": user.get("is_admin", False) } except Exception as e: diff --git a/backend/routers/agent.py b/backend/routers/agent.py index 4f603eb..9577f4e 100644 --- a/backend/routers/agent.py +++ b/backend/routers/agent.py @@ -433,8 +433,16 @@ async def generate_install_script(req_data: AgentScriptRequest, request: Request # Support both user authentication and agent API key current_user = None if authorization: - from auth_middleware import get_current_user_from_token + from auth_middleware import get_current_user_from_token, check_user_permission current_user = await get_current_user_from_token(authorization) + + # SECURITY: Check permission for agent script generation + has_permission = await check_user_permission(current_user["id"], "agents", "create") + if not has_permission: + raise HTTPException( + status_code=403, + detail="Insufficient permissions: agents.create required" + ) elif x_api_key: # Agent API key authentication for upgrade process agent_auth = await validate_agent_api_key(x_api_key) diff --git a/backend/routers/user.py b/backend/routers/user.py index 080b3e4..4108023 100644 --- a/backend/routers/user.py +++ b/backend/routers/user.py @@ -157,6 +157,13 @@ async def create_user(user_data: UserCreate, authorization: str = Header(None)): # Verify authentication current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can create users + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can create new users" + ) + conn = await get_database_connection() # Check if username already exists (only active users) @@ -242,6 +249,13 @@ async def update_user(user_id: int, user_data: dict, authorization: str = Header try: current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can update other users + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can update user information" + ) + conn = await get_database_connection() # Check if user exists @@ -642,6 +656,13 @@ async def delete_user(user_id: int, authorization: str = Header(None)): try: current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can delete users + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can delete users" + ) + conn = await get_database_connection() # Check if user exists and get details @@ -940,6 +961,13 @@ async def create_role(role_data: dict, authorization: str = Header(None)): # Verify authentication current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can create roles + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can create roles" + ) + conn = await get_database_connection() # Check if role name already exists @@ -996,6 +1024,13 @@ async def update_role(role_id: int, role_data: dict, authorization: str = Header # Verify authentication current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can update roles + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can update roles" + ) + conn = await get_database_connection() # Check if role exists @@ -1061,6 +1096,13 @@ async def delete_role(role_id: int, authorization: str = Header(None)): # Verify authentication current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can delete roles + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can delete roles" + ) + conn = await get_database_connection() # Check if role exists and is not system role @@ -1112,6 +1154,13 @@ async def assign_user_roles(user_id: int, role_data: dict, authorization: str = # Verify authentication current_user = await get_current_user_from_token(authorization) + # SECURITY: Only admin users can assign roles to users + if not current_user.get("is_admin", False): + raise HTTPException( + status_code=403, + detail="Only admin users can assign roles to users" + ) + conn = await get_database_connection() # Check if user exists diff --git a/build-images.sh b/build-images.sh index 65334c7..20b37c4 100755 --- a/build-images.sh +++ b/build-images.sh @@ -32,7 +32,9 @@ print_error() { } # Configuration -REGISTRY="${REGISTRY:-intprod-harbor.burgan.com.tr/devops}" +# Set REGISTRY environment variable or use default +# Example: export REGISTRY="your-registry.example.com/project" +REGISTRY="${REGISTRY:-your-registry.example.com/haproxy-openmanager}" BACKEND_IMAGE="${REGISTRY}/haproxy-openmanager-backend" FRONTEND_IMAGE="${REGISTRY}/haproxy-openmanager-frontend" VERSION="${VERSION:-latest}" @@ -99,10 +101,10 @@ fi print_status "Updating Kubernetes manifests with new image versions..." # Update backend deployment -sed -i.bak "s|image: intprod-harbor.burgan.com.tr/devops/haproxy-openmanager:|image: $BACKEND_IMAGE:$VERSION|g" k8s/manifests/08-backend.yaml +sed -i.bak "s|image: your-registry.example.com/haproxy-openmanager/haproxy-openmanager-backend:|image: $BACKEND_IMAGE:$VERSION|g" k8s/manifests/08-backend.yaml # Update frontend deployment -sed -i.bak "s|image: intprod-harbor.burgan.com.tr/devops/haproxy-openmanager:|image: $FRONTEND_IMAGE:$VERSION|g" k8s/manifests/09-frontend.yaml +sed -i.bak "s|image: your-registry.example.com/haproxy-openmanager/haproxy-openmanager-frontend:|image: $FRONTEND_IMAGE:$VERSION|g" k8s/manifests/09-frontend.yaml print_success "Kubernetes manifests updated" diff --git a/frontend/src/components/UserManagement.js b/frontend/src/components/UserManagement.js index 96a65f5..60073be 100644 --- a/frontend/src/components/UserManagement.js +++ b/frontend/src/components/UserManagement.js @@ -34,6 +34,7 @@ import { DownloadOutlined } from '@ant-design/icons'; import axios from 'axios'; +import { useAuth } from '../contexts/AuthContext'; const { TabPane } = Tabs; const { Option } = Select; @@ -222,6 +223,7 @@ const PERMISSION_TREE = [ ]; const UserManagement = () => { + const { isAdmin } = useAuth(); // Get admin status from auth context const [activeTab, setActiveTab] = useState('users'); // Users state @@ -718,41 +720,48 @@ const UserManagement = () => { key: 'actions', render: (_, record) => ( - - + {isAdmin() && ( + + )} } > @@ -1110,13 +1128,15 @@ const UserManagement = () => { }} /> - + {isAdmin() && ( + + )} } >