Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Development #3

Open
wants to merge 107 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
35d727c
Folder strcuture changes
narendra-sacumen Jun 8, 2022
538fec7
Folder strcuture changes
narendra-sacumen Jun 8, 2022
848cc66
Folder strcuture changes
narendra-sacumen Jun 8, 2022
bd0f2cb
Folder strcuture changes
narendra-sacumen Jun 8, 2022
02b250c
Folder strcuture changes
narendra-sacumen Jun 8, 2022
cedd76b
Ignoring node_modules from scan
narendra-sacumen Jun 8, 2022
57259b5
Ignoring node_modules from scan
narendra-sacumen Jun 8, 2022
793174a
Ignoring node_modules from scan
narendra-sacumen Jun 8, 2022
2fa163f
Ignoring node_modules from scan
narendra-sacumen Jun 8, 2022
b54b126
Ignoring node_modules from scan
narendra-sacumen Jun 8, 2022
20ff4b7
Updated development.md file with necessary info
narendra-sacumen Jun 10, 2022
54c96b2
Update filters config
narendra-sacumen Jun 10, 2022
55b52db
Removed unnecessary file
narendra-sacumen Jun 10, 2022
b583179
testcases for ms defender
devika-sacumen Jun 13, 2022
9cd5431
removed package.lock.json
devika-sacumen Jun 13, 2022
25e42b3
removed snapshort files
devika-sacumen Jun 13, 2022
e4e6351
removed snapshort files
devika-sacumen Jun 13, 2022
a9c5b0f
package.json
devika-sacumen Jun 13, 2022
7a4383a
package.json
devika-sacumen Jun 13, 2022
3dfb191
removed all unwanted files
devika-sacumen Jun 13, 2022
61a0359
changes in packege.json
devika-sacumen Jun 13, 2022
9f7bf0c
formated files
devika-sacumen Jun 13, 2022
edcdf41
removed node modules
devika-sacumen Jun 13, 2022
02a4d1d
Merge branch 'development' of https://github.com/narendra-sacumen/ms_…
devika-sacumen Jun 13, 2022
e665841
code changes in test cases
devika-sacumen Jun 13, 2022
b01d48b
code changes in test cases
devika-sacumen Jun 13, 2022
671ebb2
commited code in testcases
devika-sacumen Jun 13, 2022
790c28f
commited code in testcases
devika-sacumen Jun 13, 2022
e608d71
changes in testcaases
devika-sacumen Jun 13, 2022
ea879e1
code changes
devika-sacumen Jun 13, 2022
d2e9847
code changes
devika-sacumen Jun 13, 2022
f742cd9
code changes
devika-sacumen Jun 13, 2022
b87e90e
code changed in package.json
devika-sacumen Jun 13, 2022
569687c
formatted code
devika-sacumen Jun 13, 2022
c89a520
formatted code
devika-sacumen Jun 13, 2022
cd9a9f0
testcases for ms defender
devika-sacumen Jun 13, 2022
ff974a2
testcases for ms defender
devika-sacumen Jun 13, 2022
52a52b8
removed code which is not needed
devika-sacumen Jun 13, 2022
e638d0f
removed code which is not needed
devika-sacumen Jun 13, 2022
4846c89
remaining testcases for ms defender
devika-sacumen Jun 14, 2022
ab92acb
remaining testcases for ms defender with snapshorts
devika-sacumen Jun 14, 2022
6f65658
Addec code for recordings for http calls
narendra-sacumen Jun 14, 2022
0f80be7
few changes related to the comments
devika-sacumen Jun 14, 2022
22ecf3a
few changes related to the comments
devika-sacumen Jun 14, 2022
a1b00ad
changes regarding to the comments
devika-sacumen Jun 15, 2022
deb3ec8
commented all test files
devika-sacumen Jun 15, 2022
63cfd5f
commented all test files
devika-sacumen Jun 15, 2022
082a48e
uncommented all test files
devika-sacumen Jun 15, 2022
2660983
removed undefined according to the comment
devika-sacumen Jun 15, 2022
0e71ca9
id changed undefined to value in testcases
devika-sacumen Jun 15, 2022
49c95c5
id changed in testcase
devika-sacumen Jun 15, 2022
751b47b
changes in .env.example file
devika-sacumen Jun 16, 2022
a6c03ad
removed coverage from the Pr
devika-sacumen Jun 16, 2022
385af39
removed config commented lines
devika-sacumen Jun 20, 2022
d274f18
Removed package-lock file
narendra-sacumen Jun 20, 2022
8552395
Removed unnecessary test
narendra-sacumen Jun 20, 2022
df2f5ce
Rmeoved intune related code
narendra-sacumen Jun 20, 2022
ce5ef74
Removing sensitive info to be printed in recording files
narendra-sacumen Jun 20, 2022
1ad28a4
Removing sensitive info to be printed in recording files
narendra-sacumen Jun 20, 2022
8bcd162
Added latest recording files
narendra-sacumen Jun 20, 2022
3a8b87a
Intune related code removed
narendra-sacumen Jun 20, 2022
f7bcf73
Intune related code removed
narendra-sacumen Jun 20, 2022
f2d5ce9
unserendpoint name changes
narendra-sacumen Jun 20, 2022
381046a
msdefender steps
devika-sacumen Jun 20, 2022
fdd8d46
msdefender steps
devika-sacumen Jun 20, 2022
76f18bb
msdefender steps
devika-sacumen Jun 20, 2022
9258017
Fixed issue occruring when findings values in env variables are not set
narendra-sacumen Jun 20, 2022
65984ce
testcases for msdefender steps
devika-sacumen Jun 20, 2022
1242ef1
Added numeric severity mapping code
narendra-sacumen Jun 20, 2022
0b2e6f7
Merge branch 'development' of https://github.com/narendra-sacumen/ms_…
devika-sacumen Jun 20, 2022
31295ee
Removed unused code
narendra-sacumen Jun 20, 2022
1700019
Updated documentation for ms defender
narendra-sacumen Jun 20, 2022
1632d47
Code changes for consistant cve key
narendra-sacumen Jun 21, 2022
abad481
Code changes for consistant cve key
narendra-sacumen Jun 21, 2022
f3bb537
Code changes for consistant cve key
narendra-sacumen Jun 21, 2022
b98945e
Updated numeric severity code
narendra-sacumen Jun 21, 2022
02394c6
isDefenderapi is removed from mutating in every api
narendra-sacumen Jun 21, 2022
a1e4ad9
Removed unnecessary flag
narendra-sacumen Jun 21, 2022
45cbae5
fixed typo errors & few configurations & unit testcase mentioned in t…
devika-sacumen Jun 22, 2022
50c6de9
few more changes in testcases comments fixed
devika-sacumen Jun 22, 2022
0b8746c
BASE_API_URL is removed from env as it is required only in single file
narendra-sacumen Jun 22, 2022
8a7c14b
BASE_API_URL is removed from env as it is required only in single file
narendra-sacumen Jun 22, 2022
d648ea2
Removed env vars reading, added them to instanceconfig
narendra-sacumen Jun 22, 2022
bbd2dec
Removed env vars reading, added them to instanceconfig
narendra-sacumen Jun 22, 2022
24ba01b
snapshots fixes
devika-sacumen Jun 22, 2022
72351b3
snapshots fixes
devika-sacumen Jun 22, 2022
500bf6d
snapshots fixes
devika-sacumen Jun 22, 2022
b56c11f
snapshots fixes
devika-sacumen Jun 22, 2022
ae1e899
snapshots fixes
devika-sacumen Jun 22, 2022
99344c5
minor changes in snapshorts
devika-sacumen Jun 22, 2022
0f00f77
removed unwanted code
devika-sacumen Jun 22, 2022
71b4892
removed unwanted code
devika-sacumen Jun 22, 2022
c444e86
removed unwanted code
devika-sacumen Jun 22, 2022
a813c21
removed unwanted code
devika-sacumen Jun 22, 2022
2d07b0d
removed unwanted code
devika-sacumen Jun 22, 2022
1f9ad12
Documentation updates
narendra-sacumen Jun 22, 2022
75fa1d2
removed async from testcase
devika-sacumen Jun 23, 2022
b252a8e
removed async from testcase
devika-sacumen Jun 23, 2022
b0b3d92
testcase error resolved
devika-sacumen Jun 23, 2022
a2a133b
Merge branch 'development' of https://github.com/narendra-sacumen/ms_…
devika-sacumen Jun 23, 2022
ae36ac5
added tests for inaccwssible and insufficient permission
narendra-sacumen Jun 23, 2022
013372b
added tests for inaccwssible and insufficient permission
narendra-sacumen Jun 23, 2022
0d071d9
added tests for inaccwssible and insufficient permission
narendra-sacumen Jun 23, 2022
8f94c2d
changes in testcase
devika-sacumen Jun 23, 2022
c2b74a5
removed commented code
devika-sacumen Jun 23, 2022
bdddeec
snapshots for all testcases
devika-sacumen Jun 23, 2022
a5f1884
changed testases relationships
devika-sacumen Jun 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
CLIENT_ID=
CLIENT_SECRET=
CLIENT_SECRET=
TENANT=
FINDING_SEVERITY=
FINDING_LIMIT=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist/
.env
.eslintcache
tsconfig.tsbuildinfo
coverage/
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for adding this to .gitignore. 👍 However, all the content in that directory was still added to this branch/PR, so will need to be removed.

