| 1 | from typing import List |
| 2 | |
| 3 | from fastapi import APIRouter |
| 4 | from fastapi import Depends |
| 5 | from fastapi import HTTPException |
| 6 | from fastapi import Security |
| 7 | from loguru import logger |
| 8 | |
| 9 | from app.auth.utils import AuthHandler |
| 10 | from app.connectors.graylog.schema.management import DeletedIndexBody |
| 11 | from app.connectors.graylog.schema.management import DeletedIndexResponse |
| 12 | from app.connectors.graylog.schema.management import StartInputBody |
| 13 | from app.connectors.graylog.schema.management import StartInputResponse |
| 14 | from app.connectors.graylog.schema.management import StartStreamBody |
| 15 | from app.connectors.graylog.schema.management import StartStreamResponse |
| 16 | from app.connectors.graylog.schema.management import StopInputBody |
| 17 | from app.connectors.graylog.schema.management import StopInputResponse |
| 18 | from app.connectors.graylog.schema.management import StopStreamBody |
| 19 | from app.connectors.graylog.schema.management import StopStreamResponse |
| 20 | from app.connectors.graylog.schema.management import UrlWhitelistEntryResponse |
| 21 | from app.connectors.graylog.services.collector import get_index_names |
| 22 | from app.connectors.graylog.services.collector import get_input_ids |
| 23 | from app.connectors.graylog.services.collector import get_url_whitelist_entries |
| 24 | from app.connectors.graylog.services.management import delete_index |
| 25 | from app.connectors.graylog.services.management import start_input |
| 26 | from app.connectors.graylog.services.management import start_stream |
| 27 | from app.connectors.graylog.services.management import stop_input |
| 28 | from app.connectors.graylog.services.management import stop_stream |
| 29 | from app.connectors.graylog.services.streams import get_stream_ids |
| 30 | |
| 31 | graylog_management_router = APIRouter() |
| 32 | |
| 33 | |
| 34 | async def get_managed_index_names() -> List[str]: |
| 35 | """ |
| 36 | Retrieves the names of the managed indexes. |
| 37 | |
| 38 | Returns: |
| 39 | A list of strings representing the names of the managed indexes. |
| 40 | """ |
| 41 | return await get_index_names() |
| 42 | |
| 43 | |
| 44 | async def get_managed_input_ids() -> List[str]: |
| 45 | """ |
| 46 | Retrieves the IDs of the managed inputs. |
| 47 | |
| 48 | Returns: |
| 49 | A list of strings representing the IDs of the managed inputs. |
| 50 | """ |
| 51 | return await get_input_ids() |
| 52 | |
| 53 | |
| 54 | async def get_managed_stream_ids() -> List[str]: |
| 55 | """ |
| 56 | Retrieves the IDs of the managed streams. |
| 57 | |
| 58 | Returns: |
| 59 | A list of strings representing the IDs of the managed streams. |
| 60 | """ |
| 61 | return await get_stream_ids() |
| 62 | |
| 63 | |
| 64 | async def verify_index_name(deleted_index_body: DeletedIndexBody) -> DeletedIndexBody: |
| 65 | """ |
| 66 | Verifies if the given index name is managed by Graylog or still exists. |
| 67 | |
| 68 | Args: |
| 69 | deleted_index_body (DeletedIndexBody): The body containing the index name to be verified. |
| 70 | |
| 71 | Raises: |
| 72 | HTTPException: If the index name is not managed by Graylog or no longer exists. |
| 73 | |
| 74 | Returns: |
| 75 | DeletedIndexBody: The verified index name. |
| 76 | """ |
| 77 | # Remove any extra spaces from index_name |
| 78 | deleted_index_body.index_name = deleted_index_body.index_name.strip() |
| 79 | |
| 80 | managed_index_names = await get_managed_index_names() |
| 81 | if deleted_index_body.index_name not in managed_index_names: |
| 82 | raise HTTPException( |
| 83 | status_code=400, |
| 84 | detail=f"Index name '{deleted_index_body.index_name}' is not managed by Graylog or no longer exists.", |
| 85 | ) |
| 86 | return deleted_index_body |
| 87 | |
| 88 | |
| 89 | async def verify_input_id(stop_input_body: StopInputBody) -> StopInputBody: |
| 90 | """ |
| 91 | Verifies if the given input ID is valid and managed by Graylog. |
| 92 | |
| 93 | Args: |
| 94 | stop_input_body (StopInputBody): The input body containing the input ID to be verified. |
| 95 | |
| 96 | Raises: |
| 97 | HTTPException: If the input ID is not managed by Graylog or no longer exists. |
| 98 | |
| 99 | Returns: |
| 100 | StopInputBody: The verified input body. |
| 101 | """ |
| 102 | # Remove any extra spaces from input_id |
| 103 | stop_input_body.input_id = stop_input_body.input_id.strip() |
| 104 | |
| 105 | managed_input_ids = await get_managed_input_ids() |
| 106 | if stop_input_body.input_id not in managed_input_ids: |
| 107 | raise HTTPException( |
| 108 | status_code=400, |
| 109 | detail=f"Input ID '{stop_input_body.input_id}' is not managed by Graylog or no longer exists.", |
| 110 | ) |
| 111 | return stop_input_body |
| 112 | |
| 113 | |
| 114 | async def verify_stream_id(stop_stream_body: StopStreamBody) -> StopStreamBody: |
| 115 | """ |
| 116 | Verifies if the provided stream ID is managed by Graylog or still exists. |
| 117 | |
| 118 | Args: |
| 119 | stop_stream_body (StopStreamBody): The body containing the stream ID to be verified. |
| 120 | |
| 121 | Raises: |
| 122 | HTTPException: If the stream ID is not managed by Graylog or no longer exists. |
| 123 | |
| 124 | Returns: |
| 125 | StopStreamBody: The verified stop_stream_body object. |
| 126 | """ |
| 127 | # Remove any extra spaces from stream_id |
| 128 | stop_stream_body.stream_id = stop_stream_body.stream_id.strip() |
| 129 | |
| 130 | managed_stream_ids = await get_managed_stream_ids() |
| 131 | if stop_stream_body.stream_id not in managed_stream_ids: |
| 132 | raise HTTPException( |
| 133 | status_code=400, |
| 134 | detail=f"Stream ID '{stop_stream_body.stream_id}' is not managed by Graylog or no longer exists.", |
| 135 | ) |
| 136 | return stop_stream_body |
| 137 | |
| 138 | |
| 139 | @graylog_management_router.get( |
| 140 | "/url_whitelist", |
| 141 | response_model=UrlWhitelistEntryResponse, |
| 142 | description="Get the URL whitelist entries.", |
| 143 | dependencies=[Security(AuthHandler().get_current_user, scopes=["admin"])], |
| 144 | ) |
| 145 | async def get_url_whitelist() -> UrlWhitelistEntryResponse: |
| 146 | """ |
| 147 | Get the URL whitelist entries. |
| 148 | |
| 149 | Returns: |
| 150 | - UrlWhitelistEntryResponse: The response containing the URL whitelist entries. |
| 151 | """ |
| 152 | logger.info("Getting URL whitelist entries") |
| 153 | |
| 154 | return await get_url_whitelist_entries() |
| 155 | |
| 156 | |
| 157 | @graylog_management_router.delete( |
| 158 | "/index", |
| 159 | response_model=DeletedIndexResponse, |
| 160 | description="Delete index", |
| 161 | dependencies=[Security(AuthHandler().get_current_user, scopes=["admin"])], |
| 162 | ) |
| 163 | async def delete_index_route( |
| 164 | deleted_index_body: DeletedIndexBody = Depends(verify_index_name), |
| 165 | ) -> DeletedIndexResponse: |
| 166 | """ |
| 167 | Delete index route. |
| 168 | |
| 169 | This route is used to delete an index in Graylog. |
| 170 | |
| 171 | Parameters: |
| 172 | - deleted_index_body (DeletedIndexBody): The body of the request containing the index name. |
| 173 | |
| 174 | Returns: |
| 175 | - DeletedIndexResponse: The response containing the result of the deletion. |
| 176 | |
| 177 | """ |
| 178 | logger.info(f"Deleting index {deleted_index_body.index_name}") |
| 179 | |
| 180 | return await delete_index(deleted_index_body.index_name) |
| 181 | |
| 182 | |
| 183 | @graylog_management_router.post( |
| 184 | "/input/stop", |
| 185 | response_model=StopInputResponse, |
| 186 | description="Stop input", |
| 187 | dependencies=[Security(AuthHandler().get_current_user, scopes=["admin"])], |
| 188 | ) |
| 189 | async def stop_input_route( |
| 190 | stop_input_body: StopInputBody = Depends(verify_input_id), |
| 191 | ) -> StopInputResponse: |
| 192 | """ |
| 193 | Stop input route. |
| 194 | |
| 195 | This route is used to stop an input in Graylog. |
| 196 | |
| 197 | Parameters: |
| 198 | - stop_input_body (StopInputBody): The body of the request containing the input ID. |
| 199 | |
| 200 | Returns: |
| 201 | - StopInputResponse: The response containing the status of the input stop operation. |
| 202 | """ |
| 203 | logger.info(f"Stopping input {stop_input_body.input_id}") |
| 204 | |
| 205 | return await stop_input(stop_input_body.input_id) |
| 206 | |
| 207 | |
| 208 | @graylog_management_router.post( |
| 209 | "/input/start", |
| 210 | response_model=StartInputResponse, |
| 211 | description="Start input", |
| 212 | dependencies=[Security(AuthHandler().get_current_user, scopes=["admin"])], |
| 213 | ) |
| 214 | async def start_input_route( |
| 215 | start_input_body: StartInputBody = Depends(verify_input_id), |
| 216 | ) -> StartInputResponse: |
| 217 | """ |
| 218 | Start the input with the given input ID. |
| 219 | |
| 220 | Args: |
| 221 | start_input_body (StartInputBody): The request body containing the input ID. |
| 222 | |
| 223 | Returns: |
| 224 | StartInputResponse: The response containing the result of starting the input. |
| 225 | """ |
| 226 | logger.info(f"Starting input {start_input_body.input_id}") |
| 227 | |
| 228 | return await start_input(start_input_body.input_id) |
| 229 | |
| 230 | |
| 231 | @graylog_management_router.post( |
| 232 | "/stream/stop", |
| 233 | response_model=StopStreamResponse, |
| 234 | description="Stop stream", |
| 235 | dependencies=[Security(AuthHandler().get_current_user, scopes=["admin"])], |
| 236 | ) |
| 237 | async def stop_stream_route( |
| 238 | stop_stream_body: StopStreamBody = Depends(verify_stream_id), |
| 239 | ) -> StopStreamResponse: |
| 240 | """ |
| 241 | Stop stream route. |
| 242 | |
| 243 | This route is used to stop a stream in Graylog. |
| 244 | |
| 245 | Parameters: |
| 246 | - stop_stream_body (StopStreamBody): The request body containing the stream ID. |
| 247 | |
| 248 | Returns: |
| 249 | - StopStreamResponse: The response containing the result of stopping the stream. |
| 250 | """ |
| 251 | logger.info(f"Stopping stream {stop_stream_body.stream_id}") |
| 252 | |
| 253 | return await stop_stream(stop_stream_body.stream_id) |
| 254 | |
| 255 | |
| 256 | @graylog_management_router.post( |
| 257 | "/stream/start", |
| 258 | response_model=StartStreamResponse, |
| 259 | description="Start stream", |
| 260 | dependencies=[Security(AuthHandler().get_current_user, scopes=["admin"])], |
| 261 | ) |
| 262 | async def start_stream_route( |
| 263 | start_stream_body: StartStreamBody = Depends(verify_stream_id), |
| 264 | ) -> StartStreamResponse: |
| 265 | """ |
| 266 | Start stream route. |
| 267 | |
| 268 | This route is used to start a stream in Graylog. |
| 269 | |
| 270 | Parameters: |
| 271 | - start_stream_body (StartStreamBody): The request body containing the stream ID. |
| 272 | |
| 273 | Returns: |
| 274 | - StartStreamResponse: The response containing the result of starting the stream. |
| 275 | """ |
| 276 | logger.info(f"Starting stream {start_stream_body.stream_id}") |
| 277 | |
| 278 | return await start_stream(start_stream_body.stream_id) |