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

wiz (new) #169

Draft
wants to merge 28 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/appmixer/wiz/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

module.exports = {

type: 'pwd',

definition: {

auth: {
clientId: {
type: 'text',
name: 'Client ID'
},
clientSecret: {
type: 'text',
name: 'Client Secret'
}
},

accountNameFromProfileInfo: context => {

const name = context.clientId;
const threshold = 10;
if (name.length > threshold) {
return name.slice(0, 3) + '....' + name.slice(-3);
}
return name;
},

validate: async context => {

const url = 'https://auth.app.wiz.io/oauth/token';

const { data } = await context.httpRequest({
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
'accept': 'application/json'
},
data: {
grant_type: 'client_credentials',
audience: 'wiz-api',
client_id: context.clientId,
client_secret: context.clientSecret
},
url
});

return {
token: data.access_token,
expires: data.expires_in
};
}
}
};
9 changes: 9 additions & 0 deletions src/appmixer/wiz/bundle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "appmixer.wiz",
"version": "1.0.0",
"changelog": {
"1.0.0": [
"Initial version."
]
}
}
32 changes: 32 additions & 0 deletions src/appmixer/wiz/core/FindCloudResources/FindCloudResources.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';
const lib = require('../../lib');
const resources = require('./resources');

module.exports = {

// docs: https://win.wiz.io/reference/pull-cloud-resources
async receive(context) {

const resourceType = 'exposed'; // exposed or cloud
const resourceGetter = resources[resourceType];

const { outputType, filter, limit = 10 } = context.messages.in.content;

if (context.properties.generateOutputPortOptions) {
return lib.getOutputPortOptions(context, outputType, resourceGetter.schema);
}

let filterBy;
if (filter) {
try {
filterBy = JSON.parse(filter);
} catch (e) {
throw new context.CancelError('Invalid Input: Filter', e);
}
}

const records = await resourceGetter.getResources(context, { filterBy, limit });

return lib.sendArrayOutput({ context, records, outputType });
}
};
80 changes: 80 additions & 0 deletions src/appmixer/wiz/core/FindCloudResources/component.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"name": "appmixer.wiz.core.FindCloudResources",
"author": "Appmixer <[email protected]>",
"description": "Execute the CloudResourceSearch query to return a list of cloud resources according to different filters, such as project ID or entity type.",
"private": false,
"auth": {
"service": "appmixer:wiz"
},
"quota": {
"manager": "appmixer:wiz",
"resources": "requests"
},
"version": "1.0.0",
"inPorts": [
{
"name": "in",
"schema": {
"type": "object",
"properties": {
"filter": { "type": "string" },
"limit": { "type": "number" },
"outputType": { "type": "string" }
},
"required": []
},
"inspector": {
"inputs": {
"filter": {
"type": "textarea",
"label": "Filter",
"tooltip": "This object defines query filters to narrow down search results and return specific cloud resources.",
"index": 0
},
"limit": {
"type": "number",
"label": "Limit",
"defaultValue": 100,
"index": 1
},
"outputType": {
"type": "select",
"label": "Output Type",
"index": 2,
"defaultValue": "array",
"tooltip": "Choose whether you want to receive the result set as one complete list, or first item only or one item at a time or stream the items to a file.",
"options": [
{ "label": "First Item Only", "value": "first" },
{ "label": "All items at once", "value": "array" },
{ "label": "One item at a time", "value": "object" },
{ "label": "Store to CSV file", "value": "file" }
]
}
}
}
}
],
"outPorts": [
{
"name": "out",
"source": {
"url": "/component/appmixer/wiz/core/FindCloudResources?outPort=out",
"data": {
"properties": {
"generateOutputPortOptions": true
},
"messages": {
"in/outputType": "inputs/in/outputType"
}
}
}
},
{
"name": "notFound",
"options": [
{ "label": "Filter", "value": "filter" }
]
}
],
"icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIGNsYXNzPSJTdmdJY29uX19TdHlsZWRJY29uLXNjLXYxbnN1ei0wIGgtW2NhbGModmFyKC0tdG9wLW5hdmJhci1oZWlnaHQpLThweCldIGljb24tYWNjZW50IGRhcms6aWNvbi13aGl0ZSIgdmlld0JveD0iMTYgNCA2OCA1MCI+PHBhdGggZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzkuNzE3IDI3LjExNmEuMDk3LjA5NyAwIDAgMCAuMTc5LS4wMDZsMi44NDItNy40MWEuOTIuOTIgMCAwIDEgLjg1MS0uNTlsMi42NTEtLjAxNGEuOTE2LjkxNiAwIDAgMSAuODY1IDEuMjM1TDQwLjY5MyAzNy42NGMtLjAxLjAyNy0uMjIuMjExLS4zNTQuMzE0LS4wNjYuMDUtLjE0NC4wNTYtLjIyNC4wMzNhLjkuOSAwIDAgMS0uNTgtLjUxNmwtMy40MjEtOC4yNDZhLjQ4NC40ODQgMCAwIDAtLjg3NS0uMDE4bC00LjI5IDguNThhLjA5Ny4wOTcgMCAwIDEtLjE3OC0uMDA4bC02LjcwOS0xNy40NDVhLjkxNy45MTcgMCAwIDEgLjg1NS0xLjI0NWgyLjg4Yy4zOCAwIC43Mi4yMzQuODU2LjU4OWwyLjg0MiA3LjQzMmMuMDMuMDguMTQyLjA4NC4xNzguMDA2bDMuNTgyLTcuNzk2YS40ODUuNDg1IDAgMCAxIC44OCAwek03Mi4zNDggMTIuMDc4Yy0uMDIyLS4xMDQtLjI0NS0uMTA0LS4yNjYgMC0uMTY3LjgxMi0uNTEzIDIuMDM2LTEuMTYzIDIuNjg2LS42NTEuNjUtMS44NzYuOTk3LTIuNjg3IDEuMTYzLS4xMDQuMDIyLS4xMDQuMjQ1IDAgLjI2Ni44MTEuMTY3IDIuMDM2LjUxMyAyLjY4NiAxLjE2My44NS44NSAxLjE0MyAyLjAxIDEuMjQ0IDIuNzA4LjAwNi4wNDQuMTQ1LjA1LjE1My4wMDcuMTUzLS43NS41LTIuMDIgMS4xOTYtMi43MTUuNjUtLjY1IDEuODc1LS45OTYgMi42ODYtMS4xNjMuMTA0LS4wMjEuMTA0LS4yNDQgMC0uMjY2LS44MTEtLjE2Ni0yLjAzNi0uNTEyLTIuNjg2LTEuMTYzLS42NS0uNjUtLjk5Ny0xLjg3NC0xLjE2My0yLjY4Nk00OC4xNjQgMjAuMTA4YzAtLjUwNy40MS0uOTE3LjkxNy0uOTE3aDIuNzdjLjUwNiAwIC45MTYuNDEuOTE2LjkxN3YxNi45NmMwIC41MDYtLjQxLjkxNi0uOTE3LjkxNmgtMi43N2EuOTE3LjkxNyAwIDAgMS0uOTE2LS45MTd6TTYwLjc2NCAyNC4wNDJhLjI0Mi4yNDIgMCAwIDAtLjIxNy0uMzVoLTUuNDczYS45MTcuOTE3IDAgMCAxLS45MTctLjkxN3YtMi42NjdjMC0uNTA3LjQxLS45MTcuOTE3LS45MTdoMTIuNjI4Yy4zOTIgMCAuOTE5LjMxOS43MzIuNjY0LS4wNi4xMS03LjI2NyAxMy41OTMtNy4yOTkgMTMuNjUybC0uMDAxLjAwM2EuMjQyLjI0MiAwIDAgMCAuMjE0LjM1Nmg2LjY3Yy41MDYgMCAuOTE2LjQxLjkxNi45MTZ2Mi4yODVjMCAuNTA3LS40MS45MTctLjkxNi45MTdINTQuNjI0Yy0uNDQyIDAtLjUzLS42NDItLjMzMi0xLjAzNnoiPjwvcGF0aD48L3N2Zz4="
}
142 changes: 142 additions & 0 deletions src/appmixer/wiz/core/FindCloudResources/resources.cloud.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
* https://win.wiz.io/reference/pull-cloud-resources
* @type {string}
*/
const lib = require('../../lib');