Copy link
Author

Choose a reason for hiding this comment

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

@aiwilliams I have removed all the files related to the code coverage

190 changes: 174 additions & 16 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,186 @@
# Development

Add details here to give a brief overview of how to work with the provider APIs.
Please reference any SDKs or API docs used to help build the integration here.
This Readme document provides details on how to leverage MS Defender Graph API
to access Microsoft defender data such as the Defender agent status,
Device\Machines data, Users, and associated vulnerabilities. Here we will
explore how to set up a Microsoft Azure account to access MS defender graph API.

## Prerequisites

Supply details about software or tooling (like maybe Docker or Terraform) that
is needed for development here.
- An Azure account with an App Registration that will provide credentials for
the integration to authenticate with Microsoft Graph APIs. The App
Registration also defines the permissions the integration requires and which
the target tenant must authorize.
- An Active Directory tenant to target for ingestion. It is possible to target
the Active Directory tenants defined in the Azure account holding the App
Registration. Multi-tenant App Registrations that have not undergone
[Publisher Verification][publisher-verification] cannot access other tenants.
- A Microsoft Defender for Endpoint account to create devices and run attacks
via simulation technique. Can track vulnerabilities data, user groups creation
and mapping users to devices.

Please supply references to documentation that details how to install those
dependencies here.
A JupiterOne staff developer can provide credentials for an existing development
Azure account with an App Registration and tenants that tests are written
against. This is the easiest way to begin making changes to the integration.

