Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Memgraph support #99

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ tsconfig.tsbuildinfo
config.yaml
.env
docker/.neo4j/
docker/mg_lib
docker/mg_log
docker/mg_etc
yarn-error.log
dist/
coverage/
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Starbase from [JupiterOne](https://jupiterone.com), collects assets and
relationships from services and systems including cloud infrastructure, SaaS
applications, security controls, and more into an intuitive graph view backed by
the [Neo4j](https://neo4j.com/) database.
the [Memgraph](https://memgraph.com/) or [Neo4j](https://neo4j.com/) database.

**Security is a basic right**. Starbase's goal is to **democratize graph-based
security analysis** and overall visibility into external services and systems.
Expand Down Expand Up @@ -208,8 +208,8 @@ Commands:
2. Run `yarn starbase run` to collect data for each listed integration and then
push collected data to the storage endpoint listed in `config.yaml`.

For additional information on using Neo4j or JupiterOne as a storage endpoint,
please see the [README.md](docker/README.md) provided.
For additional information on using Memgraph, Neo4j or JupiterOne as a storage
endpoint, please see the [README.md](docker/README.md) provided.

### Running Starbase - Docker

Expand Down Expand Up @@ -276,8 +276,8 @@ Join us on `#starbase` on the
[^1]:
JupiterOne Starbase and the
[Lyft Cartography](https://github.com/lyft/cartography) projects complement
each other as both projects push graph data to a Neo4j database instance. As
such, users of Starbase can leverage the AWS connector from Cartography to
each other as both projects push graph data to Memgraph or Neo4j database instance.
As such, users of Starbase can leverage the AWS connector from Cartography to
ingest AWS assets and relationships. A more comprehensive AWS integration is
used by the [cloud hosted JupiterOne platform](https://jupiterone.com) and
we are considering open sourcing the JupiterOne AWS integration in the
Expand Down
26 changes: 26 additions & 0 deletions config.yaml.memgraph.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
integrations:
-
name: graph-jamf
instanceId: testInstanceId
directory: ./.integrations/graph-jamf
gitRemoteUrl: https://github.com/JupiterOne/graph-jamf.git
config:
JAMF_HOST: example-host
JAMF_USERNAME: example-username
JAMF_PASSWORD: example-password
-
name: graph-sentry
instanceId: testInstanceId
directory: ./.integrations/graph-sentry
gitRemoteUrl: https://github.com/JupiterOne/graph-sentry.git
config:
AUTH_TOKEN: example-token
ORGANIZATION_SLUG: example-organization
storage:
-
engine: memgraph
config:
username:
password:
uri: bolt://localhost:7687
database: memgraph
18 changes: 18 additions & 0 deletions docker/memgraph.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '3.8'
services:
memgraph:
image: 'memgraph/memgraph-platform'
hostname: memgraph
ports:
- '3000:3000'
- '7444:7444'
- '7687:7687'
volumes:
- mg_lib:/var/lib/memgraph
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the correct volume paths? It looks like you added docker/.memgraph to the .gitignore file, but these all look like they'll be in individual folders and not within a .memgraph folder.

- mg_log:/var/log/memgraph
- mg_etc:/etc/memgraph
entrypoint: ["/usr/bin/supervisord"]
volumes:
mg_lib:
mg_log:
mg_etc:
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"scripts": {
"starbase": "ts-node ./src/index.ts",
"starbase:help": "ts-node ./src/index.ts -h",
"memgraph:start": "docker-compose -f docker/memgraph.yml up -d",
"memgraph:stop": "docker-compose -f docker/memgraph.yml down",
"neo4j:start": "docker-compose -f docker/neo4j.yml up -d",
"neo4j:start:plugins": "docker-compose -f docker/neo4j.yml -f docker/neo4jplugins.yml up -d",
"neo4j:stop": "docker-compose -f docker/neo4j.yml down",
Expand Down
33 changes: 24 additions & 9 deletions src/cli/wipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,49 @@ import { executeWithLogging } from '../starbase/process';

export function wipe() {
return createCommand('wipe')
.description('wipes data from Neo4j instance with specified instance ID')
.description('wipes data from database instance with specified instance ID')
.requiredOption(
'-i, --integration-instance-id <id>',
'_integrationInstanceId assigned to uploaded entities that should be wiped from Neo4j',
'_integrationInstanceId assigned to uploaded entities that should be wiped from the database',
)
.option(
'-db, --database-name <database>',
'optional database to wipe data from (only available for enterprise Neo4j databases)',
'neo4j',
)
.action(async (options) => {
executeWithLogging(
`yarn j1-integration neo4j wipe -i ${options.integrationInstanceId} -db ${options.databaseName}`,
);
if (options.databaseName == 'neo4j'){
executeWithLogging(
`yarn j1-integration neo4j wipe -i ${options.integrationInstanceId} -db ${options.databaseName}`,
);
}
else if (options.databaseName == 'memgraph'){
executeWithLogging(
`yarn j1-integration memgraph wipe -i ${options.integrationInstanceId} -db ${options.databaseName}`,
);
}
});
}

export function wipeAll() {
return createCommand('wipe-all')
.description('wipes all data from Neo4j instance')
.description('wipes all data from database instance')
.option(
'-db, --database-name <database>',
'optional database to wipe data from (only available for enterprise Neo4j databases)',
'neo4j',
)
.action(async (options) => {
executeWithLogging(
`yarn j1-integration neo4j wipe-all -db ${options.databaseName}`,
);
if (options.databaseName == 'neo4j'){
executeWithLogging(
`yarn j1-integration neo4j wipe-all -db ${options.databaseName}`,
);
}
else if (options.databaseName == 'memgraph'){
executeWithLogging(
`yarn j1-integration memgraph wipe-all -db ${options.databaseName}`,
);
}

});
}
9 changes: 9 additions & 0 deletions src/starbase/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ const testConfig: StarbaseConfig = {
database: 'neo4j',
},
},
{
engine: 'memgraph',
config: {
username: '',
password: '',
uri: 'bolt://localhost:7687',
database: 'memgraph',
},
},
],
};

Expand Down
11 changes: 11 additions & 0 deletions src/starbase/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ NEO4J_PASSWORD=${storage.config.password}
);
}

async function writeMemgraphRootConfig(storage: StarbaseStorage) {
await fs.appendFile(
'.env',
`MEMGRAPH_URI=${storage.config.uri}
MEMGRAPH_USER=${storage.config.username}
MEMGRAPH_PASSWORD=${storage.config.password}
`,
);
}

async function writeJ1RootConfig(storage: StarbaseStorage) {
await fs.appendFile(
'.env',
Expand Down Expand Up @@ -142,6 +152,7 @@ async function parseConfigYaml(configPath: string): Promise<StarbaseConfig> {
export {
parseConfigYaml,
writeIntegrationConfig,
writeMemgraphRootConfig,
writeNeo4jRootConfig,
writeJ1RootConfig,
integrationConfigToEnvFormat,
Expand Down
11 changes: 11 additions & 0 deletions src/starbase/execution.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
writeIntegrationConfig,
writeMemgraphRootConfig,
writeNeo4jRootConfig,
writeJ1RootConfig,
} from './config';
Expand All @@ -18,6 +19,9 @@ async function setupStarbaseStorageEngine(starbaseConfig: StarbaseConfig) {
case 'neo4j':
await writeNeo4jRootConfig(storageConfig);
break;
case 'memgraph':
await writeMemgraphRootConfig(storageConfig);
break;
case 'jupiterone':
await writeJ1RootConfig(storageConfig);
break;
Expand Down Expand Up @@ -71,6 +75,13 @@ async function executeStarbase(
} to browse your Neo4J graph.`,
);
}
else if (engines.includes('memgraph')) {
console.log(
`open ${
process.env.MEMGRAPH_BROWSER_URI ?? 'http://localhost:3000/browser/'
} to browse your graph in Memgraph.`,
);
}
}

export { executeStarbase, OnSkipIntegrationExecutionFunctionParams };
20 changes: 19 additions & 1 deletion src/starbase/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { StarbaseConfigurationError } from './error';

async function collectIntegrationData(integrationDirectory: string) {
await executeWithLogging(
`yarn --cwd ${integrationDirectory} start --disable-schema-validation;`,
`yarn --cwd ${integrationDirectory} start --disable-schema-validation`,
);
}

Expand All @@ -22,6 +22,16 @@ async function writeIntegrationDataToNeo4j(
);
}

async function writeIntegrationDataToMemgraph(
integrationInstanceId: string,
integrationDirectory: string,
integrationDatabase: string = 'memgraph',
) {
await executeWithLogging(
`yarn j1-integration memgraph push -i ${integrationInstanceId} -d ${integrationDirectory}/.j1-integration -db ${integrationDatabase}`,
);
}

async function writeIntegrationDataToJupiterOne(
integrationInstanceId: string,
integrationDirectory: string,
Expand Down Expand Up @@ -52,6 +62,13 @@ async function executeIntegration<TConfig>(
storageConfig.config?.database,
);
break;
case 'memgraph':
await writeIntegrationDataToMemgraph(
integration.instanceId,
integration.directory,
storageConfig.config?.database,
);
break;
case 'jupiterone':
await writeIntegrationDataToJupiterOne(
integration.instanceId,
Expand All @@ -70,5 +87,6 @@ async function executeIntegration<TConfig>(
export {
executeIntegration,
collectIntegrationData,
writeIntegrationDataToMemgraph,
writeIntegrationDataToNeo4j,
};
9 changes: 9 additions & 0 deletions src/starbase/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ interface Neo4jStorageEngineConfig {
database?: string;
}

interface MemgraphStorageEngineConfig {
username: string;
password: string;
uri: string;
database?: string;
}

interface JupiterOneStorageEngineConfig {
/**
* The JupiterOne API key to authenticate with
Expand All @@ -35,6 +42,8 @@ interface JupiterOneStorageEngineConfig {

export type Neo4jStorage = StarbaseStorage<Neo4jStorageEngineConfig>;

export type MemgraphStorage = StarbaseStorage<MemgraphStorageEngineConfig>;

export type JupiterOneStorage = StarbaseStorage<JupiterOneStorageEngineConfig>;

export type StarbaseConfig = {
Expand Down