mirror of
https://github.com/unraid/api.git
synced 2026-05-07 07:29:45 -05:00
feat: add origin checking for graphql
This commit is contained in:
+4
-2
@@ -20,7 +20,8 @@ export interface Paths {
|
||||
'myservers-base': string;
|
||||
'myservers-config': string;
|
||||
'myservers-env': string;
|
||||
'machine-id': string;
|
||||
'ssl-certificate': string;
|
||||
'extra-origins': string;
|
||||
}
|
||||
|
||||
const thisDir = __dirname;
|
||||
@@ -53,7 +54,8 @@ export const defaultPaths = new Map<keyof Paths, string>([
|
||||
['myservers-base', '/boot/config/plugins/dynamix.my.servers/'],
|
||||
['myservers-config', '/boot/config/plugins/dynamix.my.servers/myservers.cfg'],
|
||||
['myservers-env', '/boot/config/plugins/dynamix.my.servers/env'],
|
||||
['machine-id', '/etc/machine-id']
|
||||
['ssl-certificate', '/boot/config/ssl/certs/certificate_bundle.pem'],
|
||||
['extra-origins', '/boot/config/plugins/dynamix.my.servers/extra-origins.json']
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
+61
-2
@@ -7,17 +7,20 @@ import fs from 'fs';
|
||||
import net from 'net';
|
||||
import path from 'path';
|
||||
import execa from 'execa';
|
||||
import cors from 'cors';
|
||||
import stoppable from 'stoppable';
|
||||
import chokidar from 'chokidar';
|
||||
import express from 'express';
|
||||
import http from 'http';
|
||||
import WebSocket from 'ws';
|
||||
import { pki } from 'node-forge';
|
||||
import { ApolloServer } from 'apollo-server-express';
|
||||
import { log, config, utils, paths, pubsub, coreLogger } from './core';
|
||||
import { log, config, paths, pubsub, coreLogger } from './core';
|
||||
import { getEndpoints, globalErrorHandler, exitApp, cleanStdout, sleep } from './core/utils';
|
||||
import { graphql } from './graphql';
|
||||
import packageJson from '../package.json';
|
||||
import display from './graphql/resolvers/query/display';
|
||||
import { networkState, varState } from './core/states';
|
||||
|
||||
const configFilePath = path.join(paths.get('dynamix-base')!, 'case-model.cfg');
|
||||
const customImageFilePath = path.join(paths.get('dynamix-base')!, 'case-model.png');
|
||||
@@ -37,8 +40,64 @@ chokidar.watch(customImageFilePath).on('all', updatePubsub);
|
||||
*/
|
||||
const app = express();
|
||||
|
||||
// Graphql port
|
||||
const port = process.env.PORT ?? String(config.get('port'));
|
||||
|
||||
const attemptJSONParse = (text: string, fallback: any) => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
};
|
||||
|
||||
// Cors options
|
||||
const invalidOrigin = 'The CORS policy for this site does not allow access from the specified Origin.';
|
||||
const certPem = fs.readFileSync(paths.get('ssl-certificate')!, 'utf-8');
|
||||
const { hash } = pki.certificateFromPem(certPem).subject;
|
||||
|
||||
// Get extra origins from the user
|
||||
const extraOriginPath = paths.get('extra-origins');
|
||||
// To add extra origins create a file at the "extra-origins" path
|
||||
const extraOrigins = extraOriginPath ? attemptJSONParse(fs.readFileSync(extraOriginPath, 'utf-8'), []) : [];
|
||||
|
||||
// Get local ip from first ethernet adapter in the "network" state
|
||||
const localIp = networkState.data[0].ipaddr[0];
|
||||
|
||||
// Get webui port
|
||||
const originPort = varState.data.port;
|
||||
|
||||
// Allow http://tower.local:${port}, http://${ip}:${port} and https://${hash}.unraid.net:${port}
|
||||
const allowedOrigins = [
|
||||
// The webui
|
||||
'http://tower.local',
|
||||
`http://${localIp}${originPort}`,
|
||||
`https://${hash}.unraid.net:${originPort}`,
|
||||
|
||||
// Other endpoints should be added below
|
||||
extraOrigins
|
||||
];
|
||||
|
||||
// Cors
|
||||
app.use(cors({
|
||||
origin: function (origin, callback) {
|
||||
// Disallow requests with no origin
|
||||
// (like mobile apps or curl requests)
|
||||
if (!origin) {
|
||||
callback(new Error(invalidOrigin), false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only allow known origins
|
||||
if (!allowedOrigins.includes(origin)) {
|
||||
callback(new Error(invalidOrigin), false);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, true);
|
||||
}
|
||||
}));
|
||||
|
||||
// Add Unraid API version header
|
||||
app.use(async (_req, res, next) => {
|
||||
// Only get the machine ID on first request
|
||||
@@ -203,7 +262,7 @@ export const server = {
|
||||
if (isNaN(parseInt(port, 10))) {
|
||||
try {
|
||||
fs.unlinkSync(port);
|
||||
} catch {}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
// Run callback
|
||||
|
||||
Generated
+5
@@ -10506,6 +10506,11 @@
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
|
||||
},
|
||||
"node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
"nchan": "^1.0.10",
|
||||
"node-cache": "5.1.2",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-window-polyfill": "^1.0.2",
|
||||
"number-to-color": "^0.5.0",
|
||||
"observable-to-promise": "^1.0.0",
|
||||
|
||||
Reference in New Issue
Block a user