Tools like Node.js and NPM are already covered in the [README](../README.md) so
don't bother documenting that here.
Alternatively, you may establish a new Azure account, though tests will likely
need to be improved to avoid specific account information.

## Provider account setup
## App Registration

Please provide information about the steps needed to create an account with a
provider. Images and references to a provider's documentation is very helpful
for new developers picking up your work.
In Ms Defender portal:

1. [Create a Microsoft Defender for Endpoint account](https://www.microsoft.com/en-us/security/business/threat-protection/endpoint-defender)
2. [Set up the lab and add devices](#add-devices-and-simulations)

In the Azure portal:

1. Create a mulit-tenant App Registration
2. Configure the required [API permissions](#api-permissions)
3. Add a 2-year secret

## Add Devices and Simulations

To test the integration, we will need some test data, since we are working with
MS defender, an actual environment is needed. Such an environment will have an
Organization setup, Multiple Servers running a Defender agent on it, some users
associated with each machine (Server), and finally some vulnerabilities on some
of the machines. This kind of live environment setup will be very costly as well
as a tedious job, fortunately, Microsoft predicted that and provided an option
to create a testing Lab. You can use this Lab to create virtual test Machines,
users, Defender agents, and Vulnerabilities. This virtual environment will act
as a live environment and give you similar results when you hit any MS Defender
APIs. To create a Lab go to the
[Defender portal](https://security.microsoft.com/homepage), and navigate
to **Evaluations**.

1. Setup Lab

1. Choose number of devices
2. Accept terms and provide consent by checking the check box
3. Setup lab

2. Add devices
1. Available Tools
2. Refresh the page to see the device status

It should be Status → Active and Simulator status → Completed . (It will take
some time to set up the device). After device setup is completed:

3. Go to Simulation tab and create simulation Select simulator → All Select
simulation → SafeBreach: Credential Theft Select device → testmachine1
4. Click on create simulation

### API Permissions

Need to setup API permissions under two containers (one for
[azure account data](#microsoft-graph) and one for
[defender account data](#windowsdefenderatp))

#### Microsoft Graph

1. `Organization.Read.All`
1. Read organization information
2. Needed for creating the `Account` entity
2. `Directory.Read.All`
1. Read directory data
2. Needed for creating `User`, `Group`, and `GroupUser` entities

#### WindowsDefenderATP

1. `Machine.Read.All`
1. Read machine information
2. Needed for creating `Device` and `HostAgent` entities
2. `User.Read.All`
1. Read user profiles
2. Needed for creating `User` entities
3. `Vulnerability.Read.All`
1. Read Threat and Vulnerability Management vulnerability information
2. Needed for creating `Finding` entity

## Target Tenants

The integration is tested against three Active Directory tenants:

1. The app is installed, all permissions are granted
1. The app is installed, most permissions are insufficient
1. The app is not installed
aiwilliams marked this conversation as resolved.
Show resolved Hide resolved

This allows for ensuring the Microsoft Graph API code handles some common target
configuration scenarios.

You'll need a user account with global administrator access in each tenant.
[Grant admin consent](#authentication) to the multi-tenant application as
follows:

1. Default tenant: grant permission now and always grant new permissions as
development of converters advances
2. "J1 Insufficient Permissions" tenant: grant permissions now
(`Directory.Read.All` is all at this point in setup), but never grant any
additional permisssions, to allow for testing cases where the app cannot
fetch resources
3. "J1 Inaccessible" tenant: do not install the app at all here, to allow for
testing cases where we have not been installed in a valid directory

Update `test/config.ts` with directory IDs as appropriate.

## Authentication

Supply details here for information on how to authenticate with a provider so
that developers have an idea of what's needed to hit APIs. It may be useful to
provide explanations for each value specified in the
[`IntegrationInstanceConfigFieldMap`](../src/config.ts).
The flow will provide the tenant ID where consent has been granted, which is
stored for use in Microsoft Graph API calls.

Admin consent is granted to JupiterOne by:

1. Log in to JupiterOne as a user with permission to set up an integration
2. Add a Microsoft defender integration instance
3. You will be directed to Microsoft's identity platform, where you must login
in as a global administrator of the Active Directory tenant you intend to
target/ingest
4. Review the requested permissions and grant consent

Use this `tenant` ID and information from the App Registration to create an
`.env` file for local execution of the daemon/server application (this
repository):

```
CLIENT_ID='885121e7-c3c6-4378-8f6b-e315cc5994ce'
CLIENT_SECRET='<top secret passphrase>'
TENANT='<tenant / directory id>'
```

## References

How to set up permissions in the Azure console

- https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis
- https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-overview

How to add a client secret in the Azure console

- https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret

Sample Client Credentials Flow Project

- https://github.com/AzureAD/azure-activedirectory-library-for-nodejs/blob/master/sample/client-credentials-sample.js

SDK Links

- https://docs.microsoft.com/en-us/azure/developer/javascript/azure-sdk-library-package-index
- https://docs.microsoft.com/en-us/javascript/api/overview/azure/activedirectory?view=azure-node-latest

Client Credentials oAuth flow Overview

- https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#application-permissions

[msgraph-api]: https://docs.microsoft.com/en-us/graph/overview

#### APIs used for data ingestion :

To fetch machines :
https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machines?view=o365-worldwide

To fetch Logon users :
https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machine-log-on-users?view=o365-worldwide

To fetch vulnerabilities :
https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-discovered-vulnerabilities?view=o365-worldwide
32 changes: 22 additions & 10 deletions docs/jupiterone.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,33 @@ https://github.com/JupiterOne/sdk/blob/main/docs/integrations/development.md

The following entities are created:

| Resources | Entity `_type` | Entity `_class` |
| --------- | -------------- | --------------- |
| Account | `acme_account` | `Account` |
| User | `acme_user` | `User` |
| UserGroup | `acme_group` | `UserGroup` |
| Resources | Entity `_type` | Entity `_class` |
| ------------- | ---------------------------------- | ---------------- |
| Account | `microsoft_defender_account` | `Account` |
| CVE | `cve` | `Vulnerability` |
| Device | `user_endpoint` | `Device`, `Host` |
| Machine | `microsoft_defender_machine` | `HostAgent` |
| User | `microsoft_defender_logon_user` | `User` |
| Vulnerability | `microsoft_defender_vulnerability` | `Finding` |

### Relationships

The following relationships are created:

| Source Entity `_type` | Relationship `_class` | Target Entity `_type` |
| --------------------- | --------------------- | --------------------- |
| `acme_account` | **HAS** | `acme_group` |
| `acme_account` | **HAS** | `acme_user` |
| `acme_group` | **HAS** | `acme_user` |
| Source Entity `_type` | Relationship `_class` | Target Entity `_type` |
| ---------------------------- | --------------------- | ---------------------------------- |
| `microsoft_defender_account` | **HAS** | `microsoft_defender_machine` |
| `microsoft_defender_machine` | **HAS** | `microsoft_defender_logon_user` |
| `microsoft_defender_machine` | **IDENTIFIED** | `microsoft_defender_vulnerability` |

### Mapped Relationships

The following mapped relationships are created:

| Source Entity `_type` | Relationship `_class` | Target Entity `_type` | Direction |
| ---------------------------------- | --------------------- | --------------------- | --------- |
| `microsoft_defender_machine` | **MANAGES** | `*user_endpoint*` | FORWARD |
| `microsoft_defender_vulnerability` | **IS** | `*cve*` | FORWARD |

<!--
********************************************************************************
Expand Down
5 changes: 4 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
module.exports = require('@jupiterone/integration-sdk-dev-tools/config/jest');
module.exports = {
...require('@jupiterone/integration-sdk-dev-tools/config/jest'),
setupFiles: ['dotenv/config'],
};
Comment on lines +1 to +4
Copy link
Contributor

Choose a reason for hiding this comment

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

These lines should be deleted. Line 1 already exports the content of line 3 here, and the test/config.ts file loads dotenv.

Choose a reason for hiding this comment

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

@aiwilliams , repeated line is removed .

Copy link
Contributor

Choose a reason for hiding this comment

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

This file should be exactly:

module.exports = require('@jupiterone/integration-sdk-dev-tools/config/jest');

The setupFiles should not be configured. The purpose of yarn test:env is to load the test/config.js, which configures dotenv appropriately.

41 changes: 27 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@jupiterone/integration-template",
"name": "@jupiterone/graph-microsoft-endpoint-defender",
"version": "0.0.0",
"description": "A JupiterOne Integration",
"description": "A JupiterOne Integration for Microsoft Defender for Endpoint",
"license": "MPL-2.0",
"main": "src/index.js",
"types": "src/index.d.ts",
Expand All @@ -15,26 +15,39 @@
"scripts": {
"start": "j1-integration collect",
"graph": "j1-integration visualize",
"graph:types": "j1-integration visualize-types",
"graph:spec": "j1-integration visualize-types --project-path docs/spec --output-file ./.j1-integration/types-graph/index.spec.html",
"validate:questions:dry": "j1-integration validate-question-file --dry-run",
"validate:questions": "j1-integration validate-question-file -a $MANAGED_QUESTIONS_JUPITERONE_ACCOUNT_ID -k $MANAGED_QUESTIONS_JUPITERONE_API_KEY",
"lint": "eslint . --cache --fix --ext .ts,.tsx",
"format": "prettier --write '**/*.{ts,js,json,css,md,yml}'",
"format:check": "prettier --check '**/*.{ts,js,json,css,md,yml}'",
"format": "prettier --write **/*.{ts,js,json,css,md,yml}",
"format:check": "prettier --check **/*.{ts,js,json,css,md,yml}",
"type-check": "tsc",
"test": "jest",
"test:env": "LOAD_ENV=1 yarn test",
"test:env": "LOAD_ENV=1 jest",
"test:ci": "yarn format:check && yarn lint && yarn type-check && yarn test",
"build": "tsc -p tsconfig.dist.json --declaration && cp README.md dist/README.md && cp -r jupiterone/ dist/jupiterone/",
"prepush": "yarn format:check && yarn lint && yarn type-check && jest --changedSince main"
"prepush": "yarn format:check && yarn lint && yarn type-check && jest --changedSince main",
"graph:spec": "j1-integration visualize-types --project-path docs/spec --output-file ./.j1-integration/types-graph/index.spec.html",
"graph:types": "j1-integration visualize-types",
"validate:questions": "j1-integration validate-question-file -a $MANAGED_QUESTIONS_JUPITERONE_ACCOUNT_ID -k $MANAGED_QUESTIONS_JUPITERONE_API_KEY",
"validate:questions:dry": "j1-integration validate-question-file --dry-run"
},
"dependencies": {
"@azure/identity": "^1.2.2",
"@microsoft/microsoft-graph-client": "^2.2.1",
"@testing-library/jest-dom": "^5.16.4",
"dotenv": "^16.0.1",
"isomorphic-unfetch": "^3.1.0",
"lodash": "^4.17.20"
},
"peerDependencies": {
"@jupiterone/integration-sdk-core": "^8.8.0"
"@jupiterone/integration-sdk-core": "^8.10.1"
},
"devDependencies": {
"@jupiterone/integration-sdk-core": "^8.8.0",
"@jupiterone/integration-sdk-dev-tools": "^8.8.0",
"@jupiterone/integration-sdk-testing": "^8.8.0"
"@jupiterone/integration-sdk-cli": "^8.10.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

https://github.com/JupiterOne/integration-template/blob/main/package.json indicates this is not an entry here required. Additionally, https://github.com/JupiterOne/sdk/blob/main/packages/integration-sdk-dev-tools/package.json shows that it is available as a transitive dependency.

Ideally, this package.json file would be little changed from the template form when projects are first created.

"@jupiterone/integration-sdk-core": "^8.14.0",
"@jupiterone/integration-sdk-dev-tools": "^8.13.10",
"@jupiterone/integration-sdk-testing": "^8.10.1",
"@microsoft/microsoft-graph-types": "^1.28.0",
"@microsoft/microsoft-graph-types-beta": "microsoftgraph/msgraph-typescript-typings#beta",
"@types/node": "^14",
"prettier": "2.7.0"
}
}
Loading