mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: fetch password explictly (#1107)
Include the explicit select of the password field since the mongoose schema omits it by default. Includes test cases to verify the password against the mongo instance running in the test suite and an additional error check.
This commit is contained in:
parent
261d4693a3
commit
eb6f3a0199
4 changed files with 143 additions and 1 deletions
5
.changeset/eleven-tables-hide.md
Normal file
5
.changeset/eleven-tables-hide.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@hyperdx/api": patch
|
||||
---
|
||||
|
||||
Fix the alert connection query to include the password field.
|
||||
|
|
@ -388,6 +388,15 @@ export default class CheckAlertTask implements HdxTask<CheckAlertsTaskArgs> {
|
|||
alertCount: alerts.length,
|
||||
});
|
||||
|
||||
if (!conn.password && conn.password !== '') {
|
||||
const providerName = this.provider.constructor.name;
|
||||
logger.info({
|
||||
message: `alert provider did not fetch connection password`,
|
||||
providerName,
|
||||
connectionId: conn.id,
|
||||
});
|
||||
}
|
||||
|
||||
const clickhouseClient = new clickhouse.ClickhouseClient({
|
||||
host: conn.host,
|
||||
username: conn.username,
|
||||
|
|
|
|||
|
|
@ -585,6 +585,130 @@ describe('DefaultAlertProvider', () => {
|
|||
const result = await provider.getAlertTasks();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should include password field in connection for saved search alerts', async () => {
|
||||
const team = await createTeam({ name: 'Test Team' });
|
||||
|
||||
// Create connection with specific password
|
||||
const connection = await Connection.create({
|
||||
team: team._id,
|
||||
name: 'Test Connection',
|
||||
host: 'http://localhost:8123',
|
||||
username: 'test',
|
||||
password: 'secret-password-123',
|
||||
});
|
||||
|
||||
// Create source
|
||||
const source = await Source.create({
|
||||
team: team._id,
|
||||
name: 'Test Source',
|
||||
kind: 'log',
|
||||
from: {
|
||||
databaseName: 'default',
|
||||
tableName: 'logs',
|
||||
},
|
||||
timestampValueExpression: 'timestamp',
|
||||
connection: connection._id,
|
||||
});
|
||||
|
||||
// Create saved search
|
||||
const savedSearch = await SavedSearch.create({
|
||||
team: team._id,
|
||||
name: 'Test Search',
|
||||
select: 'message',
|
||||
where: 'level: error',
|
||||
whereLanguage: 'lucene',
|
||||
orderBy: 'timestamp',
|
||||
source: source._id,
|
||||
tags: [],
|
||||
});
|
||||
|
||||
// Create alert
|
||||
await createAlert(
|
||||
team._id,
|
||||
{
|
||||
source: AlertSource.SAVED_SEARCH,
|
||||
savedSearchId: savedSearch._id.toString(),
|
||||
threshold: 10,
|
||||
thresholdType: AlertThresholdType.ABOVE,
|
||||
interval: '5m',
|
||||
channel: {
|
||||
type: 'webhook',
|
||||
webhookId: new mongoose.Types.ObjectId().toString(),
|
||||
},
|
||||
},
|
||||
new mongoose.Types.ObjectId(),
|
||||
);
|
||||
|
||||
const result = await provider.getAlertTasks();
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].conn.password).toBe('secret-password-123');
|
||||
expect(result[0].conn.username).toBe('test');
|
||||
expect(result[0].conn.host).toBe('http://localhost:8123');
|
||||
});
|
||||
|
||||
it('should include password field in connection for tile alerts', async () => {
|
||||
const team = await createTeam({ name: 'Test Team' });
|
||||
|
||||
// Create connection with specific password
|
||||
const connection = await Connection.create({
|
||||
team: team._id,
|
||||
name: 'Test Connection',
|
||||
host: 'http://localhost:8124',
|
||||
username: 'tile-user',
|
||||
password: 'tile-secret-password-456',
|
||||
});
|
||||
|
||||
// Create source
|
||||
const source = await Source.create({
|
||||
team: team._id,
|
||||
name: 'Test Source',
|
||||
kind: 'log',
|
||||
from: {
|
||||
databaseName: 'default',
|
||||
tableName: 'logs',
|
||||
},
|
||||
timestampValueExpression: 'timestamp',
|
||||
connection: connection._id,
|
||||
});
|
||||
|
||||
// Create tile with source
|
||||
const tile = makeTile({ id: 'test-tile-123' });
|
||||
tile.config.source = source._id.toString();
|
||||
|
||||
// Create dashboard
|
||||
const dashboard = await Dashboard.create({
|
||||
team: team._id,
|
||||
name: 'Test Dashboard',
|
||||
tiles: [tile],
|
||||
});
|
||||
|
||||
// Create alert
|
||||
await createAlert(
|
||||
team._id,
|
||||
{
|
||||
source: AlertSource.TILE,
|
||||
dashboardId: dashboard._id.toString(),
|
||||
tileId: tile.id,
|
||||
threshold: 10,
|
||||
thresholdType: AlertThresholdType.ABOVE,
|
||||
interval: '5m',
|
||||
channel: {
|
||||
type: 'webhook',
|
||||
webhookId: new mongoose.Types.ObjectId().toString(),
|
||||
},
|
||||
},
|
||||
new mongoose.Types.ObjectId(),
|
||||
);
|
||||
|
||||
const result = await provider.getAlertTasks();
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].conn.password).toBe('tile-secret-password-456');
|
||||
expect(result[0].conn.username).toBe('tile-user');
|
||||
expect(result[0].conn.host).toBe('http://localhost:8124');
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildLogSearchLink', () => {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ async function getSavedSearchDetails(
|
|||
|
||||
const { source } = savedSearch;
|
||||
const connId = source.connection;
|
||||
const conn = await Connection.findOne({ _id: connId, team: alert.team });
|
||||
const conn = await Connection.findOne({
|
||||
_id: connId,
|
||||
team: alert.team,
|
||||
}).select('+password');
|
||||
if (!conn) {
|
||||
logger.error({
|
||||
message: 'connection not found',
|
||||
|
|
@ -101,6 +104,7 @@ async function getTileDetails(
|
|||
}).populate<Omit<ISource, 'connection'> & { connection: IConnection }>({
|
||||
path: 'connection',
|
||||
match: { team: alert.team },
|
||||
select: '+password',
|
||||
});
|
||||
if (!source) {
|
||||
logger.error({
|
||||
|
|
|
|||
Loading…
Reference in a new issue