├── .eslintrc.js ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .lintstagedrc ├── .prettierignore ├── .prettierrc ├── CHANGELOG.md ├── CODEOWNERS ├── LICENSE ├── README.md ├── cortex.yaml ├── external └── resolvedSchemas.json ├── jest.config.js ├── jest.env.js ├── package-lock.json ├── package.json ├── src ├── IntegrationSchema.ts ├── RelationshipClass.ts ├── getSchema.test.ts ├── getSchema.ts ├── globalEntities.ts ├── index.test.ts ├── index.ts ├── registerFormats.ts ├── registerSchemas.ts ├── relationships.ts ├── schemas │ ├── AccessKey.json │ ├── AccessPolicy.json │ ├── AccessRole.json │ ├── Account.json │ ├── Alert.json │ ├── Application.json │ ├── ApplicationEndpoint.json │ ├── Assessment.json │ ├── Attacker.json │ ├── Backup.json │ ├── Certificate.json │ ├── Channel.json │ ├── Cluster.json │ ├── CodeCommit.json │ ├── CodeDeploy.json │ ├── CodeModule.json │ ├── CodeRepo.json │ ├── CodeReview.json │ ├── Configuration.json │ ├── Container.json │ ├── Control.json │ ├── ControlPolicy.json │ ├── CryptoKey.json │ ├── DataCollection.json │ ├── DataObject.json │ ├── DataStore.json │ ├── Database.json │ ├── Deployment.json │ ├── Device.json │ ├── Directory.json │ ├── Disk.json │ ├── Document.json │ ├── Domain.json │ ├── DomainRecord.json │ ├── DomainZone.json │ ├── Entity.json │ ├── Finding.json │ ├── Firewall.json │ ├── Framework.json │ ├── Function.json │ ├── Gateway.json │ ├── GraphObject.json │ ├── Group.json │ ├── Host.json │ ├── HostAgent.json │ ├── Image.json │ ├── Incident.json │ ├── Internet.json │ ├── IpAddress.json │ ├── Issue.json │ ├── Key.json │ ├── Logs.json │ ├── Model.json │ ├── Module.json │ ├── Network.json │ ├── NetworkEndpoint.json │ ├── NetworkInterface.json │ ├── Organization.json │ ├── PR.json │ ├── PasswordPolicy.json │ ├── Person.json │ ├── Policy.json │ ├── Problem.json │ ├── Procedure.json │ ├── Process.json │ ├── Product.json │ ├── Program.json │ ├── Project.json │ ├── Question.json │ ├── Queue.json │ ├── Record.json │ ├── RecordEntity.json │ ├── Repository.json │ ├── Requirement.json │ ├── Resource.json │ ├── Review.json │ ├── Risk.json │ ├── Root.json │ ├── Rule.json │ ├── Ruleset.json │ ├── Scanner.json │ ├── Secret.json │ ├── Section.json │ ├── Service.json │ ├── Site.json │ ├── Standard.json │ ├── Subscription.json │ ├── Task.json │ ├── Team.json │ ├── ThreatIntel.json │ ├── Training.json │ ├── User.json │ ├── UserGroup.json │ ├── Vault.json │ ├── Vendor.json │ ├── Vulnerability.json │ ├── Weakness.json │ ├── Workflow.json │ └── Workload.json ├── validateEntityWithSchema.test.ts └── validateEntityWithSchema.ts ├── tools ├── generate-register-schemas-function.sh ├── generate-resolved-schemas │ ├── index.ts │ ├── utils.test.ts │ └── utils.ts └── generate-schema-imports.sh ├── tsconfig.dist.json ├── tsconfig.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | parserOptions: { 5 | project: './tsconfig.json', 6 | }, 7 | plugins: ['@typescript-eslint'], 8 | extends: [ 9 | 'eslint:recommended', 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:@typescript-eslint/eslint-recommended', 12 | 'plugin:@typescript-eslint/recommended-requiring-type-checking', 13 | 'prettier', 14 | ], 15 | }; 16 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | runs-on: ${{ matrix.os }} 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | node-version: [18.x] 11 | os: [ubuntu-latest] 12 | 13 | steps: 14 | - id: setup-node 15 | name: Setup Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | 20 | - name: Check out code repository source code 21 | uses: actions/checkout@v2 22 | 23 | - name: Install dependencies 24 | run: yarn 25 | 26 | - name: Run tests 27 | run: yarn test 28 | 29 | - name: Run build 30 | run: yarn build 31 | 32 | # NOTE: publishing is now performed internally, do not 33 | # re-enable this job. 34 | 35 | # Publishing is done in a separate job to allow 36 | # for all matrix builds to complete. 37 | # release: 38 | # needs: test 39 | # runs-on: ubuntu-latest 40 | # if: github.ref == 'refs/heads/main' 41 | # strategy: 42 | # fail-fast: false 43 | # matrix: 44 | # node: [18] 45 | 46 | # steps: 47 | # - name: Setup Node 48 | # uses: actions/setup-node@v1 49 | # with: 50 | # node-version: 18.x 51 | 52 | # - name: Check out repo 53 | # uses: actions/checkout@v2 54 | # with: 55 | # fetch-depth: 2 56 | 57 | # # Fetch tags and describe the commit before the merge commit 58 | # # to see if it's a version publish 59 | # - name: Fetch tags 60 | # run: | 61 | # git fetch --tags 62 | # if git describe --exact-match --match "v*.*.*" HEAD^2 63 | # then 64 | # echo "Found version commit tag. Publishing." 65 | # echo "publish=true" >> $GITHUB_ENV 66 | # else 67 | # echo "Version commit tag not found. Not publishing." 68 | # fi 69 | 70 | # - name: Publish 71 | # if: env.publish == 'true' 72 | # env: 73 | # NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 74 | # run: | 75 | # echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > .npmrc 76 | # yarn 77 | # npm publish 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | dist 4 | yarn-error.log 5 | .idea/ 6 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged && yarn generate-schema-imports && yarn generate-resolved-schemas 5 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.ts": [ 3 | "eslint", 4 | "prettier --write" 5 | ], 6 | "*.{md,js,json}": [ 7 | "prettier --write" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | coverage -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "proseWrap": "always", 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jupiterone/engineering 2 | 3 | CODEOWNERS @jupiterone/security -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > NOTE - This repository is no longer actively maintained. 2 | > Please refer to the [Data Model Documentation](https://docs.jupiterone.io/api/data-model/jupiterone-data-model) for the most up-to-date information. 3 | 4 | # JupiterOne Graph Data Model 5 | 6 | - [Data Model Documentation](https://docs.jupiterone.io/api/data-model/jupiterone-data-model) 7 | 8 | The **JupiterOne Graph Data Model** describes a set of common classifications 9 | for data found in an organization's set of digital assets, as well as common 10 | property names and relationships. 11 | 12 | The model does not represent a strict requirement for data stored in the 13 | JupiterOne graph. It is acceptable and common to include many additional 14 | properties on any class of entity or relationship, when those properties provide 15 | value for querying and reporting. It is however strongly recommended that 16 | similar data use common class and property names where possible. 17 | 18 | The value is realized when writing queries, or using queries others have 19 | written, and when viewing a list of similar assets from any number of external 20 | systems. For example, `find Host with ipAddress="192.168.10.23"` depends on the 21 | data model, which works whether the asset is in AWS, Azure, GCP, or detected by 22 | an on-prem scanner, or is a machine in the classic sense or a serverless 23 | function. The list of results would have some common property names no matter 24 | what a value is labeled in external systems. 25 | 26 | Though the data model is not a strict schema, [there are schemas](/src/schemas) 27 | which serve to communicate the data model and are used in JupiterOne UIs to 28 | support entity creation, editing, and visualization. Additionally, integrations 29 | are encouraged to generate entities and relationships that conform to the 30 | schemas to help to drive the advancement of the data model and provide 31 | consistency in the data we ingest. See the 32 | [Integration SDK](https://github.com/JupiterOne/integration-sdk) for functions 33 | that make this easy to do. 34 | 35 | ## Entities and Relationships 36 | 37 | The data model is built for a knowledge graph -- entities and relationships, or 38 | nodes and edges -- that reflects the stateful representation of the cyber 39 | infrastructure and digital operations of an organization. 40 | 41 | The schema for each entity and relationship describes a collection of common 42 | attributes for that specific abstract class, along with graph object metadata as 43 | described in [`GraphObject.json`](/src/schemas/GraphObject.json). 44 | 45 | The data model combines the benefit of having vendor/provider specific 46 | attributes together with abstract/normalized attributes. The vendor/provider 47 | specific attributes are dynamically assigned and not defined by the data model. 48 | 49 | ## The Concept of `_type` and `_class` 50 | 51 | Each entity represents an actual operating element (a "thing") that is part of 52 | an organization's cyber operations or infrastructure. This "thing" can be either 53 | physical or logical. 54 | 55 | The metadata attributes `_type` and `_class` are used to define what the asset 56 | is: 57 | 58 | - `_type`: The value is a single string typically in the format of 59 | `${vendor}_${resource}` or `${vendor}_${product}_${resource}` in `snake_case`. 60 | 61 | > For example: `aws_instance`, `google_cloud_function`, `apple_tv`, 62 | > `sentinelone_agent` 63 | 64 | It is important to note that in some cases, `${vendor}_${resource}` may not be 65 | ideal or feasible. 66 | 67 | For example, we may have directory data that comes in from an HR integration 68 | such as BambooHR or Rippling. The `Person` entity being created should have 69 | `_type: 'employee'` or `_type: 'contractor'` rather than 70 | `_type: 'bamboohr_employee'` or `_type: 'bamboohr_contractor'`. 71 | 72 | Another exception is data that comes from an integration with another ITSM, 73 | asset discovery tool, device management tool, or CMDB. While a system might be 74 | a good "source of truth" or "system of record," they are not the actual vendor 75 | of those devices. 76 | 77 | - If a server or application is ingested from **ServiceNow**, the `_type` 78 | should _not_ be `servicenow_server` or `servicenow_application`. 79 | 80 | - If a Cisco switch is ingested from **Rumble** or **Netbox**, the `_type` 81 | should be `cisco_switch` instead of `rumble_asset` or `netbox_device`. 82 | 83 | - If a smartphone/mobile device is managed by Google Workspace and ingested 84 | via the integration, the `_type` for the device should _not_ be 85 | `google_mobile_device` because the device could be an Apple iPhone and it 86 | would be very confusing to call an iPhone a Google mobile device. Instead, 87 | it should be `apple_iphone` when the type of device is known or a generic 88 | value of `mobile_device`. 89 | 90 | - `_class`: The value is a string or string array in `TitleCase` using a generic 91 | IT or Security term to describe the higher level category of the asset. 92 | 93 | > These are defined in [`src/schemas`](src/schemas). 94 | 95 | ## Versioning this package 96 | 97 | The following needs to be the last commit on your branch right before merging to 98 | main. That's crucial to the CI process. \ 99 | If you encounter issues while doing the following procedure, rebasing won't work, 100 | you'll need to start it over again because of how tags work. 101 | 102 | 1. Update the `CHANGELOG.md` file with the new version number and the changes 103 | made in that version. Don't commit the change. 104 | 2. Stage the changes of the changelog and then run `yarn version` to commit the 105 | changes to the changelog, and bump the package number. This will also tag 106 | said commit locally on your branch. 107 | 3. Push your changes. Merge to main. 108 | -------------------------------------------------------------------------------- /cortex.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | info: 3 | title: '@jupiterone/data-model' 4 | description: Automatically generated package.json, please edit manually 5 | x-cortex-git: 6 | github: 7 | repository: JupiterOne/data-model 8 | x-cortex-owners: 9 | - type: group 10 | name: JupiterOne/engineering 11 | x-cortex-tag: '@jupiterone/data-model' 12 | x-cortex-service-groups: 13 | - tier-4 14 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | clearMocks: true, 4 | restoreMocks: true, 5 | testMatch: [ 6 | '/**/*.test.ts', 7 | '/**/*.test.js', 8 | '!**/node_modules/*', 9 | '!**/dist/*', 10 | '!**/*.bak/*', 11 | ], 12 | setupFilesAfterEnv: ['./jest.env.js'], 13 | testEnvironment: 'node', 14 | collectCoverage: true, 15 | collectCoverageFrom: ['src/**/*.ts', '!src/index.ts'], 16 | coveragePathIgnorePatterns: ['src/registerSchemas'], 17 | coverageThreshold: { 18 | global: { 19 | statements: 100, 20 | branches: 100, 21 | functions: 100, 22 | lines: 100, 23 | }, 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /jest.env.js: -------------------------------------------------------------------------------- 1 | process.env.ENABLE_GRAPH_OBJECT_SCHEMA_VALIDATION = '1'; 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jupiterone/data-model", 3 | "version": "0.57.0", 4 | "description": "Automatically generated package.json, please edit manually", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/JupiterOne/data-model" 8 | }, 9 | "license": "MPL-2.0", 10 | "main": "dist/index.js", 11 | "files": [ 12 | "dist" 13 | ], 14 | "author": "JupiterOne ", 15 | "publishConfig": { 16 | "access": "public" 17 | }, 18 | "scripts": { 19 | "prebuild": "rm -rf dist/*", 20 | "build": "yarn tsc --project tsconfig.dist.json --declaration", 21 | "generate-schema-imports": "./tools/generate-schema-imports.sh && ./tools/generate-register-schemas-function.sh", 22 | "generate-resolved-schemas": "node -r ts-node/register tools/generate-resolved-schemas/index.ts src/schemas external/resolvedSchemas.json && prettier --write external/resolvedSchemas.json", 23 | "test": "jest", 24 | "lint": "eslint src --ext .ts,.js", 25 | "format": "prettier --write '**/*.{ts,js,json,md}'", 26 | "prepack": "yarn build", 27 | "prepare": "husky install" 28 | }, 29 | "dependencies": { 30 | "ajv": "^8.0.0", 31 | "ajv-formats": "^2.0.0" 32 | }, 33 | "devDependencies": { 34 | "@types/jest": "^29.5.12", 35 | "@types/node": "^18.19.29", 36 | "@typescript-eslint/eslint-plugin": "^7.5.0", 37 | "@typescript-eslint/parser": "^7.5.0", 38 | "eslint": "^8.57.0", 39 | "eslint-config-prettier": "^9.1.0", 40 | "husky": "^6.0.0", 41 | "jest": "^29.7.0", 42 | "lint-staged": "^10.5.4", 43 | "prettier": "^3.2.5", 44 | "ts-jest": "^29.1.2", 45 | "ts-node": "^10.9.2", 46 | "typescript": "^4.9.5" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/RelationshipClass.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Standardized values for relationship `_class`. 3 | */ 4 | export enum RelationshipClass { 5 | /** 6 | * A relationship between an {AccessPolicy, Firewall} and a resource Entity. 7 | */ 8 | ALLOWS = 'ALLOWS', 9 | 10 | /** 11 | * A relationship between a User and a PR. 12 | */ 13 | APPROVED = 'APPROVED', 14 | 15 | /** 16 | * A relationship between a {AccessRole, User, Group} and AccessPolicy. 17 | */ 18 | ASSIGNED = 'ASSIGNED', 19 | 20 | /** 21 | * A relationship indicating general connectivity between two entities. 22 | * 23 | * Examples: 24 | * 25 | * - Load Balancer -> CONNECTS -> Instance 26 | * - Gateway -> CONNECTS -> Internet 27 | * - Content Distribution -> CONNECTS -> Gateway 28 | */ 29 | CONNECTS = 'CONNECTS', 30 | 31 | /** 32 | * A relationship indicating an Entity contains another Entity. A contained Entity 33 | * _should_ have a single relationship of this class to reflect that it cannot be 34 | * directly contained within multiple Entities. 35 | * 36 | * Examples: 37 | * 38 | * - Network - CONTAINS -> Network (a subnet) 39 | * - Network - CONTAINS -> Host 40 | * - Cluster - CONTAINS -> Host 41 | * - Role - CONTAINS -> Role (when roles form a hiearchy) 42 | * 43 | * @see HAS 44 | */ 45 | CONTAINS = 'CONTAINS', 46 | 47 | COMPLETED = 'COMPLETED', 48 | 49 | /** 50 | * A relationship between a User and any Entity. 51 | */ 52 | CREATED = 'CREATED', 53 | 54 | /** 55 | * A relationship between a CodeRepo and Function. 56 | */ 57 | DEFINES = 'DEFINES', 58 | 59 | /** 60 | * A relationship between an {AccessPolicy, Firewall} and a resource Entity. 61 | */ 62 | DENIES = 'DENIES', 63 | 64 | DEPLOYED = 'DEPLOYED', 65 | 66 | /** 67 | * A relationship between a ControlPolicy and any resource. 68 | */ 69 | ENFORCES = 'ENFORCES', 70 | 71 | /** 72 | * A relatioship between a Config Rule and any resource. 73 | */ 74 | EVALUATES = 'EVALUATES', 75 | 76 | /** 77 | * A relationship between a {Vulnerability, Finding} and Weakness. 78 | */ 79 | EXPLOITS = 'EXPLOITS', 80 | 81 | EXTENDS = 'EXTENDS', 82 | 83 | /** 84 | * A relationship indicating an Entity is responsible for generating another Entity. 85 | * 86 | * Examples: 87 | * 88 | * * Project - GENERATED -> Finding 89 | */ 90 | GENERATED = 'GENERATED', 91 | 92 | /** 93 | * A relationship indicating a possessive association between two Entities. 94 | * The direction of the relationship typically flows toward the possessed 95 | * Entity. 96 | * 97 | * Examples: 98 | * 99 | * - Account - HAS -> User 100 | * - Network - HAS -> AccessPolicy 101 | * - Network - HAS -> Firewall 102 | * - Finding - HAS -> ThreatIntel 103 | * - UserGroup - HAS -> User (users typically may belong to multiple groups) 104 | * 105 | * @see CONTAINS 106 | */ 107 | HAS = 'HAS', 108 | 109 | /** 110 | * A relationship between a Vendor and an Account 111 | */ 112 | HOSTS = 'HOSTS', 113 | 114 | /** 115 | * A relationship indicating an Entity identified another Entity. 116 | * 117 | * Examples: 118 | * 119 | * * Service - IDENTIFIED -> Finding 120 | */ 121 | IDENTIFIED = 'IDENTIFIED', 122 | 123 | IMPLEMENTS = 'IMPLEMENTS', 124 | 125 | /** 126 | * A relationship indicating an Entity is an instance of another Entity. 127 | * 128 | * Examples: 129 | * 130 | * * Finding - IS -> Vulnerability 131 | * * User - IS -> Person 132 | */ 133 | IS = 'IS', 134 | 135 | /** 136 | * A relationship indicating a Person knows another Person. 137 | * 138 | * Examples: 139 | * Person - KNOWS -> Person 140 | */ 141 | KNOWS = 'KNOWS', 142 | 143 | /** 144 | * A relationship indicating an Entity limits or restricts another Entity. 145 | * 146 | * Examples: 147 | * 148 | * * AccessPolicy - LIMITS -> User or Role 149 | */ 150 | LIMITS = 'LIMITS', 151 | /** 152 | * A relationship indicating an Entity sends logs to another Entity. 153 | * 154 | * Examples: 155 | * 156 | * * NetworkEndpoint - LOGS -> DataStore or Logs 157 | * * Host - LOGS -> DataStore or Logs 158 | */ 159 | LOGS = 'LOGS', 160 | 161 | MANAGES = 'MANAGES', 162 | MITIGATES = 'MITIGATES', 163 | MONITORS = 'MONITORS', 164 | 165 | NOTIFIES = 'NOTIFIES', 166 | 167 | OPENED = 'OPENED', 168 | 169 | /** 170 | * A relationship between an Entity and another Entity of the same type that it shadows or overrides. 171 | * 172 | * Examples: 173 | * 174 | * * Secret - OVERRIDES -> Secret 175 | * * Configuration - OVERRIDES -> Configuration 176 | * * AccessPolicy - OVERRIDES -> AccessPolicy 177 | */ 178 | OVERRIDES = 'OVERRIDES', 179 | 180 | OWNS = 'OWNS', 181 | 182 | PERFORMED = 'PERFORMED', 183 | PROTECTS = 'PROTECTS', 184 | PROVIDES = 'PROVIDES', 185 | 186 | /** 187 | * A relationship between a CodeRepo and an artifact. 188 | * 189 | * Examples: 190 | * 191 | * * CodeRepo - PUBLISHED -> CodeModule 192 | * * CodeRepo - PUBLISHED -> Image 193 | */ 194 | PUBLISHED = 'PUBLISHED', 195 | PUBLISHES = 'PUBLISHES', 196 | 197 | /** 198 | * A relationship indicating an Entity limits or restricts another Entity. 199 | */ 200 | RESTRICTS = 'RESTRICTS', 201 | 202 | REVIEWED = 'REVIEWED', 203 | REPORTED = 'REPORTED', 204 | 205 | /** 206 | * A relationships indicating an Entity performs some sort of task that is the other Entity 207 | */ 208 | RUNS = 'RUNS', 209 | 210 | /** 211 | * A relationships indicating an Entity performs some kind of scan on another Entity. 212 | * 213 | * Examples: 214 | * 215 | * * Service - SCANS -> Host 216 | */ 217 | SCANS = 'SCANS', 218 | 219 | /** 220 | * A relationships indicating an Entity sends something to another Entity 221 | * 222 | * Examples: 223 | * 224 | * Queue - SENDS -> Queue 225 | */ 226 | SENDS = 'SENDS', 227 | 228 | /** 229 | * A relationship indicating an Entitiy triggers an event on another Entity 230 | * 231 | * Example: 232 | * - Gateway -> TRIGGERS -> Function 233 | * - Kinesis -> TRIGGERS -> Function 234 | * - Metric -> TRIGGERS -> Alarm 235 | * - IDS -> TRIGGERS -> Alarm 236 | * 237 | */ 238 | TRIGGERS = 'TRIGGERS', 239 | 240 | TRUSTS = 'TRUSTS', 241 | 242 | /** 243 | * A relationship between a User and any Entity. 244 | */ 245 | UPDATED = 'UPDATED', 246 | 247 | /** 248 | * A relationship indicating an Entity utilizes another Entity. Typically, the 249 | * target Entity can be "used" by many source Entities. 250 | * 251 | * Examples: 252 | * 253 | * * Host - USES -> DataStore 254 | * * UserRole - USES -> AccessPolicy 255 | */ 256 | USES = 'USES', 257 | 258 | /** 259 | * A relationship indicating that a device has some kind of application 260 | * installed. 261 | * 262 | * Examples: 263 | * 264 | * Device - INSTALLED -> Application 265 | */ 266 | INSTALLED = 'INSTALLED', 267 | 268 | /** 269 | * A relationship indicating that an Entity fails to comply with 270 | * a rule or agreement defined by another Entity. 271 | * 272 | * Examples: 273 | * - Problem - VIOLATES -> Requirement 274 | * - Problem - VIOLATES -> Control 275 | */ 276 | VIOLATES = 'VIOLATES', 277 | } 278 | -------------------------------------------------------------------------------- /src/getSchema.test.ts: -------------------------------------------------------------------------------- 1 | import { getSchema } from './getSchema'; 2 | 3 | test('returns undefined if no schema for class', () => { 4 | expect(getSchema('ChimkenNumget')).toBeUndefined(); 5 | }); 6 | 7 | test('returns schema if it exists for class', () => { 8 | expect(getSchema('Account')).toMatchObject({ 9 | $id: '#Account', 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/getSchema.ts: -------------------------------------------------------------------------------- 1 | import { IntegrationEntitySchema, IntegrationSchema } from '.'; 2 | 3 | export function getSchema(_class: string): IntegrationEntitySchema | undefined { 4 | const validate = IntegrationSchema.getSchema('#' + _class); 5 | if (!validate) { 6 | return undefined; 7 | } 8 | 9 | return validate.schema as IntegrationEntitySchema; 10 | } 11 | -------------------------------------------------------------------------------- /src/globalEntities.ts: -------------------------------------------------------------------------------- 1 | export const EVERYONE = { 2 | _class: ['UserGroup', 'Everyone'], 3 | _type: 'everyone', 4 | _key: 'global:everyone', 5 | principal: '*', 6 | public: true, 7 | displayName: 'Everyone (Public Global)', 8 | }; 9 | 10 | export const INTERNET = { 11 | _class: ['Internet', 'Network'], 12 | _type: 'internet', 13 | _key: 'global:internet', 14 | CIDR: '0.0.0.0/0', 15 | CIDRv6: '::/0', 16 | public: true, 17 | displayName: 'Internet', 18 | }; 19 | -------------------------------------------------------------------------------- /src/index.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { IntegrationSchema } from './index'; 4 | 5 | function getMockDataStoreEntity(_class: string | string[]) { 6 | return { 7 | _type: 'some-type-of-thing', 8 | _class, 9 | _key: 'some-key-unique', 10 | name: 'Name of Thing', 11 | displayName: 'Name of Thing', 12 | classification: 'not an enum', 13 | encrypted: true, 14 | }; 15 | } 16 | 17 | describe('GraphObject', () => { 18 | const entity = { 19 | _type: 'some-type-of-thing', 20 | _class: ['GraphObject'], 21 | _key: 'some-key-unique', 22 | }; 23 | 24 | const validate = IntegrationSchema.getSchema('#GraphObject')!; 25 | 26 | test('validates complete entity', () => { 27 | expect(validate(entity)).toBe(true); 28 | }); 29 | }); 30 | 31 | describe('Entity', () => { 32 | const entity = { 33 | _type: 'some-type-of-thing', 34 | _class: ['Entity'], 35 | _key: 'some-key-unique', 36 | name: 'Name of Thing', 37 | displayName: 'Name of Thing', 38 | }; 39 | 40 | const validate = IntegrationSchema.getSchema('#Entity')!; 41 | 42 | test('validates complete entity', () => { 43 | expect(validate(entity)).toBe(true); 44 | }); 45 | }); 46 | 47 | ['DataStore', 'Disk'].forEach((_class) => { 48 | describe(_class, () => { 49 | const validate = IntegrationSchema.getSchema(`#${_class}`)!; 50 | 51 | test('validates complete entity', () => { 52 | expect(validate(getMockDataStoreEntity(_class))).toBe(true); 53 | }); 54 | 55 | test('classification disallows undefined value', () => { 56 | validate({ 57 | ...getMockDataStoreEntity(_class), 58 | classification: undefined, 59 | }); 60 | expect(validate.errors![0]).toMatchObject({ 61 | message: expect.stringContaining('classification'), 62 | }); 63 | }); 64 | 65 | test('classification allows null value', () => { 66 | expect( 67 | validate({ 68 | ...getMockDataStoreEntity(_class), 69 | classification: null, 70 | }), 71 | ).toBe(true); 72 | }); 73 | 74 | test('encrypted disallows undefined value', () => { 75 | validate({ 76 | ...getMockDataStoreEntity(_class), 77 | encrypted: undefined, 78 | }); 79 | expect(validate.errors![0]).toMatchObject({ 80 | message: expect.stringContaining('encrypted'), 81 | }); 82 | }); 83 | 84 | test('encrypted allows null value', () => { 85 | expect( 86 | validate({ 87 | ...getMockDataStoreEntity(_class), 88 | encrypted: null, 89 | }), 90 | ).toBe(true); 91 | }); 92 | }); 93 | }); 94 | 95 | describe('DataStore & Disk', () => { 96 | test('should validate entity that has both DataStore and Disk classes using DataStore schema', () => { 97 | const validate = IntegrationSchema.getSchema('#DataStore')!; 98 | expect(validate(getMockDataStoreEntity(['DataStore', 'Disk']))).toBe(true); 99 | }); 100 | 101 | test('should validate entity that has both DataStore and Disk classes using Disk schema', () => { 102 | const validate = IntegrationSchema.getSchema('#Disk')!; 103 | expect(validate(getMockDataStoreEntity(['DataStore', 'Disk']))).toBe(true); 104 | }); 105 | }); 106 | 107 | describe('Control', () => { 108 | test('should allow "function" to be an array', () => { 109 | const validate = IntegrationSchema.getSchema('#Control')!; 110 | 111 | expect( 112 | validate({ 113 | _type: 'some-type-of-thing', 114 | _class: 'Control', 115 | _key: 'some-key-unique', 116 | name: 'Name of Thing', 117 | displayName: 'Name of Thing', 118 | function: ['appsec', 'bug-bounty', 'pen-test'], 119 | }), 120 | ).toBe(true); 121 | }); 122 | 123 | test('should allow "function" to be a string', () => { 124 | const validate = IntegrationSchema.getSchema('#Control')!; 125 | 126 | expect( 127 | validate({ 128 | _type: 'some-type-of-thing', 129 | _class: 'Control', 130 | _key: 'some-key-unique', 131 | name: 'Name of Thing', 132 | displayName: 'Name of Thing', 133 | function: 'appsec', 134 | }), 135 | ).toBe(true); 136 | }); 137 | 138 | test('should throw if invalid string value assigned to "function"', () => { 139 | const validate = IntegrationSchema.getSchema('#Control')!; 140 | 141 | expect( 142 | validate({ 143 | _type: 'some-type-of-thing', 144 | _class: 'Control', 145 | _key: 'some-key-unique', 146 | name: 'Name of Thing', 147 | displayName: 'Name of Thing', 148 | function: 'INVALID_FUNCTION_VAL', 149 | }), 150 | ).toBe(false); 151 | }); 152 | 153 | test('should throw if invalid array value assigned to "function"', () => { 154 | const validate = IntegrationSchema.getSchema('#Control')!; 155 | 156 | expect( 157 | validate({ 158 | _type: 'some-type-of-thing', 159 | _class: 'Control', 160 | _key: 'some-key-unique', 161 | name: 'Name of Thing', 162 | displayName: 'Name of Thing', 163 | function: ['bug-bounty', 'INVALID_FUNCTION_VAL', 'appsec'], 164 | }), 165 | ).toBe(false); 166 | }); 167 | }); 168 | 169 | describe('Problem', () => { 170 | test('should require the same properties as a Finding entity', () => { 171 | const validateFinding = IntegrationSchema.getSchema('#Finding')!; 172 | const validateProblem = IntegrationSchema.getSchema('#Problem')!; 173 | const entity = { 174 | _type: 'some-type-of-thing', 175 | _class: 'Control', 176 | _key: 'some-key-unique', 177 | name: 'Name of Thing', 178 | displayName: 'Name of Thing', 179 | category: 'test', 180 | severity: 'high', 181 | numericSeverity: 10, 182 | open: false, 183 | }; 184 | 185 | expect(validateFinding(entity)).toBe(true); 186 | expect(validateProblem(entity)).toBe(true); 187 | 188 | const { 189 | category, 190 | severity, 191 | numericSeverity, 192 | open, 193 | ...entityWithoutFindingProperties 194 | } = entity; 195 | 196 | expect(validateFinding(entityWithoutFindingProperties)).toBe(false); 197 | expect(validateProblem(entityWithoutFindingProperties)).toBe(false); 198 | }); 199 | }); 200 | 201 | describe('Question', () => { 202 | test('should require queries to be provided', () => { 203 | const validateQuestion = IntegrationSchema.getSchema('#Question')!; 204 | const entity = { 205 | _type: 'some-type-of-question', 206 | _class: 'Question', 207 | _key: 'some-key-unique', 208 | name: 'Name of Question', 209 | displayName: 'Name of Question', 210 | }; 211 | 212 | expect(validateQuestion(entity)).toBe(false); 213 | expect( 214 | validateQuestion({ 215 | ...entity, 216 | queries: [], 217 | }), 218 | ).toBe(true); 219 | }); 220 | }); 221 | 222 | describe('Secret', () => { 223 | test('simple entity validation to ensure Secret schema exists', () => { 224 | const validateSecret = IntegrationSchema.getSchema('#Secret')!; 225 | const entity = { 226 | _type: 'some-type-of-secret', 227 | _class: 'Secret', 228 | _key: 'some-key-unique', 229 | name: 'Name of Secret', 230 | displayName: 'Name of Secret', 231 | }; 232 | 233 | expect(validateSecret(entity)).toBe(true); 234 | }); 235 | }); 236 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { registerSchemas } from './registerSchemas'; 2 | export { registerFormats } from './registerFormats'; 3 | 4 | export { EVERYONE, INTERNET } from './globalEntities'; 5 | 6 | export { RelationshipClass } from './RelationshipClass'; 7 | export * from './relationships'; 8 | 9 | export type IntegrationEntitySchema = { 10 | $ref?: string; 11 | allOf?: IntegrationEntitySchema[]; 12 | properties?: { 13 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 14 | [propertyName: string]: any; 15 | }; 16 | required?: string[]; 17 | }; 18 | 19 | export { IntegrationSchema } from './IntegrationSchema'; 20 | 21 | import * as integrationSchemas from './IntegrationSchema'; 22 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 23 | const { IntegrationSchema, ...allSchemas } = integrationSchemas; 24 | export const entitySchemas = allSchemas; 25 | export type EntityClass = keyof typeof entitySchemas; 26 | export const entityClasses = Object.keys(entitySchemas) as EntityClass[]; 27 | 28 | export { validateEntityWithSchema } from './validateEntityWithSchema'; 29 | export { getSchema } from './getSchema'; 30 | -------------------------------------------------------------------------------- /src/registerFormats.ts: -------------------------------------------------------------------------------- 1 | import addFormats from 'ajv-formats'; 2 | import Ajv from 'ajv'; 3 | 4 | const ipv4 = addFormats.get('ipv4') as RegExp; 5 | const ipv6 = addFormats.get('ipv6') as RegExp; 6 | const ipv4CidrRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(3[0-2]|[12]?[0-9])$/; 7 | const ipv6CidrRegex = /^([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^([0-9a-fA-F]{1,4}:){1,7}:\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^::\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}$/; 8 | 9 | const isValidIpFormat = { 10 | name: 'ip', 11 | fn: (x) => ipv4.test(x) || ipv6.test(x), 12 | }; 13 | 14 | const isValidIpCidrFormat = { 15 | name: 'ipCidr', 16 | fn: (x) => ipv4CidrRegex.test(x) || ipv6CidrRegex.test(x), 17 | }; 18 | 19 | export function registerFormats(ajvInstance: Ajv): void { 20 | ajvInstance.addFormat(isValidIpFormat.name, isValidIpFormat.fn); 21 | ajvInstance.addFormat(isValidIpCidrFormat.name, isValidIpCidrFormat.fn); 22 | 23 | addFormats(ajvInstance); 24 | } 25 | -------------------------------------------------------------------------------- /src/registerSchemas.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS AUTOMATICALLY GENERATED! 2 | // using the script tools/generate-register-schemas-function.sh 3 | 4 | import Ajv from 'ajv'; 5 | 6 | // Dynamically imported schemas 7 | import AccessKeyJson from './schemas/AccessKey.json'; 8 | import AccessPolicyJson from './schemas/AccessPolicy.json'; 9 | import AccessRoleJson from './schemas/AccessRole.json'; 10 | import AccountJson from './schemas/Account.json'; 11 | import AlertJson from './schemas/Alert.json'; 12 | import ApplicationJson from './schemas/Application.json'; 13 | import ApplicationEndpointJson from './schemas/ApplicationEndpoint.json'; 14 | import AssessmentJson from './schemas/Assessment.json'; 15 | import AttackerJson from './schemas/Attacker.json'; 16 | import BackupJson from './schemas/Backup.json'; 17 | import CertificateJson from './schemas/Certificate.json'; 18 | import ChannelJson from './schemas/Channel.json'; 19 | import ClusterJson from './schemas/Cluster.json'; 20 | import CodeCommitJson from './schemas/CodeCommit.json'; 21 | import CodeDeployJson from './schemas/CodeDeploy.json'; 22 | import CodeModuleJson from './schemas/CodeModule.json'; 23 | import CodeRepoJson from './schemas/CodeRepo.json'; 24 | import CodeReviewJson from './schemas/CodeReview.json'; 25 | import ConfigurationJson from './schemas/Configuration.json'; 26 | import ContainerJson from './schemas/Container.json'; 27 | import ControlJson from './schemas/Control.json'; 28 | import ControlPolicyJson from './schemas/ControlPolicy.json'; 29 | import CryptoKeyJson from './schemas/CryptoKey.json'; 30 | import DataCollectionJson from './schemas/DataCollection.json'; 31 | import DataObjectJson from './schemas/DataObject.json'; 32 | import DataStoreJson from './schemas/DataStore.json'; 33 | import DatabaseJson from './schemas/Database.json'; 34 | import DeploymentJson from './schemas/Deployment.json'; 35 | import DeviceJson from './schemas/Device.json'; 36 | import DirectoryJson from './schemas/Directory.json'; 37 | import DiskJson from './schemas/Disk.json'; 38 | import DocumentJson from './schemas/Document.json'; 39 | import DomainJson from './schemas/Domain.json'; 40 | import DomainRecordJson from './schemas/DomainRecord.json'; 41 | import DomainZoneJson from './schemas/DomainZone.json'; 42 | import EntityJson from './schemas/Entity.json'; 43 | import FindingJson from './schemas/Finding.json'; 44 | import FirewallJson from './schemas/Firewall.json'; 45 | import FrameworkJson from './schemas/Framework.json'; 46 | import FunctionJson from './schemas/Function.json'; 47 | import GatewayJson from './schemas/Gateway.json'; 48 | import GraphObjectJson from './schemas/GraphObject.json'; 49 | import GroupJson from './schemas/Group.json'; 50 | import HostJson from './schemas/Host.json'; 51 | import HostAgentJson from './schemas/HostAgent.json'; 52 | import ImageJson from './schemas/Image.json'; 53 | import IncidentJson from './schemas/Incident.json'; 54 | import InternetJson from './schemas/Internet.json'; 55 | import IpAddressJson from './schemas/IpAddress.json'; 56 | import IssueJson from './schemas/Issue.json'; 57 | import KeyJson from './schemas/Key.json'; 58 | import LogsJson from './schemas/Logs.json'; 59 | import ModelJson from './schemas/Model.json'; 60 | import ModuleJson from './schemas/Module.json'; 61 | import NetworkJson from './schemas/Network.json'; 62 | import NetworkEndpointJson from './schemas/NetworkEndpoint.json'; 63 | import NetworkInterfaceJson from './schemas/NetworkInterface.json'; 64 | import OrganizationJson from './schemas/Organization.json'; 65 | import PRJson from './schemas/PR.json'; 66 | import PasswordPolicyJson from './schemas/PasswordPolicy.json'; 67 | import PersonJson from './schemas/Person.json'; 68 | import PolicyJson from './schemas/Policy.json'; 69 | import ProblemJson from './schemas/Problem.json'; 70 | import ProcedureJson from './schemas/Procedure.json'; 71 | import ProcessJson from './schemas/Process.json'; 72 | import ProductJson from './schemas/Product.json'; 73 | import ProgramJson from './schemas/Program.json'; 74 | import ProjectJson from './schemas/Project.json'; 75 | import QuestionJson from './schemas/Question.json'; 76 | import QueueJson from './schemas/Queue.json'; 77 | import RecordJson from './schemas/Record.json'; 78 | import RecordEntityJson from './schemas/RecordEntity.json'; 79 | import RepositoryJson from './schemas/Repository.json'; 80 | import RequirementJson from './schemas/Requirement.json'; 81 | import ResourceJson from './schemas/Resource.json'; 82 | import ReviewJson from './schemas/Review.json'; 83 | import RiskJson from './schemas/Risk.json'; 84 | import RootJson from './schemas/Root.json'; 85 | import RuleJson from './schemas/Rule.json'; 86 | import RulesetJson from './schemas/Ruleset.json'; 87 | import ScannerJson from './schemas/Scanner.json'; 88 | import SecretJson from './schemas/Secret.json'; 89 | import SectionJson from './schemas/Section.json'; 90 | import ServiceJson from './schemas/Service.json'; 91 | import SiteJson from './schemas/Site.json'; 92 | import StandardJson from './schemas/Standard.json'; 93 | import SubscriptionJson from './schemas/Subscription.json'; 94 | import TaskJson from './schemas/Task.json'; 95 | import TeamJson from './schemas/Team.json'; 96 | import ThreatIntelJson from './schemas/ThreatIntel.json'; 97 | import TrainingJson from './schemas/Training.json'; 98 | import UserJson from './schemas/User.json'; 99 | import UserGroupJson from './schemas/UserGroup.json'; 100 | import VaultJson from './schemas/Vault.json'; 101 | import VendorJson from './schemas/Vendor.json'; 102 | import VulnerabilityJson from './schemas/Vulnerability.json'; 103 | import WeaknessJson from './schemas/Weakness.json'; 104 | import WorkflowJson from './schemas/Workflow.json'; 105 | import WorkloadJson from './schemas/Workload.json'; 106 | 107 | export function registerSchemas(ajvInstance: Ajv): void { 108 | ajvInstance.addSchema(AccessKeyJson); 109 | ajvInstance.addSchema(AccessPolicyJson); 110 | ajvInstance.addSchema(AccessRoleJson); 111 | ajvInstance.addSchema(AccountJson); 112 | ajvInstance.addSchema(AlertJson); 113 | ajvInstance.addSchema(ApplicationJson); 114 | ajvInstance.addSchema(ApplicationEndpointJson); 115 | ajvInstance.addSchema(AssessmentJson); 116 | ajvInstance.addSchema(AttackerJson); 117 | ajvInstance.addSchema(BackupJson); 118 | ajvInstance.addSchema(CertificateJson); 119 | ajvInstance.addSchema(ChannelJson); 120 | ajvInstance.addSchema(ClusterJson); 121 | ajvInstance.addSchema(CodeCommitJson); 122 | ajvInstance.addSchema(CodeDeployJson); 123 | ajvInstance.addSchema(CodeModuleJson); 124 | ajvInstance.addSchema(CodeRepoJson); 125 | ajvInstance.addSchema(CodeReviewJson); 126 | ajvInstance.addSchema(ConfigurationJson); 127 | ajvInstance.addSchema(ContainerJson); 128 | ajvInstance.addSchema(ControlJson); 129 | ajvInstance.addSchema(ControlPolicyJson); 130 | ajvInstance.addSchema(CryptoKeyJson); 131 | ajvInstance.addSchema(DataCollectionJson); 132 | ajvInstance.addSchema(DataObjectJson); 133 | ajvInstance.addSchema(DataStoreJson); 134 | ajvInstance.addSchema(DatabaseJson); 135 | ajvInstance.addSchema(DeploymentJson); 136 | ajvInstance.addSchema(DeviceJson); 137 | ajvInstance.addSchema(DirectoryJson); 138 | ajvInstance.addSchema(DiskJson); 139 | ajvInstance.addSchema(DocumentJson); 140 | ajvInstance.addSchema(DomainJson); 141 | ajvInstance.addSchema(DomainRecordJson); 142 | ajvInstance.addSchema(DomainZoneJson); 143 | ajvInstance.addSchema(EntityJson); 144 | ajvInstance.addSchema(FindingJson); 145 | ajvInstance.addSchema(FirewallJson); 146 | ajvInstance.addSchema(FrameworkJson); 147 | ajvInstance.addSchema(FunctionJson); 148 | ajvInstance.addSchema(GatewayJson); 149 | ajvInstance.addSchema(GraphObjectJson); 150 | ajvInstance.addSchema(GroupJson); 151 | ajvInstance.addSchema(HostJson); 152 | ajvInstance.addSchema(HostAgentJson); 153 | ajvInstance.addSchema(ImageJson); 154 | ajvInstance.addSchema(IncidentJson); 155 | ajvInstance.addSchema(InternetJson); 156 | ajvInstance.addSchema(IpAddressJson); 157 | ajvInstance.addSchema(IssueJson); 158 | ajvInstance.addSchema(KeyJson); 159 | ajvInstance.addSchema(LogsJson); 160 | ajvInstance.addSchema(ModelJson); 161 | ajvInstance.addSchema(ModuleJson); 162 | ajvInstance.addSchema(NetworkJson); 163 | ajvInstance.addSchema(NetworkEndpointJson); 164 | ajvInstance.addSchema(NetworkInterfaceJson); 165 | ajvInstance.addSchema(OrganizationJson); 166 | ajvInstance.addSchema(PRJson); 167 | ajvInstance.addSchema(PasswordPolicyJson); 168 | ajvInstance.addSchema(PersonJson); 169 | ajvInstance.addSchema(PolicyJson); 170 | ajvInstance.addSchema(ProblemJson); 171 | ajvInstance.addSchema(ProcedureJson); 172 | ajvInstance.addSchema(ProcessJson); 173 | ajvInstance.addSchema(ProductJson); 174 | ajvInstance.addSchema(ProgramJson); 175 | ajvInstance.addSchema(ProjectJson); 176 | ajvInstance.addSchema(QuestionJson); 177 | ajvInstance.addSchema(QueueJson); 178 | ajvInstance.addSchema(RecordJson); 179 | ajvInstance.addSchema(RecordEntityJson); 180 | ajvInstance.addSchema(RepositoryJson); 181 | ajvInstance.addSchema(RequirementJson); 182 | ajvInstance.addSchema(ResourceJson); 183 | ajvInstance.addSchema(ReviewJson); 184 | ajvInstance.addSchema(RiskJson); 185 | ajvInstance.addSchema(RootJson); 186 | ajvInstance.addSchema(RuleJson); 187 | ajvInstance.addSchema(RulesetJson); 188 | ajvInstance.addSchema(ScannerJson); 189 | ajvInstance.addSchema(SecretJson); 190 | ajvInstance.addSchema(SectionJson); 191 | ajvInstance.addSchema(ServiceJson); 192 | ajvInstance.addSchema(SiteJson); 193 | ajvInstance.addSchema(StandardJson); 194 | ajvInstance.addSchema(SubscriptionJson); 195 | ajvInstance.addSchema(TaskJson); 196 | ajvInstance.addSchema(TeamJson); 197 | ajvInstance.addSchema(ThreatIntelJson); 198 | ajvInstance.addSchema(TrainingJson); 199 | ajvInstance.addSchema(UserJson); 200 | ajvInstance.addSchema(UserGroupJson); 201 | ajvInstance.addSchema(VaultJson); 202 | ajvInstance.addSchema(VendorJson); 203 | ajvInstance.addSchema(VulnerabilityJson); 204 | ajvInstance.addSchema(WeaknessJson); 205 | ajvInstance.addSchema(WorkflowJson); 206 | ajvInstance.addSchema(WorkloadJson); 207 | } 208 | -------------------------------------------------------------------------------- /src/relationships.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-redundant-type-constituents */ 2 | export interface FirewallRuleProperties { 3 | /** 4 | * The rule's position in the list, indicating priority order of the rule. 5 | * Aliased as `priority`. 6 | */ 7 | ruleNumber?: number; 8 | 9 | /** 10 | * The rule's position in the list, indicating priority order of the rule. 11 | * Aliased as `ruleNumber`. 12 | */ 13 | priority?: number; 14 | 15 | /** 16 | * The internet protocol allowed by the rule, '*' indicating there is no 17 | * restriction on the protocol. 18 | * Aliased as `protocol`. 19 | */ 20 | ipProtocol: '*' | string; 21 | 22 | /** 23 | * The internet protocol allowed by the rule, '*' indicating there is no 24 | * restriction on the protocol. 25 | * Aliased as `ipProtocol`. 26 | */ 27 | protocol: '*' | string; 28 | 29 | /** 30 | * Packets having a src port matching the fromPort are allowed. 31 | */ 32 | fromPort?: number; 33 | 34 | /** 35 | * Packets having a dst port matching the toPort are allowed. 36 | */ 37 | toPort?: number; 38 | 39 | /** 40 | * 'fromPort-toPort' or '*' (any) 41 | */ 42 | portRange?: '*' | string; 43 | 44 | /** 45 | * Traffic is allowed to flow out of instances associated with the owning 46 | * entity. 47 | * Aliased as `outbound`. 48 | */ 49 | egress: boolean; 50 | 51 | /** 52 | * Traffic is allowed to flow out of instances associated with the owning 53 | * entity. 54 | * Aliased as `egress`. 55 | */ 56 | outbound: boolean; 57 | 58 | /** 59 | * Traffic is allowed to flow into instances associated with the owning 60 | * entity. 61 | * Aliased as `inbound`. 62 | */ 63 | ingress: boolean; 64 | 65 | /** 66 | * Traffic is allowed to flow into instances associated with the owning 67 | * entity. 68 | * Aliased as `ingress`. 69 | */ 70 | inbound: boolean; 71 | } 72 | -------------------------------------------------------------------------------- /src/schemas/AccessKey.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#AccessKey", 4 | "description": "A key used to grant access, such as ssh-key, access-key, api-key/token, mfa-token/device, etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Key" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/AccessPolicy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#AccessPolicy", 4 | "description": "A policy for access control assigned to a Host, Role, User, UserGroup, or Service.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "admin": { 13 | "description": "Indicates if the policy grants administrative privilege.", 14 | "type": "boolean" 15 | }, 16 | "rules": { 17 | "description": "Rules of this policy. Each rule is written 'as-code' that can be operationalized with a control provider or within JupiterOne's rules engine.", 18 | "type": "array", 19 | "items": { 20 | "type": "string" 21 | } 22 | }, 23 | "content": { 24 | "description": "Content of a policy contains the raw policy rules, if applicable. For example, the JSON text of an AWS IAM Policy. This is stored in raw data.", 25 | "type": "string" 26 | } 27 | }, 28 | "required": [], 29 | "excludes": ["status"] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/schemas/AccessRole.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#AccessRole", 4 | "description": "An access control role mapped to a Principal (e.g. user, group, or service).", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "superAdmin": { 13 | "description": "Is the role an administrator role?", 14 | "type": "boolean" 15 | }, 16 | "systemRole": { 17 | "description": "Is this a system role?", 18 | "type": "boolean" 19 | }, 20 | "privilegeServiceIds": { 21 | "description": "The role's privilege service IDs", 22 | "type": "array", 23 | "items": { 24 | "type": "string" 25 | } 26 | }, 27 | "privilegeNames": { 28 | "description": "The role's privilege names", 29 | "type": "array", 30 | "items": { 31 | "type": "string" 32 | } 33 | } 34 | }, 35 | "required": [] 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /src/schemas/Account.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Account", 4 | "description": "An organizational account for a service or a set of services (e.g. AWS, Okta, Bitbucket Team, Google G-Suite account, Apple Developer Account). Each Account should be connected to a Service.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "accessURL": { 13 | "description": "The main URL to access this account, e.g. https://jupiterone.okta.com", 14 | "type": "string", 15 | "format": "uri" 16 | }, 17 | "mfaEnabled": { 18 | "description": "Specifies whether multi-factor authentication (MFA) is enabled/required for users of this account.", 19 | "type": "boolean" 20 | } 21 | }, 22 | "required": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/schemas/Alert.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Alert", 4 | "description": "A notice of any unusual or dangerous circumstance that is sent to responsible parties for the purpose of triggering action.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/schemas/Application.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Application", 4 | "description": "A software product or application.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "COTS": { 13 | "description": "Indicates if this is a Commercial Off-The-Shelf software application. Custom in-house developed application should have this set to false.", 14 | "type": "boolean", 15 | "default": false 16 | }, 17 | "FOSS": { 18 | "description": "Indicates if this is a Free or Open-Source software application or library. Custom in-house developed application should have this set to false.", 19 | "type": "boolean", 20 | "default": false 21 | }, 22 | "SaaS": { 23 | "description": "Indicates if this is a Software-as-a-Service product.", 24 | "type": "boolean", 25 | "default": false 26 | }, 27 | "external": { 28 | "description": "Indicates if this is an externally acquired software application. Custom in-house developed application should have this set to false.", 29 | "type": "boolean", 30 | "default": false 31 | }, 32 | "mobile": { 33 | "description": "Indicates if this is a mobile app.", 34 | "type": "boolean", 35 | "default": false 36 | }, 37 | "license": { 38 | "description": "Stores the type of license", 39 | "type": "string", 40 | "examples": [ 41 | "BSD", 42 | "CC-BY-3.0", 43 | "CC-BY-4.0", 44 | "GPL-2.0", 45 | "GPL-3.0", 46 | "LGPL-2.0", 47 | "LGPL-2.1", 48 | "LGPL-3.0", 49 | "MIT", 50 | "EULA", 51 | "Proprietary", 52 | "UNLICENSED", 53 | "other" 54 | ] 55 | }, 56 | "licenseURL": { 57 | "description": "The URL to the full license", 58 | "type": "string", 59 | "format": "uri" 60 | }, 61 | "productionURL": { 62 | "description": "The Production URL", 63 | "type": "string", 64 | "format": "uri" 65 | }, 66 | "stagingURL": { 67 | "description": "The Non-Production / Staging URL", 68 | "type": "string", 69 | "format": "uri" 70 | }, 71 | "devURL": { 72 | "description": "The Development URL", 73 | "type": "string", 74 | "format": "uri" 75 | }, 76 | "testURL": { 77 | "description": "The Test URL", 78 | "type": "string", 79 | "format": "uri" 80 | }, 81 | "alternateURLs": { 82 | "description": "The additional URLs related to this application.", 83 | "type": "array", 84 | "items": { 85 | "type": "string" 86 | } 87 | } 88 | }, 89 | "required": [] 90 | } 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /src/schemas/ApplicationEndpoint.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#ApplicationEndpoint", 4 | "description": "An application endpoint is a program interface that either initiates or receives a request, such as an API.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "address": { 13 | "description": "The endpoint address (e.g. an URI/URL, hostname)", 14 | "type": "string" 15 | } 16 | }, 17 | "required": ["address"] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Assessment.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Assessment", 4 | "description": "An object to represent an assessment, including both compliance assessment such as a HIPAA Risk Assessment or a technical assessment such as a Penetration Testing. Each assessment should have findings (e.g. Vulnerability or Risk) associated.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of the Assessment.", 14 | "type": "string", 15 | "examples": [ 16 | "Risk Assessment", 17 | "Readiness Assessment", 18 | "Gap Assessment", 19 | "Validation Assessment", 20 | "Compliance Assessment", 21 | "Self Assessment", 22 | "Certification", 23 | "Audit", 24 | "Technical Review", 25 | "Operational Review", 26 | "Penetration Testing", 27 | "Vulnerability Scan", 28 | "Other" 29 | ] 30 | }, 31 | "summary": { 32 | "description": "The summary description of the Assessment.", 33 | "type": "string" 34 | }, 35 | "internal": { 36 | "description": "Indicates if this is an internal or external assessment/audit. Defaults to true.", 37 | "type": "boolean", 38 | "default": true 39 | }, 40 | "startedOn": { 41 | "description": "The timestamp (in milliseconds since epoch) when the Assessment was started.", 42 | "type": "number", 43 | "format": "date-time" 44 | }, 45 | "completedOn": { 46 | "description": "The timestamp (in milliseconds since epoch) when the Assessment was completed.", 47 | "type": "number", 48 | "format": "date-time" 49 | }, 50 | "reportURL": { 51 | "description": "Link to the assessment report, if available.", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "assessor": { 56 | "description": "Email or name or ID of the assessor", 57 | "type": "string" 58 | }, 59 | "assessors": { 60 | "description": "List of email or name or ID of the assessors", 61 | "type": "array", 62 | "items": { 63 | "type": "string" 64 | } 65 | } 66 | }, 67 | "required": ["category", "summary", "internal"] 68 | } 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /src/schemas/Attacker.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Attacker", 4 | "description": "An attacker or threat actor.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {} 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/schemas/Backup.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Backup", 4 | "description": "A specific repository or data store containing backup data.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "encrypted": { 13 | "description": "Indicates whether the backup data is encrypted.", 14 | "type": "boolean" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Certificate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Certificate", 4 | "description": "A digital Certificate such as an SSL or S/MIME certificate.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Channel.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Channel", 4 | "description": "A communication channel, such as a Slack channel or AWS SNS topic.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "encrypted": { 13 | "description": "Indicates whether the communication channel is encrypted.", 14 | "type": "boolean" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Cluster.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Cluster", 4 | "description": "A cluster of compute or database resources/workloads.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/CodeCommit.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#CodeCommit", 4 | "description": "A code commit to a repo. The commit id is captured in the _id property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "branch": { 13 | "description": "The branch the code was committed to.", 14 | "type": "string" 15 | }, 16 | "message": { 17 | "description": "The commit message.", 18 | "type": "string" 19 | }, 20 | "merge": { 21 | "description": "Indicates if this commit is a merge, defaults to false.", 22 | "type": "boolean", 23 | "default": false 24 | }, 25 | "versionBump": { 26 | "description": "Indicates if this commit is a versionBump, defaults to false.", 27 | "type": "boolean", 28 | "default": false 29 | } 30 | }, 31 | "required": ["branch", "message", "merge", "versionBump"] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /src/schemas/CodeDeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#CodeDeploy", 4 | "description": "A code deploy job.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "jobName": { 13 | "description": "Build/deploy job name.", 14 | "type": "string" 15 | }, 16 | "jobNumber": { 17 | "description": "Build/deploy job number.", 18 | "type": "integer" 19 | }, 20 | "summary": { 21 | "description": "Descriptive text of the job.", 22 | "type": "string" 23 | }, 24 | "action": { 25 | "description": "Deploy action (e.g. plan, apply, destroy, rollback).", 26 | "type": "string" 27 | }, 28 | "target": { 29 | "description": "Name of the target system or environment.", 30 | "type": "string" 31 | }, 32 | "production": { 33 | "description": "Indicates if this is a production deploy, defaults to true.", 34 | "type": "boolean", 35 | "default": true 36 | } 37 | }, 38 | "required": [] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /src/schemas/CodeModule.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#CodeModule", 4 | "description": "A software module. Such as an npm_module or java_library.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "public": { 13 | "description": "Indicates if this is a public module.", 14 | "type": "boolean" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/CodeRepo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#CodeRepo", 4 | "description": "A source code repository. A CodeRepo is also a DataRepository therefore should carry all the required properties of DataRepository.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "application": { 13 | "description": "The application that this repo is part of.", 14 | "type": "string" 15 | }, 16 | "project": { 17 | "description": "The project that this repo belongs to.", 18 | "type": "string" 19 | }, 20 | "public": { 21 | "description": "Indicates if this is a public repo.", 22 | "type": "boolean" 23 | } 24 | }, 25 | "required": [] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/CodeReview.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#CodeReview", 4 | "description": "A code review record.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "title": { 13 | "description": "The title text of the review.", 14 | "type": "string" 15 | }, 16 | "summary": { 17 | "description": "The summary text of the review.", 18 | "type": "string" 19 | }, 20 | "state": { 21 | "description": "The state of the review.", 22 | "type": "string" 23 | } 24 | }, 25 | "required": ["title"] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/Configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Configuration", 4 | "description": "A Configuration contains definitions that describe a resource such as a Task, Deployment or Workload. For example, an `aws_ecs_task_definition` is a `Configuration`.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Container.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Container", 4 | "description": "A standard unit of software that packages up code and all its dependencies and configurations.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "image": { 13 | "description": "The container image that the container is built from", 14 | "type": "string" 15 | }, 16 | "dockerVersion": { 17 | "description": "The version of the Docker Engine", 18 | "type": "string" 19 | } 20 | }, 21 | "required": [] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/Control.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Control", 4 | "description": "A security or IT Control. A control can be implemented by a vendor/service, a person/team, a program/process, an automation code/script/configuration, or a system/host/device. Therefore, this is most likely an additional Class applied to a Service (e.g. Okta SSO), a Device (e.g. a physical firewall), or a HostAgent (e.g. Carbon Black CbDefense Agent). Controls are mapped to security policy procedures and compliance standards/requirements.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "function": { 13 | "description": "The function of the control. It can be a string or string array. Value of each item should be either all lower case or, in the case of an acronym, all upper case.", 14 | "oneOf": [ 15 | { 16 | "type": "string", 17 | "enum": [ 18 | "directory", 19 | "inventory", 20 | "access-control", 21 | "access-review", 22 | "compliance", 23 | "monitoring", 24 | "logging", 25 | "auditing", 26 | "scheduling", 27 | "configuration-audit", 28 | "key-management", 29 | "password-management", 30 | "secret-management", 31 | "config-management", 32 | "device-management", 33 | "patch-management", 34 | "endpoint-management", 35 | "endpoint-protection", 36 | "data-protection", 37 | "data-encryption", 38 | "pen-test", 39 | "bug-bounty", 40 | "appsec", 41 | "application-security", 42 | "container-security", 43 | "package-registry", 44 | "infrastructure", 45 | "ticketing", 46 | "training", 47 | "firewall", 48 | "networking", 49 | "wifi", 50 | "physical-access", 51 | "video-surveillance", 52 | "DNS", 53 | "VPN", 54 | "IAM", 55 | "SSO", 56 | "MFA", 57 | "PAM", 58 | "DLP", 59 | "SAST", 60 | "DAST", 61 | "IAST", 62 | "MAST", 63 | "RASP", 64 | "SCA", 65 | "SCM", 66 | "VAS", 67 | "VMS", 68 | "AV", 69 | "CA", 70 | "PKI", 71 | "IDS", 72 | "IPS", 73 | "HIDS", 74 | "NIDS", 75 | "WAF", 76 | "MDM", 77 | "EMM", 78 | "EDR", 79 | "EPP", 80 | "SIEM", 81 | "ITAM", 82 | "ITSM", 83 | "SSH", 84 | "SFTP", 85 | "VRM" 86 | ] 87 | }, 88 | { 89 | "type": "array", 90 | "uniqueItems": true, 91 | "items": { 92 | "type": "string", 93 | "enum": [ 94 | "directory", 95 | "inventory", 96 | "access-control", 97 | "access-review", 98 | "compliance", 99 | "monitoring", 100 | "logging", 101 | "auditing", 102 | "scheduling", 103 | "configuration-audit", 104 | "key-management", 105 | "password-management", 106 | "secret-management", 107 | "config-management", 108 | "device-management", 109 | "patch-management", 110 | "endpoint-management", 111 | "endpoint-protection", 112 | "data-protection", 113 | "data-encryption", 114 | "pen-test", 115 | "bug-bounty", 116 | "appsec", 117 | "application-security", 118 | "container-security", 119 | "package-registry", 120 | "infrastructure", 121 | "ticketing", 122 | "training", 123 | "firewall", 124 | "networking", 125 | "wifi", 126 | "physical-access", 127 | "video-surveillance", 128 | "DNS", 129 | "VPN", 130 | "IAM", 131 | "SSO", 132 | "MFA", 133 | "PAM", 134 | "DLP", 135 | "SAST", 136 | "DAST", 137 | "IAST", 138 | "MAST", 139 | "RASP", 140 | "SCA", 141 | "SCM", 142 | "VAS", 143 | "VMS", 144 | "AV", 145 | "CA", 146 | "PKI", 147 | "IDS", 148 | "IPS", 149 | "HIDS", 150 | "NIDS", 151 | "WAF", 152 | "MDM", 153 | "EMM", 154 | "EDR", 155 | "EPP", 156 | "SIEM", 157 | "ITAM", 158 | "ITSM", 159 | "SSH", 160 | "SFTP", 161 | "VRM" 162 | ] 163 | } 164 | } 165 | ] 166 | } 167 | }, 168 | "required": [] 169 | } 170 | ] 171 | } 172 | -------------------------------------------------------------------------------- /src/schemas/ControlPolicy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#ControlPolicy", 4 | "description": "An technical or operational policy with rules that govern (or enforce, evaluate, monitor) a security control.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of policy.", 14 | "type": "string", 15 | "enum": ["compliance", "config", "password", "other"] 16 | }, 17 | "rules": { 18 | "description": "Rules of policy.", 19 | "type": "array", 20 | "items": { 21 | "type": "string" 22 | } 23 | }, 24 | "content": { 25 | "description": "Contents of the raw rules, if applicable.", 26 | "type": "string" 27 | } 28 | }, 29 | "required": [] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/schemas/CryptoKey.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#CryptoKey", 4 | "description": "A key used to perform cryptographic functions, such as an encryption key.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Key" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/DataCollection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#DataCollection", 4 | "description": "An individual collection of data. The collection may exist in various formats, such as a table (e.g. a MySQL table). The exact data type is described in the _type property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "PII": { 13 | "description": "Indicates if this data table contains Personally Identifiable Information", 14 | "type": "boolean" 15 | }, 16 | "PHI": { 17 | "description": "Indicates if this data table contains Protected Health Information", 18 | "type": "boolean" 19 | }, 20 | "PCI": { 21 | "description": "Indicates if this data table contains Payment Card Information", 22 | "type": "boolean" 23 | }, 24 | "encryptionRequired": { 25 | "description": "If the objects in the table need to be encrypted", 26 | "type": "boolean" 27 | }, 28 | "encrypted": { 29 | "description": "If the data in the table is encrypted", 30 | "type": "boolean" 31 | }, 32 | "public": { 33 | "description": "Indicates if the data table is open to public access", 34 | "type": "boolean" 35 | } 36 | }, 37 | "required": ["classification"] 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /src/schemas/DataObject.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#DataObject", 4 | "description": "An individual data object, such as an aws-s3-object, sharepoint-document, source-code, or a file (on disk). The exact data type is described in the _type property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "A user-provided category of the data, such as 'Source Code', 'Report', 'Patent Application', 'Business Plan', 'Customer Record', 'Genetic Data', etc.", 14 | "type": "string" 15 | }, 16 | "format": { 17 | "description": "The format of the data, such as 'document', 'raw', 'plaintext', 'binary', etc.", 18 | "type": "string" 19 | }, 20 | "location": { 21 | "description": "URI to the data, e.g. file path", 22 | "type": "string" 23 | }, 24 | "PII": { 25 | "description": "Indicates if this data object is or contains Personally Identifiable Information", 26 | "type": "boolean" 27 | }, 28 | "PHI": { 29 | "description": "Indicates if this data object is or contains Protected Health Information", 30 | "type": "boolean" 31 | }, 32 | "PCI": { 33 | "description": "Indicates if this data object is or contains Payment Card Information", 34 | "type": "boolean" 35 | }, 36 | "encryptionRequired": { 37 | "description": "If the data needs to be encrypted", 38 | "type": "boolean" 39 | }, 40 | "encrypted": { 41 | "description": "If the data is encrypted", 42 | "type": "boolean" 43 | }, 44 | "public": { 45 | "description": "Indicates if the data object is open to public access", 46 | "type": "boolean" 47 | } 48 | }, 49 | "required": ["classification"] 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /src/schemas/DataStore.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#DataStore", 4 | "description": "A virtual repository where data is stored, such as aws-s3-bucket, aws-rds-cluster, aws-dynamodb-table, bitbucket-repo, sharepoint-site, docker-registry. The exact type is described in the _type property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "location": { 13 | "description": "URI to the data store, e.g. https://docker-registry.jupiterone.com or https://jupiterone.sharepoint.com. Or a description to the physical location.", 14 | "type": "string" 15 | }, 16 | "encryptionRequired": { 17 | "description": "If the data needs to be encrypted", 18 | "type": "boolean" 19 | }, 20 | "encryptionAlgorithm": { 21 | "description": "Encryption algorithm used to encrypt the data store", 22 | "type": "string" 23 | }, 24 | "encryptionKeyRef": { 25 | "description": "Reference to the encryption key used to encrypt the data store", 26 | "type": "string" 27 | }, 28 | "encrypted": { 29 | "description": "If the data store is encrypted", 30 | "type": ["boolean", "null"] 31 | }, 32 | "public": { 33 | "description": "Indicates if the data store is open to public access", 34 | "type": "boolean" 35 | }, 36 | "hasBackup": { 37 | "description": "Indicates if the data store is data backup has been configured/enabled.", 38 | "type": "boolean" 39 | }, 40 | "retentionPeriodDays": { 41 | "description": "The number of days for which data is retained", 42 | "type": "number" 43 | } 44 | }, 45 | "required": ["classification", "encrypted"] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /src/schemas/Database.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Database", 4 | "description": "A database cluster/instance.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "location": { 11 | "description": "URI to access the database.", 12 | "type": "string" 13 | }, 14 | "encryptionRequired": { 15 | "description": "If the data needs to be encrypted", 16 | "type": "boolean" 17 | }, 18 | "encrypted": { 19 | "description": "If the repository is encrypted", 20 | "type": ["boolean", "null"] 21 | } 22 | }, 23 | "required": [] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/schemas/Deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Deployment", 4 | "description": "A deployment of code, application, infrastructure or service. For example, a Kubernetes deployment. An auto scaling group is also considered a deployment.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "desiredSize": { 13 | "description": "Desired size (i.e. number of instances) associated with this deployment.", 14 | "type": "number" 15 | }, 16 | "currentSize": { 17 | "description": "Current size (i.e. number of instances) active with this deployment.", 18 | "type": "number" 19 | }, 20 | "maxSize": { 21 | "description": "Maximum size (i.e. number of instances) limited by this deployment.", 22 | "type": "number" 23 | } 24 | }, 25 | "required": [] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/Device.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Device", 4 | "description": "A physical device or media, such as a server, laptop, workstation, smartphone, tablet, router, firewall, switch, wifi-access-point, usb-drive, etc. The exact data type is described in the _type property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "category": { 11 | "description": "The device category", 12 | "type": ["string", "null"], 13 | "examples": [ 14 | "server", 15 | "endpoint", 16 | "storage-media", 17 | "mobile", 18 | "network", 19 | "other" 20 | ] 21 | }, 22 | "make": { 23 | "description": "Same as hardwareVendor: The manufacturer or vendor of the device, e.g. Apple Inc., Generic", 24 | "type": ["string", "null"] 25 | }, 26 | "model": { 27 | "description": "Same as hardwareModel: The device hardware model, e.g. MacBookPro13,3", 28 | "type": ["string", "null"] 29 | }, 30 | "version": { 31 | "description": "Same as hardwareVersion: The device hardware version", 32 | "type": "string" 33 | }, 34 | "serial": { 35 | "description": "Same as hardwareSerial: The device serial number", 36 | "type": ["string", "null"] 37 | }, 38 | "deviceId": { 39 | "description": "The unique device identifier, traditionally known as a UDID", 40 | "type": ["string", "null"] 41 | }, 42 | "hardwareVendor": { 43 | "description": "The manufacturer or vendor of the device, e.g. Apple Inc., Generic", 44 | "type": "string" 45 | }, 46 | "hardwareModel": { 47 | "description": "The device hardware model, e.g. MacBookPro13,3", 48 | "type": "string" 49 | }, 50 | "hardwareVersion": { 51 | "description": "The device hardware version", 52 | "type": "string" 53 | }, 54 | "hardwareSerial": { 55 | "description": "The device serial number", 56 | "type": "string" 57 | }, 58 | "assetTag": { 59 | "description": "The asset tag number/label that matches the identifier in asset tracking system, for company owned physical devices", 60 | "type": "string" 61 | }, 62 | "platform": { 63 | "description": "Operating System Platform", 64 | "type": "string", 65 | "enum": [ 66 | "darwin", 67 | "linux", 68 | "unix", 69 | "windows", 70 | "android", 71 | "ios", 72 | "embedded", 73 | "other" 74 | ] 75 | }, 76 | "osDetails": { 77 | "description": "Operating System Full Details (e.g. macOS High Sierra version 10.13.6)", 78 | "type": "string" 79 | }, 80 | "osName": { 81 | "description": "Operating System Name (e.g. macOS)", 82 | "type": "string" 83 | }, 84 | "osVersion": { 85 | "description": "Operating System Version (e.g. 10.13.6)", 86 | "type": "string" 87 | }, 88 | "userEmails": { 89 | "description": "The email addresses of the users this device is assigned to. Used if the device is shared by more than one user. Otherwise the 'owner' is the sole user. Leave empty/undefined if the device is unassigned.", 90 | "type": "array", 91 | "items": { 92 | "type": "string", 93 | "format": "email" 94 | } 95 | }, 96 | "location": { 97 | "description": "Site where this device is located.", 98 | "type": "string" 99 | }, 100 | "cost": { 101 | "description": "The purchase cost of the device.", 102 | "type": "number" 103 | }, 104 | "value": { 105 | "description": "The estimated business value of the device. The value is typically calculated as the monetary cost of the device + the value of data on the device.", 106 | "type": "number" 107 | }, 108 | "BYOD": { 109 | "description": "Indicates if this is a BYOD device -- an employee-provided device that has access to company systems/resources.", 110 | "type": "boolean", 111 | "default": false 112 | }, 113 | "autoSecurityPatchEnabled": { 114 | "description": "Indicates if security updates are auto-installed", 115 | "type": "boolean", 116 | "default": false 117 | }, 118 | "autoSystemPatchEnabled": { 119 | "description": "Indicates if operating system updates are auto-installed", 120 | "type": "boolean", 121 | "default": false 122 | }, 123 | "encrypted": { 124 | "description": "Indicates if the primary device storage is encrypted", 125 | "type": "boolean", 126 | "default": false 127 | }, 128 | "malwareProtected": { 129 | "description": "Indicates if malware protection is enabled", 130 | "type": "boolean", 131 | "default": false 132 | }, 133 | "firewallEnabled": { 134 | "description": "Indicates if local/host firewall is enabled", 135 | "type": "boolean", 136 | "default": false 137 | }, 138 | "remoteAccessEnabled": { 139 | "description": "Indicates if remote access/login to the device is enabled", 140 | "type": "boolean", 141 | "default": false 142 | }, 143 | "screenLockEnabled": { 144 | "description": "Indicates if screen lock protection is enabled", 145 | "type": "boolean", 146 | "default": false 147 | }, 148 | "screenLockTimeout": { 149 | "description": "Screen lock timeout in seconds", 150 | "type": "number" 151 | }, 152 | "lastSeenOn": { 153 | "description": "The timestamp (in milliseconds since epoch) when the device either last checked in or was scanned.", 154 | "type": ["number", "null"], 155 | "format": "date-time" 156 | }, 157 | "status": { 158 | "description": "Status label of this device", 159 | "type": "string", 160 | "enum": [ 161 | "assigned", 162 | "archived", 163 | "decommissioned", 164 | "defective", 165 | "deployed", 166 | "disposed", 167 | "locked", 168 | "lost/stolen", 169 | "pending", 170 | "ready", 171 | "unknown", 172 | "other" 173 | ] 174 | } 175 | }, 176 | "required": [ 177 | "category", 178 | "make", 179 | "model", 180 | "serial", 181 | "deviceId", 182 | "lastSeenOn" 183 | ] 184 | } 185 | ] 186 | } 187 | -------------------------------------------------------------------------------- /src/schemas/Directory.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Directory", 4 | "description": "Directory, such as LDAP or Active Directory.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "type": { 13 | "description": "Directory type.", 14 | "type": "string", 15 | "examples": ["LDAP", "AD"] 16 | }, 17 | "directoryServers": { 18 | "description": "List of directory servers.", 19 | "type": "array", 20 | "items": { 21 | "type": "string" 22 | } 23 | }, 24 | "domainControllers": { 25 | "description": "List of domain controllers.", 26 | "type": "array", 27 | "items": { 28 | "type": "string" 29 | } 30 | }, 31 | "parent": { 32 | "description": "Parent directory, if the entity is a sub-directory.", 33 | "type": "string" 34 | } 35 | }, 36 | "required": [] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /src/schemas/Disk.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Disk", 4 | "description": "A disk storage device such as an AWS EBS volume", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#DataStore" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/schemas/Document.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Document", 4 | "description": "A document or data object.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "product": { 13 | "description": "The name of the product this document is applicable to. This reference is used when the document is product related, such as a product requirement document (PRD) or software bill-of-materials (SBOM).", 14 | "type": "string" 15 | }, 16 | "version": { 17 | "description": "The version of this document.", 18 | "type": "string" 19 | } 20 | }, 21 | "required": [] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/Domain.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Domain", 4 | "description": "An internet domain.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "domainName": { 13 | "description": "Domain name.", 14 | "type": "string" 15 | }, 16 | "whoisServer": { 17 | "description": "WHOIS server that is responsible for resolving the details of this domain.", 18 | "type": "string" 19 | }, 20 | "registrar": { 21 | "description": "Domain registrar where this domain is registered.", 22 | "type": "string" 23 | }, 24 | "registrarName": { 25 | "description": "Domain registrar name.", 26 | "type": "string" 27 | }, 28 | "registrarUrl": { 29 | "description": "Domain registrar URL.", 30 | "type": "string" 31 | }, 32 | "nameservers": { 33 | "description": "List of nameservers.", 34 | "type": "array", 35 | "items": { 36 | "type": "string" 37 | } 38 | }, 39 | "contactEmails": { 40 | "description": "List of contact emails.", 41 | "type": "array", 42 | "items": { 43 | "type": "string" 44 | } 45 | }, 46 | "abuseContactEmail": { 47 | "description": "Abuse contact email.", 48 | "type": "string" 49 | }, 50 | "registrantContactEmail": { 51 | "description": "Registrant contact email.", 52 | "type": "string" 53 | }, 54 | "techContactEmail": { 55 | "description": "Technical contact email.", 56 | "type": "string" 57 | }, 58 | "adminContactEmail": { 59 | "description": "Administrative contact email.", 60 | "type": "string" 61 | }, 62 | "billingContactEmail": { 63 | "description": "Billing contact email.", 64 | "type": "string" 65 | }, 66 | "autoRenew": { 67 | "description": "Indicates whether auto-renewal is configured.", 68 | "type": "boolean" 69 | }, 70 | "locked": { 71 | "description": "Indicates whether domain transfer is locked/protected.", 72 | "type": "boolean" 73 | }, 74 | "parent": { 75 | "description": "Parent domain, if the entity is a sub-domain.", 76 | "type": "string" 77 | } 78 | }, 79 | "required": ["domainName"] 80 | } 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /src/schemas/DomainRecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#DomainRecord", 4 | "description": "The DNS Record of a Domain Zone.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "type": { 13 | "description": "DNS Record type.", 14 | "type": "string", 15 | "enum": [ 16 | "A", 17 | "AAAA", 18 | "ALIAS", 19 | "CAA", 20 | "CERT", 21 | "CNAME", 22 | "DNSKEY", 23 | "DS", 24 | "LOC", 25 | "MX", 26 | "NX", 27 | "NS", 28 | "NAPTR", 29 | "PTR", 30 | "SMIMEA", 31 | "SOA", 32 | "SPF", 33 | "SRV", 34 | "SSHFP", 35 | "TLSA", 36 | "TXT", 37 | "URI" 38 | ] 39 | }, 40 | "TTL": { 41 | "description": "Time to Live before resolver cache expires.", 42 | "type": "number" 43 | }, 44 | "value": { 45 | "description": "The record value. Could be referenced as `data`, `content`, `resourceRecords`, `aliasTarget` or another property name depending on the DNS provider.", 46 | "anyOf": [ 47 | { 48 | "type": "string" 49 | }, 50 | { 51 | "type": "array", 52 | "items": { 53 | "type": "string" 54 | } 55 | } 56 | ] 57 | } 58 | }, 59 | "required": ["type", "TTL"] 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /src/schemas/DomainZone.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#DomainZone", 4 | "description": "The DNS Zone of an Internet Domain.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "domainName": { 13 | "description": "Domain name.", 14 | "type": "string" 15 | }, 16 | "parent": { 17 | "description": "Parent domain, if the entity is a sub-domain.", 18 | "type": "string" 19 | }, 20 | "recordsCount": { 21 | "description": "Total number of DNS records in this zone.", 22 | "type": "number" 23 | } 24 | }, 25 | "required": ["domainName"] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/Entity.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Entity", 4 | "description": "A node in the graph database that represents an Entity. This reference schema defines common shared properties among most Entities.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#GraphObject" }, 8 | { 9 | "properties": { 10 | "id": { 11 | "description": "Identifiers of this entity assigned by the providers. Values are expected to be unique within the provider scope.", 12 | "anyOf": [ 13 | { 14 | "type": "string" 15 | }, 16 | { 17 | "type": "array", 18 | "items": { 19 | "type": "string" 20 | } 21 | } 22 | ] 23 | }, 24 | "name": { 25 | "description": "Name of this entity", 26 | "type": "string" 27 | }, 28 | "displayName": { 29 | "description": "Display name, e.g. a person's preferred name or an AWS account alias", 30 | "type": "string" 31 | }, 32 | "summary": { 33 | "description": "A summary / short description of this entity.", 34 | "type": "string" 35 | }, 36 | "description": { 37 | "description": "An extended description of this entity.", 38 | "type": "string" 39 | }, 40 | "classification": { 41 | "description": "The sensitivity of the data; should match company data classification scheme", 42 | "type": ["string", "null"], 43 | "examples": ["critical", "confidential", "internal", "public"] 44 | }, 45 | "criticality": { 46 | "description": "A number that represents the value or criticality of this entity, on a scale between 1-10.", 47 | "type": "integer", 48 | "minimum": 1, 49 | "maximum": 10 50 | }, 51 | "risk": { 52 | "description": "The risk level of this entity, on a scale between 1-10.", 53 | "type": "integer", 54 | "minimum": 1, 55 | "maximum": 10 56 | }, 57 | "trust": { 58 | "description": "The trust level of this entity, on a scale between 1-10.", 59 | "type": "integer", 60 | "minimum": 1, 61 | "maximum": 10 62 | }, 63 | "complianceStatus": { 64 | "description": "The compliance status of the entity, as a percentage of compliancy.", 65 | "type": "number", 66 | "minimum": 0, 67 | "maximum": 1 68 | }, 69 | "status": { 70 | "description": "Status of this entity set by the external source system or by a user, e.g. Active, Inactive, Decommissioned", 71 | "type": "string", 72 | "examples": [ 73 | "active", 74 | "inactive", 75 | "suspended", 76 | "terminated", 77 | "open", 78 | "closed", 79 | "pending", 80 | "unknown", 81 | "other" 82 | ] 83 | }, 84 | "active": { 85 | "description": "Indicates if this entity is currently active.", 86 | "type": "boolean" 87 | }, 88 | "public": { 89 | "description": "Indicates if this is a public-facing resource (e.g. a public IP or public DNS record) or if the entity is publicly accessible. Default is false.", 90 | "type": "boolean" 91 | }, 92 | "validated": { 93 | "description": "Indicates if this node has been validated as a known/valid Entity.", 94 | "type": "boolean" 95 | }, 96 | "temporary": { 97 | "description": "Indicates if this node is a temporary resource, such as a lambda instance or an EC2 instance started by ECS.", 98 | "type": "boolean" 99 | }, 100 | "trusted": { 101 | "description": "Indicates if this is a trusted resource. For example, a trusted Network, Host, Device, Application, Person, User, or Vendor.", 102 | "type": "boolean" 103 | }, 104 | "createdOn": { 105 | "description": "The timestamp (in milliseconds since epoch) when the entity was created at the source. This is different than `_createdOn` which is the timestamp the entity was first ingested into JupiterOne.", 106 | "type": "number", 107 | "format": "date-time" 108 | }, 109 | "updatedOn": { 110 | "description": "The timestamp (in milliseconds since epoch) when the entity was last updated at the source.", 111 | "type": "number", 112 | "format": "date-time" 113 | }, 114 | "deletedOn": { 115 | "description": "The timestamp (in milliseconds since epoch) when the entity was deleted at the source.", 116 | "type": "number", 117 | "format": "date-time" 118 | }, 119 | "discoveredOn": { 120 | "description": "The timestamp (in milliseconds since epoch) when the entity was discovered.", 121 | "type": "number", 122 | "format": "date-time" 123 | }, 124 | "expiresOn": { 125 | "description": "If the entity is a temporary resource, optionally set the expiration date. For example, the expiration date of an SSL cert.", 126 | "type": "number", 127 | "format": "date-time" 128 | }, 129 | "createdBy": { 130 | "description": "The source/principal/user that created the entity", 131 | "type": "string" 132 | }, 133 | "updatedBy": { 134 | "description": "The source/principal/user that updated the entity", 135 | "type": "string" 136 | }, 137 | "deletedBy": { 138 | "description": "The source/principal/user that deleted the entity", 139 | "type": "string" 140 | }, 141 | "discoveredBy": { 142 | "description": "The source/principal/user that discovered the entity", 143 | "type": "string" 144 | }, 145 | "webLink": { 146 | "description": "Web link to the source. For example: https://console.aws.amazon.com/iam/home#/roles/Administrator. This property is used by the UI to add a hyperlink to the entity.", 147 | "type": "string", 148 | "format": "uri" 149 | }, 150 | "owner": { 151 | "description": "The owner of this entity. This could reference the name of the owner, or as reference ID/key to another entity in the graph as the owner.", 152 | "type": "string" 153 | }, 154 | "tags": { 155 | "description": "An array of unnamed tags", 156 | "type": "array", 157 | "items": { 158 | "type": "string" 159 | } 160 | }, 161 | "notes": { 162 | "description": "User provided notes about this entity", 163 | "type": "array", 164 | "items": { 165 | "type": "string" 166 | } 167 | } 168 | }, 169 | "required": ["name", "displayName"] 170 | } 171 | ] 172 | } 173 | -------------------------------------------------------------------------------- /src/schemas/Finding.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Finding", 4 | "description": "A security finding, which may be a vulnerability or just an informative issue. A single finding may impact one or more resources. The `IMPACTS` relationship between the Vulnerability and the resource entity that was impacted serves as the record of the finding. The `IMPACTS` relationship carries properties such as 'identifiedOn', 'remediatedOn', 'remediationDueOn', 'issueLink', etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of the finding.", 14 | "anyOf": [ 15 | { 16 | "type": "string" 17 | }, 18 | { 19 | "type": "array", 20 | "items": { "type": "string" }, 21 | "examples": [ 22 | "data", 23 | "application", 24 | "host", 25 | "network", 26 | "endpoint", 27 | "malware", 28 | "event" 29 | ] 30 | } 31 | ] 32 | }, 33 | "assessment": { 34 | "description": "The name/id of the assessment that produced this finding.", 35 | "type": "string" 36 | }, 37 | "status": { 38 | "description": "Status of the vulnerability", 39 | "type": "string" 40 | }, 41 | "severity": { 42 | "description": "Severity rating based on impact and exploitability.", 43 | "type": "string", 44 | "examples": [ 45 | "none", 46 | "informational", 47 | "low", 48 | "medium", 49 | "high", 50 | "critical" 51 | ] 52 | }, 53 | "numericSeverity": { 54 | "description": "Severity rating based on impact and exploitability.", 55 | "type": "number", 56 | "examples": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 57 | }, 58 | "priority": { 59 | "description": "Priority level mapping to Severity rating. Can be a string such as 'critical', 'high', 'medium', 'low', 'info'. Or an integer usually between 0-5.", 60 | "type": "string" 61 | }, 62 | "score": { 63 | "description": "The overall vulnerability score, e.g. CVSSv3.", 64 | "type": "number" 65 | }, 66 | "impact": { 67 | "description": "The impact description or rating.", 68 | "type": "string" 69 | }, 70 | "exploitability": { 71 | "description": "The exploitability score/rating.", 72 | "type": "number" 73 | }, 74 | "vector": { 75 | "description": "The vulnerability attack vector. (e.g. a CVSSv3 vector looks like this - 'AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N')", 76 | "type": "string" 77 | }, 78 | "stepsToReproduce": { 79 | "description": "Steps to reproduce this finding.", 80 | "type": "array", 81 | "items": { 82 | "type": "string" 83 | } 84 | }, 85 | "recommendation": { 86 | "description": "Recommendation on how to remediate/fix this finding.", 87 | "type": "string" 88 | }, 89 | "targets": { 90 | "description": "The target listing of projects, applications, repos or systems this vulnerability impacts. Specifying either the project/repo name or the application URL here will auto-map this Vulnerability to the corresponding Project/CodeRepo/Application entity if a match is found.", 91 | "type": "array", 92 | "items": { 93 | "type": "string" 94 | } 95 | }, 96 | "targetDetails": { 97 | "description": "Additional details about the targets. Can be a string or an array.", 98 | "type": "array", 99 | "items": { 100 | "type": "string" 101 | } 102 | }, 103 | "remediationSLA": { 104 | "description": "The number of days that the Vulnerability must be remediated within, based on SLA set by the organization's internal vulnerability management program policy. The actually due date is set by 'remediationDueOn' property on the `IMPACTS` relationship between the Vulnerability and its impacted resource entity.", 105 | "type": "integer" 106 | }, 107 | "blocksProduction": { 108 | "description": "Indicates whether this vulnerability finding is a blocking issue. If true, it should block a production deploy. Defaults to false.", 109 | "type": "boolean", 110 | "default": false 111 | }, 112 | "open": { 113 | "description": "Indicates if this is an open vulnerability.", 114 | "type": "boolean" 115 | }, 116 | "production": { 117 | "description": "Indicates if this vulnerability is in production.", 118 | "type": "boolean" 119 | }, 120 | "public": { 121 | "description": "Indicates if this is a publicly disclosed vulnerability. If yes, this is usually a CVE and the 'webLink' should be set to 'https://nvd.nist.gov/vuln/detail/${CVE-Number}' or to a vendor URL. If not, it is most likely a custom application vulnerability.", 122 | "type": "boolean" 123 | }, 124 | "validated": { 125 | "description": "Indicates if this Vulnerability finding has been validated by the security team.", 126 | "type": "boolean" 127 | }, 128 | "references": { 129 | "description": "The array of links to references.", 130 | "type": "array", 131 | "items": { 132 | "type": "string" 133 | } 134 | } 135 | }, 136 | "required": ["category", "severity", "numericSeverity", "open"] 137 | } 138 | ] 139 | } 140 | -------------------------------------------------------------------------------- /src/schemas/Firewall.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Firewall", 4 | "description": "A piece of hardware or software that protects a network/host/application.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "category": { 11 | "description": "The category of the Firewall. Indicates the scope that the Firewall applies to -- i.e. Network, Host, Application.", 12 | "type": "array", 13 | "items": { 14 | "type": "string", 15 | "enum": ["network", "host", "application", "other"] 16 | } 17 | }, 18 | "isStateful": { 19 | "description": "Indicates if the rules in the firewall is stateful.", 20 | "type": "boolean" 21 | } 22 | }, 23 | "required": ["category"] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/schemas/Framework.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Framework", 4 | "description": "An object to represent a standard compliance or technical security framework.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#GraphObject" 9 | }, 10 | { 11 | "properties": { 12 | "name": { 13 | "description": "Name of this entity", 14 | "type": "string" 15 | }, 16 | "displayName": { 17 | "description": "Display name", 18 | "type": "string" 19 | }, 20 | "summary": { 21 | "description": "A summary / short description of this entity.", 22 | "type": "string" 23 | }, 24 | "description": { 25 | "description": "An extended description of this entity.", 26 | "type": "string" 27 | }, 28 | "standard": { 29 | "description": "The name of the framework standard.", 30 | "type": "string", 31 | "examples": [ 32 | "HIPAA", 33 | "NIST", 34 | "CSA STAR", 35 | "PCI DSS", 36 | "NIST CSF", 37 | "FedRAMP", 38 | "ISO 27001", 39 | "SOC", 40 | "OWASP", 41 | "Other" 42 | ] 43 | }, 44 | "version": { 45 | "description": "The version of the framework. For example, OWASP may have version 2010, 2013, 2017.", 46 | "type": "string" 47 | } 48 | }, 49 | "required": ["name", "displayName", "standard", "version"] 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /src/schemas/Function.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Function", 4 | "description": "A virtual application function. For example, an aws_lambda_function, azure_function, or google_cloud_function", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "image": { 13 | "description": "The image of this function, typically refers to a zip package.", 14 | "type": "string" 15 | }, 16 | "version": { 17 | "description": "The version of this function.", 18 | "type": "string" 19 | }, 20 | "runtime": { 21 | "description": "The runtime of this function. For example: 'nodejs6.10', 'nodejs8.10', or 'python2.7'.", 22 | "type": "string" 23 | }, 24 | "memorySize": { 25 | "description": "The allocated memory of this function to execute.", 26 | "type": "string" 27 | }, 28 | "codeSize": { 29 | "description": "The size of code of this function.", 30 | "type": "string" 31 | }, 32 | "codeHash": { 33 | "description": "The hash of code of this function.", 34 | "type": "string" 35 | }, 36 | "trigger": { 37 | "description": "What triggers this function to execute.", 38 | "type": "string" 39 | }, 40 | "handler": { 41 | "description": "The handler of this function", 42 | "type": "string" 43 | } 44 | }, 45 | "required": [] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /src/schemas/Gateway.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Gateway", 4 | "description": "A gateway/proxy that can be a system/appliance or software service, such as a network router or application gateway.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "category": { 11 | "description": "The category of the Gateway (corresponds to which OSI layer does the Proxy operates at).", 12 | "type": "array", 13 | "items": { 14 | "type": "string", 15 | "enum": ["network", "application", "data", "other"] 16 | } 17 | }, 18 | "function": { 19 | "description": "The function of the Gateway", 20 | "type": "array", 21 | "items": { 22 | "type": "string", 23 | "enum": [ 24 | "routing", 25 | "nat", 26 | "api-gateway", 27 | "content-filtering", 28 | "content-distribution", 29 | "load-balancing", 30 | "firewall", 31 | "ssl-termination", 32 | "reverse-proxy", 33 | "remote-access-gateway", 34 | "application-protection", 35 | "intrusion-detection", 36 | "intrusion-prevention", 37 | "mail-filtering", 38 | "malware-protection", 39 | "other" 40 | ] 41 | } 42 | }, 43 | "public": { 44 | "description": "Indicates if the Gateway is open to public access", 45 | "type": "boolean" 46 | } 47 | }, 48 | "required": ["category", "function", "public"] 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /src/schemas/GraphObject.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#GraphObject", 4 | "description": "Standard metadata properties of a graph object, maintained by the system. These are visible to users but may not be directly modified.", 5 | "type": "object", 6 | "propertyNames": { 7 | "pattern": "^(_|tag\\.)?[A-Za-z0-9. -]+$" 8 | }, 9 | "properties": { 10 | "_key": { 11 | "description": "An identifier unique within the scope containing the object. For example, for a Bitbucket repo, this will be the GUID of the repo as assigned by Bitbucket. For an IAM Role, this will be the ARN of the role.", 12 | "type": "string", 13 | "minLength": 10 14 | }, 15 | "_class": { 16 | "description": "One or more classes conforming to a standard, abstract security data model. For example, an EC2 instance will have '_class':'Host'.", 17 | "oneOf": [ 18 | { 19 | "type": "string", 20 | "minLength": 2 21 | }, 22 | { 23 | "type": "array", 24 | "minItems": 1, 25 | "items": { 26 | "type": "string", 27 | "minLength": 2 28 | } 29 | } 30 | ] 31 | }, 32 | "_type": { 33 | "description": "The type of object, typically reflecting the vendor and resource type. For example, 'aws_iam_user'. In some cases, a system knows about a type of entity that other systems know about, such as 'user_endpoint' or 'cve'.", 34 | "type": "string", 35 | "minLength": 3 36 | } 37 | }, 38 | "patternProperties": { 39 | "^tag\\.": { 40 | "description": "Named tags assigned to the entity (i.e., 'tag.Name', 'tag.OtherName')", 41 | "anyOf": [ 42 | { 43 | "type": "string" 44 | }, 45 | { 46 | "type": "number" 47 | }, 48 | { 49 | "type": "boolean" 50 | } 51 | ] 52 | } 53 | }, 54 | "required": ["_key", "_class", "_type"] 55 | } 56 | -------------------------------------------------------------------------------- /src/schemas/Group.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Group", 4 | "description": "A defined, generic group of Entities. This could represent a group of Resources, Users, Workloads, DataRepositories, etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": {}, 10 | "required": [] 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/schemas/Host.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Host", 4 | "description": "A compute instance that itself owns a whole network stack and serves as an environment for workloads. Typically it runs an operating system. The exact host type is described in the _type property of the Entity. The UUID of the host should be captured in the _id property of the Entity", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "fqdn": { 11 | "description": "Fully qualified domain name(s)", 12 | "anyOf": [ 13 | { "type": "string" }, 14 | { 15 | "type": "array", 16 | "uniqueItems": true, 17 | "items": { 18 | "type": "string" 19 | } 20 | } 21 | ] 22 | }, 23 | "hostname": { 24 | "description": "The primary/local hostname", 25 | "type": ["string", "null"] 26 | }, 27 | "ipAddress": { 28 | "description": "A listing of all IP addresses associated with this Host", 29 | "anyOf": [ 30 | { "type": "string", "format": "ip" }, 31 | { "type": "string", "format": "ipCidr" }, 32 | { 33 | "type": "array", 34 | "uniqueItems": true, 35 | "items": { 36 | "type": "string", 37 | "format": "ip" 38 | } 39 | }, 40 | { 41 | "type": "array", 42 | "uniqueItems": true, 43 | "items": { 44 | "type": "string", 45 | "format": "ipCidr" 46 | } 47 | } 48 | ] 49 | }, 50 | "publicDnsName": { 51 | "description": "The public DNS name", 52 | "type": "string", 53 | "format": "hostname" 54 | }, 55 | "privateDnsName": { 56 | "description": "The private DNS name", 57 | "type": "string", 58 | "format": "hostname" 59 | }, 60 | "publicIpAddress": { 61 | "description": "The public IP address or addresses", 62 | "anyOf": [ 63 | { "type": "string", "format": "ip" }, 64 | { 65 | "type": "array", 66 | "uniqueItems": true, 67 | "items": { 68 | "type": "string", 69 | "format": "ip" 70 | } 71 | } 72 | ] 73 | }, 74 | "privateIpAddress": { 75 | "description": "The private IP address or addresses", 76 | "anyOf": [ 77 | { "type": "string", "format": "ip" }, 78 | { 79 | "type": "array", 80 | "uniqueItems": true, 81 | "items": { 82 | "type": "string", 83 | "format": "ip" 84 | } 85 | } 86 | ] 87 | }, 88 | "macAddress": { 89 | "description": "A listing of all MAC addresses associated with this Host", 90 | "anyOf": [ 91 | { "type": "string" }, 92 | { 93 | "type": "array", 94 | "uniqueItems": true, 95 | "items": { 96 | "type": "string" 97 | } 98 | } 99 | ] 100 | }, 101 | "platform": { 102 | "description": "Operating System Platform", 103 | "type": "string", 104 | "enum": [ 105 | "darwin", 106 | "linux", 107 | "unix", 108 | "windows", 109 | "android", 110 | "ios", 111 | "embedded", 112 | "other" 113 | ] 114 | }, 115 | "osDetails": { 116 | "description": "Operating System Full Details (e.g. macOS High Sierra version 10.13.6)", 117 | "type": "string" 118 | }, 119 | "osName": { 120 | "description": "Operating System Name (e.g. macOS)", 121 | "type": "string" 122 | }, 123 | "osVersion": { 124 | "description": "Operating System Version (e.g. 10.13.6)", 125 | "type": "string" 126 | }, 127 | "physical": { 128 | "description": "Indicates if this is a physical host, such as a physical server.", 129 | "type": "boolean" 130 | }, 131 | "state": { 132 | "description": "The current state of a host (e.g. pending, running, shutting-down, terminated, stopping, stopped)", 133 | "type": "string" 134 | } 135 | }, 136 | "required": ["hostname"] 137 | } 138 | ] 139 | } 140 | -------------------------------------------------------------------------------- /src/schemas/HostAgent.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#HostAgent", 4 | "description": "A software agent or sensor that runs on a host/endpoint.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "function": { 13 | "description": "The function of sensor/agent", 14 | "type": "array", 15 | "items": { 16 | "type": "string", 17 | "enum": [ 18 | "endpoint-compliance", 19 | "endpoint-configuration", 20 | "endpoint-protection", 21 | "anti-malware", 22 | "DLP", 23 | "FIM", 24 | "host-firewall", 25 | "HIDS", 26 | "log-monitor", 27 | "activity-monitor", 28 | "vulnerability-detection", 29 | "container-security", 30 | "other" 31 | ] 32 | } 33 | }, 34 | "lastSeenOn": { 35 | "description": "The timestamp (in milliseconds since epoch) when the device either last checked in or was scanned.", 36 | "type": ["number", "null"], 37 | "format": "date-time" 38 | } 39 | }, 40 | "required": ["function", "lastSeenOn"] 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /src/schemas/Image.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Image", 4 | "description": "A system image. For example, an AWS AMI (Amazon Machine Image).", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Incident.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Incident", 4 | "description": "An operational or security incident. An event that negatively affects the confidentiality, integrity or availability of an organization's assets.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of the incident", 14 | "type": "string", 15 | "examples": [ 16 | "1. General Incident", 17 | "2. Attack on Internal Facing Assets", 18 | "3. Attack on External Facing Assets", 19 | "4. Malware", 20 | "5. Social Engineering", 21 | "6. Data Breach", 22 | "7. Physical or Environmental" 23 | ] 24 | }, 25 | "severity": { 26 | "description": "Severity rating based on impact. Can be a string such as 'critical', 'major', 'minor', or an integer usually between 1-3.", 27 | "type": "string" 28 | }, 29 | "impacts": { 30 | "description": "The target listing of [IDs/keys to] systems and resources this incident impacts.", 31 | "type": "array", 32 | "items": { 33 | "type": "string" 34 | } 35 | }, 36 | "reportable": { 37 | "description": "Indicates if this is a reportable incident per applicable regulations, such as HIPAA, PCI, or GDPR.", 38 | "type": "boolean", 39 | "default": false 40 | }, 41 | "reporter": { 42 | "description": "The person/entity who reported this incident.", 43 | "type": "string" 44 | }, 45 | "postmortem": { 46 | "description": "Summary and/or a link to the documented lesson learned.", 47 | "type": "string" 48 | } 49 | }, 50 | "required": ["category", "severity", "reportable"] 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /src/schemas/Internet.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Internet", 4 | "description": "The Internet node in the graph. There should be only one Internet node.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#GraphObject" 9 | }, 10 | { 11 | "properties": { 12 | "displayName": { 13 | "description": "Display name", 14 | "type": "string", 15 | "const": "Internet" 16 | }, 17 | "CIDR": { 18 | "description": "The IPv4 network CIDR block", 19 | "type": "string", 20 | "const": "0.0.0.0/0" 21 | }, 22 | "CIDRv6": { 23 | "description": "The IPv6 network CIDR block", 24 | "type": "string", 25 | "const": "::/0" 26 | }, 27 | "public": { 28 | "description": "Indicates if the network is open to public access", 29 | "type": "boolean", 30 | "const": true 31 | } 32 | } 33 | } 34 | ], 35 | "required": ["displayName"] 36 | } 37 | -------------------------------------------------------------------------------- /src/schemas/IpAddress.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#IpAddress", 4 | "description": "An re-assignable IpAddress resource entity. Do not create an entity for an IP Address _configured_ on a Host. Use this only if the IP Address is a reusable resource, such as an Elastic IP Address object in AWS.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "dnsName": { 13 | "description": "The assigned DNS name", 14 | "type": "string", 15 | "format": "hostname" 16 | }, 17 | "ipAddress": { 18 | "description": "The assigned IP address", 19 | "type": "string", 20 | "format": "ip" 21 | }, 22 | "publicIpAddress": { 23 | "description": "The assigned public IP address", 24 | "type": "string", 25 | "format": "ip" 26 | }, 27 | "privateIpAddress": { 28 | "description": "The assigned private IP address", 29 | "type": "string", 30 | "format": "ip" 31 | }, 32 | "ipVersion": { 33 | "description": "Indicates IP version 4 or 6", 34 | "type": "integer", 35 | "default": 4, 36 | "enum": [4, 6] 37 | } 38 | }, 39 | "required": ["ipAddress"] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/schemas/Issue.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Issue", 4 | "description": "An issue as used by GitHub, Jira, or other project trackers.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [], 13 | "excludes": [] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/schemas/Key.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Key", 4 | "description": "An ssh-key, access-key, api-key/token, pgp-key, etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "fingerprint": { 13 | "description": "The fingerprint that identifies the key", 14 | "type": "string" 15 | }, 16 | "material": { 17 | "description": "The key material", 18 | "type": "string" 19 | }, 20 | "usage": { 21 | "description": "The key usage - for example: ssh access or data encryption", 22 | "type": "string" 23 | } 24 | }, 25 | "required": [] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/Logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Logs", 4 | "description": "A specific repository or destination containing application, network, or system logs.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "type": { 13 | "description": "The type of logs", 14 | "type": "string", 15 | "examples": ["network", "system", "application", "access", "other"] 16 | } 17 | }, 18 | "required": [] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/schemas/Model.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Model", 4 | "description": "A system of postulates, data, and inferences presented as a mathematical description of an entity or state of affairs. For example, a machine learning model.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "encrypted": { 13 | "description": "Indicates whether the model is encrypted", 14 | "type": "boolean", 15 | "default": false 16 | } 17 | }, 18 | "required": [] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/schemas/Module.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Module", 4 | "description": "A software or hardware module. Such as an npm_module or java_library.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "public": { 13 | "description": "Indicates if this is a public module.", 14 | "type": "boolean" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Network.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Network", 4 | "description": "A network, such as an aws-vpc, aws-subnet, cisco-meraki-vlan.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "environment": { 13 | "description": "The environment of network", 14 | "type": "string", 15 | "examples": [ 16 | "development", 17 | "test", 18 | "staging", 19 | "production", 20 | "private", 21 | "wireless", 22 | "guest", 23 | "remote-access", 24 | "administrative", 25 | "other" 26 | ] 27 | }, 28 | "CIDR": { 29 | "description": "The IPv4 network CIDR block (e.g. 0.0.0.0/0)", 30 | "type": ["string", "null"], 31 | "pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$" 32 | }, 33 | "CIDRv6": { 34 | "description": "The IPv6 network CIDR block (e.g. ::/0)", 35 | "type": "string", 36 | "format": "ipv6" 37 | }, 38 | "public": { 39 | "description": "Indicates if the network is publicly accessible.", 40 | "type": "boolean" 41 | }, 42 | "internal": { 43 | "description": "Indicates if this is an internal/private network.", 44 | "type": "boolean" 45 | }, 46 | "wireless": { 47 | "description": "Indicates if this is a wireless network.", 48 | "type": "boolean" 49 | } 50 | }, 51 | "required": ["CIDR", "public", "internal"] 52 | } 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /src/schemas/NetworkEndpoint.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#NetworkEndpoint", 4 | "description": "A network endpoint for connecting to or accessing network resources. For example, NFS mount targets or VPN endpoints.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "ipAddress": { 13 | "description": "The endpoint IP address", 14 | "type": "string", 15 | "format": "ip" 16 | } 17 | }, 18 | "required": [] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/schemas/NetworkInterface.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#NetworkInterface", 4 | "description": "An re-assignable software defined network interface resource entity. Do not create an entity for a network interface _configured_ on a Host. Use this only if the network interface is a reusable resource, such as an Elastic Network Interface object in AWS.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "macAddress": { 13 | "description": "The assigned MAC address", 14 | "type": "string", 15 | "format": "hostname" 16 | }, 17 | "dnsName": { 18 | "description": "The assigned DNS name", 19 | "type": "string", 20 | "format": "hostname" 21 | }, 22 | "ipAddress": { 23 | "description": "The assigned primary IP address", 24 | "type": "string", 25 | "format": "ip" 26 | }, 27 | "publicIpAddress": { 28 | "description": "The assigned public IP address", 29 | "type": "string", 30 | "format": "ip" 31 | }, 32 | "privateIpAddress": { 33 | "description": "The assigned private IP address", 34 | "type": "string", 35 | "format": "ip" 36 | }, 37 | "ipVersion": { 38 | "description": "Indicates IP version 4 or 6", 39 | "type": "integer", 40 | "default": 4, 41 | "enum": [4, 6] 42 | } 43 | }, 44 | "required": [] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /src/schemas/Organization.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Organization", 4 | "description": "An organization, such as a company (e.g. JupiterOne) or a business unit (e.g. HR). An organization can be internal or external. Note that there is a more specific Vendor class.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "_type": { 13 | "description": "The type of organization (within the context of the primary organization).", 14 | "type": "string", 15 | "examples": [ 16 | "company", 17 | "department", 18 | "business-unit", 19 | "subsidiary", 20 | "government-agency", 21 | "partner", 22 | "other" 23 | ] 24 | }, 25 | "website": { 26 | "description": "The organization's main website URL.", 27 | "type": "string", 28 | "format": "uri" 29 | }, 30 | "emailDomain": { 31 | "description": "The domain name for internal organization email addresses.", 32 | "type": "string" 33 | }, 34 | "external": { 35 | "description": "Indicates if this organization is external", 36 | "type": "boolean" 37 | } 38 | }, 39 | "required": [], 40 | "excludes": ["status", "public", "temporary", "expiresOn"] 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /src/schemas/PR.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#PR", 4 | "description": "A pull request.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "title": { 13 | "description": "The title text of the PR.", 14 | "type": "string" 15 | }, 16 | "summary": { 17 | "description": "The summary text of the PR.", 18 | "type": "string" 19 | }, 20 | "state": { 21 | "description": "The state of the PR.", 22 | "type": "string", 23 | "examples": ["open", "merged", "declined", "superseded"] 24 | }, 25 | "source": { 26 | "description": "The source branch.", 27 | "type": "string" 28 | }, 29 | "target": { 30 | "description": "The target/destination branch.", 31 | "type": "string" 32 | }, 33 | "repository": { 34 | "description": "The name of the CodeRepo this PR belongs to.", 35 | "type": "string" 36 | }, 37 | "approved": { 38 | "description": "Indicates if every commit associated with this PR has been approved by a reviewer other than the code author.", 39 | "type": "boolean" 40 | }, 41 | "validated": { 42 | "description": "Indicates if every commit associated with this PR was submitted by a validated author known to the organization.", 43 | "type": "boolean" 44 | } 45 | }, 46 | "required": ["title", "state", "source", "target", "repository"] 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /src/schemas/PasswordPolicy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#PasswordPolicy", 4 | "description": "A password policy is a specific `Ruleset`. It is separately defined because of its pervasive usage across digital environments and the well known properties (such as length and complexity) unique to a password policy.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "minLength": { 13 | "description": "Minimum password length", 14 | "type": "integer" 15 | }, 16 | "requireSymbols": { 17 | "description": "Indicates if a password must contain at least one symbol", 18 | "type": "boolean" 19 | }, 20 | "requireNumbers": { 21 | "description": "Indicates if a password must contain at least one number", 22 | "type": "boolean" 23 | }, 24 | "requireUppercase": { 25 | "description": "Indicates if a password must contain at least one uppercase character", 26 | "type": "boolean" 27 | }, 28 | "requireLowercase": { 29 | "description": "Indicates if a password must contain at least one lowercase character", 30 | "type": "boolean" 31 | }, 32 | "maxAgeDays": { 33 | "description": "Specifies how long (in days) a password remains valid before it expires (0 indicates no limit - passwords do not expire)", 34 | "type": "integer" 35 | }, 36 | "minAgeMins": { 37 | "description": "Specifies the minimum time interval (in minutes) between password changes (0 indicates no limit)", 38 | "type": "integer" 39 | }, 40 | "historyCount": { 41 | "description": "Specifies the number of previous passwords that users are prevented from reusing (0 indicates none)", 42 | "type": "integer" 43 | }, 44 | "preventReset": { 45 | "description": "Indicates if the user is allowed/prevented to change their own password", 46 | "type": "boolean" 47 | }, 48 | "expiryWarningDays": { 49 | "description": "Specifies the number of days prior to password expiration when a user will be warned to reset their password (0 indicates no warning)", 50 | "type": "integer" 51 | }, 52 | "hardExpiry": { 53 | "description": "Specifies whether users are prevented from setting a new password after their password has expired", 54 | "type": "boolean" 55 | }, 56 | "excludeUsername": { 57 | "description": "Indicates if the username must be excluded from the password", 58 | "type": "boolean" 59 | }, 60 | "excludeAttributes": { 61 | "description": "The user profile attributes whose values must be excluded from the password", 62 | "type": "array", 63 | "items": { 64 | "type": "string" 65 | } 66 | }, 67 | "excludeCommonPasswords": { 68 | "description": "Indicates whether to check passwords against a common/weak password dictionary", 69 | "type": "boolean" 70 | }, 71 | "lockoutAttempts": { 72 | "description": "Specifies the number of times users can attempt to log in to their accounts with an invalid password before their accounts are locked (0 indicates no limit)", 73 | "type": "integer" 74 | }, 75 | "autoUnlockMins": { 76 | "description": "Specifies the time interval (in minutes) a locked account remains locked before it is automatically unlocked (0 indicates no limit)", 77 | "type": "integer" 78 | }, 79 | "requireMFA": { 80 | "description": "Specifies whether multi-factor authentication (MFA) is required", 81 | "type": "boolean" 82 | } 83 | }, 84 | "required": [], 85 | "excludes": [ 86 | "classification", 87 | "criticality", 88 | "trust", 89 | "risk", 90 | "status", 91 | "public", 92 | "temporary", 93 | "expiresOn" 94 | ] 95 | } 96 | ] 97 | } 98 | -------------------------------------------------------------------------------- /src/schemas/Person.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Person", 4 | "description": "An entity that represents an actual person, such as an employee of an organization.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "firstName": { 13 | "description": "The person's official first name in the system (such as HR database)", 14 | "type": "string" 15 | }, 16 | "lastName": { 17 | "description": "The person's official last name in the system (such as HR database)", 18 | "type": "string" 19 | }, 20 | "middleName": { 21 | "description": "The person's official middle name in the system (such as HR database)", 22 | "type": "string" 23 | }, 24 | "email": { 25 | "description": "The email addresses of the person; the first one in the array is the primary email.", 26 | "type": "array", 27 | "items": { 28 | "type": "string", 29 | "format": "email" 30 | } 31 | }, 32 | "emailDomain": { 33 | "description": "The domain portion of the email addresses associated with the user account.", 34 | "type": "array", 35 | "items": { 36 | "type": "string" 37 | } 38 | }, 39 | "title": { 40 | "description": "The person's role or title within an organization", 41 | "type": "string" 42 | }, 43 | "phone": { 44 | "description": "The person's phone numbers; the first one in the array is the primary contact number.", 45 | "type": "array", 46 | "items": { 47 | "type": "string" 48 | } 49 | }, 50 | "address": { 51 | "description": "The person's physical contact address", 52 | "type": "string" 53 | }, 54 | "employeeId": { 55 | "description": "The person's employee ID/number within an organization", 56 | "type": "string" 57 | }, 58 | "employeeType": { 59 | "description": "The type of employment", 60 | "type": "string", 61 | "examples": [ 62 | "employee", 63 | "contractor", 64 | "intern", 65 | "vendor", 66 | "advisor", 67 | "other" 68 | ] 69 | }, 70 | "userIds": { 71 | "description": "One or more user Ids associated with this person", 72 | "type": "array", 73 | "items": { 74 | "type": "string" 75 | } 76 | }, 77 | "manager": { 78 | "description": "Name of the person's manager", 79 | "type": "string" 80 | }, 81 | "managerId": { 82 | "description": "Employee ID of the person's manager", 83 | "type": "string" 84 | }, 85 | "managerEmail": { 86 | "description": "Email of the person's manager", 87 | "type": "string", 88 | "format": "email" 89 | }, 90 | "backgroundCheckedOn": { 91 | "description": "Timestamp of the background and/or reference check", 92 | "type": "number", 93 | "format": "date-time" 94 | }, 95 | "backgroundCheckedBy": { 96 | "description": "The agency or person conducted the background/reference check", 97 | "type": "string" 98 | } 99 | }, 100 | "required": ["firstName", "lastName", "email"], 101 | "excludes": ["owner", "createdOn", "updatedOn", "expiresOn"] 102 | } 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /src/schemas/Policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Policy", 4 | "description": "A written policy documentation.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "title": { 13 | "description": "Title of the policy", 14 | "type": "string" 15 | }, 16 | "summary": { 17 | "description": "Summary or overview the describes the policy. Summary text is intended as guidance to the author and not included in the published version.", 18 | "type": "string" 19 | }, 20 | "author": { 21 | "description": "Author of the record", 22 | "type": "string" 23 | }, 24 | "content": { 25 | "description": "Text content of the policy. For policies/procedures used by the Policy Builder app, this will contain the template text in markdown format. Stored in raw data.", 26 | "type": "string" 27 | }, 28 | "applicable": { 29 | "description": "Indicates if policy or procedure is applicable based on the organization's current risk and compliance needs. A Policy that is not applicable may become applicable later as the organization's requirements and maturity change.", 30 | "type": "boolean" 31 | }, 32 | "adopted": { 33 | "description": "Indicates if policy or procedure has been adopted. Only adopted policies and procedures are included in the published view of the Policy Builder app.", 34 | "type": "boolean" 35 | } 36 | }, 37 | "required": ["title", "summary", "content"], 38 | "excludes": ["category", "reporter"] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /src/schemas/Problem.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Problem", 4 | "description": "A problem identified from the analysis and correlation of assets and findings that is a notable issue worthy of action. It could be (or become) the cause, or potential cause, of one or more incidents or findings.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Finding" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/schemas/Procedure.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Procedure", 4 | "description": "A written procedure and control documentation. A Procedure typically `IMPLEMENTS` a parent Policy. An actual Control further `IMPLEMENTS` a Procedure.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "title": { 13 | "description": "Title of the procedure", 14 | "type": "string" 15 | }, 16 | "summary": { 17 | "description": "Summary or overview the describes the procedure. Summary text is intended as guidance to the author and not included in the published version.", 18 | "type": "string" 19 | }, 20 | "author": { 21 | "description": "Author of the record", 22 | "type": "string" 23 | }, 24 | "content": { 25 | "description": "Text content of the policy. For policies/procedures used by the Policy Builder app, this will contain the template text in markdown format. Stored in raw data.", 26 | "type": "string" 27 | }, 28 | "control": { 29 | "description": "The type of control specified by this procedure.", 30 | "type": "string", 31 | "examples": [ 32 | "administrative", 33 | "technical", 34 | "physical", 35 | "operational", 36 | "other" 37 | ] 38 | }, 39 | "applicable": { 40 | "description": "Indicates if procedure is applicable based on the organization's current risk and compliance needs. A Policy that is not applicable may become applicable later as the organization's requirements and maturity change.", 41 | "type": "boolean" 42 | }, 43 | "adopted": { 44 | "description": "Indicates if procedure has been adopted. Only adopted policies and procedures are included in the published view of the Policy Builder app.", 45 | "type": "boolean" 46 | } 47 | }, 48 | "required": ["title", "summary", "content"], 49 | "excludes": ["category", "reporter"] 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /src/schemas/Process.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Process", 4 | "description": "A compute process -- i.e. an instance of a computer program / software application that is being executed by one or many threads. This is NOT a program level operational process (i.e. a Procedure).", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "state": { 13 | "description": "Indicates the state of the process.", 14 | "type": "string" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Product.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Product", 4 | "description": "A product developed by the organization, such as a software product.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "Category that defines the product (e.g. 'web', 'mobile').", 14 | "type": "string" 15 | }, 16 | "description": { 17 | "description": "Description of the product", 18 | "type": "string" 19 | }, 20 | "appLink": { 21 | "description": "App links/URLs related to this product.", 22 | "type": "array", 23 | "items": { 24 | "type": "string" 25 | } 26 | }, 27 | "statusPage": { 28 | "description": "Link to the status page of this product (for a SaaS product).", 29 | "type": "array", 30 | "items": { 31 | "type": "string" 32 | } 33 | }, 34 | "projectKey": { 35 | "description": "Project key(s) that reference a Jira project, Bitbucket project, or similar related to this product.", 36 | "type": "array", 37 | "items": { 38 | "type": "string" 39 | } 40 | } 41 | }, 42 | "required": [] 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /src/schemas/Program.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Program", 4 | "description": "A program. For example, a bug bounty/vuln disclosure program.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "type": { 13 | "description": "The type of program.", 14 | "type": "string" 15 | }, 16 | "overview": { 17 | "description": "Program overview.", 18 | "type": "string" 19 | } 20 | }, 21 | "required": [] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/Project.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Project", 4 | "description": "A software development project. Can be used for other generic projects as well but the defined properties are geared towards software development projects.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "key": { 13 | "description": "A defined project key. It is ideal for a code project to have a consistent key that matches that of issue tracking project. For example, the key for a Bitbucket project should match the key of its corresponding Jira project.", 14 | "type": "string" 15 | }, 16 | "productionURL": { 17 | "description": "The Production URL", 18 | "type": "string", 19 | "format": "uri" 20 | }, 21 | "stagingURL": { 22 | "description": "The Non-Production / Staging URL", 23 | "type": "string", 24 | "format": "uri" 25 | }, 26 | "devURL": { 27 | "description": "The Development URL", 28 | "type": "string", 29 | "format": "uri" 30 | }, 31 | "testURL": { 32 | "description": "The Test URL", 33 | "type": "string", 34 | "format": "uri" 35 | }, 36 | "alternateURLs": { 37 | "description": "The additional URLs related to this application.", 38 | "type": "array", 39 | "items": { 40 | "type": "string" 41 | } 42 | } 43 | }, 44 | "required": [] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /src/schemas/Question.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Question", 4 | "description": "An object that represents an inquiry, usually around some matter of uncertainty or difficulty.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "queries": { 13 | "description": "A request for information that contributes to answering a question.", 14 | "anyOf": [ 15 | { 16 | "type": "array", 17 | "items": { "type": "string" } 18 | } 19 | ] 20 | } 21 | }, 22 | "required": ["queries"] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/schemas/Queue.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Queue", 4 | "description": "A scheduling queue of computing processes or devices.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "priority": { 13 | "description": "The priority of the queue", 14 | "type": "number" 15 | }, 16 | "items": { 17 | "description": "The items (processes, devices, jobs, etc.) in the queue", 18 | "type": "array" 19 | } 20 | }, 21 | "required": [] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/Record.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Record", 4 | "description": "A DNS record; or an official record (e.g. Risk); or a written document (e.g. Policy/Procedure); or a reference (e.g. Vulnerability/Weakness). The exact record type is captured in the _type property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [], 13 | "excludes": [] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/schemas/RecordEntity.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#RecordEntity", 4 | "description": "A node in the graph database that represents a Record Entity, with a set of different defined common properties than standard (resource) entities.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#GraphObject" 9 | }, 10 | { 11 | "properties": { 12 | "name": { 13 | "description": "Name of this entity", 14 | "type": "string" 15 | }, 16 | "displayName": { 17 | "description": "Display name, e.g. a person's preferred name or an AWS account alias", 18 | "type": "string" 19 | }, 20 | "summary": { 21 | "description": "A summary / short description of this entity.", 22 | "type": "string" 23 | }, 24 | "description": { 25 | "description": "An extended description of this entity.", 26 | "type": "string" 27 | }, 28 | "classification": { 29 | "description": "The sensitivity of the data; should match company data classification scheme. For example: critical - confidential - internal - public.", 30 | "type": "string", 31 | "examples": ["critical", "confidential", "internal", "public"] 32 | }, 33 | "category": { 34 | "description": "The category of the official record", 35 | "type": "string", 36 | "examples": [ 37 | "exception", 38 | "finding", 39 | "hr", 40 | "incident", 41 | "issue", 42 | "job", 43 | "legal", 44 | "request", 45 | "policy", 46 | "procedure", 47 | "problem", 48 | "review", 49 | "risk", 50 | "other" 51 | ] 52 | }, 53 | "webLink": { 54 | "description": "Hyperlink to the location of this record, e.g. URL to a Jira issue", 55 | "type": "string", 56 | "format": "uri" 57 | }, 58 | "content": { 59 | "description": "Text content of the record/documentation", 60 | "type": "string" 61 | }, 62 | "open": { 63 | "description": "Indicates if this record is currently open. For example, an open Vulnerability finding (Vulnerability extends Record).", 64 | "type": "boolean" 65 | }, 66 | "public": { 67 | "description": "If this is a public record. Defaults to false.", 68 | "type": "boolean", 69 | "default": false 70 | }, 71 | "production": { 72 | "description": "If this is a production record. For example, a production change management ticket would have this set to `true`, and have a `category` = `change` property. Another example would be a Vulnerability finding in production.", 73 | "type": "boolean" 74 | }, 75 | "approved": { 76 | "description": "If this is record has been reviewed and approved.", 77 | "type": "boolean" 78 | }, 79 | "approvedOn": { 80 | "description": "The timestamp (in milliseconds since epoch) when this record was approved.", 81 | "type": "number", 82 | "format": "date-time" 83 | }, 84 | "approvers": { 85 | "description": "The list of approvers on the record.", 86 | "type": "array", 87 | "items": { 88 | "type": "string" 89 | } 90 | }, 91 | "reporter": { 92 | "description": "The person or system that reported or created this record.", 93 | "type": "string" 94 | }, 95 | "reportedOn": { 96 | "description": "The timestamp (in milliseconds since epoch) when this record was reported/opened. In most cases, this would be the same as `createdOn` but occasionally a record can be created at a different time than when it was first reported.", 97 | "type": "number", 98 | "format": "date-time" 99 | }, 100 | "createdOn": { 101 | "description": "The timestamp (in milliseconds since epoch) when the entity was created at the source. This is different than `_createdOn` which is the timestamp the entity was first ingested into JupiterOne.", 102 | "type": "number", 103 | "format": "date-time" 104 | }, 105 | "updatedOn": { 106 | "description": "The timestamp (in milliseconds since epoch) when the entity was last updated at the source.", 107 | "type": "number", 108 | "format": "date-time" 109 | }, 110 | "exception": { 111 | "description": "Indicates if this record has an applied exception. For example, exception for a known finding or a PR that is not fully approved.", 112 | "type": "boolean" 113 | }, 114 | "exceptionReason": { 115 | "description": "Reason / description of the exception.", 116 | "type": "string" 117 | } 118 | }, 119 | "required": ["name", "displayName"] 120 | } 121 | ] 122 | } 123 | -------------------------------------------------------------------------------- /src/schemas/Repository.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Repository", 4 | "description": "A repository that contains resources. For example, a Docker container registry repository hosting Docker container images.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "public": { 13 | "description": "Indicates if this is a public repo.", 14 | "type": "boolean" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Requirement.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Requirement", 4 | "description": "An individual requirement for security, compliance, regulation or design.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "title": { 13 | "description": "The title text of the requirement.", 14 | "type": "string" 15 | }, 16 | "summary": { 17 | "description": "The summary text of the requirement.", 18 | "type": "string" 19 | }, 20 | "state": { 21 | "description": "The state of the requirement (e.g. 'implemented').", 22 | "type": "string" 23 | } 24 | }, 25 | "required": ["title"] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/Resource.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Resource", 4 | "description": "A generic assignable resource. A resource is typically non-functional by itself unless used by or attached to a host or workload.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Review.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Review", 4 | "description": "A review record.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "title": { 13 | "description": "The title text of the review.", 14 | "type": "string" 15 | }, 16 | "summary": { 17 | "description": "The summary text of the review.", 18 | "type": "string" 19 | }, 20 | "state": { 21 | "description": "The state of the review.", 22 | "type": "string" 23 | } 24 | }, 25 | "required": ["title"] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/schemas/Risk.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Risk", 4 | "description": "An object that represents an identified Risk as the result of an Assessment. The collection of Risk objects in JupiterOne make up the Risk Register. A Control may have a `MITIGATES` relationship to a Risk.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "assessment": { 13 | "description": "The name/id of the assessment that produced this risk.", 14 | "type": "string" 15 | }, 16 | "category": { 17 | "description": "The category (or area) of the risk. For example, 'process maturity' or 'natural disaster'.", 18 | "type": "string" 19 | }, 20 | "probability": { 21 | "description": "Probability rating of the risk: '3: high/certain', '2: medium/likely', '1: low/unlikely', '0: none/negligible'.", 22 | "type": "integer", 23 | "examples": [0, 1, 2, 3] 24 | }, 25 | "impact": { 26 | "description": "Impact rating. '3: high/severe', '2: medium/moderate', '1: low/minor', '0: none/insignificant'.", 27 | "type": "integer", 28 | "examples": [0, 1, 2, 3] 29 | }, 30 | "score": { 31 | "description": "Overall Risk Score = Probability x Impact", 32 | "type": "integer" 33 | }, 34 | "details": { 35 | "description": "Additional details to describe the risk.", 36 | "type": "string" 37 | }, 38 | "mitigation": { 39 | "description": "Description of the mitigation, either planned or implemented, if applicable.", 40 | "type": "string" 41 | }, 42 | "status": { 43 | "description": "Current status of this documented risk. Default status is `open`.", 44 | "type": "string", 45 | "examples": [ 46 | "reported", 47 | "acknowledged", 48 | "accepted", 49 | "mitigated", 50 | "prioritized", 51 | "transferred", 52 | "pending", 53 | "open" 54 | ] 55 | } 56 | }, 57 | "required": ["probability", "impact", "score", "status"] 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /src/schemas/Root.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Root", 4 | "description": "The root node in the graph. There should be only one Root node per organization account.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#GraphObject" 9 | }, 10 | { 11 | "properties": { 12 | "displayName": { 13 | "description": "Display name", 14 | "type": "string" 15 | } 16 | } 17 | } 18 | ], 19 | "required": ["displayName"] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Rule.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Rule", 4 | "description": "An operational or configuration compliance rule, often part of a Ruleset.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of ruleset.", 14 | "type": "string", 15 | "examples": ["compliance", "config", "password", "other"] 16 | }, 17 | "content": { 18 | "description": "Contents of the rule, if applicable.", 19 | "type": "string" 20 | } 21 | }, 22 | "required": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/schemas/Ruleset.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Ruleset", 4 | "description": "An operational or configuration compliance ruleset with rules that govern (or enforce, evaluate, monitor) a security control or IT system.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of ruleset.", 14 | "type": "string", 15 | "examples": ["compliance", "config", "password", "other"] 16 | }, 17 | "rules": { 18 | "description": "Rules of ruleset. Each rule is written 'as-code' that can be operationalized with a control provider or within JupiterOne's rules engine.", 19 | "type": "array", 20 | "items": { 21 | "type": "string" 22 | } 23 | }, 24 | "content": { 25 | "description": "Contents of the raw rules, if applicable.", 26 | "type": "string" 27 | } 28 | }, 29 | "required": [] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/schemas/Scanner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Scanner", 4 | "description": "A system vulnerability, application code or network infrastructure scanner.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of scanner", 14 | "type": "array", 15 | "items": { 16 | "type": "string", 17 | "examples": ["system", "network", "application", "other"] 18 | } 19 | } 20 | }, 21 | "required": ["category"] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/Secret.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Secret", 4 | "description": "A stored encrypted secret, accessed by permitted users or applications.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Section.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Section", 4 | "description": "An object to represent a section such as a compliance section.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Service.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Service", 4 | "description": "A service provided by a vendor.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of service, e.g. software, platform, infrastructure, other", 14 | "type": "array", 15 | "items": { 16 | "type": "string", 17 | "examples": [ 18 | "software", 19 | "platform", 20 | "infrastructure", 21 | "physical", 22 | "network", 23 | "application", 24 | "security", 25 | "other" 26 | ] 27 | } 28 | }, 29 | "function": { 30 | "description": "The functions provided by the service, e.g. access-review, database, load-balancing, other", 31 | "type": "array", 32 | "items": { 33 | "type": "string", 34 | "examples": [ 35 | "access-review", 36 | "api-gateway", 37 | "auditing", 38 | "caching", 39 | "certificate-management", 40 | "config-auditing", 41 | "content-distribution", 42 | "container-orchestration", 43 | "container-registry", 44 | "compute", 45 | "database", 46 | "data-analytics", 47 | "data-warehousing", 48 | "ddos-protection", 49 | "desktop-virtualization", 50 | "DLP", 51 | "DNS", 52 | "email", 53 | "encryption", 54 | "file-system", 55 | "IAM", 56 | "indexing", 57 | "key-management", 58 | "kubernetes-management", 59 | "load-balancing", 60 | "logging", 61 | "monitoring", 62 | "networking", 63 | "notification", 64 | "password-management", 65 | "provisioning", 66 | "queuing", 67 | "scheduling", 68 | "serverless", 69 | "SFTP", 70 | "SIEM", 71 | "storage", 72 | "VAS", 73 | "WAF", 74 | "workflow", 75 | "workload-management", 76 | "other" 77 | ] 78 | } 79 | }, 80 | "endpoints": { 81 | "description": "Array of service endpoints, e.g. ec2.amazonaws.com", 82 | "type": "array", 83 | "items": { 84 | "type": "string" 85 | } 86 | }, 87 | "fedrampModerate": { 88 | "description": "Indicates whether this service is compliant with FedRAMP Moderate", 89 | "type": "boolean" 90 | }, 91 | "hipaaEligible": { 92 | "description": "Indicates whether this service is HIPPA eligible", 93 | "type": "boolean" 94 | } 95 | }, 96 | "required": ["category", "function"] 97 | } 98 | ] 99 | } 100 | -------------------------------------------------------------------------------- /src/schemas/Site.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Site", 4 | "description": "The physical location of an organization. A Person (i.e. employee) would typically has a relationship to a Site (i.e. located_at or work_at). Also used as the abstract reference to AWS Regions.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "Type of site", 14 | "type": "array", 15 | "items": { 16 | "type": "string", 17 | "examples": [ 18 | "headquarters", 19 | "branch", 20 | "campus", 21 | "office", 22 | "aws-region", 23 | "data-center", 24 | "lab", 25 | "other" 26 | ] 27 | } 28 | }, 29 | "location": { 30 | "description": "The address/location of the site. Or an AWS Region (e.g. us-east-2).", 31 | "type": "string" 32 | }, 33 | "hours": { 34 | "description": "Hours of operation. e.g. M-F 9am-6pm", 35 | "type": "string" 36 | }, 37 | "secured": { 38 | "description": "Indicates the site is secured with physical controls such as key card access and surveillance cameras.", 39 | "type": "boolean" 40 | }, 41 | "restricted": { 42 | "description": "Indicates that access to the site is restricted (a level above secured access).", 43 | "type": "boolean" 44 | } 45 | }, 46 | "required": [] 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /src/schemas/Standard.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Standard", 4 | "description": "An object to represent a standard such as a compliance or technical standard.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "name": { 13 | "description": "The name of the standard.", 14 | "type": "string", 15 | "examples": [ 16 | "HIPAA", 17 | "NIST", 18 | "CSA STAR", 19 | "PCI DSS", 20 | "NIST CSF", 21 | "FedRAMP", 22 | "ISO 27001", 23 | "SOC", 24 | "OWASP", 25 | "Other" 26 | ] 27 | }, 28 | "version": { 29 | "description": "The version of the standard. For example, OWASP may have version 2010, 2013, 2017.", 30 | "type": "string" 31 | } 32 | }, 33 | "required": ["name", "version"] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /src/schemas/Subscription.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Subscription", 4 | "description": "A subscription to a service or channel.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "authenticated": { 13 | "description": "Indicates whether the subscription is authenticated.", 14 | "type": "boolean" 15 | }, 16 | "pending": { 17 | "description": "Indicates whether the subscription is pending.", 18 | "type": "boolean" 19 | } 20 | }, 21 | "required": [] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/Task.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Task", 4 | "description": "A computational task. Examples include AWS Batch Job, ECS Task, etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/Team.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Team", 4 | "description": "A team consists of multiple member Person entities. For example, the Development team or the Security team.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "email": { 13 | "description": "The team email address", 14 | "type": "string", 15 | "format": "email" 16 | } 17 | }, 18 | "required": [], 19 | "excludes": ["status", "public", "temporary", "expiresOn"] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/schemas/ThreatIntel.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#ThreatIntel", 4 | "description": "Threat intelligence captures information collected from vulnerability risk analysis by those with substantive expertise and access to all-source information. Threat intelligence helps a security professional determine the risk of a vulnerability finding to their organization.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "references": { 13 | "description": "The array of links to references.", 14 | "type": "array", 15 | "items": { 16 | "type": "string" 17 | } 18 | } 19 | }, 20 | "required": [] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /src/schemas/Training.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Training", 4 | "description": "A training module, such as a security awareness training or secure development training.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": {}, 12 | "required": [], 13 | "excludes": [] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/schemas/User.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#User", 4 | "description": "A user account/login to access certain systems and/or services. Examples include okta-user, aws-iam-user, ssh-user, local-user (on a host), etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "username": { 11 | "description": "Username", 12 | "type": "string" 13 | }, 14 | "email": { 15 | "description": "The primary email address associated with the user account", 16 | "type": "string", 17 | "format": "email" 18 | }, 19 | "emailDomain": { 20 | "description": "The domain portion of the email addresses associated with the user account.", 21 | "type": "array", 22 | "items": { 23 | "type": "string" 24 | } 25 | }, 26 | "shortLoginId": { 27 | "description": "The shortened login Id. For example, if the username is the full email address (first.last@company.com), the shortLoginId would be the part before @ (first.last).", 28 | "type": "string" 29 | }, 30 | "mfaEnabled": { 31 | "description": "Specifies whether multi-factor authentication (MFA) is enabled for this user.", 32 | "type": "boolean" 33 | }, 34 | "mfaType": { 35 | "description": "Specifies what type of multi-factor authentication (MFA) is being used by this user.", 36 | "type": "string" 37 | }, 38 | "active": { 39 | "description": "Specifies whether user account is active or disabled.", 40 | "type": "boolean" 41 | }, 42 | "firstName": { 43 | "description": "The user's official first name in the system (such as HR database)", 44 | "type": "string" 45 | }, 46 | "lastName": { 47 | "description": "The user's official last name in the system (such as HR database)", 48 | "type": "string" 49 | }, 50 | "passwordChangedOn": { 51 | "description": "The timestamp (in milliseconds since epoch) of when the user's password was last rotated for this particular account.", 52 | "type": "number", 53 | "format": "date-time" 54 | } 55 | }, 56 | "required": [] 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /src/schemas/UserGroup.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#UserGroup", 4 | "description": "A user group, typically associated with some type of access control, such as a group in Okta or in Office365. If a UserGroup has an access policy attached, and all member Users of the UserGroup would inherit the policy.", 5 | "type": "object", 6 | "allOf": [ 7 | { "$ref": "#Entity" }, 8 | { 9 | "properties": { 10 | "email": { 11 | "description": "The group email address", 12 | "type": "string", 13 | "format": "email" 14 | } 15 | }, 16 | "required": [] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/schemas/Vault.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Vault", 4 | "description": "A collection of secrets such as a key ring", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "name": { 13 | "description": "Name of the vault", 14 | "type": "string" 15 | } 16 | }, 17 | "required": ["name"] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Vendor", 4 | "description": "An external organization that is a vendor or service provider.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of vendor.", 14 | "anyOf": [ 15 | { 16 | "type": "string" 17 | }, 18 | { 19 | "type": "array", 20 | "items": { 21 | "type": "string" 22 | } 23 | } 24 | ], 25 | "examples": [ 26 | "business-operations", 27 | "cloud", 28 | "facilities", 29 | "finance", 30 | "infrastructure", 31 | "legal", 32 | "purchasing", 33 | "security", 34 | "software", 35 | "platform-development", 36 | "platform-social-media", 37 | "professional-services-staffing", 38 | "professional-services-recruiting", 39 | "professional-services-consulting", 40 | "generic-service-provider", 41 | "generic-subscription", 42 | "CSP", 43 | "ISP", 44 | "MSP", 45 | "MSSP", 46 | "IdP", 47 | "other" 48 | ] 49 | }, 50 | "website": { 51 | "description": "The vendor's main website URL.", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "departments": { 56 | "description": "List of business departments the vendor provides service for (e.g. IT, HR, Finance, Marketing, Development/Engineering, Security).", 57 | "type": "array", 58 | "items": { 59 | "type": "string" 60 | } 61 | }, 62 | "emailDomain": { 63 | "description": "The email domain for the vendor (e.g. @jupiterone.io).", 64 | "type": "string" 65 | }, 66 | "mainContactName": { 67 | "description": "The vendor's point of contact person.", 68 | "type": "string" 69 | }, 70 | "mainContactEmail": { 71 | "description": "Email of the vendor's point of contact person.", 72 | "type": "string", 73 | "format": "email" 74 | }, 75 | "mainContactPhone": { 76 | "description": "Phone number of the vendor's point of contact person.", 77 | "type": "string" 78 | }, 79 | "mainContactAddress": { 80 | "description": "Main physical/mailing address of the vendor.", 81 | "type": "string" 82 | }, 83 | "mainContactTitle": { 84 | "description": "The title of the vendor's main point of contact. For example, 'Manager of Operations'.", 85 | "type": "string" 86 | }, 87 | "alternateContactName": { 88 | "description": "The vendor's alternate/secondary point of contact person.", 89 | "type": "string" 90 | }, 91 | "alternateContactEmail": { 92 | "description": "Email of the vendor's alternate/secondary point of contact person.", 93 | "type": "string", 94 | "format": "email" 95 | }, 96 | "alternateContactPhone": { 97 | "description": "Phone number of the vendor's alternate/secondary point of contact person.", 98 | "type": "string" 99 | }, 100 | "alternateContactAddress": { 101 | "description": "Alternate/secondary physical/mailing address of the vendor.", 102 | "type": "string" 103 | }, 104 | "alternateContactTitle": { 105 | "description": "The title of the vendor's alternate/secondary point of contact. For example, 'CISO'.", 106 | "type": "string" 107 | }, 108 | "admins": { 109 | "description": "List of admin users to the vendor account, if applicable. If this vendor account is integrated directly to JupiterOne and its data is ingested, the admin users should be already mapped as User entities.", 110 | "type": "array", 111 | "items": { 112 | "type": "string" 113 | } 114 | }, 115 | "breachResponseDays": { 116 | "description": "The number of days the vendor agrees to report an identified data breach, per vendor agreement and/or SLA. This is typically 3 to 30 days. Note that GDPR requires breach notification within 3 days / 72 hours.", 117 | "type": "integer" 118 | }, 119 | "linkToNDA": { 120 | "description": "Link to Non-Disclosure Agreement (NDA) document.", 121 | "type": "string", 122 | "format": "uri" 123 | }, 124 | "linkToMSA": { 125 | "description": "Link to Master Service Agreement (MSA) document.", 126 | "type": "string", 127 | "format": "uri" 128 | }, 129 | "linkToSLA": { 130 | "description": "Link to Service Level Agreement (SLA) document.", 131 | "type": "string", 132 | "format": "uri" 133 | }, 134 | "linkToBAA": { 135 | "description": "Link to Business Associate Agreement (BAA) document - for HIPAA only.", 136 | "type": "string", 137 | "format": "uri" 138 | }, 139 | "linkToDPA": { 140 | "description": "Link to GDPR Data Processing Addendum (DPA) document - for GDPR only.", 141 | "type": "string", 142 | "format": "uri" 143 | }, 144 | "linkToVTR": { 145 | "description": "Link to the external vendor technology risk (VTR) report.", 146 | "type": "string", 147 | "format": "uri" 148 | }, 149 | "linkToISA": { 150 | "description": "Link to the external information security assessment (ISA) report.", 151 | "type": "string", 152 | "format": "uri" 153 | }, 154 | "statusPage": { 155 | "description": "Link to the vendor's service status page (e.g. https://status.aws.amazon.com/).", 156 | "type": "string", 157 | "format": "uri" 158 | }, 159 | "validatedOn": { 160 | "description": "The timestamp (in milliseconds since epoch) of when this vendor was last validated per the vendor management policy.", 161 | "type": "number", 162 | "format": "date-time" 163 | } 164 | }, 165 | "required": ["category"], 166 | "excludes": ["status", "public", "temporary", "expiresOn"] 167 | } 168 | ] 169 | } 170 | -------------------------------------------------------------------------------- /src/schemas/Vulnerability.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Vulnerability", 4 | "description": "A security vulnerability (application or system or infrastructure). A single vulnerability may relate to multiple findings and impact multiple resources. The `IMPACTS` relationship between the Vulnerability and the resource entity that was impacted serves as the record of the finding. The `IMPACTS` relationship carries properties such as 'identifiedOn', 'remediatedOn', 'remediationDueOn', 'issueLink', etc.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of the vulnerability finding", 14 | "type": ["string", "null"], 15 | "examples": ["application", "system", "infrastructure", "other"] 16 | }, 17 | "status": { 18 | "description": "Status of the vulnerability", 19 | "type": "string" 20 | }, 21 | "severity": { 22 | "description": "Severity rating based on impact and exploitability. Can be a string such as 'critical', 'high', 'medium', 'low', 'info'. Or an integer usually between 0-5.", 23 | "type": ["string", "null"] 24 | }, 25 | "priority": { 26 | "description": "Priority level mapping to Severity rating. Can be a string such as 'critical', 'high', 'medium', 'low', 'info'. Or an integer usually between 0-5.", 27 | "type": "string" 28 | }, 29 | "score": { 30 | "description": "The overall vulnerability score, e.g. CVSSv3.", 31 | "type": "number" 32 | }, 33 | "impact": { 34 | "description": "The impact score/rating.", 35 | "type": "number" 36 | }, 37 | "exploitability": { 38 | "description": "The exploitability score/rating.", 39 | "type": "number" 40 | }, 41 | "vector": { 42 | "description": "The vulnerability attack vector. (e.g. a CVSSv3 vector looks like this - 'AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N')", 43 | "type": "string" 44 | }, 45 | "impacts": { 46 | "description": "The target listing of projects, applications, repos or systems this vulnerability impacts. Specifying either the project/repo name or the application URL here will auto-map this Vulnerability to the corresponding Project/CodeRepo/Application entity if a match is found.", 47 | "type": "array", 48 | "items": { 49 | "type": "string" 50 | } 51 | }, 52 | "remediationSLA": { 53 | "description": "The number of days that the Vulnerability must be remediated within, based on SLA set by the organization's internal vulnerability management program policy. The actually due date is set by 'remediationDueOn' property on the `IMPACTS` relationship between the Vulnerability and its impacted resource entity.", 54 | "type": "integer" 55 | }, 56 | "blocking": { 57 | "description": "Indicates whether this vulnerability finding is a blocking issue. If true, it should block a production deploy. Defaults to false.", 58 | "type": ["boolean", "null"], 59 | "default": false 60 | }, 61 | "open": { 62 | "description": "Indicates if this is an open vulnerability.", 63 | "type": ["boolean", "null"] 64 | }, 65 | "production": { 66 | "description": "Indicates if this vulnerability is in production.", 67 | "type": ["boolean", "null"] 68 | }, 69 | "public": { 70 | "description": "Indicates if this is a publicly disclosed vulnerability. If yes, this is usually a CVE and the 'webLink' should be set to 'https://nvd.nist.gov/vuln/detail/${CVE-Number}' or to a vendor URL. If not, it is most likely a custom application vulnerability.", 71 | "type": ["boolean", "null"] 72 | }, 73 | "validated": { 74 | "description": "Indicates if this Vulnerability finding has been validated by the security team.", 75 | "type": "boolean" 76 | }, 77 | "references": { 78 | "description": "The array of links to references.", 79 | "type": "array", 80 | "items": { 81 | "type": "string" 82 | } 83 | } 84 | }, 85 | "required": [ 86 | "category", 87 | "severity", 88 | "blocking", 89 | "open", 90 | "production", 91 | "public" 92 | ] 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /src/schemas/Weakness.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Weakness", 4 | "description": "A security weakness.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#RecordEntity" 9 | }, 10 | { 11 | "properties": { 12 | "category": { 13 | "description": "The category of the vulnerability finding", 14 | "type": "string", 15 | "examples": ["application", "system", "infrastructure", "other"] 16 | }, 17 | "exploitability": { 18 | "description": "Indicates the likelihood of exploit.", 19 | "type": "string" 20 | }, 21 | "references": { 22 | "description": "The array of links to references.", 23 | "type": "array", 24 | "items": { 25 | "type": "string" 26 | } 27 | } 28 | }, 29 | "required": [] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/schemas/Workflow.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Workflow", 4 | "description": "A workflow such as an AWS CodePipeline, GitHub repository workflow, or Apache Airflow.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "name": { 13 | "description": "Name of the workflow", 14 | "type": "string" 15 | } 16 | }, 17 | "required": [] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/schemas/Workload.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "#Workload", 4 | "description": "A virtual compute instance, it could be an aws-ec2-instance, a docker-container, an aws-lambda-function, an application-process, or a vmware-instance. The exact workload type is described in the _type property of the Entity.", 5 | "type": "object", 6 | "allOf": [ 7 | { 8 | "$ref": "#Entity" 9 | }, 10 | { 11 | "properties": { 12 | "image": { 13 | "description": "The image this workload is derived from, such as an AMI or docker image. At the abstract level, this usually maps to the _id of a Resource.", 14 | "type": "string" 15 | }, 16 | "fqdn": { 17 | "description": "The fully qualified domain name of attached to the instance, if applicable", 18 | "type": "string" 19 | } 20 | }, 21 | "required": [] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/validateEntityWithSchema.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { entityClasses } from './index'; 4 | import { validateEntityWithSchema } from './validateEntityWithSchema'; 5 | 6 | const requiredGraphObjectProperties = { 7 | _class: ['GraphObject'], 8 | _key: 'my_testing_key', 9 | _type: 'my_testing_type', 10 | name: 'John', 11 | displayName: 'Wick', 12 | }; 13 | 14 | test('throws error if schema does not exist', () => { 15 | expect(() => validateEntityWithSchema({ _class: ['ChimkenNumget'] })).toThrow( 16 | 'Could not find schema for class ChimkenNumget!', 17 | ); 18 | }); 19 | 20 | test('throws error if entity fails to validate', () => { 21 | expect(() => validateEntityWithSchema({ _class: ['Account'] })).toThrow( 22 | "Entity fails to validate as class 'Account'", 23 | ); 24 | }); 25 | 26 | test('does not throw if entity successfully validates', () => { 27 | expect(() => 28 | validateEntityWithSchema({ 29 | _class: ['GraphObject'], 30 | _key: 'my_testing_key', 31 | _type: 'my_testing_type', 32 | } as any), 33 | ).not.toThrow(); 34 | }); 35 | 36 | describe('schemas', () => { 37 | for (const entityClass of entityClasses) { 38 | test(entityClass, () => { 39 | expect(() => 40 | validateEntityWithSchema({ 41 | ...requiredGraphObjectProperties, 42 | _class: [entityClass], 43 | _key: undefined, 44 | } as any), 45 | ).toThrow(/'_key'/); 46 | 47 | expect(() => 48 | validateEntityWithSchema({ 49 | ...requiredGraphObjectProperties, 50 | _class: [entityClass], 51 | _type: undefined, 52 | } as any), 53 | ).toThrow(/'_type'/); 54 | 55 | if ('GraphObject' === entityClass) return; 56 | 57 | expect(() => 58 | validateEntityWithSchema({ 59 | ...requiredGraphObjectProperties, 60 | _class: [entityClass], 61 | displayName: undefined, 62 | } as any), 63 | ).toThrow(/'displayName'/); 64 | }); 65 | } 66 | }); 67 | 68 | describe('Host', () => { 69 | const requiredProperties = { 70 | ...requiredGraphObjectProperties, 71 | hostname: 'test', 72 | _class: ['Host'], 73 | }; 74 | 75 | test('allows IPv4 as publicIpAddress', () => { 76 | expect(() => 77 | validateEntityWithSchema({ 78 | ...requiredProperties, 79 | publicIpAddress: '10.10.10.10', 80 | } as any), 81 | ).not.toThrow(); 82 | }); 83 | 84 | test('disallows IPv4 with netmask as publicIpAddress', () => { 85 | expect(() => 86 | validateEntityWithSchema({ 87 | ...requiredProperties, 88 | publicIpAddress: '10.10.10.10/32', 89 | } as any), 90 | ).toThrow(/must match format/); 91 | }); 92 | 93 | test('allows IPv6 as publicIpAddress', () => { 94 | expect(() => 95 | validateEntityWithSchema({ 96 | ...requiredProperties, 97 | publicIpAddress: 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 98 | } as any), 99 | ).not.toThrow(); 100 | }); 101 | 102 | test('allows single IPv4 address in ipAddress', () => { 103 | expect(() => 104 | validateEntityWithSchema({ 105 | ...requiredProperties, 106 | ipAddress: '192.168.1.1', 107 | } as any), 108 | ).not.toThrow(); 109 | }); 110 | 111 | test('allows single IPv4 CIDR block in ipAddress', () => { 112 | expect(() => 113 | validateEntityWithSchema({ 114 | ...requiredProperties, 115 | ipAddress: '192.168.1.0/24', 116 | } as any), 117 | ).not.toThrow(); 118 | }); 119 | 120 | test('allows single IPv6 address in ipAddress', () => { 121 | expect(() => 122 | validateEntityWithSchema({ 123 | ...requiredProperties, 124 | ipAddress: '2001:db8::1', 125 | } as any), 126 | ).not.toThrow(); 127 | }); 128 | 129 | test('allows single IPv6 CIDR block in ipAddress', () => { 130 | expect(() => 131 | validateEntityWithSchema({ 132 | ...requiredProperties, 133 | ipAddress: '2001:db8::/32', 134 | } as any), 135 | ).not.toThrow(); 136 | }); 137 | 138 | test('allows array of IPv4 addresses in ipAddress', () => { 139 | expect(() => 140 | validateEntityWithSchema({ 141 | ...requiredProperties, 142 | ipAddress: ['192.168.1.1', '10.0.0.1'], 143 | } as any), 144 | ).not.toThrow(); 145 | }); 146 | 147 | test('allows array of IPv4 and IPv6 addresses in ipAddress', () => { 148 | expect(() => 149 | validateEntityWithSchema({ 150 | ...requiredProperties, 151 | ipAddress: ['192.168.1.1', '2001:db8::1'], 152 | } as any), 153 | ).not.toThrow(); 154 | }); 155 | 156 | test('allows array with IPv4 CIDR blocks in ipAddress', () => { 157 | expect(() => 158 | validateEntityWithSchema({ 159 | ...requiredProperties, 160 | ipAddress: ['192.168.1.0/24', '10.0.0.0/16'], 161 | } as any), 162 | ).not.toThrow(); 163 | }); 164 | 165 | test('disallows invalid IPv4 address in ipAddress', () => { 166 | expect(() => 167 | validateEntityWithSchema({ 168 | ...requiredProperties, 169 | ipAddress: '256.256.256.256', 170 | } as any), 171 | ).toThrow(); 172 | }); 173 | 174 | test('disallows invalid IPv4 CIDR block in ipAddress', () => { 175 | expect(() => 176 | validateEntityWithSchema({ 177 | ...requiredProperties, 178 | ipAddress: '192.168.1.0/33', // Invalid CIDR notation 179 | } as any), 180 | ).toThrow(); 181 | }); 182 | }); 183 | 184 | describe('IpAddress', () => { 185 | const requiredProperties = { 186 | ...requiredGraphObjectProperties, 187 | _class: ['IpAddress'], 188 | }; 189 | 190 | test('allows IPv4 as ipAddress', () => { 191 | expect(() => 192 | validateEntityWithSchema({ 193 | ...requiredProperties, 194 | ipAddress: '10.10.10.10', 195 | } as any), 196 | ).not.toThrow(); 197 | }); 198 | 199 | test('disallows IPv4 with netmask as ipAddress', () => { 200 | expect(() => 201 | validateEntityWithSchema({ 202 | ...requiredProperties, 203 | ipAddress: '10.10.10.10/32', 204 | } as any), 205 | ).toThrow(/must match format/); 206 | }); 207 | 208 | test('allows IPv6 as ipAddress', () => { 209 | expect(() => 210 | validateEntityWithSchema({ 211 | ...requiredProperties, 212 | ipAddress: 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 213 | } as any), 214 | ).not.toThrow(); 215 | }); 216 | }); 217 | 218 | describe('Entity', () => { 219 | const requiredProperties = { 220 | ...requiredGraphObjectProperties, 221 | _class: ['Entity'], 222 | }; 223 | 224 | test('allows string as id', () => { 225 | expect(() => 226 | validateEntityWithSchema({ 227 | ...requiredProperties, 228 | id: 'sumpinsumpin', 229 | } as any), 230 | ).not.toThrow(); 231 | }); 232 | 233 | test('allows string[] as id', () => { 234 | expect(() => 235 | validateEntityWithSchema({ 236 | ...requiredProperties, 237 | id: ['sumpinsumpin', 'nuttinnuttin'], 238 | } as any), 239 | ).not.toThrow(); 240 | }); 241 | 242 | test('allows number as tag.*', () => { 243 | expect(() => 244 | validateEntityWithSchema({ 245 | ...requiredProperties, 246 | 'tag.Anything': 1234, 247 | } as any), 248 | ).not.toThrow(); 249 | }); 250 | 251 | test('allows boolean as tag.*', () => { 252 | expect(() => 253 | validateEntityWithSchema({ 254 | ...requiredProperties, 255 | 'tag.Anything': true, 256 | } as any), 257 | ).not.toThrow(); 258 | }); 259 | }); 260 | 261 | describe('Vendor: category can be string | string[]', () => { 262 | test('allows string as category', () => { 263 | expect(() => 264 | validateEntityWithSchema({ 265 | ...requiredGraphObjectProperties, 266 | _class: ['Vendor'], 267 | category: 'fighter', 268 | } as any), 269 | ).not.toThrow(); 270 | }); 271 | 272 | test('allows string[] as category', () => { 273 | expect(() => 274 | validateEntityWithSchema({ 275 | ...requiredGraphObjectProperties, 276 | _class: ['Vendor'], 277 | category: ['lover', 'fighter'], 278 | } as any), 279 | ).not.toThrow(); 280 | }); 281 | }); 282 | 283 | describe('#DataObject', () => { 284 | test('should accept "classification" string value', () => { 285 | expect(() => 286 | validateEntityWithSchema({ 287 | ...requiredGraphObjectProperties, 288 | _class: ['DataObject'], 289 | classification: 'critical', 290 | } as any), 291 | ).not.toThrow(); 292 | }); 293 | 294 | test('should accept "classification" null value', () => { 295 | expect(() => 296 | validateEntityWithSchema({ 297 | ...requiredGraphObjectProperties, 298 | _class: ['DataObject'], 299 | classification: null, 300 | } as any), 301 | ).not.toThrow(); 302 | }); 303 | }); 304 | 305 | describe('#DataCollection', () => { 306 | function createDataCollectionEntity(partial?: Record): any { 307 | return { 308 | ...requiredGraphObjectProperties, 309 | PII: false, 310 | PHI: false, 311 | PCI: false, 312 | encryptionRequired: false, 313 | encrypted: false, 314 | public: false, 315 | classification: 'critical', 316 | ...partial, 317 | _class: ['DataCollection'], 318 | }; 319 | } 320 | 321 | test('should accept known properties', () => { 322 | expect(() => 323 | validateEntityWithSchema(createDataCollectionEntity()), 324 | ).not.toThrow(); 325 | }); 326 | 327 | test('should accept "classification" null value', () => { 328 | expect(() => 329 | validateEntityWithSchema( 330 | createDataCollectionEntity({ 331 | classification: null, 332 | }), 333 | ), 334 | ).not.toThrow(); 335 | }); 336 | }); 337 | -------------------------------------------------------------------------------- /src/validateEntityWithSchema.ts: -------------------------------------------------------------------------------- 1 | import { IntegrationSchema } from '.'; 2 | 3 | /** 4 | * Validates an entity using the data model schemas, throwing an error when 5 | * validation fails. 6 | */ 7 | export function validateEntityWithSchema(entity: { _class: string[] }): void { 8 | for (const c of entity._class) { 9 | const validate = IntegrationSchema.getSchema(`#${c}`); 10 | if (!validate) { 11 | throw new Error(`Could not find schema for class ${c}!`); 12 | } 13 | 14 | if (!validate(entity)) { 15 | throw new Error( 16 | `Entity fails to validate as class '${c}':\n\n${JSON.stringify( 17 | validate.errors, 18 | null, 19 | 2, 20 | )}`, 21 | ); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tools/generate-register-schemas-function.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # absolute path to where this script is located 4 | here=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) 5 | 6 | cd $here; 7 | 8 | # Define the path to the directory containing the JSON schemas 9 | schemaDir="../src/schemas" 10 | 11 | # Define the output TypeScript file 12 | outputFile="../src/registerSchemas.ts" 13 | 14 | # Write the fixed part of the template to the outputFile 15 | echo "// THIS FILE IS AUTOMATICALLY GENERATED!" > "$outputFile" 16 | echo "// using the script tools/generate-register-schemas-function.sh" >> "$outputFile" 17 | echo "" >> "$outputFile" 18 | echo "import Ajv from 'ajv';" >> "$outputFile" 19 | echo "" >> "$outputFile" 20 | 21 | # Dynamically generate import statements and ajvInstance.addSchema calls 22 | importStatements="" 23 | schemaCalls="" 24 | 25 | # Loop over the JSON files in the schema directory without changing the current directory 26 | for file in "$schemaDir"/*.json; do 27 | # Extract just the filename from the path 28 | filename=$(basename -- "$file") 29 | 30 | # Remove the file extension to get the schema name 31 | schemaName=$(echo "$filename" | sed 's/.json$//') 32 | 33 | # Create the import statement 34 | importStatements+="import ${schemaName}Json from './schemas/${filename}';"$'\n' 35 | 36 | # Create the ajvInstance.addSchema call 37 | schemaCalls+=" ajvInstance.addSchema(${schemaName}Json);"$'\n' 38 | done 39 | 40 | # trim the trailing new line 41 | schemaCalls=$(echo "$schemaCalls" | sed '$d') 42 | 43 | # Write the dynamic parts to the outputFile 44 | echo "// Dynamically imported schemas" >> "$outputFile" 45 | echo "$importStatements" >> "$outputFile" 46 | echo "export function registerSchemas(ajvInstance: Ajv): void {" >> "$outputFile" 47 | echo "$schemaCalls" >> "$outputFile" 48 | echo "}" >> "$outputFile" 49 | -------------------------------------------------------------------------------- /tools/generate-resolved-schemas/index.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises'; 2 | import { 3 | resolveSchema, 4 | buildIdToSchemaMap, 5 | readAllSchemas, 6 | Schema, 7 | } from './utils'; 8 | 9 | void (async function () { 10 | if (process.argv.length < 3) { 11 | console.error( 12 | `Not enough arguments supplied.\nUsage: node generate-resolved-schemas.js `, 13 | ); 14 | return; 15 | } 16 | const schemaPath = process.argv[2]; 17 | const outputPath = process.argv[3]; 18 | 19 | const schemas = await readAllSchemas(schemaPath); 20 | const idToSchemaMap = buildIdToSchemaMap(schemas); 21 | const resolvedSchemas: { 22 | [key: string]: Schema; 23 | } = {}; 24 | 25 | for (const id of Object.keys(idToSchemaMap)) { 26 | const resolvedSchema = resolveSchema(idToSchemaMap, id); 27 | resolvedSchemas[id] = resolvedSchema; 28 | } 29 | 30 | await fs.writeFile(outputPath, JSON.stringify(resolvedSchemas)); 31 | })(); 32 | -------------------------------------------------------------------------------- /tools/generate-resolved-schemas/utils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'node:fs/promises'; 2 | import { readdir } from 'node:fs/promises'; 3 | import path from 'path'; 4 | 5 | type SchemaProperty = object; 6 | type SchemaProperties = Record; 7 | export type Schema = { 8 | $schema: string; 9 | $id: string; 10 | description: string; 11 | type: string; 12 | properties?: SchemaProperties; 13 | required?: string[]; 14 | allOf?: ( 15 | | { properties: SchemaProperties; required?: string[] } 16 | | { $ref: Ref } 17 | )[]; 18 | }; 19 | 20 | /** 21 | * buildIdToSchemaMap creates a lookup map for schemas from their id. 22 | * @param { Schema[] } schemas - an array of schemas 23 | * @returns { Record } an object with each schema mapped to it's id 24 | */ 25 | export function buildIdToSchemaMap(schemas: Schema[]): Record { 26 | const map = {}; 27 | for (const schema of schemas) { 28 | map[schema.$id] = schema; 29 | } 30 | return map; 31 | } 32 | 33 | /** 34 | * resolveSchema resolves a schema with `id` to have all properties, both 35 | * defined and inherited in a single object `properties`. 36 | * @param { Record } idToSchemas - lookup for schemas by their id 37 | * @param { string } id - the id of the schema to resolve 38 | * @returns resolved schema with all properties under a single `properties` field 39 | */ 40 | export function resolveSchema( 41 | idToSchemas: Record, 42 | id: string, 43 | ): Schema { 44 | const schema = idToSchemas[id]; 45 | if (schema.properties) { 46 | return schema; 47 | } 48 | 49 | const { properties, required } = resolvePropertiesAndRequired( 50 | idToSchemas, 51 | id, 52 | ); 53 | 54 | return { 55 | $schema: schema.$schema, 56 | $id: schema.$id, 57 | description: schema.description, 58 | type: schema.type, 59 | properties: sortObject(properties), 60 | required, 61 | }; 62 | } 63 | 64 | /** 65 | * resolveProperties resolves the properties of a schema by first recursively 66 | * resolving the properties of any parent schemas, then resolving the properties 67 | * defined on the schema itself. 68 | * 69 | * Inherited properties will be overwritten by the more local version of the 70 | * property. {e.g. parent defines `username` and child defines `username`. 71 | * the child's version of `username` will overwrite the parent's. } 72 | * 73 | * @param { Record } idToSchemas - a lookup for schema ids to the schema 74 | * @param { string } id - the $id of the schema to resolve 75 | * @returns { Record } an object with all resolved properties of the schema 76 | */ 77 | function resolvePropertiesAndRequired( 78 | idToSchemas: Record, 79 | id: string, 80 | ): { properties: SchemaProperties; required?: string[] } { 81 | let resolvedProperties: SchemaProperties = {}; 82 | let resolvedRequired: string[] = []; 83 | const schema = idToSchemas[id]; 84 | // The top-level schema that all other schemas inherit from is 85 | // GraphObject. It defines properties at the top-level. This is 86 | // used as the base case. 87 | if (schema.$id === '#GraphObject') { 88 | return { 89 | properties: schema.properties ?? {}, 90 | required: schema.required, 91 | }; 92 | } 93 | 94 | if (schema.allOf) { 95 | for (const obj of schema.allOf) { 96 | if ('$ref' in obj) { 97 | const { properties: parentProperties, required: parentRequired } = 98 | resolvePropertiesAndRequired(idToSchemas, obj['$ref']); 99 | 100 | resolvedProperties = { 101 | ...addInheritedToProperties(parentProperties), 102 | ...resolvedProperties, 103 | }; 104 | 105 | resolvedRequired = [...(parentRequired ?? []), ...resolvedRequired]; 106 | } 107 | 108 | if ('properties' in obj) { 109 | resolvedProperties = { 110 | ...resolvedProperties, 111 | ...obj['properties'], 112 | }; 113 | resolvedRequired = [...resolvedRequired, ...(obj['required'] ?? [])]; 114 | } 115 | } 116 | } 117 | 118 | return { 119 | properties: resolvedProperties, 120 | required: resolvedRequired.length 121 | ? Array.from(new Set(resolvedRequired)) 122 | : undefined, 123 | }; 124 | } 125 | /** 126 | * sortObject sorts an objects and returns an object with keys in alphabetical 127 | * order 128 | * @param { Object } obj 129 | * @returns an object with the keys in sorted alphabetical order 130 | */ 131 | function sortObject>(obj: T) { 132 | const orderedKeys = Object.keys(obj).sort((a, b) => { 133 | if (a.toLowerCase() < b.toLowerCase()) { 134 | return -1; 135 | } else { 136 | return 1; 137 | } 138 | }); 139 | 140 | const sortedObj: Record = {}; 141 | for (const key of orderedKeys) { 142 | sortedObj[key] = obj[key]; 143 | } 144 | return sortedObj as T; 145 | } 146 | 147 | /** 148 | * addInheritedToProperties adds an inherited property set to true in each 149 | * child object 150 | * @param { Record } properties 151 | * @returns an object with inherited properties set to true 152 | */ 153 | function addInheritedToProperties(properties: SchemaProperties) { 154 | const inheritedProperties = {}; 155 | for (const [key, value] of Object.entries(properties)) { 156 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 157 | inheritedProperties[key] = { ...value, inherited: true }; 158 | } 159 | return inheritedProperties; 160 | } 161 | 162 | /** 163 | * readAllSchemas reads all schemas from `src/schemas` and returns an array of 164 | * parsed Schemas. 165 | * @returns { Promise } - An array of parsed Schemas 166 | */ 167 | export async function readAllSchemas(dir: string): Promise { 168 | const files: string[] = await readdir(dir); 169 | const schemas: Schema[] = []; 170 | for (const file of files) { 171 | const filePath = path.join(dir, file); 172 | const schemaBlob = await fs.readFile(filePath); 173 | const schemaString = schemaBlob.toString(); 174 | try { 175 | JSON.parse(schemaString); 176 | } catch (err) { 177 | console.log(filePath, schemaString); 178 | } 179 | const parsedSchema = JSON.parse(schemaString) as Schema; 180 | schemas.push(parsedSchema); 181 | } 182 | 183 | return schemas; 184 | } 185 | -------------------------------------------------------------------------------- /tools/generate-schema-imports.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MARKER='// Schema Imports' 4 | 5 | sed -i"" -e "\|$MARKER|,$ {" -e "\|$MARKER|b" -e d -e "}" src/IntegrationSchema.ts 6 | 7 | for SCHEMA_FILENAME in $(ls src/schemas | sort); do 8 | SCHEMA=$(echo $SCHEMA_FILENAME | cut -d . -f 1) 9 | sed -i"" "\|$MARKER|a\\ 10 | import ${SCHEMA}Json from './schemas/$SCHEMA_FILENAME';\\ 11 | export const ${SCHEMA} = ${SCHEMA}Json;\\ 12 | IntegrationSchema.addSchema($SCHEMA);\\ 13 | \\ 14 | " src/IntegrationSchema.ts 15 | done 16 | 17 | git add src/IntegrationSchema.ts 18 | -------------------------------------------------------------------------------- /tsconfig.dist.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["src/**/*.test.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["dist"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "target": "es2018", 6 | "lib": ["es2018"], 7 | "module": "commonjs", 8 | "inlineSourceMap": true, 9 | "moduleResolution": "node", 10 | "noUnusedLocals": true, 11 | "pretty": true, 12 | "resolveJsonModule": true, 13 | "esModuleInterop": true, 14 | "noImplicitThis": true, 15 | "alwaysStrict": true, 16 | "strictNullChecks": true, 17 | "strictFunctionTypes": true, 18 | "allowJs": false 19 | } 20 | } 21 | --------------------------------------------------------------------------------