Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

#### 🐛 Bug Fix

- Adding in optional Neo4j database name configuration [#78](https://github.com/JupiterOne/starbase/pull/78) ([@adam-in-ict](https://github.com/adam-in-ict))
- Initial Starbase documentation website [#75](https://github.com/JupiterOne/starbase/pull/75) ([@austinkelleher](https://github.com/austinkelleher))
- Adding in optional Neo4j database name configuration
[#78](https://github.com/JupiterOne/starbase/pull/78)
([@adam-in-ict](https://github.com/adam-in-ict))
- Initial Starbase documentation website
[#75](https://github.com/JupiterOne/starbase/pull/75)
([@austinkelleher](https://github.com/austinkelleher))

#### Authors: 2

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,12 @@ cp config.yaml.example config.yaml
> ORGANIZATION_ID: '...'
> CONFIGURE_ORGANIZATION_PROJECTS: false
> storage:
> engine: neo4j
> config:
> username: neo4j
> password: devpass
> uri: bolt://localhost:7687
> database: neo4j
> - engine: neo4j
> config:
> username: neo4j
> password: devpass
> uri: bolt://localhost:7687
> database: neo4j
> ```

### Running Starbase
Expand Down
13 changes: 7 additions & 6 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ integrations:
AUTH_TOKEN: example-token
ORGANIZATION_SLUG: example-organization
storage:
engine: neo4j
config:
username: neo4j
password: devpass
uri: bolt://localhost:7687
database: neo4j
-
engine: neo4j
config:
username: neo4j
password: devpass
uri: bolt://localhost:7687
database: neo4j
18 changes: 10 additions & 8 deletions src/starbase/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,17 @@ const testConfig: StarbaseConfig = {
},
},
],
storage: {
engine: 'neo4j',
config: {
username: 'neo4j',
password: 'devpass',
uri: 'bolt://localhost:7687',
database: 'neo4j',
storage: [
{
engine: 'neo4j',
config: {
username: 'neo4j',
password: 'devpass',
uri: 'bolt://localhost:7687',
database: 'neo4j',
},
},
},
],
};

describe('#parseConfig', () => {
Expand Down
20 changes: 18 additions & 2 deletions src/starbase/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ const configSchema: Schema = {
type: 'array',
items: integrationSchema,
},
storage: storageSchema,
storage: {
type: 'array',
items: storageSchema,
},
},
};

Expand All @@ -54,7 +57,7 @@ function integrationConfigToEnvFormat(config: StarbaseIntegration['config']) {
* This is the `.env` file that is written to the root of the Starbase project.
*/
async function writeNeo4jRootConfig(storage: StarbaseStorage) {
await fs.writeFile(
await fs.appendFile(
'.env',
`NEO4J_URI=${storage.config.uri}
NEO4J_USER=${storage.config.username}
Expand All @@ -63,6 +66,18 @@ NEO4J_PASSWORD=${storage.config.password}
);
}

async function writeJ1RootConfig(storage: StarbaseStorage) {
await fs.appendFile(
'.env',
`JUPITERONE_API_KEY=${storage.config.apiKey}
JUPITERONE_ACCOUNT=${storage.config.accountId}
JUPITERONE_API_BASEURL=${
storage.config.apiBaseUrl || 'https://api.us.jupiterone.io'
}
`,
);
}

async function writeIntegrationConfig<TConfig = any>(
integration: StarbaseIntegration<TConfig>,
) {
Expand Down Expand Up @@ -128,5 +143,6 @@ export {
parseConfigYaml,
writeIntegrationConfig,
writeNeo4jRootConfig,
writeJ1RootConfig,
integrationConfigToEnvFormat,
};
42 changes: 30 additions & 12 deletions src/starbase/execution.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { writeIntegrationConfig, writeNeo4jRootConfig } from './config';
import {
writeIntegrationConfig,
writeNeo4jRootConfig,
writeJ1RootConfig,
} from './config';
import { executeIntegration } from './integration';
import { isDirectoryPresent } from '@jupiterone/integration-sdk-runtime';
import { StarbaseConfigurationError } from './error';
Expand All @@ -7,13 +11,22 @@ import { StarbaseConfig, StarbaseIntegration } from './types';
async function setupStarbaseStorageEngine(starbaseConfig: StarbaseConfig) {
if (!starbaseConfig.storage) return;

if (starbaseConfig.storage.engine !== 'neo4j') {
throw new StarbaseConfigurationError(
'Invalid storage engine supplied. Neo4j is the only storage engine supported at this time.',
);
}
// TODO: determine if we need to validate array here

await writeNeo4jRootConfig(starbaseConfig.storage);
for (const storageConfig of starbaseConfig.storage || []) {
switch (storageConfig.engine) {
case 'neo4j':
await writeNeo4jRootConfig(storageConfig);
break;
case 'jupiterone':
await writeJ1RootConfig(storageConfig);
break;
default:
throw new StarbaseConfigurationError(
`Invalid storage engine supplied: '${storageConfig.engine}'.`,
);
}
}
}

type OnSkipIntegrationExecutionFunctionParams = {
Expand Down Expand Up @@ -48,11 +61,16 @@ async function executeStarbase(
await writeIntegrationConfig(integration);
await executeIntegration(integration, starbaseConfig);
}
console.log(
`open ${
process.env.NEO4J_BROWSER_URI ?? 'http://localhost:7474/browser/'
} to browse your Neo4J graph.`,
);

const engines = (starbaseConfig.storage || []).map((s) => s.engine);

if (engines.includes('neo4j')) {
console.log(
`open ${
process.env.NEO4J_BROWSER_URI ?? 'http://localhost:7474/browser/'
} to browse your Neo4J graph.`,
);
}
}

export { executeStarbase, OnSkipIntegrationExecutionFunctionParams };
49 changes: 42 additions & 7 deletions src/starbase/integration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { StarbaseConfig, StarbaseIntegration } from './types';
import {
JupiterOneStorage,
StarbaseConfig,
StarbaseIntegration,
} from './types';
import { executeWithLogging } from './process';
import { StarbaseConfigurationError } from './error';

async function collectIntegrationData(integrationDirectory: string) {
await executeWithLogging(
Expand All @@ -17,19 +22,49 @@ async function writeIntegrationDataToNeo4j(
);
}

async function writeIntegrationDataToJupiterOne(
integrationInstanceId: string,
integrationDirectory: string,
storageConfig: JupiterOneStorage,
) {
const isDev = storageConfig.config.apiBaseUrl?.match(/dev/) || false;
const optDevFlags = isDev
? `--api-base-url ${storageConfig.config.apiBaseUrl}`
: '';
await executeWithLogging(
`yarn j1-integration sync -i ${integrationInstanceId} -p ${integrationDirectory} ${optDevFlags}`,
);
}

async function executeIntegration<TConfig>(
integration: StarbaseIntegration<TConfig>,
starbaseConfig: StarbaseConfig,
) {
await collectIntegrationData(integration.directory);

// TODO: Remove this in favor of custom storage engine handler functions.
if (starbaseConfig.storage?.engine === 'neo4j') {
await writeIntegrationDataToNeo4j(
integration.instanceId,
integration.directory,
starbaseConfig.storage?.config?.database,
);

for (const storageConfig of starbaseConfig.storage || []) {
switch (storageConfig.engine) {
case 'neo4j':
await writeIntegrationDataToNeo4j(
integration.instanceId,
integration.directory,
storageConfig.config?.database,
);
break;
case 'jupiterone':
await writeIntegrationDataToJupiterOne(
integration.instanceId,
integration.directory,
storageConfig,
);
break;
default:
throw new StarbaseConfigurationError(
`Invalid storage engine supplied: '${storageConfig.engine}'.`,
);
}
}
}

Expand Down
23 changes: 20 additions & 3 deletions src/starbase/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,33 @@ export type StarbaseStorage<TStorageConfig = any> = {
config: TStorageConfig;
};

interface Neo4jStorageConfig {
interface Neo4jStorageEngineConfig {
username: string;
password: string;
uri: string;
database?: string;
}

export type Neo4jStorage = StarbaseStorage<Neo4jStorageConfig>;
interface JupiterOneStorageEngineConfig {
/**
* The JupiterOne API key to authenticate with
*/
apiKey: string;
/**
* The JupiterOne account ID to target
*/
accountId: string;
/**
* If provided this option specifies which base URL to use for synchronization (default: `https://api.us.jupiterone.io`)
*/
apiBaseUrl?: string;
}

export type Neo4jStorage = StarbaseStorage<Neo4jStorageEngineConfig>;

export type JupiterOneStorage = StarbaseStorage<JupiterOneStorageEngineConfig>;

export type StarbaseConfig = {
integrations: StarbaseIntegration[];
storage?: StarbaseStorage;
storage?: StarbaseStorage[];
};