const query = `
query CloudResourceSearch(
$filterBy: CloudResourceFilters
$first: Int
$after: String
) {
cloudResources(
filterBy: $filterBy
first: $first
after: $after
) {
nodes {
...CloudResourceFragment
}
pageInfo {
hasNextPage
endCursor
}
}
}
fragment CloudResourceFragment on CloudResource {
id
name
type
subscriptionId
subscriptionExternalId
graphEntity{
id
providerUniqueId
name
type
projects {
id
}
properties
firstSeen
lastSeen
}
}
`;

const outputSchema = {
'id': { 'type': 'string', 'title': 'Id' },
'name': { 'type': 'string', 'title': 'Name' },
'type': { 'type': 'string', 'title': 'Type' },
'subscriptionId': { 'type': 'string', 'title': 'Subscription Id' },
'subscriptionExternalId': { 'type': 'string', 'title': 'Subscription External ID' },
'graphEntity': {
'type': 'object',
'properties': {
'id': { 'type': 'string', 'title': 'Graph Entity.Id' },
'providerUniqueId': { 'type': 'null', 'title': 'Graph Entity.Provider Unique ID' },
'name': { 'type': 'string', 'title': 'Graph Entity.Name' },
'type': { 'type': 'string', 'title': 'Graph Entity.Type' },
'projects': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'id': { 'type': 'string', 'title': 'Graph Entity.Projects.Id' }
}
},
'title': 'Graph Entity.Projects'
},
'properties': {
'type': 'object',
'properties': {
'_environments': { 'type': 'string', 'title': 'Graph Entity.Properties.Environments' },
'_productIDs': {
'type': 'array',
'items': { 'type': 'string' },
'title': 'Graph Entity.Properties.Product IDs'
},
'_vertexID': { 'type': 'string', 'title': 'Graph Entity.Properties.Vertex ID' },
'cloudPlatform': { 'type': 'string', 'title': 'Graph Entity.Properties.Cloud Platform' },
'description': { 'type': 'null', 'title': 'Graph Entity.Properties.Description' },
'externalId': { 'type': 'string', 'title': 'Graph Entity.Properties.External Id' },
'name': { 'type': 'string', 'title': 'Graph Entity.Properties.Name' },
'namespace': { 'type': 'null', 'title': 'Graph Entity.Properties.Namespace' },
'nativeType': { 'type': 'null', 'title': 'Graph Entity.Properties.Native Type' },
'providerUniqueId': { 'type': 'null', 'title': 'Graph Entity.Properties.Provider Unique Id' },
'region': { 'type': 'null', 'title': 'Graph Entity.Properties.Region' },
'subscriptionExternalId': {
'type': 'string',
'title': 'Graph Entity.Properties.Subscription External Id'
}, 'updatedAt': { 'type': 'string', 'title': 'Graph Entity.Properties.Updated At' }
},
'title': 'Graph Entity.Properties'
},
'firstSeen': { 'type': 'string', 'title': 'Graph Entity.First Seen' },
'lastSeen': { 'type': 'string', 'title': 'Graph Entity.Last Seen' }
},
'title': 'Graph Entity'
}
};

module.exports = {
schema: outputSchema,
async getResources(context, { PAGE_SIZE = 500, limit, filterBy }) {

let nextPageToken = null;
let totalRecordsCount = 0;
let records = [];

do {
const { data } = await lib.makeApiCall({
context,
method: 'POST',
data: {
query,
variables: {
first: Math.min(PAGE_SIZE, limit - totalRecordsCount),
after: nextPageToken,
filterBy: filterBy
}
}
});

if (data.errors) {
throw new context.CancelError(data.errors);
}

const { pageInfo = {}, nodes } = data.data.cloudResources;

if (nodes.length === 0) {
return context.sendJson({ filter: filterBy }, 'notFound');
}

records = records.concat(nodes);
totalRecordsCount += nodes.length;
nextPageToken = pageInfo.hasNextPage ? pageInfo.endCursor : null;
} while (nextPageToken && totalRecordsCount < limit);

return records;
}
};
Loading
Loading