Skip to content

New Components - sailpoint #14935

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

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions components/sailpoint/.gitignore

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import sailpoint from "../../sailpoint.app.mjs";

export default {
key: "sailpoint-list-certification-campaigns",
name: "List Certification Campaigns",
description: "Retrieves multiple certification campaigns in IdentityNow. [See the documentation](https://developer.sailpoint.com/docs/api/v2024/get-active-campaigns)",
version: "0.0.1",
type: "action",
props: {
sailpoint,
filter: {
propDefinition: [
"sailpoint",
"filter",
],
optional: true,
},
},
async run({ $ }) {
const response = this.sailpoint.paginate({
fn: this.sailpoint.listCertificationCampaigns,
params: {
detail: "full",
},
});

const responseArray = [];

for await (const item of response) {
responseArray.push(item);
}

$.export("$summary", `Successfully retrieved ${responseArray.length} certification campaigns`);
return responseArray;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { REQUEST_TYPE_OPTIONS } from "../../common/constants.mjs";
import identitynow from "../../identitynow.app.mjs";

export default {
key: "sailpoint-submit-access-request",
name: "Submit Access Request",
description: "Sends an access request to IdentityNow. [See the documentation](https://developer.sailpoint.com/docs/api/v2024/create-access-request)",
version: "0.0.1",
type: "action",
props: {
identitynow,
requestedFor: {
propDefinition: [
identitynow,
"requestedFor",
],
},
requestType: {
type: "string",
label: "Request Type",
description: "Type of access request.",
options: REQUEST_TYPE_OPTIONS,
default: REQUEST_TYPE_OPTIONS[0].value,
},
requestedItems: {
type: "string[]",
label: "Requested Items",
description: "List of requested items as JSON strings. **Example: [{\"type\": \"ROLE\",\"id\": \"2c9180835d2e5168015d32f890ca1581\",\"comment\": \"Requesting access profile for John Doe\",\"clientMetadata\": {\"requestedAppId\":\"2c91808f7892918f0178b78da4a305a1\",\"requestedAppName\":\"test-app\"},\"removeDate\": \"2020-07-11T21:23:15.000Z\"}]**. [See the documentation](https://developer.sailpoint.com/docs/api/v2024/create-access-request) for forther information.",
},
clientMetadata: {
type: "object",
label: "Client Metadata",
description: "Arbitrary key-value pairs. They will never be processed by the IdentityNow system but will be returned on associated APIs such as /account-activities. **Example: {\"requestedAppId\":\"2c91808f7892918f0178b78da4a305a1\",\"requestedAppName\":\"test-app\"}**.",
optional: true,
},
},
async run({ $ }) {
const response = await this.identitynow.submitAccessRequest({
$,
data: {
requestedFor: this.requestedFor,
requestType: this.requestType,
resquestItems: this.resquestItems,
clientMetadata: this.clientMetadata,
},
});
$.export("$summary", "Access request submitted successfully.");
return response;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import FormData from "form-data";
import fs from "fs";
import { checkTmp } from "../../common/utils.mjs";
import sailpoint from "../../sailpoint.app.mjs";

export default {
key: "sailpoint-upload-account-source-file",
name: "Upload Account Source File",
description: "Uploads a CSV-formatted account source file to IdentityNow. [See the documentation]()",
version: "0.0.1",
type: "action",
props: {
sailpoint,
sourceId: {
propDefinition: [
sailpoint,
"sourceId",
],
},
filePath: {
type: "string",
label: "File Path",
description: "The path to a file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).",
},
},
async run({ $ }) {
const data = new FormData();

data.append("file", fs.createReadStream(checkTmp(this.filePath)));

const response = await this.sailpoint.uploadSourceAccountFile({
$,
sourceId: this.sourceId,
data,
headers: data.getHeaders(),
});

$.export("$summary", `Successfully uploaded file for source account: ${response.id} (${response.name})`);
return response;
},
};
13 changes: 0 additions & 13 deletions components/sailpoint/app/sailpoint.app.ts

This file was deleted.

20 changes: 20 additions & 0 deletions components/sailpoint/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const LIMIT = 100;

export const REQUEST_TYPE_OPTIONS = [
{
label: "Grant Access",
value: "GRANT_ACCESS",
},
{
label: "Revoke Access",
value: "REVOKE_ACCESS",
},
];

export const WEBHOOK_TYPE_OPTIONS = [
"HTTP",
"EVENTBRIDGE",
"INLINE",
"SCRIPT",
"WORKFLOW",
];
8 changes: 8 additions & 0 deletions components/sailpoint/common/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
checkTmp(filename) {
if (!filename.startsWith("/tmp")) {
return `/tmp/${filename}`;
}
return filename;
},
};
9 changes: 6 additions & 3 deletions components/sailpoint/package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
{
"name": "@pipedream/sailpoint",
"version": "0.0.3",
"version": "0.1.0",
"description": "Pipedream SailPoint Components",
"main": "dist/app/sailpoint.app.mjs",
"main": "sailpoint.app.mjs",
"keywords": [
"pipedream",
"sailpoint"
],
"files": ["dist"],
"homepage": "https://pipedream.com/apps/sailpoint",
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.0.3"
}
}

145 changes: 145 additions & 0 deletions components/sailpoint/sailpoint.app.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { axios } from "@pipedream/platform";
import { LIMIT } from "./common/constants.mjs";

export default {
type: "app",
app: "sailpoint",
propDefinitions: {
requestedFor: {
type: "string[]",
label: "Requested For",
description: "List of Identity IDs for whom the Access is requested.",
async options({ page }) {
const data = await this.listIdentityIds({
params: {
limit: LIMIT,
offset: LIMIT * page,
},
});

return data.map(({
id: value, name: label,
}) => ({
label,
value,
}));
},
},
sourceId: {
type: "string",
label: "Source ID",
description: "ID of the source to upload the account file.",
async options({ page }) {
const data = await this.listSoruceIds({
params: {
limit: LIMIT,
offset: LIMIT * page,
},
});

return data.map(({
id: value, name: label,
}) => ({
label,
value,
}));
},
},
},
methods: {
_baseUrl() {
return "https://sailpoint.api.identitynow.com/v2024";
},
_headers(headers = {}) {
return {
...headers,
Accept: "application/json",
Authorization: `Bearer ${this.$auth.oauth_access_token}`,
};
},
_makeRequest({
$ = this, path, headers, ...opts
}) {
return axios($, {
url: this._baseUrl() + path,
headers: this._headers(headers),
...opts,
});
},
listIdentityIds(opts = {}) {
return this._makeRequest({
path: "/identities",
headers: {
"X-SailPoint-Experimental": true,
},
...opts,
});
},
listSoruceIds(opts = {}) {
return this._makeRequest({
path: "/sources",
...opts,
});
},
submitAccessRequest(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/access-requests",
...opts,
});
},
uploadSourceAccountFile({
sourceId, ...opts
}) {
return this._makeRequest({
method: "POST",
path: `/sources/${sourceId}/schemas/accounts`,
...opts,
});
},
createWebhook(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/trigger-subscriptions",
headers: {
"X-SailPoint-Experimental": true,
},
...opts,
});
},
deleteWebhook(webhookId) {
return this._makeRequest({
method: "POST",
path: `/trigger-subscriptions/${webhookId}`,
headers: {
"X-SailPoint-Experimental": true,
},
});
},
},
async *paginate({
fn, params = {}, maxResults = null, ...opts
}) {
let hasMore = false;
let count = 0;
let page = 0;

do {
params.page = ++page;
const data = await fn({
params,
...opts,
});
for (const d of data) {
yield d;

if (maxResults && ++count === maxResults) {
return count;
}
}

hasMore = data.length;

} while (hasMore);
},
};
Loading
Loading