Skip to content

Commit

Permalink
Merge pull request #34 from Netflix-Skunkworks/thrift
Browse files Browse the repository at this point in the history
Migration from shelling out to osquery to using Thrift
  • Loading branch information
rmcvey authored Jul 31, 2018
2 parents 87851e4 + ef0273a commit cf1cfc3
Show file tree
Hide file tree
Showing 23 changed files with 2,932 additions and 230 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ All notable changes to this project will be documented in this file.

----

## [1.2.0](https://github.com/Netflix-Skunkworks/stethoscope-app/tree/1.2.0) - 2018-07-29

-----

### Changed
- Updated to use thrift socket via osqueryd rather than shelling out to osqueryi
- startup order of operations, now wait for osqueryd to spawn before bootstrapping browser window and express server

### Added
- request-level caching and timing data for powershell commands
- `cross-env` dep to simplify env var handling

### Fixed
- issue with semver mishandling
- vulnerability from drag and drop links

## [1.0.2](#) - 2018-04-10

-----
Expand Down
Binary file renamed bin/osqueryi_darwin → bin/osqueryd.exe
100755 → 100644
Binary file not shown.
Binary file added bin/osqueryd_darwin
Binary file not shown.
47 changes: 41 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 16 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Stethoscope",
"version": "1.1.10",
"version": "1.2.0",
"private": true,
"homepage": "./",
"author": "Netflix",
Expand All @@ -15,14 +15,16 @@
},
"mac": {
"category": "public.app-category.utilities",
"extraResources": [
"bin/osqueryd_darwin"
],
"files": [
"bin/osqueryi_darwin",
"practices/*",
"build/**",
"public/**",
"resolvers/**",
"sources/*",
"src/lib/*.js",
"src/lib/**",
"src/*.json",
"src/*.js",
"server.js",
Expand All @@ -31,14 +33,16 @@
},
"win": {
"target": "nsis",
"extraResources": [
"bin/osqueryd.exe"
],
"files": [
"bin/osqueryi.exe",
"practices/*",
"build/**",
"public/**",
"resolvers/**",
"sources/*",
"src/lib/*.js",
"src/lib/**",
"src/*.json",
"src/*.js",
"server.js",
Expand All @@ -51,14 +55,16 @@
"linux": {
"target": "AppImage",
"category": "System",
"extraResources": [
"bin/osqueryi_linux"
],
"files": [
"bin/osqueryi_linux",
"practices/*",
"build/**",
"public/**",
"resolvers/**",
"sources/*",
"src/lib/*.js",
"src/lib/**",
"src/*.json",
"src/*.js",
"server.js",
Expand All @@ -84,7 +90,7 @@
"scripts": {
"start": "nf start -p 12000",
"test": "react-scripts test --env=jsdom",
"electron": "electron .",
"electron": "cross-env NODE_ENV=development electron .",
"electron:start": "node src/start-react",
"react:start": "react-scripts start",
"build": "rm -r dist/ ; react-scripts build && electron-builder -mwl",
Expand All @@ -100,6 +106,7 @@
"body-parser": "^1.18.2",
"classnames": "^2.2.5",
"cors": "^2.8.4",
"cross-env": "^5.2.0",
"electron-settings": "^3.1.4",
"electron-updater": "^2.21.4",
"es6-promisify": "^6.0.0",
Expand All @@ -117,6 +124,7 @@
"semver": "^5.4.1",
"showdown": "^1.8.6",
"socket.io": "^2.0.4",
"thrift": "^0.11.0",
"winston": "^2.4.2",
"winston-daily-rotate-file": "^3.1.3"
},
Expand Down
2 changes: 1 addition & 1 deletion resolvers/Device.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const pkg = require('../package.json')
const OSQuery = require('../sources/osquery')
const OSQuery = require('../sources/osquery_thrift')
const NetworkInterface = require('../src/lib/NetworkInterface')
const Security = require('./Security')
const { ON, OFF, UNKNOWN, UNSUPPORTED, NUDGE } = require('../src/constants')
Expand Down
2 changes: 1 addition & 1 deletion resolvers/platform/MacDevice.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const OSQuery = require('../../sources/osquery')
const OSQuery = require('../../sources/osquery_thrift')
const macFriendlyName = require('../../sources/macmodels')

const MacDevice = {
Expand Down
2 changes: 1 addition & 1 deletion resolvers/platform/MacSecurity.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const semver = require('semver')
const Device = require('../Device')
const OSQuery = require('../../sources/osquery')
const OSQuery = require('../../sources/osquery_thrift')
const { getScreenLock } = require('../../src/lib/applescript')
const pkg = require('../../package.json')
const { NUDGE, UNKNOWN } = require('../../src/constants')
Expand Down
14 changes: 9 additions & 5 deletions resolvers/platform/WindowsDevice.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const OSQuery = require('../../sources/osquery')
const OSQuery = require('../../sources/osquery_thrift')
const powershell = require('../../src/lib/powershell')

const WindowsDevice = {
Expand All @@ -8,10 +8,14 @@ const WindowsDevice = {
},

async disks (root, args, context) {
const descriptors = await OSQuery.all('logical_drives', {
fields: ['device_id as label']
})
return powershell.disks(descriptors)
const descriptors = await OSQuery.all('bitlocker_info')

return descriptors.map(disk => ({
label: disk.drive_letter,
name: disk.drive_letter,
uuid: disk.persistent_volume_id,
encrypted: disk.protection_status === '1' && disk.conversion_status === '1'
}))
},

async applications (root, args, context) {
Expand Down
21 changes: 10 additions & 11 deletions resolvers/platform/WindowsSecurity.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const semver = require('semver')
const Device = require('../Device')
const OSQuery = require('../../sources/osquery')
const OSQuery = require('../../sources/osquery_thrift')
const powershell = require('../../src/lib/powershell')
const pkg = require('../../package.json')
const { NUDGE, UNKNOWN } = require('../../src/constants')
Expand Down Expand Up @@ -48,21 +48,20 @@ const WindowsSecurity = {
where path = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogin'
*/
async screenLock (root, args, context) {
const { autoAdminLogin } = await OSQuery.first('registry', {
fields: ['name', 'data as autoAdminLogin'],
where: `path = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoAdminLogin'`
})

// const { autoAdminLogin } = await OSQuery.first('registry', {
// fields: ['name', 'data as autoAdminLogin'],
// where: `path = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoAdminLogin'`
// })
const { windowsMaxScreenLockTimeout = 600 } = args

const screenLockIsActive = await powershell.getScreenLockActive()
const workstationLockIsDisabled = await powershell.getDisableLockWorkStation()
//const screenLockIsActive = await powershell.getScreenLockActive()
//const workstationLockIsDisabled = await powershell.getDisableLockWorkStation()
const { pluggedIn, battery } = await powershell.getScreenLockTimeout()

return (
workstationLockIsDisabled === false &&
screenLockIsActive === true &&
autoAdminLogin !== '1' &&
// workstationLockIsDisabled === false &&
// screenLockIsActive === true &&
// autoAdminLogin !== '1' &&
pluggedIn <= windowsMaxScreenLockTimeout &&
battery <= windowsMaxScreenLockTimeout
)
Expand Down
14 changes: 11 additions & 3 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const semver = require('semver')
const { graphql } = require('graphql')
const { makeExecutableSchema } = require('graphql-tools')
const Resolvers = require('./resolvers/')
const OSQuery = require('./sources/osquery')
const Schema = fs.readFileSync(path.join(__dirname, './schema.graphql'), 'utf8')
const spacesToCamelCase = require('./src/lib/spacesToCamelCase')
const powershell = require('./src/lib/powershell')
const defaultPolicyServer = HOST

const app = express()
Expand All @@ -27,7 +27,7 @@ const io = require('socket.io')(http, { wsEngine: 'ws' })
// sessionId is used as a key
const alertCache = new Map()

module.exports = function startServer (env, log, appActions) {
module.exports = function startServer (env, log, appActions, OSQuery) {
const find = filePath => env === 'development' ? filePath : path.join(__dirname, filePath)

const settingsHandle = fs.readFileSync(find('./practices/config.yaml'), 'utf8')
Expand Down Expand Up @@ -81,10 +81,11 @@ module.exports = function startServer (env, log, appActions) {
app.use('/graphiql', cors(corsOptions), graphiqlExpress({ endpointURL: '/scan' }))
}

// TODO remove raw query for validation and device info??
app.use(['/scan', '/graphql'], cors(corsOptions), (req, res) => {
req.setTimeout(60000)
// flush any cached queries from the previous request
OSQuery.flushCache()
powershell.flushCache()

const context = {
platform: os.platform() || process.platform,
Expand Down Expand Up @@ -139,6 +140,13 @@ module.exports = function startServer (env, log, appActions) {
if (!result.extensions) result.extensions = {}
result.extensions.timing = OSQuery.getTimingInfo()

if (os.platform() === 'win32') {
const { total, queries } = powershell.getTimingInfo()
log.info(total, queries)
result.extensions.timing.total += total
result.extensions.timing.queries.push(...queries)
}

res.json(result)
}).catch(err => {
log.error(err.message)
Expand Down
Loading

0 comments on commit cf1cfc3

Please sign in to comment.