avp-cli
Version:
Small CLI to help interacts with the Amazon Verified Permissions (AVP) service.
585 lines (578 loc) • 22 kB
JavaScript
import inquirer from "inquirer";
import fs from "fs";
import path from "path";
export const getAnswers = () => {
return inquirer
.prompt([
{
name: "action",
message: "What would you like to do?",
type: "list",
choices: [
{ name: "Test Scenario", value: "testScenario" },
{
name: "Test Batch Authorization Scenario",
value: "testBatchAuthorizationScenario",
},
{ name: "Manual approach", value: "manual" },
{ name: "Use prepared scenarios", value: "scenarios" },
{ name: "Exit", value: "exit" },
],
},
])
.then((answers) => {
if (answers.action === "testScenario") {
let scenarios = fetchScenarios();
return inquirer
.prompt([
{
name: "selectedScenario",
message: "Choose a scenario",
type: "list",
choices: scenarios,
},
])
.then((scenarioAnswers) => {
if (scenarioAnswers.selectedScenario === "back") {
return getAnswers();
}
let tests = fetchTestsForScenario(scenarioAnswers.selectedScenario);
return inquirer
.prompt([
{
name: "selectedTest",
message: "Choose a test",
type: "list",
choices: tests,
},
])
.then((testAnswers) => {
return {
action: "isAuthorized",
testFilePath: testAnswers.selectedTest,
};
});
});
} else if (answers.action === "testBatchAuthorizationScenario") {
return inquirer
.prompt([
{
name: "selectedScenario",
message: "Choose a scenario",
type: "list",
choices: ["ecommerceBatchScenario", "back"],
},
])
.then((scenarioAnswers) => {
if (scenarioAnswers.selectedScenario === "back") {
return getAnswers();
}
let tests = fetchBatchTestsForScenario(
scenarioAnswers.selectedScenario
);
return inquirer
.prompt([
{
name: "selectedTest",
message: "Choose a test",
type: "list",
choices: tests,
},
])
.then((testAnswers) => {
return {
action: "batchIsAuthorized",
batchTestFilePath: testAnswers.selectedTest,
};
});
});
} else if (answers.action === "scenarios") {
return inquirer
.prompt([
{
name: "scenario",
message: "Choose a scenario",
type: "list",
choices: [
{ name: "Documents Scenario", value: "documentsScenario" },
{
name: "Ecommerce with Context Scenario",
value: "ecommerceContextScenario",
},
{
name: "Ecommerce with Group Scenario",
value: "ecommerceGroupScenario",
},
{
name: "Ecommerce with Template-Linked Policies Scenario",
value: "ecommercePolicyTemplateScenario",
},
{
name: "Ecommerce with Cognito Integration Scenario",
value: "ecommerceCognitoIntegrationScenario",
},
{
name: "Ecommerce with Cognito Groups Scenario",
value: "ecommerceCognitoGroupsScenario",
},
{
name: "Ecommerce with Hierarchy and ABAC Scenario",
value: "ecommerceHierarchyAndAbacScenario",
},
{
name: "Ecommerce with Batch Authorization",
value: "ecommerceBatchScenario",
},
{ name: "Back", value: "back" },
],
},
])
.then((scenarioAnswers) => {
if (scenarioAnswers.scenario === "back") {
return getAnswers();
} else if (
scenarioAnswers.scenario ===
"ecommerceCognitoIntegrationScenario" ||
scenarioAnswers.scenario === "ecommerceCognitoGroupsScenario"
) {
return inquirer
.prompt([
{
name: "userPoolArn",
message: "Enter the ARN of the Cognito User Pool",
type: "input",
},
{
name: "appClientId",
message: "Enter the App Client ID",
type: "input",
},
])
.then((cognitoAnswers) => {
return {
action: scenarioAnswers.scenario,
...cognitoAnswers,
};
});
} else {
answers.action = scenarioAnswers.scenario;
return answers;
}
});
} else if (answers.action === "manual") {
return inquirer
.prompt([
{
name: "action",
message: "What would you like to do?",
type: "list",
choices: [
{
name: "Make an authorization decision",
value: "isAuthorized",
},
{
name: "Make a batch authorization decision",
value: "batchIsAuthorized",
},
{
name: "Make a batch authorization decision with Cognito Identity Token",
value: "batchIsAuthorizedWithToken",
},
{
name: "Make an authorization decision with Cognito Identity Token",
value: "isAuthorizedWithToken",
},
{ name: "Add Policy Template", value: "createPolicyTemplate" },
{ name: "Add Schema to a Policy Store", value: "putSchema" },
{ name: "Add Static Policy", value: "createStaticPolicy" },
{ name: "Add Template Policy", value: "createTemplatePolicy" },
{ name: "Create a Policy Store", value: "createPolicyStore" },
{
name: "Create Identity Source",
value: "createIdentitySource",
},
{
name: "Delete a Identity Source",
value: "deleteIdentitySource",
},
{ name: "Delete a Policy", value: "deletePolicy" },
{ name: "Delete a Policy Store", value: "deletePolicyStore" },
{
name: "Delete a Policy Template",
value: "deletePolicyTemplate",
},
{ name: "Get Identity Source", value: "getIdentitySource" },
{ name: "Get Policy", value: "getPolicy" },
{ name: "Get Policy Store", value: "getPolicyStore" },
{ name: "Get Policy Template", value: "getPolicyTemplate" },
{ name: "Get Schema", value: "getSchema" },
{
name: "List all Policies in a Policy Store",
value: "listPolicies",
},
{ name: "List all Policy Stores", value: "listPolicyStores" },
{ name: "List Identity Sources", value: "listIdentitySources" },
{ name: "List Policy Templates", value: "listPolicyTemplates" },
{
name: "Update Identity Source",
value: "updateIdentitySource",
},
{ name: "Update Policy Store", value: "updatePolicyStore" },
{
name: "Update Policy Template",
value: "updatePolicyTemplate",
},
{ name: "Update Static Policy", value: "updateStaticPolicy" },
{ name: "Back", value: "back" },
{ name: "Exit", value: "exit" },
],
},
{
name: "policyStoreId",
message: "Enter the ID of the policy store",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Policy Store ID cannot be empty.";
},
when: (answers) =>
answers.action === "getPolicyStore" ||
answers.action === "deletePolicyStore" ||
answers.action === "putSchema" ||
answers.action === "createStaticPolicy" ||
answers.action === "getSchema" ||
answers.action === "getPolicy" ||
answers.action === "updateStaticPolicy" ||
answers.action === "deletePolicy" ||
answers.action === "listPolicies" ||
answers.action === "createTemplatePolicy" ||
answers.action === "createPolicyTemplate" ||
answers.action === "deleteIdentitySource" ||
answers.action === "deletePolicyTemplate" ||
answers.action === "getIdentitySource" ||
answers.action === "getPolicyTemplate" ||
answers.action === "listIdentitySources" ||
answers.action === "listPolicyTemplates" ||
answers.action === "updatePolicyStore" ||
answers.action === "updatePolicyTemplate" ||
answers.action === "createIdentitySource" ||
answers.action === "updateIdentitySource",
},
{
name: "validationMode",
message: "Choose a validation mode for the policy store",
type: "list",
choices: ["OFF", "STRICT"],
default: "STRICT",
when: (answers) =>
answers.action === "createPolicyStore" ||
answers.action === "updatePolicyStore",
},
{
name: "pathToSchema",
message: "Enter a path to schema",
type: "input",
validate: function (value) {
if (value.trim() === "") {
return "Path cannot be empty.";
}
if (value.endsWith(".json")) {
return true;
}
return "Path should end with the .json extension.";
},
when: (answers) => answers.action === "putSchema",
},
{
name: "identitySourceId",
message: "Enter identitySourceId",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Identity Source Id cannot be empty.";
},
when: (answers) =>
answers.action === "deleteIdentitySource" ||
answers.action === "getIdentitySource" ||
answers.action === "updateIdentitySource",
},
{
name: "policyId",
message: "Enter the ID of the policy",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Policy ID cannot be empty.";
},
when: (answers) =>
answers.action === "getPolicy" ||
answers.action === "updateStaticPolicy" ||
answers.action === "deletePolicy",
},
{
name: "policyPath",
message: "Enter a path to policy (cedar extension file)",
type: "input",
validate: function (value) {
if (value.trim() === "") {
return "Path cannot be empty.";
}
if (value.endsWith(".cedar")) {
return true;
}
return "Path should end with the .cedar extension.";
},
when: (answers) =>
answers.action === "createStaticPolicy" ||
answers.action === "updateStaticPolicy" ||
answers.action === "createPolicyTemplate",
},
{
name: "policyDescription",
message: "Enter the new description for the policy",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Policy description cannot be empty.";
},
when: (answers) => answers.action === "updateStaticPolicy",
},
{
name: "policyStoreDescription",
message: "Enter the description for the policy store",
type: "input",
when: (answers) =>
answers.action === "createPolicyStore" ||
answers.action === "updatePolicyStore",
},
{
name: "description",
message: "Enter the description for the policy template",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Description of the policy template cannot be empty.";
},
when: (answers) =>
answers.action === "createPolicyTemplate" ||
answers.action === "updatePolicyTemplate",
},
{
name: "statement",
message: "Enter statement of the policy ",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Policy statement cannot be empty.";
},
when: (answers) => answers.action === "updatePolicyTemplate",
},
{
name: "policyTemplateId",
message: "Enter the ID for the policy template",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Policy Template ID cannot be empty.";
},
when: (answers) =>
answers.action === "createTemplatePolicy" ||
answers.action === "deletePolicyTemplate" ||
answers.action === "getPolicyTemplate" ||
answers.action === "updatePolicyTemplate",
},
{
name: "principalEntityType",
message: "Enter the entity type of the principal",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Entity type cannot be empty.";
},
when: (answers) =>
answers.action === "createTemplatePolicy" ||
answers.action === "createIdentitySource" ||
answers.action === "updateIdentitySource",
},
{
name: "principalEntityId",
message: "Enter the entity ID of the principal",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Entity ID cannot be empty.";
},
when: (answers) => answers.action === "createTemplatePolicy",
},
{
name: "resourceEntityType",
message: "Enter the entity type of the resource",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Entity type cannot be empty.";
},
when: (answers) => answers.action === "createTemplatePolicy",
},
{
name: "testFilePath",
message: "Enter the path for json test file",
type: "input",
validate: function (value) {
if (value.trim() === "") {
return "Path to test file cannot be empty.";
}
if (value.endsWith(".json")) {
return true;
}
return "Path should end with the .json extension.";
},
when: (answers) =>
answers.action === "isAuthorized" ||
answers.action === "isAuthorizedWithToken",
},
{
name: "batchTestFilePath",
message: "Enter the path for batch authorization json test file",
type: "input",
default: "structureBatchAuthorizationRequest.json",
validate: function (value) {
if (value.trim() === "") {
return "Path to test file cannot be empty.";
}
if (value.endsWith(".json")) {
return true;
}
return "Path should end with the .json extension.";
},
when: (answers) => answers.action === "batchIsAuthorized",
},
{
name: "batchWithTokenTestFilePath",
message:
"Enter the path for batch authorization with token json test file",
type: "input",
default: "structureBatchAuthorizationWithTokenRequest.json",
validate: function (value) {
if (value.trim() === "") {
return "Path to test file cannot be empty.";
}
if (value.endsWith(".json")) {
return true;
}
return "Path should end with the .json extension.";
},
when: (answers) =>
answers.action === "batchIsAuthorizedWithToken",
},
{
name: "resourceEntityId",
message: "Enter the entity ID of the resource",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Entity ID cannot be empty.";
},
when: (answers) => answers.action === "createTemplatePolicy",
},
{
name: "userPoolArn",
message: "Enter the Amazon Cognito User Pool ARN",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Amazon Cognito User Pool ARN cannot be empty.";
},
when: (answers) =>
answers.scenario === "ecommerceCognitoIntegrationScenario" ||
answers.scenario === "ecommerceCognitoGroupsScenario" ||
answers.action === "createIdentitySource" ||
answers.action === "updateIdentitySource",
},
{
name: "appClientId",
message: "Enter the Amazon Cognito App Client ID",
type: "input",
validate: function (value) {
if (value.trim() !== "") {
return true;
}
return "Amazon Cognito App Client ID cannot be empty.";
},
when: (answers) =>
answers.scenario === "ecommerceCognitoIntegrationScenario" ||
answers.scenario === "ecommerceCognitoGroupsScenario" ||
answers.action === "createIdentitySource" ||
answers.action === "updateIdentitySource",
},
{
name: "groupEntityType",
message:
"Enter the entity type for groups, or press enter to skip",
type: "input",
when: (answers) => answers.action === "createIdentitySource",
},
])
.then((answers) => {
if (answers.action === "back") {
return getAnswers();
} else {
return answers;
}
});
} else {
return answers;
}
});
};
const fetchScenarios = () => {
const scenarioDir = "./scenarios/";
const scenarioDirs = fs
.readdirSync(scenarioDir)
.filter((dir) => fs.statSync(path.join(scenarioDir, dir)).isDirectory());
scenarioDirs.push({ name: "Back", value: "back" });
return scenarioDirs;
};
function fetchTestsForScenario(scenarioName) {
const scenarioData = JSON.parse(
fs.readFileSync(`./scenarios/${scenarioName}/${scenarioName}.json`, "utf-8")
);
return scenarioData.tests.map((test) => ({
name: `${test.description} (${test.type})`,
value: test.path,
}));
}
function fetchBatchTestsForScenario(scenarioName) {
const scenarioData = JSON.parse(
fs.readFileSync(`./scenarios/${scenarioName}/${scenarioName}.json`, "utf-8")
);
return scenarioData.batchTests.map((test) => ({
name: `${test.description}`,
value: test.path,
}));
}