diff --git a/Packs/HashiCorpTerraform/.pack-ignore b/Packs/HashiCorpTerraform/.pack-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/HashiCorpTerraform/.secrets-ignore b/Packs/HashiCorpTerraform/.secrets-ignore new file mode 100644 index 000000000000..a3a577a674b1 --- /dev/null +++ b/Packs/HashiCorpTerraform/.secrets-ignore @@ -0,0 +1,2 @@ +https://app.terraform.io +https://test_url.com \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/Author_image.png b/Packs/HashiCorpTerraform/Author_image.png new file mode 100644 index 000000000000..5536a3be2913 Binary files /dev/null and b/Packs/HashiCorpTerraform/Author_image.png differ diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform.py b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform.py new file mode 100644 index 000000000000..77a6bd1ff8c5 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform.py @@ -0,0 +1,358 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 +from requests import Response + + +RUN_HR_KEY_TO_RES_KEY = { + 'Run id': 'id', + 'Status': 'attributes.status', + 'Plan id': 'relationships.plan.data.id', + 'Planned at': 'attributes.status-timestamps.planned-at' +} +PLAN_HR_KEY_TO_RES_KEY = { + "Plan id": "id", + "Status": "attributes.status", + "Agent Queued at": "attributes.status-timestamps.agent-queued-at" +} +POLICIES_HR_KEY_TO_RES_KEY = { + 'Policy id': 'id', + 'Policy name': 'attributes.name', + 'Policy description': 'attributes.description', + 'Kind': 'attributes.kind', + 'Policy Set ids': 'relationships.policy-sets.data.id', + 'Organization id': 'relationships.organization.data.id' +} +SET_HR_KEY_TO_RES_KEY = { + 'Policy set id': 'id', + 'Policy Set name': 'attributes.name', + 'Description': 'attributes.description', + 'Organization': 'relationships.organization.data.id', + 'Policies ids': 'relationships.policies.data.id', + 'Workspaces': 'relationships.workspaces.data.id', + 'Projects': 'relationships.projects.data.id' +} +CHECK_HR_KEY_TO_RES_KEY = { + 'Policy check id': 'id', + 'Result': 'attributes.result', + 'Status': 'attributes.status', + 'Scope ': 'attributes.scope' +} + + +class Client(BaseClient): + def __init__( + self, url: str, token: str, + default_organization_name: str | None = None, + default_workspace_id: str | None = None, + verify: bool = True, proxy: bool = False): + self._default_organization_name = default_organization_name + self._default_workspace_id = default_workspace_id + + headers = { + 'Authorization': f'Bearer {token}' + } + super().__init__(base_url=url, verify=verify, proxy=proxy, headers=headers) + + def test_connection(self): + return self._http_request('GET', 'account/details') + + def runs_list_request(self, workspace_id: str | None = None, + run_id: str | None = None, filter_status: str | None = None, + page_number: str | None = None, page_size: str | None = None) -> dict: + params = {} + if not run_id: + if filter_status: + params['filter[status]'] = filter_status + if page_number: + params['page[number]'] = page_number + if page_size: + params['page[size]'] = page_size + + workspace_id = workspace_id or self._default_workspace_id + if not workspace_id: + raise DemistoException( + "Please provide either, the instance param 'Default Workspace Id' or the command argument 'workspace_id'" + ) + url_suffix = f'/runs/{run_id}' if run_id else f'/workspaces/{workspace_id}/runs' + response = self._http_request('GET', url_suffix, params=params) + + return response + + def run_action(self, run_id: str, action: str, comment: str | None = None) -> Response: + + return self._http_request( + 'POST', + f'runs/{run_id}/actions/{action}', + json_data={'comment': comment} if comment and action != 'force-execute' else None, + headers=self._headers | {'Content-Type': 'application/vnd.api+json'}, + ok_codes=[200, 202, 403, 404, 409], + resp_type='response') + + def get_plan(self, plan_id: str, json_output: bool) -> Response: + url_suffix = f'/plans/{plan_id}{"/json-output" if json_output else ""}' + return self._http_request('GET', url_suffix, resp_type='response') + + def list_policies(self, organization_name: str | None = None, policy_kind: str | None = None, + policy_name: str | None = None, policy_id: str | None = None) -> dict: + + params = {} + if not policy_id: + if policy_kind: + params['filter[kind]'] = policy_kind + if policy_name: + params['search[name]'] = policy_name + organization_name = organization_name or self._default_organization_name + if not organization_name: + raise DemistoException( + "Please provide either the instance param '\ + 'Default Organization Name' or the command argument 'organization_name'") + + url_suffix = f'/policies/{policy_id}' if policy_id else f'/organizations/{organization_name}/policies' + response = self._http_request('GET', url_suffix, params=params) + + return response + + def list_policy_sets(self, organization_name: str | None, policy_set_id: str | None, + versioned: str | None, policy_set_kind: str | None, include: str | None, + policy_set_name: str | None, page_number: str | None, + page_size: str | None) -> dict: + params: dict[str, str] = {} + if not policy_set_id: + if versioned: + params['filter[versioned]'] = versioned + if policy_set_kind: + params['filter[kind]'] = policy_set_kind + if include: + params['include'] = include + if policy_set_name: + params['search[name]'] = policy_set_name + if page_number: + params['page[number]'] = page_number + if page_size: + params['page[size]'] = page_size + organization_name = organization_name or self._default_organization_name + if not organization_name: + raise DemistoException( + "Please provide either the instance param 'Default Organization Name'\ + ' or the command argument 'organization_name'") + + url_suffix = f'/policy-sets/{policy_set_id}' if policy_set_id else f'/organizations/{organization_name}/policy-sets' + return self._http_request('GET', url_suffix, params=params) + + def list_policy_checks(self, run_id: str | None, policy_check_id: str | None, + page_number: str | None, page_size: str | None) -> dict: + """List Terraform policy checks""" + params = {} + if page_number: + params['page[number]'] = page_number + if page_size: + params['page[size]'] = page_size + + url_suffix = f'/runs/{run_id}/policy-checks' if run_id else f'/policy-checks/{policy_check_id}' + return self._http_request('GET', url_suffix, params=params) + + +def runs_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: + workspace_id = args.get('workspace_id') + run_id = args.get('run_id') + filter_status = args.get('filter_status') + page_number = args.get('page_number') + page_size = args.get('page_size') + + res = client.runs_list_request(workspace_id, run_id, filter_status, page_number, page_size) + # when run_id is provided, it returns a single run instead of a list + data = [res.get('data', {})] if run_id else res.get('data', []) + hr_items = [ + {hr_key: demisto.get(run, response_key) for hr_key, response_key in RUN_HR_KEY_TO_RES_KEY.items()} + for run in data + ] + command_results = CommandResults( + outputs_prefix='Terraform.Run', + outputs_key_field='data.id', + outputs=res, + readable_output=tableToMarkdown('Terraform Runs', hr_items, removeNull=True) + ) + + return command_results + + +def run_action_command(client: Client, args: Dict[str, Any]) -> str: + + run_id = args.get('run_id') + action = args.get('action') + comment = args.get('comment') + + if not run_id or not action: + raise DemistoException("run_id and action are required") + + if action == 'force-execute' and comment: + raise DemistoException("comment parameter is invalid for force-execute action") + + res = client.run_action( + run_id=run_id, + action=action, + comment=comment + ) + + action_msg = f'queued an {action} request for run id {run_id}' + if res.status_code == 202: + return f'Successfully {action_msg}' + else: + raise DemistoException(f'Error occurred when {action_msg}: {res.json().get("errors",[{}])[0].get("title")}') + + +def plan_get_command(client: Client, args: Dict[str, Any]) -> CommandResults | dict[str, Any]: + plan_id = args.get('plan_id') + json_output = argToBoolean(args.get('json_output', False)) + + if not plan_id: + raise DemistoException("plan_id is required") + res = client.get_plan(plan_id, json_output) + + if json_output: + return fileResult(filename=f'{plan_id}.json', + data=res.content, + file_type=EntryType.ENTRY_INFO_FILE) + + res_json = res.json() + plan = res_json.get('data', {}) + hr_plan = {hr_key: demisto.get(plan, response_key) for hr_key, response_key in PLAN_HR_KEY_TO_RES_KEY.items()} + + command_results = CommandResults( + outputs_prefix='Terraform.Plan', + outputs_key_field='id', + outputs=plan, + raw_response=res_json, + readable_output=tableToMarkdown('Terraform Plan', hr_plan) + ) + + return command_results + + +def policies_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: + organization_name = args.get('organization_name') + policy_kind = args.get('policy_kind') + policy_name = args.get('policy_name') + policy_id = args.get('policy_id') + + res = client.list_policies(organization_name, policy_kind, policy_name, policy_id) + # when policy_id is provided, it returns a single policy instead of a list + data = [res.get('data', {})] if policy_id else res.get('data', []) + hr_items = [ + {hr_key: demisto.dt(policy, response_key) for hr_key, response_key in POLICIES_HR_KEY_TO_RES_KEY.items()} + for policy in data + ] + + command_results = CommandResults( + outputs_prefix='Terraform.Policy', + outputs_key_field='id', + outputs=data, + raw_response=res, + readable_output=tableToMarkdown('Terraform Policies', hr_items, removeNull=True) + ) + + return command_results + + +def policy_set_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: + organization_name = args.get('organization_name') + policy_set_id = args.get('policy_set_id') + versioned = args.get('versioned') + policy_set_kind = args.get('policy_set_kind') + include = args.get('include') + policy_set_name = args.get('policy_set_name') + page_number = args.get('page_number') + page_size = args.get('page_size') + + res = client.list_policy_sets(organization_name, policy_set_id, versioned, + policy_set_kind, include, policy_set_name, + page_number, page_size) + # when policy_set_id is provided, it returns a single policy set instead of a list + data = [res.get('data', {})] if policy_set_id else res.get('data', []) + hr_items = [ + {hr_key: demisto.dt(policy_set, response_key) for hr_key, response_key in SET_HR_KEY_TO_RES_KEY.items()} + for policy_set in data + ] + + return CommandResults( + outputs_prefix='Terraform.PolicySet', + outputs_key_field='id', + outputs=data, + raw_response=res, + readable_output=tableToMarkdown('Terraform Policy Sets', hr_items, removeNull=True) + ) + + +def policies_checks_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: + run_id = args.get('run_id') + policy_check_id = args.get('policy_check_id') + page_number = args.get('page_number') + page_size = args.get('page_size') + + res = client.list_policy_checks(run_id, policy_check_id, page_number, page_size) + + # when policy_check_id is provided, it returns a single check instead of a list + data = [res.get('data', {})] if policy_check_id else res.get('data', []) + hr_items = [ + {hr_key: demisto.get(policy_check, response_key) for hr_key, response_key in CHECK_HR_KEY_TO_RES_KEY.items()} + for policy_check in data + ] + + return CommandResults( + outputs_prefix='Terraform.PolicyCheck', + outputs_key_field='id', + outputs=data, + raw_response=res, + readable_output=tableToMarkdown('Terraform Policy Checks', hr_items, removeNull=True) + ) + + +def test_module(client: Client) -> str: + try: + client.test_connection() + except Exception as e: + if 'Unauthorized' in str(e): + raise DemistoException('Unauthorized: Please be sure you put a valid API Token') + raise e + return 'ok' + + +def main() -> None: + + params: Dict[str, Any] = demisto.params() + args: Dict[str, Any] = demisto.args() + url = params.get('server_url', 'https://app.terraform.io/api/v2').rstrip('/') + token = params.get('credentials', {}).get('password') + default_workspace_id = params.get('default_workspace_id') + default_organization_name = params.get('default_organization_name') + verify_certificate: bool = not params.get('insecure', False) + proxy = params.get('proxy', False) + + command = demisto.command() + demisto.debug(f'Command being called is {command}') + + try: + client: Client = Client(url, token, default_organization_name, default_workspace_id, verify_certificate, proxy) + + commands = { + 'terraform-runs-list': runs_list_command, + 'terraform-run-action': run_action_command, + 'terraform-plan-get': plan_get_command, + 'terraform-policies-list': policies_list_command, + 'terraform-policy-set-list': policy_set_list_command, + 'terraform-policies-checks-list': policies_checks_list_command, + } + + if command == 'test-module': + return_results(test_module(client)) + elif command in commands: + return_results(commands[command](client, args)) + else: + raise NotImplementedError(f'{command} command is not implemented.') + + except Exception as e: + return_error(str(e)) + + +if __name__ in ['__main__', 'builtin', 'builtins']: + main() diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform.yml b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform.yml new file mode 100644 index 000000000000..0125fdfb39bc --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform.yml @@ -0,0 +1,627 @@ +commonfields: + id: HashicorpTerraform + version: -1 +configuration: +- display: Server URL + name: server_url + required: true + type: 0 + defaultvalue: https://app.terraform.io/api/v2 + section: Connect +- displaypassword: API Token + additionalinfo: The API Key to use for connection. + name: credentials + required: true + hiddenusername: true + type: 9 + section: Connect +- display: Default Organization Name + name: default_organization_name + type: 0 + required: false + section: Connect + additionalinfo: There is an option to override with a command input parameter. If not provided, policy commands should require the organization name. +- display: Default Workspace ID + name: default_workspace_id + type: 0 + required: false + section: Collect + additionalinfo: There is an option to override with an input parameter. If not provided, some commands should require the workspace ID. +- display: Trust any certificate (not secure) + name: insecure + type: 8 + required: false +- display: Use system proxy settings + name: proxy + type: 8 + required: false +name: HashicorpTerraform +display: HashiCorp Terraform +category: IT Services +description: Hashicorp Terraform provide infrastructure automation to provision and manage resources in any cloud or data center with Terraform. +script: + commands: + - name: terraform-runs-list + description: List runs in a workspace. + arguments: + - name: workspace_id + description: The workspace ID to list runs for. + - name: run_id + description: The run ID to get a specific run. + - name: filter_status + description: The run status to filter by. + auto: PREDEFINED + predefined: + - pending + - fetching + - fetching_completed + - pre_plan_running + - pre_plan_completed + - queuing + - plan_queued + - planning + - planned + - cost_estimating + - cost_estimated + - policy_checking + - policy_override + - policy_soft_failed + - policy_checked + - confirmed + - post_plan_running + - post_plan_completed + - planned_and_finished + - planned_and_saved + - apply_queued + - applying + - applied + - discarded + - errored + - canceled + - force_canceled + - name: page_number + description: The page number of the results to return. Default is 1. + - name: page_size + description: The number of results to return per page. Default is 20, maximum is 100. + outputs: + - contextPath: Terraform.Run.data.id + type: String + description: The run ID. + - contextPath: Terraform.Run.data.attributes.status + type: String + description: The run status. + - contextPath: Terraform.Run.data.relationships.plan.data.id + type: String + description: The plan ID. + - contextPath: Terraform.Run.data.attributes.status-timestamps.planned-at + type: Date + description: The datetime the plan was planned. + - contextPath: Terraform.Run.data.type + description: THe run type. + type: String + - contextPath: Terraform.Run.data.attributes.actions.is-cancelable + description: Flag indicating whether the Terraform run can be canceled. + type: Boolean + - contextPath: Terraform.Run.data.attributes.actions.is-confirmable + description: Flag indicating whether the Terraform run can be confirmed. + type: Boolean + - contextPath: Terraform.Run.data.attributes.actions.is-discardable + description: Flag indicating whether the Terraform run can be discarded. + type: Boolean + - contextPath: Terraform.Run.data.attributes.actions.is-force-cancelable + description: Flag indicating whether the Terraform run can be force-canceled. + type: Boolean + - contextPath: Terraform.Run.data.attributes.canceled-at + description: Timestamp indicating when the Terraform run was canceled. + type: Unknown + - contextPath: Terraform.Run.data.attributes.created-at + description: Timestamp indicating when the Terraform run was created. + type: Date + - contextPath: Terraform.Run.data.attributes.has-changes + description: Flag indicating whether there are changes in the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.auto-apply + description: Flag indicating whether auto-apply is enabled for the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.allow-empty-apply + description: Flag indicating whether empty apply is allowed for the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.allow-config-generation + description: Flag indicating whether configuration generation is allowed for the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.is-destroy + description: Flag indicating whether the Terraform run is a destroy operation. + type: Boolean + - contextPath: Terraform.Run.data.attributes.message + description: Text message associated with the Terraform run. + type: String + - contextPath: Terraform.Run.data.attributes.plan-only + description: Flag indicating whether the Terraform run is for planning only. + type: Boolean + - contextPath: Terraform.Run.data.attributes.source + description: Source of the Terraform run. + type: String + - contextPath: Terraform.Run.data.attributes.status-timestamps.plan-queueable-at + description: Timestamp indicating when the Terraform run is queueable in the plan stage. + type: Date + - contextPath: Terraform.Run.data.attributes.trigger-reason + description: Reason for triggering the Terraform run. + type: String + - contextPath: Terraform.Run.data.attributes.target-addrs + description: Target addresses associated with the Terraform run. + type: Unknown + - contextPath: Terraform.Run.data.attributes.permissions.can-apply + description: Flag indicating whether the user has permission to apply changes. + type: Boolean + - contextPath: Terraform.Run.data.attributes.permissions.can-cancel + description: Flag indicating whether the user has permission to cancel the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.permissions.can-comment + description: Flag indicating whether the user has permission to add comments. + type: Boolean + - contextPath: Terraform.Run.data.attributes.permissions.can-discard + description: Flag indicating whether the user has permission to discard the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.permissions.can-force-execute + description: Flag indicating whether the user has permission to force execute the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.permissions.can-force-cancel + description: Flag indicating whether the user has permission to force cancel the Terraform run. + type: Boolean + - contextPath: Terraform.Run.data.attributes.permissions.can-override-policy-check + description: Flag indicating whether the user has permission to override policy checks. + type: Boolean + - contextPath: Terraform.Run.data.attributes.refresh + description: Flag indicating whether the Terraform run should perform a refresh. + type: Boolean + - contextPath: Terraform.Run.data.attributes.refresh-only + description: Flag indicating whether the Terraform run is for refresh only. + type: Boolean + - contextPath: Terraform.Run.data.attributes.replace-addrs + description: Replacement addresses associated with the Terraform run. + type: Unknown + - contextPath: Terraform.Run.data.attributes.save-plan + description: Flag indicating whether the Terraform run plan should be saved. + type: Boolean + - contextPath: Terraform.Run.data.attributes.variables + description: Variables associated with the Terraform run. + type: Unknown + - contextPath: Terraform.Run.data.relationships.apply.data.id + description: The apply ID of the run. + type: String + - contextPath: Terraform.Run.data.relationships.comments + description: Relationship information for comments associated with the Terraform run. + type: String + - contextPath: Terraform.Run.data.relationships.configuration-version + description: Relationship information for the Terraform configuration version associated with the run. + type: String + - contextPath: Terraform.Run.data.relationships.cost-estimate + description: Relationship information for cost estimates associated with the Terraform run. + type: String + - contextPath: Terraform.Run.data.relationships.created-by + description: Relationship information for the user who created the Terraform run. + type: String + - contextPath: Terraform.Run.data.relationships.input-state-version + description: Relationship information for the input state version associated with the Terraform run. + type: String + - contextPath: Terraform.Run.data.relationships.run-events + description: Relationship information for events associated with the Terraform run. + type: String + - contextPath: Terraform.Run.data.relationships.policy-checks + description: Relationship information for policy checks associated with the Terraform run. + type: String + - contextPath: Terraform.Run.data.relationships.workspace + description: Relationship information for the Terraform workspace associated with the run. + type: String + - contextPath: Terraform.Run.data.relationships.workspace-run-alerts + description: Relationship information for alerts associated with the Terraform workspace run. + type: String + - contextPath: Terraform.Run.data.links.self + description: Link to the Terraform run data. + type: String + - name: terraform-run-action + arguments: + - name: run_id + required: true + description: The Terraform run ID to execute the action on. + - name: action + auto: PREDEFINED + required: true + predefined: + - apply + - cancel + - discard + - force-cancel + - force-execute + description: The action to execute on the Terraform run. + - name: comment + description: An optional comment to associate with the action. Not available for the action "force-execute". + description: 'Perform an action on a Terraform run. The available actions are: apply, cancel, discard, force-cancel, force-execute.' + - name: terraform-plan-get + arguments: + - name: plan_id + required: true + description: The ID of the Terraform plan to retrieve. + - name: json_output + description: Whether to return the plan as a JSON fileResult. + auto: PREDEFINED + predefined: + - "true" + - "false" + defaultValue: "false" + outputs: + - contextPath: Terraform.Plan.id + type: String + description: The plan ID. + - contextPath: Terraform.Plan.attributes.status + type: String + description: The plan status. + - contextPath: Terraform.Plan.type + description: Type of the Terraform plan data. + type: String + - contextPath: Terraform.Plan.attributes.has-changes + description: Flag indicating whether the Terraform plan has changes. + type: Boolean + - contextPath: Terraform.Plan.attributes.status-timestamps.started-at + description: Timestamp indicating when the Terraform plan started. + type: Date + - contextPath: Terraform.Plan.attributes.status-timestamps.finished-at + description: Timestamp indicating when the Terraform plan finished. + type: Date + - contextPath: Terraform.Plan.attributes.status-timestamps.agent-queued-at + description: Timestamp indicating when the Terraform plan was queued for an agent. + type: Date + - contextPath: Terraform.Plan.attributes.log-read-url + description: URL for reading the Terraform plan log. + type: String + - contextPath: Terraform.Plan.attributes.resource-additions + description: Number of resource additions in the Terraform plan. + type: Number + - contextPath: Terraform.Plan.attributes.resource-changes + description: Number of resource changes in the Terraform plan. + type: Number + - contextPath: Terraform.Plan.attributes.resource-destructions + description: Number of resource destructions in the Terraform plan. + type: Number + - contextPath: Terraform.Plan.attributes.resource-imports + description: Number of resource imports in the Terraform plan. + type: Number + - contextPath: Terraform.Plan.attributes.structured-run-output-enabled + description: Flag indicating whether structured run output is enabled in the Terraform plan. + type: Boolean + - contextPath: Terraform.Plan.attributes.generated-configuration + description: Flag indicating whether the Terraform plan has generated configuration. + type: Boolean + - contextPath: Terraform.Plan.attributes.actions.is-exportable + description: Flag indicating whether the Terraform plan is exportable. + type: Boolean + - contextPath: Terraform.Plan.attributes.execution-details.mode + description: Execution mode details for the Terraform plan. + type: String + - contextPath: Terraform.Plan.attributes.permissions.can-export + description: Flag indicating whether the user has permission to export the Terraform plan. + type: Boolean + - contextPath: Terraform.Plan.relationships.state-versions.data + description: Relationship information for state versions associated with the Terraform plan. + type: Unknown + - contextPath: Terraform.Plan.relationships.exports.data + description: Relationship information for exports associated with the Terraform plan. + type: Unknown + - contextPath: Terraform.Plan.links.self + description: Link to the Terraform plan data. + type: String + - contextPath: Terraform.Plan.links.json-output + description: Link to the JSON output of the Terraform plan. + type: String + - contextPath: Terraform.Plan.links.json-output-redacted + description: Link to the redacted JSON output of the Terraform plan. + type: String + - contextPath: Terraform.Plan.links.json-schema + description: Link to the JSON schema of the Terraform plan. + type: String + description: Get the plan JSON file or the plan meta data. + - name: terraform-policies-list + description: List the policies for an organization or get a specific policy. + arguments: + - name: organization_name + description: The name of the organization. + - name: policy_kind + description: If specified, restricts results to those with the matching policy kind value. + auto: PREDEFINED + predefined: + - sentinel + - opa + - name: policy_name + description: If specified, search the organization's policies by name. + - name: policy_id + description: If specified, get the specific policy. + outputs: + - contextPath: Terraform.Policy.id + description: The policy ID. + type: String + - contextPath: Terraform.Policy.type + description: The policy type. + type: String + - contextPath: Terraform.Policy.attributes.name + description: Name of the Terraform policy. + type: String + - contextPath: Terraform.Policy.attributes.description + description: Description of the Terraform policy. + type: Unknown + - contextPath: Terraform.Policy.attributes.enforce.path + description: Path for enforcing the Terraform policy. + type: String + - contextPath: Terraform.Policy.attributes.enforce.mode + description: Enforcement mode for the Terraform policy. + type: String + - contextPath: Terraform.Policy.attributes.policy-set-count + description: Count of policy sets associated with the Terraform policy. + type: Number + - contextPath: Terraform.Policy.attributes.updated-at + description: Timestamp indicating when the Terraform policy was last updated. + type: Date + - contextPath: Terraform.Policy.attributes.kind + description: Kind of the Terraform policy. + type: String + - contextPath: Terraform.Policy.attributes.enforcement-level + description: Enforcement level for the Terraform policy. + type: String + - contextPath: Terraform.Policy.relationships.organization.data.id + description: Unique identifier for the organization associated with the Terraform policy. + type: String + - contextPath: Terraform.Policy.relationships.organization.data.type + description: Type of the organization associated with the Terraform policy. + type: String + - contextPath: Terraform.Policy.relationships.policy-sets.data.id + description: The IDs of the policy sets that contain this policy. + type: String + - contextPath: Terraform.Policy.relationships.policy-sets.data.type + description: Type of the policy sets associated with the Terraform policy. + type: String + - contextPath: Terraform.Policy.links.self + description: Link to the Terraform policy data. + type: String + - contextPath: Terraform.Policy.links.upload + description: Link for uploading the Terraform policy. + type: String + - contextPath: Terraform.Policy.links.download + description: Link for downloading the Terraform policy. + type: String + - contextPath: Terraform.Policy.links.self + description: Link to the Terraform policy. + type: String + - contextPath: Terraform.Policy.links.first + description: Link to the first page of Terraform policies. + type: String + - contextPath: Terraform.Policy.links.prev + description: Link to the previous page of Terraform policies. + type: Unknown + - contextPath: Terraform.Policy.links.next + description: Link to the next page of Terraform policies. + type: Unknown + - contextPath: Terraform.Policy.links.last + description: Link to the last page of Terraform policies. + type: String + - contextPath: Terraform.Policy.meta.pagination.current-page + description: Current page number in the pagination of Terraform policies. + type: Number + - contextPath: Terraform.Policy.meta.pagination.page-size + description: Number of policies displayed per page in pagination. + type: Number + - contextPath: Terraform.Policy.meta.pagination.prev-page + description: Previous page number in the pagination of Terraform policies. + type: Unknown + - contextPath: Terraform.Policy.meta.pagination.next-page + description: Next page number in the pagination of Terraform policies. + type: Unknown + - contextPath: Terraform.Policy.meta.pagination.total-pages + description: Total number of pages in the pagination of Terraform policies. + type: Number + - contextPath: Terraform.Policy.meta.pagination.total-count + description: Total count of Terraform policies. + type: Number + - name: terraform-policy-set-list + description: List the policy sets for an organization or get a specific policy set. + arguments: + - name: organization_name + required: false + description: The name of the organization. + - name: policy_set_id + description: If specified, get the specific policy set. + - name: versioned + description: Allows filtering policy sets based on whether they are versioned, or use individual policy relationships. A true value returns versioned sets, and a false value returns sets with individual policy relationships. If omitted, all policy sets are returned. + auto: PREDEFINED + predefined: + - "true" + - "false" + - name: policy_set_kind + description: If specified, restricts results to those with the matching policy kind value. + auto: PREDEFINED + predefined: + - sentinel + - opa + - name: include + description: Enables you to include related resource data. Value must be a comma-separated list containing one or more projects, workspaces, workspace-exclusions, policies, newest_version, or current_version. + - name: policy_set_name + description: Allows searching the organization's policy sets by name. + - name: page_number + description: The page number of the results to return. Default is 1. + - name: page_size + description: The number of results to return per page. Default is 20, maximum is 100. + outputs: + - contextPath: Terraform.PolicySet.id + description: The policy set ID. + type: String + - contextPath: Terraform.PolicySet.type + description: The policy set type. + type: String + - contextPath: Terraform.PolicySet.attributes.name + description: Name of the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.attributes.description + description: Description of the Terraform policy set. + type: Unknown + - contextPath: Terraform.PolicySet.attributes.global + description: Flag indicating whether the Terraform policy set is global. + type: Boolean + - contextPath: Terraform.PolicySet.attributes.workspace-count + description: Number of workspaces associated with the Terraform policy set. + type: Number + - contextPath: Terraform.PolicySet.attributes.project-count + description: Number of projects associated with the Terraform policy set. + type: Number + - contextPath: Terraform.PolicySet.attributes.created-at + description: Timestamp indicating when the Terraform policy set was created. + type: Date + - contextPath: Terraform.PolicySet.attributes.updated-at + description: Timestamp indicating when the Terraform policy set was last updated. + type: Date + - contextPath: Terraform.PolicySet.attributes.kind + description: Kind of the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.attributes.agent-enabled + description: Flag indicating whether the Terraform policy set has agents enabled. + type: Boolean + - contextPath: Terraform.PolicySet.attributes.policy-count + description: Number of policies associated with the Terraform policy set. + type: Number + - contextPath: Terraform.PolicySet.attributes.versioned + description: Flag indicating whether the Terraform policy set is versioned. + type: Boolean + - contextPath: Terraform.PolicySet.relationships.organization.data.id + description: ID of the organization associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.organization.data.type + description: Type of the organization associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.policies.data.id + description: ID of the policies associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.policies.data.type + description: Type of the policies associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.workspaces.data.id + description: ID of the workspaces associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.workspaces.data.type + description: Type of the workspaces associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.projects.data.id + description: Relationship information for projects associated with the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.relationships.workspace-exclusions.data + description: Relationship information for workspace exclusions associated with the Terraform policy set. + type: Unknown + - contextPath: Terraform.PolicySet.links.self + description: Link to the Terraform policy set data. + type: String + - contextPath: Terraform.PolicySet.links.self + description: Link to the Terraform policy set. + type: String + - contextPath: Terraform.PolicySet.links.first + description: Link to the first page of Terraform policy sets. + type: String + - contextPath: Terraform.PolicySet.links.prev + description: Link to the previous page of Terraform policy sets. + type: Unknown + - contextPath: Terraform.PolicySet.links.next + description: Link to the next page of Terraform policy sets. + type: Unknown + - contextPath: Terraform.PolicySet.links.last + description: Link to the last page of Terraform policy sets. + type: String + - contextPath: Terraform.PolicySet.meta.pagination.current-page + description: Current page number in the pagination of Terraform policy sets. + type: Number + - contextPath: Terraform.PolicySet.meta.pagination.page-size + description: Number of items per page in the pagination of Terraform policy sets. + type: Number + - contextPath: Terraform.PolicySet.meta.pagination.prev-page + description: Link to the previous page in the pagination of Terraform policy sets. + type: Unknown + - contextPath: Terraform.PolicySet.meta.pagination.next-page + description: Link to the next page in the pagination of Terraform policy sets. + type: Unknown + - contextPath: Terraform.PolicySet.meta.pagination.total-pages + description: Total number of pages in the pagination of Terraform policy sets. + type: Number + - contextPath: Terraform.PolicySet.meta.pagination.total-count + description: Total number of Terraform policy sets. + type: Number + - name: terraform-policies-checks-list + description: List the policy checks for a Terraform run. + arguments: + - name: run_id + description: The run ID to list results for. + - name: policy_check_id + description: The policy check ID to retrieve details for. + - name: page_number + description: The page number of the results to return. Default is 1. + - name: page_size + description: The number of results to return per page. Default is 20, maximum is 100. + outputs: + - contextPath: Terraform.PolicyCheck.id + description: The policy check ID. + type: String + - contextPath: Terraform.PolicyCheck.type + description: Type of the Terraform policy check data. + type: String + - contextPath: Terraform.PolicyCheck.attributes.result.result + description: Overall result of the Terraform policy check. + type: Boolean + - contextPath: Terraform.PolicyCheck.attributes.result.passed + description: Number of policy checks that passed. + type: Number + - contextPath: Terraform.PolicyCheck.attributes.result.total-failed + description: Total number of policy checks that failed. + type: Number + - contextPath: Terraform.PolicyCheck.attributes.result.hard-failed + description: Number of policy checks that resulted in hard failures. + type: Number + - contextPath: Terraform.PolicyCheck.attributes.result.soft-failed + description: Number of policy checks that resulted in soft failures. + type: Number + - contextPath: Terraform.PolicyCheck.attributes.result.advisory-failed + description: Number of policy checks that resulted in advisory failures. + type: Number + - contextPath: Terraform.PolicyCheck.attributes.result.duration-ms + description: Duration of the policy check execution in milliseconds. + type: Number + - contextPath: Terraform.PolicyCheck.attributes.result.sentinel + description: Sentinel-specific result of the policy check. + type: Unknown + - contextPath: Terraform.PolicyCheck.attributes.scope + description: Scope or context of the Terraform policy check. + type: String + - contextPath: Terraform.PolicyCheck.attributes.status + description: Status of the Terraform policy check. + type: String + - contextPath: Terraform.PolicyCheck.attributes.status-timestamps.queued-at + description: Timestamp indicating when the Terraform policy check was queued. + type: Date + - contextPath: Terraform.PolicyCheck.attributes.status-timestamps.soft-failed-at + description: Timestamp indicating when the Terraform policy check encountered a soft failure. + type: Date + - contextPath: Terraform.PolicyCheck.attributes.actions.is-overridable + description: Flag indicating whether the Terraform policy check is overridable. + type: Boolean + - contextPath: Terraform.PolicyCheck.attributes.permissions.can-override + description: Flag indicating whether the user has permission to override the Terraform policy check. + type: Boolean + - contextPath: Terraform.PolicyCheck.relationships.run.data.id + description: Unique identifier for the Terraform run associated with the policy check. + type: String + - contextPath: Terraform.PolicyCheck.relationships.run.data.type + description: Type of the Terraform run associated with the policy check. + type: String + - contextPath: Terraform.PolicyCheck.links.output + description: Link to the output of the Terraform policy check. + type: String + runonce: false + script: '-' + type: python + subtype: python3 + dockerimage: demisto/python3:3.10.13.83255 +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_description.md b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_description.md new file mode 100644 index 000000000000..3263290dffc5 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_description.md @@ -0,0 +1,10 @@ +## HashiCorp Terraform Help + + +**Note:** +There are 3 different types of tokens - Organization, User, Team +A customer should use a User or Team token that has admin level access to the workspace. +For details, see [HashiCorp API Tokens](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/api-tokens). + +- *Default Workspace ID* can be taken from *Projects & workspaces* within the selected organization. +- *Default Organization Name* can be taken from the organizations listed in [organizations](https://app.terraform.io/app/organizations). diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_image.png b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_image.png new file mode 100644 index 000000000000..5536a3be2913 Binary files /dev/null and b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_image.png differ diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_test.py b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_test.py new file mode 100644 index 000000000000..bc8c563f9361 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/HashiCorpTerraform_test.py @@ -0,0 +1,159 @@ +import pytest +from CommonServerPython import * +from HashiCorpTerraform import Client, runs_list_command, \ + run_action_command, plan_get_command, policies_list_command, policy_set_list_command, policies_checks_list_command +import re +SERVER_URL = 'https://test_url.com' + + +def util_load_json(path): + with open(path, encoding='utf-8') as f: + return json.loads(f.read()) + + +@pytest.fixture() +def client(): + return Client( + url=SERVER_URL, token=None, + default_organization_name=None, default_workspace_id=None, + verify=None, proxy=None) + + +def test_runs_list_command(client, requests_mock): + """ + Given: + - Client object. + When: + - run the list runs command. + Then: + - validate the results are as expected. + """ + mock_response = util_load_json('./test_data/runs_list_request.json')['mock_response'] + requests_mock.get(re.compile(f'{SERVER_URL}.*'), json=mock_response) + expected_results = util_load_json('./test_data/runs_list_request.json')['expected_results'] + + results = runs_list_command(client=client, args={'workspace_id': 'workspace_id'}) + + assert results.to_context() == expected_results + + +def test_run_action_command(client, requests_mock): + """ + Given: + - Client object. + When: + - error occurred when run the run action command. + Then: + - validate the exception raised as expected. + """ + mock_response = util_load_json('./test_data/run_action_request.json')['mock_response'] + requests_mock.post(re.compile(f'{SERVER_URL}.*'), json=mock_response, status_code=409) + + run_id = 'run-ABCABCABCABCABCa' + with pytest.raises(DemistoException) as err: + run_action_command(client=client, args={ + 'run_id': run_id, + 'action': 'apply', 'comment': 'comment' + }) + assert f'Error occurred when queued an apply request for run id {run_id}' in str(err) + + +def test_plan_get_command(client, requests_mock): + """ + Given: + - Client object. + When: + - run the get plan command to get the plan meta data. + Then: + - validate the results are as expected. + """ + args = {'plan_id': 'plan-Abcabcabcabcabc4'} + + mock_response = util_load_json('./test_data/plan_get_request.json')['mock_response'] + expected_results = util_load_json('./test_data/plan_get_request.json')['expected_results'] + + requests_mock.get(re.compile(f'{SERVER_URL}.*'), json=mock_response) + results = plan_get_command(client=client, args=args) + assert results.to_context() == expected_results + + +def test_policies_list_command(client, requests_mock, mocker): + """ + Given: + - Client object. + When: + - run the get policies list command. + Then: + - validate the results are as expected. + """ + organization_name = 'organization_name' + args = {'organization_name': organization_name} + + mock_response = util_load_json('./test_data/policies_list_request.json')['mock_response'] + expected_results = util_load_json('./test_data/policies_list_request.json')['expected_results'] + + requests_mock.get(f'{SERVER_URL}/organizations/{organization_name}/policies', json=mock_response) + mocker.patch.object(demisto, 'dt', side_effect=lambda _, key: key) + + results = policies_list_command(client=client, args=args) + assert results.to_context() == expected_results + + +def test_policy_set_list_command(client, requests_mock, mocker): + """ + Given: + - Client object. + When: + - run the get policy set list command. + Then: + - validate the results are as expected. + """ + + organization_name = 'organization_name' + args = {'organization_name': organization_name} + + mock_response = util_load_json('./test_data/policy_set_list_request.json')['mock_response'] + expected_results = util_load_json('./test_data/policy_set_list_request.json')['expected_results'] + + requests_mock.get(f'{SERVER_URL}/organizations/{organization_name}/policy-sets', json=mock_response) + mocker.patch.object(demisto, 'dt', side_effect=lambda _, key: key) + results = policy_set_list_command(client=client, args=args) + assert results.to_context() == expected_results + + +def test_policies_checks_list_command(client, requests_mock): + """ + Given: + - Client object. + When: + - run the get policies checks list command. + Then: + - validate the results are as expected. + """ + run_id = 'run-abcabcabcabcabc1' + args = {'run_id': run_id} + + mock_response = util_load_json('./test_data/policies_check_list_request.json')['mock_response'] + expected_results = util_load_json('./test_data/policies_check_list_request.json')['expected_results'] + + requests_mock.get(f'{SERVER_URL}/runs/{run_id}/policy-checks', json=mock_response) + results = policies_checks_list_command(client=client, args=args) + assert results.to_context() == expected_results + + +def test_test_module_command(client, mocker): + """ + Given: + - Client object with error occurred in test_connection. + When: + - run the test module command. + Then: + - validate the expected exception. + """ + import HashiCorpTerraform + mocker.patch.object(client, 'test_connection', side_effect=Exception('Unauthorized')) + + with pytest.raises(DemistoException) as err: + HashiCorpTerraform.test_module(client) + + assert 'Unauthorized: Please be sure you put a valid API Token' in str(err) diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/README.md b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/README.md new file mode 100644 index 000000000000..11f87ab3ca36 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/README.md @@ -0,0 +1,753 @@ +Hashicorp Terraform provide infrastructure automation to provision and manage resources in any cloud or data center with Terraform. +This integration was integrated and tested with version v1.4.4 of HashicorpTerraform. + +## Configure HashiCorp Terraform on Cortex XSOAR + +1. Navigate to **Settings** > **Integrations** > **Servers & Services**. +2. Search for HashiCorp Terraform. +3. Click **Add instance** to create and configure a new integration instance. + + | **Parameter** | **Description** | **Required** | + | --- | --- | --- | + | Server URL | | True | + | API Token | The API Key to use for connection. | True | + | Default Organization Name | There is an option to override with a command input parameter. If not provided, policy commands should require the organization name. | False | + | Default Workspace ID | There is an option to override with an input parameter. If not provided, some commands should require the workspace ID. | False | + | Trust any certificate (not secure) | | False | + | Use system proxy settings | | False | + +4. Click **Test** to validate the URLs, token, and connection. + +## Commands + +You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. +After you successfully execute a command, a DBot message appears in the War Room with the command details. + +### terraform-runs-list + +*** +List runs in a workspace. + +#### Base Command + +`terraform-runs-list` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| workspace_id | The workspace ID to list runs for. | Optional | +| run_id | The run ID to get a specific run. | Optional | +| filter_status | The run status to filter by. Possible values are: pending, fetching, fetching_completed, pre_plan_running, pre_plan_completed, queuing, plan_queued, planning, planned, cost_estimating, cost_estimated, policy_checking, policy_override, policy_soft_failed, policy_checked, confirmed, post_plan_running, post_plan_completed, planned_and_finished, planned_and_saved, apply_queued, applying, applied, discarded, errored, canceled, force_canceled. | Optional | +| page_number | The page number of the results to return. Default is 1. | Optional | +| page_size | The number of results to return per page. Default is 20, maximum is 100. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Terraform.Run.data.id | String | The run ID. | +| Terraform.Run.data.attributes.status | String | The run status. | +| Terraform.Run.data.relationships.plan.data.id | String | The plan ID. | +| Terraform.Run.data.attributes.status-timestamps.planned-at | Date | The datetime the plan was planned. | +| Terraform.Run.data.type | String | THe run type. | +| Terraform.Run.data.attributes.actions.is-cancelable | Boolean | Flag indicating whether the Terraform run can be canceled. | +| Terraform.Run.data.attributes.actions.is-confirmable | Boolean | Flag indicating whether the Terraform run can be confirmed. | +| Terraform.Run.data.attributes.actions.is-discardable | Boolean | Flag indicating whether the Terraform run can be discarded. | +| Terraform.Run.data.attributes.actions.is-force-cancelable | Boolean | Flag indicating whether the Terraform run can be force-canceled. | +| Terraform.Run.data.attributes.canceled-at | Unknown | Timestamp indicating when the Terraform run was canceled. | +| Terraform.Run.data.attributes.created-at | Date | Timestamp indicating when the Terraform run was created. | +| Terraform.Run.data.attributes.has-changes | Boolean | Flag indicating whether there are changes in the Terraform run. | +| Terraform.Run.data.attributes.auto-apply | Boolean | Flag indicating whether auto-apply is enabled for the Terraform run. | +| Terraform.Run.data.attributes.allow-empty-apply | Boolean | Flag indicating whether empty apply is allowed for the Terraform run. | +| Terraform.Run.data.attributes.allow-config-generation | Boolean | Flag indicating whether configuration generation is allowed for the Terraform run. | +| Terraform.Run.data.attributes.is-destroy | Boolean | Flag indicating whether the Terraform run is a destroy operation. | +| Terraform.Run.data.attributes.message | String | Text message associated with the Terraform run. | +| Terraform.Run.data.attributes.plan-only | Boolean | Flag indicating whether the Terraform run is for planning only. | +| Terraform.Run.data.attributes.source | String | Source of the Terraform run. | +| Terraform.Run.data.attributes.status-timestamps.plan-queueable-at | Date | Timestamp indicating when the Terraform run is queueable in the plan stage. | +| Terraform.Run.data.attributes.trigger-reason | String | Reason for triggering the Terraform run. | +| Terraform.Run.data.attributes.target-addrs | Unknown | Target addresses associated with the Terraform run. | +| Terraform.Run.data.attributes.permissions.can-apply | Boolean | Flag indicating whether the user has permission to apply changes. | +| Terraform.Run.data.attributes.permissions.can-cancel | Boolean | Flag indicating whether the user has permission to cancel the Terraform run. | +| Terraform.Run.data.attributes.permissions.can-comment | Boolean | Flag indicating whether the user has permission to add comments. | +| Terraform.Run.data.attributes.permissions.can-discard | Boolean | Flag indicating whether the user has permission to discard the Terraform run. | +| Terraform.Run.data.attributes.permissions.can-force-execute | Boolean | Flag indicating whether the user has permission to force execute the Terraform run. | +| Terraform.Run.data.attributes.permissions.can-force-cancel | Boolean | Flag indicating whether the user has permission to force cancel the Terraform run. | +| Terraform.Run.data.attributes.permissions.can-override-policy-check | Boolean | Flag indicating whether the user has permission to override policy checks. | +| Terraform.Run.data.attributes.refresh | Boolean | Flag indicating whether the Terraform run should perform a refresh. | +| Terraform.Run.data.attributes.refresh-only | Boolean | Flag indicating whether the Terraform run is for refresh only. | +| Terraform.Run.data.attributes.replace-addrs | Unknown | Replacement addresses associated with the Terraform run. | +| Terraform.Run.data.attributes.save-plan | Boolean | Flag indicating whether the Terraform run plan should be saved. | +| Terraform.Run.data.attributes.variables | Unknown | Variables associated with the Terraform run. | +| Terraform.Run.data.relationships.apply.data.id | String | The apply ID of the run. | +| Terraform.Run.data.relationships.comments | String | Relationship information for comments associated with the Terraform run. | +| Terraform.Run.data.relationships.configuration-version | String | Relationship information for the Terraform configuration version associated with the run. | +| Terraform.Run.data.relationships.cost-estimate | String | Relationship information for cost estimates associated with the Terraform run. | +| Terraform.Run.data.relationships.created-by | String | Relationship information for the user who created the Terraform run. | +| Terraform.Run.data.relationships.input-state-version | String | Relationship information for the input state version associated with the Terraform run. | +| Terraform.Run.data.relationships.run-events | String | Relationship information for events associated with the Terraform run. | +| Terraform.Run.data.relationships.policy-checks | String | Relationship information for policy checks associated with the Terraform run. | +| Terraform.Run.data.relationships.workspace | String | Relationship information for the Terraform workspace associated with the run. | +| Terraform.Run.data.relationships.workspace-run-alerts | String | Relationship information for alerts associated with the Terraform workspace run. | +| Terraform.Run.data.links.self | String | Link to the Terraform run data. | + +#### Command example +```!terraform-runs-list``` +#### Context Example +```json +{ + "Terraform": { + "Run": { + "data": [ + { + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": true, + "is-discardable": true, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": false, + "canceled-at": null, + "created-at": "2023-12-17T10:23:43.258Z", + "has-changes": true, + "is-destroy": false, + "message": "Triggered via UI", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-cancel": true, + "can-force-execute": true, + "can-override-policy-check": true + }, + "plan-only": false, + "refresh": true, + "refresh-only": false, + "replace-addrs": [ + "fakewebservices_load_balancer.primary_lb" + ], + "save-plan": false, + "source": "tfe-ui", + "status": "planned", + "status-timestamps": { + "plan-queueable-at": "2023-12-17T10:23:43+00:00", + "plan-queued-at": "2023-12-17T10:23:43+00:00", + "planned-at": "2023-12-17T10:23:52+00:00", + "planning-at": "2023-12-17T10:23:48+00:00", + "queuing-at": "2023-12-17T10:23:43+00:00" + }, + "target-addrs": null, + "terraform-version": "1.4.4", + "trigger-reason": "manual", + "variables": [] + }, + "id": "run-8wpCneWr4TLSzfat", + "links": { + "self": "/api/v2/runs/run-8wpCneWr4TLSzfat" + }, + "relationships": { + "apply": { + "data": { + "id": "apply-uEYtCmrtg5MvjgTr", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/apply" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/comments" + } + }, + "configuration-version": { + "data": { + "id": "cv-YDcZaBNiRbrdy1w1", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user-LR5kedWrdZXBWF71", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/created-by" + } + }, + "plan": { + "data": { + "id": "plan-T7zpGYFEioRfWEAq", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/plan" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/policy-checks" + } + }, + "run-events": { + "data": [ + { + "id": "re-ga2h6eu41RqrmZRn", + "type": "run-events" + }, + { + "id": "re-ciqzHkW3bDooRzcn", + "type": "run-events" + }, + { + "id": "re-ENvbqnmE72YFj7Wq", + "type": "run-events" + }, + { + "id": "re-xkz1fSTKM25GxkMk", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-8wpCneWr4TLSzfat/task-stages" + } + }, + "workspace": { + "data": { + "id": "ws-ZTbNWsfXHRWRVNmE", + "type": "workspaces" + } + } + }, + "type": "runs" + } + ], + "links": { + "first": "https://app.terraform.io/api/v2/workspaces/ws-ZTbNWsfXHRWRVNmE/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "last": "https://app.terraform.io/api/v2/workspaces/ws-ZTbNWsfXHRWRVNmE/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "next": null, + "prev": null, + "self": "https://app.terraform.io/api/v2/workspaces/ws-ZTbNWsfXHRWRVNmE/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "next-page": null, + "page-size": 20, + "prev-page": null, + "total-count": 9, + "total-pages": 1 + }, + "status-counts": { + "applied": 1, + "apply-queued": 0, + "applying": 0, + "assessed": 0, + "assessing": 0, + "canceled": 2, + "confirmed": 0, + "cost-estimated": 0, + "cost-estimating": 0, + "discarded": 4, + "errored": 0, + "fetching": 0, + "fetching-completed": 0, + "pending": 0, + "plan-queued": 0, + "planned": 1, + "planned-and-finished": 4, + "planned-and-saved": 0, + "planning": 0, + "policy-checked": 0, + "policy-checking": 0, + "policy-override": 0, + "policy-soft-failed": 0, + "post-apply-completed": 0, + "post-apply-running": 0, + "post-plan-awaiting-decision": 0, + "post-plan-completed": 0, + "post-plan-running": 0, + "pre-apply-awaiting-decision": 0, + "pre-apply-completed": 0, + "pre-apply-running": 0, + "pre-plan-awaiting-decision": 0, + "pre-plan-completed": 0, + "pre-plan-running": 0, + "queuing": 0, + "queuing-apply": 0, + "total": 12 + } + } + } + } +} +``` + +#### Human Readable Output + +>### Terraform Runs +>|Plan id|Planned at|Run id|Status| +>|---|---|---|---| +>| plan-T7zpGYFEioRfWEAq | 2023-12-17T10:23:52+00:00 | run-8wpCneWr4TLSzfat | planned | +>| plan-1JUTBdedobs1Absf | 2023-12-11T11:35:35+00:00 | run-kMNQfAmoDr1k8eaT | discarded | +>| plan-21bfTFiDJ6Rz1VTZ | | run-jb2j5r3gBievUPfR | canceled | +>| plan-twBdAcLwiGwuE7kt | 2023-12-11T11:29:38+00:00 | run-g7ihSa71hCV9yZt7 | discarded | +>| plan-JEgrv5aBeNUDDRaA | 2023-12-11T11:12:04+00:00 | run-yCYvcx1ZEmmKGXnB | discarded | +>| plan-kJLmtoaywxkXM54P | 2023-12-11T09:11:48+00:00 | run-akCRvcJ6L5cQtAhc | discarded | +>| plan-ZunKDF28KpCyiZAn | 2023-12-10T07:10:08+00:00 | run-rpSjBkbhiKAfMuwX | planned_and_finished | +>| plan-V4fvpvCzGQrsZikD | 2023-11-30T09:21:42+00:00 | run-Q2kS54r6pJjdyYfk | planned_and_finished | +>| plan-ZYYZD69ESo16jENX | 2023-10-25T10:33:11+00:00 | run-wBdFQ6egn91GGRne | applied | + + +### terraform-run-action + +*** +Perform an action on a Terraform run. The available actions are: apply, cancel, discard, force-cancel, force-execute. + +#### Base Command + +`terraform-run-action` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| run_id | The Terraform run ID to execute the action on. | Required | +| action | The action to execute on the Terraform run. Possible values are: apply, cancel, discard, force-cancel, force-execute. | Required | +| comment | An optional comment to associate with the action. Not available for the action "force-execute". | Optional | + +#### Context Output + +There is no context output for this command. +#### Command example +```!terraform-run-action run_id=run-8wpCneWr4TLSzfat action="discard" comment="test comment"``` +#### Human Readable Output + +>Successfully queued an discard request for run id run-8wpCneWr4TLSzfat + +### terraform-plan-get + +*** +Get the plan JSON file or the plan meta data. + +#### Base Command + +`terraform-plan-get` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| plan_id | The ID of the Terraform plan to retrieve. | Required | +| json_output | Whether to return the plan as a JSON fileResult. Possible values are: true, false. Default is false. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Terraform.Plan.id | String | The plan ID. | +| Terraform.Plan.attributes.status | String | The plan status. | +| Terraform.Plan.type | String | Type of the Terraform plan data. | +| Terraform.Plan.attributes.has-changes | Boolean | Flag indicating whether the Terraform plan has changes. | +| Terraform.Plan.attributes.status-timestamps.started-at | Date | Timestamp indicating when the Terraform plan started. | +| Terraform.Plan.attributes.status-timestamps.finished-at | Date | Timestamp indicating when the Terraform plan finished. | +| Terraform.Plan.attributes.status-timestamps.agent-queued-at | Date | Timestamp indicating when the Terraform plan was queued for an agent. | +| Terraform.Plan.attributes.log-read-url | String | URL for reading the Terraform plan log. | +| Terraform.Plan.attributes.resource-additions | Number | Number of resource additions in the Terraform plan. | +| Terraform.Plan.attributes.resource-changes | Number | Number of resource changes in the Terraform plan. | +| Terraform.Plan.attributes.resource-destructions | Number | Number of resource destructions in the Terraform plan. | +| Terraform.Plan.attributes.resource-imports | Number | Number of resource imports in the Terraform plan. | +| Terraform.Plan.attributes.structured-run-output-enabled | Boolean | Flag indicating whether structured run output is enabled in the Terraform plan. | +| Terraform.Plan.attributes.generated-configuration | Boolean | Flag indicating whether the Terraform plan has generated configuration. | +| Terraform.Plan.attributes.actions.is-exportable | Boolean | Flag indicating whether the Terraform plan is exportable. | +| Terraform.Plan.attributes.execution-details.mode | String | Execution mode details for the Terraform plan. | +| Terraform.Plan.attributes.permissions.can-export | Boolean | Flag indicating whether the user has permission to export the Terraform plan. | +| Terraform.Plan.relationships.state-versions.data | Unknown | Relationship information for state versions associated with the Terraform plan. | +| Terraform.Plan.relationships.exports.data | Unknown | Relationship information for exports associated with the Terraform plan. | +| Terraform.Plan.links.self | String | Link to the Terraform plan data. | +| Terraform.Plan.links.json-output | String | Link to the JSON output of the Terraform plan. | +| Terraform.Plan.links.json-output-redacted | String | Link to the redacted JSON output of the Terraform plan. | +| Terraform.Plan.links.json-schema | String | Link to the JSON schema of the Terraform plan. | + +#### Command example +```!terraform-plan-get plan_id=plan-V4fvpvCzGQrsZikD``` +#### Context Example +```json +{ + "Terraform": { + "Plan": { + "attributes": { + "actions": { + "is-exportable": true + }, + "execution-details": { + "mode": "remote" + }, + "generated-configuration": false, + "has-changes": false, + "log-read-url": "url", + "permissions": { + "can-export": true + }, + "resource-additions": 0, + "resource-changes": 0, + "resource-destructions": 0, + "resource-imports": 0, + "status": "finished", + "status-timestamps": { + "agent-queued-at": "2023-11-30T09:21:33+00:00", + "finished-at": "2023-11-30T09:21:41+00:00", + "started-at": "2023-11-30T09:21:37+00:00" + }, + "structured-run-output-enabled": true + }, + "id": "plan-V4fvpvCzGQrsZikD", + "links": { + "json-output": "/api/v2/plans/plan-V4fvpvCzGQrsZikD/json-output", + "json-output-redacted": "/api/v2/plans/plan-V4fvpvCzGQrsZikD/json-output-redacted", + "json-schema": "/api/v2/plans/plan-V4fvpvCzGQrsZikD/json-schema", + "self": "/api/v2/plans/plan-V4fvpvCzGQrsZikD" + }, + "relationships": { + "exports": { + "data": [] + }, + "state-versions": { + "data": [] + } + }, + "type": "plans" + } + } +} +``` + +#### Human Readable Output + +>### Terraform Plan +>|Agent Queued at|Plan id|Status| +>|---|---|---| +>| 2023-11-30T09:21:33+00:00 | plan-V4fvpvCzGQrsZikD | finished | + + +#### Command example +```!terraform-plan-get plan_id=plan-V4fvpvCzGQrsZikD json_output="true"``` +#### Context Example +```json +{ + "InfoFile": { + "EntryID": "375@03d8b507-a516-4959-8133-979b2d80a807", + "Extension": "json", + "Info": "application/json", + "Name": "plan-V4fvpvCzGQrsZikD.json", + "Size": 3686, + "Type": "JSON data" + } +} +``` + +#### Human Readable Output + + + +### terraform-policies-list + +*** +List the policies for an organization or get a specific policy. + +#### Base Command + +`terraform-policies-list` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| organization_name | The name of the organization. | Optional | +| policy_kind | If specified, restricts results to those with the matching policy kind value. Possible values are: sentinel, opa. | Optional | +| policy_name | If specified, search the organization's policies by name. | Optional | +| policy_id | If specified, get the specific policy. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Terraform.Policy.id | String | The policy ID. | +| Terraform.Policy.type | String | The policy type. | +| Terraform.Policy.attributes.name | String | Name of the Terraform policy. | +| Terraform.Policy.attributes.description | Unknown | Description of the Terraform policy. | +| Terraform.Policy.attributes.enforce.path | String | Path for enforcing the Terraform policy. | +| Terraform.Policy.attributes.enforce.mode | String | Enforcement mode for the Terraform policy. | +| Terraform.Policy.attributes.policy-set-count | Number | Count of policy sets associated with the Terraform policy. | +| Terraform.Policy.attributes.updated-at | Date | Timestamp indicating when the Terraform policy was last updated. | +| Terraform.Policy.attributes.kind | String | Kind of the Terraform policy. | +| Terraform.Policy.attributes.enforcement-level | String | Enforcement level for the Terraform policy. | +| Terraform.Policy.relationships.organization.data.id | String | Unique identifier for the organization associated with the Terraform policy. | +| Terraform.Policy.relationships.organization.data.type | String | Type of the organization associated with the Terraform policy. | +| Terraform.Policy.relationships.policy-sets.data.id | String | The IDs of the policy sets that contain this policy. | +| Terraform.Policy.relationships.policy-sets.data.type | String | Type of the policy sets associated with the Terraform policy. | +| Terraform.Policy.links.self | String | Link to the Terraform policy data. | +| Terraform.Policy.links.upload | String | Link for uploading the Terraform policy. | +| Terraform.Policy.links.download | String | Link for downloading the Terraform policy. | +| Terraform.Policy.links.self | String | Link to the Terraform policy. | +| Terraform.Policy.links.first | String | Link to the first page of Terraform policies. | +| Terraform.Policy.links.prev | Unknown | Link to the previous page of Terraform policies. | +| Terraform.Policy.links.next | Unknown | Link to the next page of Terraform policies. | +| Terraform.Policy.links.last | String | Link to the last page of Terraform policies. | +| Terraform.Policy.meta.pagination.current-page | Number | Current page number in the pagination of Terraform policies. | +| Terraform.Policy.meta.pagination.page-size | Number | Number of policies displayed per page in pagination. | +| Terraform.Policy.meta.pagination.prev-page | Unknown | Previous page number in the pagination of Terraform policies. | +| Terraform.Policy.meta.pagination.next-page | Unknown | Next page number in the pagination of Terraform policies. | +| Terraform.Policy.meta.pagination.total-pages | Number | Total number of pages in the pagination of Terraform policies. | +| Terraform.Policy.meta.pagination.total-count | Number | Total count of Terraform policies. | + +#### Command example +```!terraform-policies-list``` +#### Context Example +```json +{ + "Terraform": { + "Policy": { + "attributes": { + "description": null, + "enforce": [ + { + "mode": "hard-mandatory", + "path": "nat-policies.sentinel" + } + ], + "enforcement-level": "hard-mandatory", + "kind": "sentinel", + "name": "nat-policies", + "policy-set-count": 1, + "updated-at": "2023-11-14T18:12:36.702Z" + }, + "id": "pol-ycCqXorxsFjaH5aK", + "links": { + "download": "/api/v2/policies/pol-ycCqXorxsFjaH5aK/download", + "self": "/api/v2/policies/pol-ycCqXorxsFjaH5aK", + "upload": "/api/v2/policies/pol-ycCqXorxsFjaH5aK/upload" + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-40dc3b", + "type": "organizations" + } + }, + "policy-sets": { + "data": [ + { + "id": "polset-hc2bvqDW8YRgHEt8", + "type": "policy-sets" + } + ] + } + }, + "type": "policies" + } + } +} +``` + +#### Human Readable Output + +>### Terraform Policies +>|Kind|Organization id|Policy Set ids|Policy id|Policy name| +>|---|---|---|---|---| +>| sentinel | example-org-40dc3b | polset-hc2bvqDW8YRgHEt8 | pol-ycCqXorxsFjaH5aK | nat-policies | + + +### terraform-policy-set-list + +*** +List the policy sets for an organization or get a specific policy set. + +#### Base Command + +`terraform-policy-set-list` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| organization_name | The name of the organization. | Optional | +| policy_set_id | If specified, get the specific policy set. | Optional | +| versioned | Allows filtering policy sets based on whether they are versioned, or use individual policy relationships. A true value returns versioned sets, and a false value returns sets with individual policy relationships. If omitted, all policy sets are returned. Possible values are: true, false. | Optional | +| policy_set_kind | If specified, restricts results to those with the matching policy kind value. Possible values are: sentinel, opa. | Optional | +| include | Enables you to include related resource data. Value must be a comma-separated list containing one or more projects, workspaces, workspace-exclusions, policies, newest_version, or current_version. | Optional | +| policy_set_name | Allows searching the organization's policy sets by name. | Optional | +| page_number | The page number of the results to return. Default is 1. | Optional | +| page_size | The number of results to return per page. Default is 20, maximum is 100. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Terraform.PolicySet.id | String | The policy set ID. | +| Terraform.PolicySet.type | String | The policy set type. | +| Terraform.PolicySet.attributes.name | String | Name of the Terraform policy set. | +| Terraform.PolicySet.attributes.description | Unknown | Description of the Terraform policy set. | +| Terraform.PolicySet.attributes.global | Boolean | Flag indicating whether the Terraform policy set is global. | +| Terraform.PolicySet.attributes.workspace-count | Number | Number of workspaces associated with the Terraform policy set. | +| Terraform.PolicySet.attributes.project-count | Number | Number of projects associated with the Terraform policy set. | +| Terraform.PolicySet.attributes.created-at | Date | Timestamp indicating when the Terraform policy set was created. | +| Terraform.PolicySet.attributes.updated-at | Date | Timestamp indicating when the Terraform policy set was last updated. | +| Terraform.PolicySet.attributes.kind | String | Kind of the Terraform policy set. | +| Terraform.PolicySet.attributes.agent-enabled | Boolean | Flag indicating whether the Terraform policy set has agents enabled. | +| Terraform.PolicySet.attributes.policy-count | Number | Number of policies associated with the Terraform policy set. | +| Terraform.PolicySet.attributes.versioned | Boolean | Flag indicating whether the Terraform policy set is versioned. | +| Terraform.PolicySet.relationships.organization.data.id | String | ID of the organization associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.organization.data.type | String | Type of the organization associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.policies.data.id | String | ID of the policies associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.policies.data.type | String | Type of the policies associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.workspaces.data.id | String | ID of the workspaces associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.workspaces.data.type | String | Type of the workspaces associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.projects.data.id | String | Relationship information for projects associated with the Terraform policy set. | +| Terraform.PolicySet.relationships.workspace-exclusions.data | Unknown | Relationship information for workspace exclusions associated with the Terraform policy set. | +| Terraform.PolicySet.links.self | String | Link to the Terraform policy set data. | +| Terraform.PolicySet.links.self | String | Link to the Terraform policy set. | +| Terraform.PolicySet.links.first | String | Link to the first page of Terraform policy sets. | +| Terraform.PolicySet.links.prev | Unknown | Link to the previous page of Terraform policy sets. | +| Terraform.PolicySet.links.next | Unknown | Link to the next page of Terraform policy sets. | +| Terraform.PolicySet.links.last | String | Link to the last page of Terraform policy sets. | +| Terraform.PolicySet.meta.pagination.current-page | Number | Current page number in the pagination of Terraform policy sets. | +| Terraform.PolicySet.meta.pagination.page-size | Number | Number of items per page in the pagination of Terraform policy sets. | +| Terraform.PolicySet.meta.pagination.prev-page | Unknown | Link to the previous page in the pagination of Terraform policy sets. | +| Terraform.PolicySet.meta.pagination.next-page | Unknown | Link to the next page in the pagination of Terraform policy sets. | +| Terraform.PolicySet.meta.pagination.total-pages | Number | Total number of pages in the pagination of Terraform policy sets. | +| Terraform.PolicySet.meta.pagination.total-count | Number | Total number of Terraform policy sets. | + +#### Command example +```!terraform-policy-set-list``` +#### Context Example +```json +{ + "Terraform": { + "PolicySet": { + "attributes": { + "agent-enabled": false, + "created-at": "2023-11-08T11:25:06.196Z", + "description": null, + "global": false, + "kind": "sentinel", + "name": "test-policy-set", + "policy-count": 1, + "project-count": 0, + "updated-at": "2023-11-08T11:25:06.196Z", + "versioned": false, + "workspace-count": 1 + }, + "id": "polset-hc2bvqDW8YRgHEt8", + "links": { + "self": "/api/v2/policy-sets/polset-hc2bvqDW8YRgHEt8" + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-40dc3b", + "type": "organizations" + } + }, + "policies": { + "data": [ + { + "id": "pol-ycCqXorxsFjaH5aK", + "type": "policies" + } + ] + }, + "projects": { + "data": [] + }, + "workspace-exclusions": { + "data": [] + }, + "workspaces": { + "data": [ + { + "id": "ws-u7kVixWpJYWiERMG", + "type": "workspaces" + } + ] + } + }, + "type": "policy-sets" + } + } +} +``` + +#### Human Readable Output + +>### Terraform Policy Sets +>|Organization|Policies ids|Policy Set name|Policy set id|Workspaces| +>|---|---|---|---|---| +>| example-org-40dc3b | pol-ycCqXorxsFjaH5aK | test-policy-set | polset-hc2bvqDW8YRgHEt8 | ws-u7kVixWpJYWiERMG | + + +### terraform-policies-checks-list + +*** +List the policy checks for a Terraform run. + +#### Base Command + +`terraform-policies-checks-list` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| run_id | The run ID to list results for. | Optional | +| policy_check_id | The policy check ID to retrieve details for. | Optional | +| page_number | The page number of the results to return. Default is 1. | Optional | +| page_size | The number of results to return per page. Default is 20, maximum is 100. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Terraform.PolicyCheck.id | String | The policy check ID. | +| Terraform.PolicyCheck.type | String | Type of the Terraform policy check data. | +| Terraform.PolicyCheck.attributes.result.result | Boolean | Overall result of the Terraform policy check. | +| Terraform.PolicyCheck.attributes.result.passed | Number | Number of policy checks that passed. | +| Terraform.PolicyCheck.attributes.result.total-failed | Number | Total number of policy checks that failed. | +| Terraform.PolicyCheck.attributes.result.hard-failed | Number | Number of policy checks that resulted in hard failures. | +| Terraform.PolicyCheck.attributes.result.soft-failed | Number | Number of policy checks that resulted in soft failures. | +| Terraform.PolicyCheck.attributes.result.advisory-failed | Number | Number of policy checks that resulted in advisory failures. | +| Terraform.PolicyCheck.attributes.result.duration-ms | Number | Duration of the policy check execution in milliseconds. | +| Terraform.PolicyCheck.attributes.result.sentinel | Unknown | Sentinel-specific result of the policy check. | +| Terraform.PolicyCheck.attributes.scope | String | Scope or context of the Terraform policy check. | +| Terraform.PolicyCheck.attributes.status | String | Status of the Terraform policy check. | +| Terraform.PolicyCheck.attributes.status-timestamps.queued-at | Date | Timestamp indicating when the Terraform policy check was queued. | +| Terraform.PolicyCheck.attributes.status-timestamps.soft-failed-at | Date | Timestamp indicating when the Terraform policy check encountered a soft failure. | +| Terraform.PolicyCheck.attributes.actions.is-overridable | Boolean | Flag indicating whether the Terraform policy check is overridable. | +| Terraform.PolicyCheck.attributes.permissions.can-override | Boolean | Flag indicating whether the user has permission to override the Terraform policy check. | +| Terraform.PolicyCheck.relationships.run.data.id | String | Unique identifier for the Terraform run associated with the policy check. | +| Terraform.PolicyCheck.relationships.run.data.type | String | Type of the Terraform run associated with the policy check. | +| Terraform.PolicyCheck.links.output | String | Link to the output of the Terraform policy check. | + +#### Command example +```!terraform-policies-checks-list run_id=run-8wpCneWr4TLSzfat``` +#### Human Readable Output + +>### Terraform Policy Checks +>**No entries.** + diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/command_examples b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/command_examples new file mode 100644 index 000000000000..b43d6c9d41cc --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/command_examples @@ -0,0 +1,7 @@ +!terraform-runs-list +!terraform-policy-set-list +!terraform-policies-list +!terraform-run-action run_id=run-8wpCneWr4TLSzfat action="discard" comment="test comment" +!terraform-policies-checks-list run_id=run-8wpCneWr4TLSzfat +!terraform-plan-get plan_id=plan-V4fvpvCzGQrsZikD +!terraform-plan-get plan_id=plan-V4fvpvCzGQrsZikD json_output="true" diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/plan_get_request.json b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/plan_get_request.json new file mode 100644 index 000000000000..3dc25896be2a --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/plan_get_request.json @@ -0,0 +1,143 @@ +{ + "mock_response": { + "data": { + "id": "plan-Abcabcabcabcabc4", + "type": "plans", + "attributes": { + "has-changes": false, + "status": "finished", + "status-timestamps": { + "started-at": "2023-11-30T09:21:37+00:00", + "finished-at": "2023-11-30T09:21:41+00:00", + "agent-queued-at": "2023-11-30T09:21:33+00:00" + }, + "resource-additions": 0, + "resource-changes": 0, + "resource-destructions": 0, + "resource-imports": 0, + "structured-run-output-enabled": true, + "generated-configuration": false, + "actions": { + "is-exportable": true + }, + "execution-details": { + "mode": "remote" + }, + "permissions": { + "can-export": true + } + }, + "relationships": { + "state-versions": { + "data": [] + }, + "exports": { + "data": [] + } + }, + "links": { + "self": "/api/v2/plans/plan-Abcabcabcabcabc4", + "json-output": "/api/v2/plans/plan-Abcabcabcabcabc4/json-output", + "json-output-redacted": "/api/v2/plans/plan-Abcabcabcabcabc4/json-output-redacted", + "json-schema": "/api/v2/plans/plan-Abcabcabcabcabc4/json-schema" + } + } + }, + "expected_results": { + "Type": 1, + "ContentsFormat": "json", + "Contents": { + "data": { + "id": "plan-Abcabcabcabcabc4", + "type": "plans", + "attributes": { + "has-changes": false, + "status": "finished", + "status-timestamps": { + "started-at": "2023-11-30T09:21:37+00:00", + "finished-at": "2023-11-30T09:21:41+00:00", + "agent-queued-at": "2023-11-30T09:21:33+00:00" + }, + "resource-additions": 0, + "resource-changes": 0, + "resource-destructions": 0, + "resource-imports": 0, + "structured-run-output-enabled": true, + "generated-configuration": false, + "actions": { + "is-exportable": true + }, + "execution-details": { + "mode": "remote" + }, + "permissions": { + "can-export": true + } + }, + "relationships": { + "state-versions": { + "data": [] + }, + "exports": { + "data": [] + } + }, + "links": { + "self": "/api/v2/plans/plan-Abcabcabcabcabc4", + "json-output": "/api/v2/plans/plan-Abcabcabcabcabc4/json-output", + "json-output-redacted": "/api/v2/plans/plan-Abcabcabcabcabc4/json-output-redacted", + "json-schema": "/api/v2/plans/plan-Abcabcabcabcabc4/json-schema" + } + } + }, + "HumanReadable": "### Terraform Plan\n|Agent Queued at|Plan id|Status|\n|---|---|---|\n| 2023-11-30T09:21:33+00:00 | plan-Abcabcabcabcabc4 | finished |\n", + "EntryContext": { + "Terraform.Plan(val.id && val.id == obj.id)": { + "id": "plan-Abcabcabcabcabc4", + "type": "plans", + "attributes": { + "has-changes": false, + "status": "finished", + "status-timestamps": { + "started-at": "2023-11-30T09:21:37+00:00", + "finished-at": "2023-11-30T09:21:41+00:00", + "agent-queued-at": "2023-11-30T09:21:33+00:00" + }, + "resource-additions": 0, + "resource-changes": 0, + "resource-destructions": 0, + "resource-imports": 0, + "structured-run-output-enabled": true, + "generated-configuration": false, + "actions": { + "is-exportable": true + }, + "execution-details": { + "mode": "remote" + }, + "permissions": { + "can-export": true + } + }, + "relationships": { + "state-versions": { + "data": [] + }, + "exports": { + "data": [] + } + }, + "links": { + "self": "/api/v2/plans/plan-Abcabcabcabcabc4", + "json-output": "/api/v2/plans/plan-Abcabcabcabcabc4/json-output", + "json-output-redacted": "/api/v2/plans/plan-Abcabcabcabcabc4/json-output-redacted", + "json-schema": "/api/v2/plans/plan-Abcabcabcabcabc4/json-schema" + } + } + }, + "IndicatorTimeline": [], + "IgnoreAutoExtract": false, + "Note": false, + "Relationships": [] + } +} \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policies_check_list_request.json b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policies_check_list_request.json new file mode 100644 index 000000000000..bc9aa991eba5 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policies_check_list_request.json @@ -0,0 +1,137 @@ +{ + "mock_response": { + "data": [ + { + "id": "polchk-abcabcabcabcabc4", + "type": "policy-checks", + "attributes": { + "result": { + "result": false, + "passed": 0, + "total-failed": 1, + "hard-failed": 0, + "soft-failed": 1, + "advisory-failed": 0, + "duration-ms": 0 + }, + "scope": "organization", + "status": "soft_failed", + "status-timestamps": { + "queued-at": "2017-11-29T20:02:17+00:00", + "soft-failed-at": "2017-11-29T20:02:20+00:00" + }, + "actions": { + "is-overridable": true + }, + "permissions": { + "can-override": false + } + }, + "relationships": { + "run": { + "data": { + "id": "run-abcabcabcabcabc4", + "type": "runs" + } + } + }, + "links": { + "output": "/api/v2/policy-checks/polchk-abcabcabcabcabc4/output" + } + } + ] + }, + "expected_results": { + "Type": 1, + "ContentsFormat": "json", + "Contents": { + "data": [ + { + "id": "polchk-abcabcabcabcabc4", + "type": "policy-checks", + "attributes": { + "result": { + "result": false, + "passed": 0, + "total-failed": 1, + "hard-failed": 0, + "soft-failed": 1, + "advisory-failed": 0, + "duration-ms": 0 + }, + "scope": "organization", + "status": "soft_failed", + "status-timestamps": { + "queued-at": "2017-11-29T20:02:17+00:00", + "soft-failed-at": "2017-11-29T20:02:20+00:00" + }, + "actions": { + "is-overridable": true + }, + "permissions": { + "can-override": false + } + }, + "relationships": { + "run": { + "data": { + "id": "run-abcabcabcabcabc4", + "type": "runs" + } + } + }, + "links": { + "output": "/api/v2/policy-checks/polchk-abcabcabcabcabc4/output" + } + } + ] + }, + "HumanReadable": "### Terraform Policy Checks\n|Policy check id|Result|Scope |Status|\n|---|---|---|---|\n| polchk-abcabcabcabcabc4 | result: false
passed: 0
total-failed: 1
hard-failed: 0
soft-failed: 1
advisory-failed: 0
duration-ms: 0 | organization | soft_failed |\n", + "EntryContext": { + "Terraform.PolicyCheck(val.id && val.id == obj.id)": [ + { + "id": "polchk-abcabcabcabcabc4", + "type": "policy-checks", + "attributes": { + "result": { + "result": false, + "passed": 0, + "total-failed": 1, + "hard-failed": 0, + "soft-failed": 1, + "advisory-failed": 0, + "duration-ms": 0 + }, + "scope": "organization", + "status": "soft_failed", + "status-timestamps": { + "queued-at": "2017-11-29T20:02:17+00:00", + "soft-failed-at": "2017-11-29T20:02:20+00:00" + }, + "actions": { + "is-overridable": true + }, + "permissions": { + "can-override": false + } + }, + "relationships": { + "run": { + "data": { + "id": "run-abcabcabcabcabc4", + "type": "runs" + } + } + }, + "links": { + "output": "/api/v2/policy-checks/polchk-abcabcabcabcabc4/output" + } + } + ] + }, + "IndicatorTimeline": [], + "IgnoreAutoExtract": false, + "Note": false, + "Relationships": [] + } +} \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policies_list_request.json b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policies_list_request.json new file mode 100644 index 000000000000..c172fdca10f6 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policies_list_request.json @@ -0,0 +1,174 @@ +{ + "mock_response": { + "data": [ + { + "id": "pol-Abcabcabcabcabc4", + "type": "policies", + "attributes": { + "name": "nat-policies", + "description": null, + "enforce": [ + { + "path": "nat-policies.sentinel", + "mode": "hard-mandatory" + } + ], + "policy-set-count": 1, + "updated-at": "2023-11-14T18:12:36.702Z", + "kind": "sentinel", + "enforcement-level": "hard-mandatory" + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-123Abc", + "type": "organizations" + } + }, + "policy-sets": { + "data": [ + { + "id": "polset-Abcabcabcabcabc5", + "type": "policy-sets" + } + ] + } + }, + "links": { + "self": "/api/v2/policies/pol-Abcabcabcabcabc4", + "upload": "/api/v2/policies/pol-Abcabcabcabcabc4/upload", + "download": "/api/v2/policies/pol-Abcabcabcabcabc4/download" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/organizations/example-org-123Abc/policies?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/organizations/example-org-123Abc/policies?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/organizations/example-org-123Abc/policies?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 1 + } + } + }, + "expected_results": { + "Type": 1, + "ContentsFormat": "json", + "Contents": { + "data": [ + { + "id": "pol-Abcabcabcabcabc4", + "type": "policies", + "attributes": { + "name": "nat-policies", + "description": null, + "enforce": [ + { + "path": "nat-policies.sentinel", + "mode": "hard-mandatory" + } + ], + "policy-set-count": 1, + "updated-at": "2023-11-14T18:12:36.702Z", + "kind": "sentinel", + "enforcement-level": "hard-mandatory" + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-123Abc", + "type": "organizations" + } + }, + "policy-sets": { + "data": [ + { + "id": "polset-Abcabcabcabcabc5", + "type": "policy-sets" + } + ] + } + }, + "links": { + "self": "/api/v2/policies/pol-Abcabcabcabcabc4", + "upload": "/api/v2/policies/pol-Abcabcabcabcabc4/upload", + "download": "/api/v2/policies/pol-Abcabcabcabcabc4/download" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/organizations/example-org-123Abc/policies?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/organizations/example-org-123Abc/policies?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/organizations/example-org-123Abc/policies?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 1 + } + } + }, + "HumanReadable": "### Terraform Policies\n|Kind|Organization id|Policy Set ids|Policy description|Policy id|Policy name|\n|---|---|---|---|---|---|\n| attributes.kind | relationships.organization.data.id | relationships.policy-sets.data.id | attributes.description | id | attributes.name |\n", + "EntryContext": { + "Terraform.Policy(val.id && val.id == obj.id)": [ + { + "id": "pol-Abcabcabcabcabc4", + "type": "policies", + "attributes": { + "name": "nat-policies", + "description": null, + "enforce": [ + { + "path": "nat-policies.sentinel", + "mode": "hard-mandatory" + } + ], + "policy-set-count": 1, + "updated-at": "2023-11-14T18:12:36.702Z", + "kind": "sentinel", + "enforcement-level": "hard-mandatory" + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-123Abc", + "type": "organizations" + } + }, + "policy-sets": { + "data": [ + { + "id": "polset-Abcabcabcabcabc5", + "type": "policy-sets" + } + ] + } + }, + "links": { + "self": "/api/v2/policies/pol-Abcabcabcabcabc4", + "upload": "/api/v2/policies/pol-Abcabcabcabcabc4/upload", + "download": "/api/v2/policies/pol-Abcabcabcabcabc4/download" + } + } + ] + }, + "IndicatorTimeline": [], + "IgnoreAutoExtract": false, + "Note": false, + "Relationships": [] + } +} \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policy_set_list_request.json b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policy_set_list_request.json new file mode 100644 index 000000000000..819c88b2fa8c --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/policy_set_list_request.json @@ -0,0 +1,207 @@ +{ + "mock_response": { + "data": [ + { + "id": "polset-abcABCabcabc1234", + "type": "policy-sets", + "attributes": { + "name": "test-policy-set", + "description": null, + "global": false, + "workspace-count": 1, + "project-count": 0, + "created-at": "2023-11-08T11:25:06.196Z", + "updated-at": "2023-11-08T11:25:06.196Z", + "kind": "sentinel", + "agent-enabled": false, + "policy-count": 1, + "versioned": false + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-12ab3c", + "type": "organizations" + } + }, + "policies": { + "data": [ + { + "id": "pol-abcabcabcabcabc6", + "type": "policies" + } + ] + }, + "workspaces": { + "data": [ + { + "id": "ws-abcabcabcabcabc6", + "type": "workspaces" + } + ] + }, + "projects": { + "data": [] + }, + "workspace-exclusions": { + "data": [] + } + }, + "links": { + "self": "/api/v2/policy-sets/polset-abcABCabcabc1234" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/organizations/example-org-12ab3c/policy-sets?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/organizations/example-org-12ab3c/policy-sets?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/organizations/example-org-12ab3c/policy-sets?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 1 + } + } + }, + "expected_results": { + "Type": 1, + "ContentsFormat": "json", + "Contents": { + "data": [ + { + "id": "polset-abcABCabcabc1234", + "type": "policy-sets", + "attributes": { + "name": "test-policy-set", + "description": null, + "global": false, + "workspace-count": 1, + "project-count": 0, + "created-at": "2023-11-08T11:25:06.196Z", + "updated-at": "2023-11-08T11:25:06.196Z", + "kind": "sentinel", + "agent-enabled": false, + "policy-count": 1, + "versioned": false + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-12ab3c", + "type": "organizations" + } + }, + "policies": { + "data": [ + { + "id": "pol-abcabcabcabcabc6", + "type": "policies" + } + ] + }, + "workspaces": { + "data": [ + { + "id": "ws-abcabcabcabcabc6", + "type": "workspaces" + } + ] + }, + "projects": { + "data": [] + }, + "workspace-exclusions": { + "data": [] + } + }, + "links": { + "self": "/api/v2/policy-sets/polset-abcABCabcabc1234" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/organizations/example-org-12ab3c/policy-sets?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/organizations/example-org-12ab3c/policy-sets?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/organizations/example-org-12ab3c/policy-sets?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 1 + } + } + }, + "HumanReadable": "### Terraform Policy Sets\n|Description|Organization|Policies ids|Policy Set name|Policy set id|Projects|Workspaces|\n|---|---|---|---|---|---|---|\n| attributes.description | relationships.organization.data.id | relationships.policies.data.id | attributes.name | id | relationships.projects.data.id | relationships.workspaces.data.id |\n", + "EntryContext": { + "Terraform.PolicySet(val.id && val.id == obj.id)": [ + { + "id": "polset-abcABCabcabc1234", + "type": "policy-sets", + "attributes": { + "name": "test-policy-set", + "description": null, + "global": false, + "workspace-count": 1, + "project-count": 0, + "created-at": "2023-11-08T11:25:06.196Z", + "updated-at": "2023-11-08T11:25:06.196Z", + "kind": "sentinel", + "agent-enabled": false, + "policy-count": 1, + "versioned": false + }, + "relationships": { + "organization": { + "data": { + "id": "example-org-12ab3c", + "type": "organizations" + } + }, + "policies": { + "data": [ + { + "id": "pol-abcabcabcabcabc6", + "type": "policies" + } + ] + }, + "workspaces": { + "data": [ + { + "id": "ws-abcabcabcabcabc6", + "type": "workspaces" + } + ] + }, + "projects": { + "data": [] + }, + "workspace-exclusions": { + "data": [] + } + }, + "links": { + "self": "/api/v2/policy-sets/polset-abcABCabcabc1234" + } + } + ] + }, + "IndicatorTimeline": [], + "IgnoreAutoExtract": false, + "Note": false, + "Relationships": [] + } +} \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/run_action_request.json b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/run_action_request.json new file mode 100644 index 000000000000..499123f8b2ba --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/run_action_request.json @@ -0,0 +1,10 @@ +{ + "mock_response": { + "errors": [ + { + "status": "409", + "title": "transition not allowed" + } + ] + } +} \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/runs_list_request.json b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/runs_list_request.json new file mode 100644 index 000000000000..f578ebd11650 --- /dev/null +++ b/Packs/HashiCorpTerraform/Integrations/HashiCorpTerraform/test_data/runs_list_request.json @@ -0,0 +1,985 @@ +{ + "mock_response": { + "data": [ + { + "id": "run-ABCABCABCABCABCA", + "type": "runs", + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": false, + "is-discardable": false, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": false, + "canceled-at": null, + "created-at": "2023-11-30T09:21:33.373Z", + "has-changes": false, + "is-destroy": false, + "message": "Triggered via UI", + "plan-only": false, + "refresh": true, + "refresh-only": true, + "replace-addrs": [], + "save-plan": false, + "source": "tfe-ui", + "status-timestamps": { + "planned-at": "2023-11-30T09:21:42+00:00", + "queuing-at": "2023-11-30T09:21:33+00:00", + "planning-at": "2023-11-30T09:21:37+00:00", + "plan-queued-at": "2023-11-30T09:21:33+00:00", + "plan-queueable-at": "2023-11-30T09:21:33+00:00", + "planned-and-finished-at": "2023-11-30T09:21:42+00:00" + }, + "status": "planned_and_finished", + "target-addrs": null, + "trigger-reason": "manual", + "terraform-version": "1.4.4", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-execute": true, + "can-force-cancel": true, + "can-override-policy-check": true + }, + "variables": [] + }, + "relationships": { + "workspace": { + "data": { + "id": "ws-ABCABCABCABCABCA", + "type": "workspaces" + } + }, + "apply": { + "data": { + "id": "apply-ABCABCABCABCABCA", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/apply" + } + }, + "configuration-version": { + "data": { + "id": "cv-ABCABCABCABCABCA", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user-ABCABCABCABCABCA", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/created-by" + } + }, + "plan": { + "data": { + "id": "plan-ABCABCABCABCABCA", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/plan" + } + }, + "run-events": { + "data": [ + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/task-stages" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/policy-checks" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/comments" + } + } + }, + "links": { + "self": "/api/v2/runs/run-ABCABCABCABCABCA" + } + }, + { + "id": "run-ABCABCABCABCABCA", + "type": "runs", + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": false, + "is-discardable": false, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": true, + "canceled-at": null, + "created-at": "2023-10-25T10:33:02.368Z", + "has-changes": true, + "is-destroy": false, + "message": "Triggered via CLI", + "plan-only": false, + "refresh": true, + "refresh-only": false, + "replace-addrs": null, + "save-plan": false, + "source": "terraform+cloud", + "status-timestamps": { + "applied-at": "2023-10-25T10:33:19+00:00", + "planned-at": "2023-10-25T10:33:11+00:00", + "queuing-at": "2023-10-25T10:33:02+00:00", + "applying-at": "2023-10-25T10:33:16+00:00", + "planning-at": "2023-10-25T10:33:07+00:00", + "confirmed-at": "2023-10-25T10:33:11+00:00", + "plan-queued-at": "2023-10-25T10:33:03+00:00", + "apply-queued-at": "2023-10-25T10:33:12+00:00", + "queuing-apply-at": "2023-10-25T10:33:11+00:00", + "plan-queueable-at": "2023-10-25T10:33:02+00:00" + }, + "status": "applied", + "target-addrs": null, + "trigger-reason": "manual", + "terraform-version": "1.4.4", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-execute": true, + "can-force-cancel": true, + "can-override-policy-check": true + }, + "variables": [] + }, + "relationships": { + "workspace": { + "data": { + "id": "ws-ABCABCABCABCABCA", + "type": "workspaces" + } + }, + "apply": { + "data": { + "id": "apply-ABCABCABCABCABCA", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/apply" + } + }, + "configuration-version": { + "data": { + "id": "cv-ABCABCABCABCABCA", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user--ABCABCABCABCABCA", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/created-by" + } + }, + "plan": { + "data": { + "id": "plan-ABCABCABCABCABCA", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/plan" + } + }, + "run-events": { + "data": [ + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/task-stages" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/policy-checks" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/comments" + } + } + }, + "links": { + "self": "/api/v2/runs/run-ABCABCABCABCABCA" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 2 + }, + "status-counts": { + "pending": 0, + "fetching": 0, + "fetching-completed": 0, + "pre-plan-running": 0, + "pre-plan-completed": 0, + "queuing": 0, + "plan-queued": 0, + "planning": 0, + "planned": 0, + "confirmed": 0, + "queuing-apply": 0, + "apply-queued": 0, + "applying": 0, + "applied": 1, + "discarded": 0, + "errored": 0, + "canceled": 0, + "cost-estimating": 0, + "cost-estimated": 0, + "policy-checking": 0, + "policy-override": 0, + "policy-checked": 0, + "policy-soft-failed": 0, + "planned-and-finished": 2, + "planned-and-saved": 0, + "post-plan-running": 0, + "post-plan-completed": 0, + "pre-apply-running": 0, + "pre-apply-completed": 0, + "post-apply-running": 0, + "post-apply-completed": 0, + "assessing": 0, + "assessed": 0, + "pre-plan-awaiting-decision": 0, + "post-plan-awaiting-decision": 0, + "pre-apply-awaiting-decision": 0, + "total": 3 + } + } + }, + "expected_results": { + "Type": 1, + "ContentsFormat": "json", + "Contents": { + "data": [ + { + "id": "run-ABCABCABCABCABCA", + "type": "runs", + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": false, + "is-discardable": false, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": false, + "canceled-at": null, + "created-at": "2023-11-30T09:21:33.373Z", + "has-changes": false, + "is-destroy": false, + "message": "Triggered via UI", + "plan-only": false, + "refresh": true, + "refresh-only": true, + "replace-addrs": [], + "save-plan": false, + "source": "tfe-ui", + "status-timestamps": { + "planned-at": "2023-11-30T09:21:42+00:00", + "queuing-at": "2023-11-30T09:21:33+00:00", + "planning-at": "2023-11-30T09:21:37+00:00", + "plan-queued-at": "2023-11-30T09:21:33+00:00", + "plan-queueable-at": "2023-11-30T09:21:33+00:00", + "planned-and-finished-at": "2023-11-30T09:21:42+00:00" + }, + "status": "planned_and_finished", + "target-addrs": null, + "trigger-reason": "manual", + "terraform-version": "1.4.4", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-execute": true, + "can-force-cancel": true, + "can-override-policy-check": true + }, + "variables": [] + }, + "relationships": { + "workspace": { + "data": { + "id": "ws-ABCABCABCABCABCA", + "type": "workspaces" + } + }, + "apply": { + "data": { + "id": "apply-ABCABCABCABCABCA", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/apply" + } + }, + "configuration-version": { + "data": { + "id": "cv-ABCABCABCABCABCA", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user-ABCABCABCABCABCA", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/created-by" + } + }, + "plan": { + "data": { + "id": "plan-ABCABCABCABCABCA", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/plan" + } + }, + "run-events": { + "data": [ + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/task-stages" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/policy-checks" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/comments" + } + } + }, + "links": { + "self": "/api/v2/runs/run-ABCABCABCABCABCA" + } + }, + { + "id": "run-ABCABCABCABCABCA", + "type": "runs", + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": false, + "is-discardable": false, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": true, + "canceled-at": null, + "created-at": "2023-10-25T10:33:02.368Z", + "has-changes": true, + "is-destroy": false, + "message": "Triggered via CLI", + "plan-only": false, + "refresh": true, + "refresh-only": false, + "replace-addrs": null, + "save-plan": false, + "source": "terraform+cloud", + "status-timestamps": { + "applied-at": "2023-10-25T10:33:19+00:00", + "planned-at": "2023-10-25T10:33:11+00:00", + "queuing-at": "2023-10-25T10:33:02+00:00", + "applying-at": "2023-10-25T10:33:16+00:00", + "planning-at": "2023-10-25T10:33:07+00:00", + "confirmed-at": "2023-10-25T10:33:11+00:00", + "plan-queued-at": "2023-10-25T10:33:03+00:00", + "apply-queued-at": "2023-10-25T10:33:12+00:00", + "queuing-apply-at": "2023-10-25T10:33:11+00:00", + "plan-queueable-at": "2023-10-25T10:33:02+00:00" + }, + "status": "applied", + "target-addrs": null, + "trigger-reason": "manual", + "terraform-version": "1.4.4", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-execute": true, + "can-force-cancel": true, + "can-override-policy-check": true + }, + "variables": [] + }, + "relationships": { + "workspace": { + "data": { + "id": "ws-ABCABCABCABCABCA", + "type": "workspaces" + } + }, + "apply": { + "data": { + "id": "apply-ABCABCABCABCABCA", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/apply" + } + }, + "configuration-version": { + "data": { + "id": "cv-ABCABCABCABCABCA", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user--ABCABCABCABCABCA", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/created-by" + } + }, + "plan": { + "data": { + "id": "plan-ABCABCABCABCABCA", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/plan" + } + }, + "run-events": { + "data": [ + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/task-stages" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/policy-checks" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/comments" + } + } + }, + "links": { + "self": "/api/v2/runs/run-ABCABCABCABCABCA" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 2 + }, + "status-counts": { + "pending": 0, + "fetching": 0, + "fetching-completed": 0, + "pre-plan-running": 0, + "pre-plan-completed": 0, + "queuing": 0, + "plan-queued": 0, + "planning": 0, + "planned": 0, + "confirmed": 0, + "queuing-apply": 0, + "apply-queued": 0, + "applying": 0, + "applied": 1, + "discarded": 0, + "errored": 0, + "canceled": 0, + "cost-estimating": 0, + "cost-estimated": 0, + "policy-checking": 0, + "policy-override": 0, + "policy-checked": 0, + "policy-soft-failed": 0, + "planned-and-finished": 2, + "planned-and-saved": 0, + "post-plan-running": 0, + "post-plan-completed": 0, + "pre-apply-running": 0, + "pre-apply-completed": 0, + "post-apply-running": 0, + "post-apply-completed": 0, + "assessing": 0, + "assessed": 0, + "pre-plan-awaiting-decision": 0, + "post-plan-awaiting-decision": 0, + "pre-apply-awaiting-decision": 0, + "total": 3 + } + } + }, + "HumanReadable": "### Terraform Runs\n|Plan id|Planned at|Run id|Status|\n|---|---|---|---|\n| plan-ABCABCABCABCABCA | 2023-11-30T09:21:42+00:00 | run-ABCABCABCABCABCA | planned_and_finished |\n| plan-ABCABCABCABCABCA | 2023-10-25T10:33:11+00:00 | run-ABCABCABCABCABCA | applied |\n", + "EntryContext": { + "Terraform.Run(val.data.id && val.data.id == obj.data.id)": { + "data": [ + { + "id": "run-ABCABCABCABCABCA", + "type": "runs", + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": false, + "is-discardable": false, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": false, + "canceled-at": null, + "created-at": "2023-11-30T09:21:33.373Z", + "has-changes": false, + "is-destroy": false, + "message": "Triggered via UI", + "plan-only": false, + "refresh": true, + "refresh-only": true, + "replace-addrs": [], + "save-plan": false, + "source": "tfe-ui", + "status-timestamps": { + "planned-at": "2023-11-30T09:21:42+00:00", + "queuing-at": "2023-11-30T09:21:33+00:00", + "planning-at": "2023-11-30T09:21:37+00:00", + "plan-queued-at": "2023-11-30T09:21:33+00:00", + "plan-queueable-at": "2023-11-30T09:21:33+00:00", + "planned-and-finished-at": "2023-11-30T09:21:42+00:00" + }, + "status": "planned_and_finished", + "target-addrs": null, + "trigger-reason": "manual", + "terraform-version": "1.4.4", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-execute": true, + "can-force-cancel": true, + "can-override-policy-check": true + }, + "variables": [] + }, + "relationships": { + "workspace": { + "data": { + "id": "ws-ABCABCABCABCABCA", + "type": "workspaces" + } + }, + "apply": { + "data": { + "id": "apply-ABCABCABCABCABCA", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/apply" + } + }, + "configuration-version": { + "data": { + "id": "cv-ABCABCABCABCABCA", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user-ABCABCABCABCABCA", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/created-by" + } + }, + "plan": { + "data": { + "id": "plan-ABCABCABCABCABCA", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/plan" + } + }, + "run-events": { + "data": [ + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + }, + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/task-stages" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/policy-checks" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/comments" + } + } + }, + "links": { + "self": "/api/v2/runs/run-ABCABCABCABCABCA" + } + }, + { + "id": "run-ABCABCABCABCABCA", + "type": "runs", + "attributes": { + "actions": { + "is-cancelable": false, + "is-confirmable": false, + "is-discardable": false, + "is-force-cancelable": false + }, + "allow-config-generation": false, + "allow-empty-apply": false, + "auto-apply": true, + "canceled-at": null, + "created-at": "2023-10-25T10:33:02.368Z", + "has-changes": true, + "is-destroy": false, + "message": "Triggered via CLI", + "plan-only": false, + "refresh": true, + "refresh-only": false, + "replace-addrs": null, + "save-plan": false, + "source": "terraform+cloud", + "status-timestamps": { + "applied-at": "2023-10-25T10:33:19+00:00", + "planned-at": "2023-10-25T10:33:11+00:00", + "queuing-at": "2023-10-25T10:33:02+00:00", + "applying-at": "2023-10-25T10:33:16+00:00", + "planning-at": "2023-10-25T10:33:07+00:00", + "confirmed-at": "2023-10-25T10:33:11+00:00", + "plan-queued-at": "2023-10-25T10:33:03+00:00", + "apply-queued-at": "2023-10-25T10:33:12+00:00", + "queuing-apply-at": "2023-10-25T10:33:11+00:00", + "plan-queueable-at": "2023-10-25T10:33:02+00:00" + }, + "status": "applied", + "target-addrs": null, + "trigger-reason": "manual", + "terraform-version": "1.4.4", + "permissions": { + "can-apply": true, + "can-cancel": true, + "can-comment": true, + "can-discard": true, + "can-force-execute": true, + "can-force-cancel": true, + "can-override-policy-check": true + }, + "variables": [] + }, + "relationships": { + "workspace": { + "data": { + "id": "ws-ABCABCABCABCABCA", + "type": "workspaces" + } + }, + "apply": { + "data": { + "id": "apply-ABCABCABCABCABCA", + "type": "applies" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/apply" + } + }, + "configuration-version": { + "data": { + "id": "cv-ABCABCABCABCABCA", + "type": "configuration-versions" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/configuration-version" + } + }, + "created-by": { + "data": { + "id": "user--ABCABCABCABCABCA", + "type": "users" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/created-by" + } + }, + "plan": { + "data": { + "id": "plan-ABCABCABCABCABCA", + "type": "plans" + }, + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/plan" + } + }, + "run-events": { + "data": [ + { + "id": "re-ABCABCABCABCABCA", + "type": "run-events" + } + ], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/run-events" + } + }, + "task-stages": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/task-stages" + } + }, + "policy-checks": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/policy-checks" + } + }, + "comments": { + "data": [], + "links": { + "related": "/api/v2/runs/run-ABCABCABCABCABCA/comments" + } + } + }, + "links": { + "self": "/api/v2/runs/run-ABCABCABCABCABCA" + } + } + ], + "links": { + "self": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "first": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20", + "prev": null, + "next": null, + "last": "https://app.terraform.io/api/v2/workspaces/ws-ABCABCABCABCABCA/runs?page%5Bnumber%5D=1&page%5Bsize%5D=20" + }, + "meta": { + "pagination": { + "current-page": 1, + "page-size": 20, + "prev-page": null, + "next-page": null, + "total-pages": 1, + "total-count": 2 + }, + "status-counts": { + "pending": 0, + "fetching": 0, + "fetching-completed": 0, + "pre-plan-running": 0, + "pre-plan-completed": 0, + "queuing": 0, + "plan-queued": 0, + "planning": 0, + "planned": 0, + "confirmed": 0, + "queuing-apply": 0, + "apply-queued": 0, + "applying": 0, + "applied": 1, + "discarded": 0, + "errored": 0, + "canceled": 0, + "cost-estimating": 0, + "cost-estimated": 0, + "policy-checking": 0, + "policy-override": 0, + "policy-checked": 0, + "policy-soft-failed": 0, + "planned-and-finished": 2, + "planned-and-saved": 0, + "post-plan-running": 0, + "post-plan-completed": 0, + "pre-apply-running": 0, + "pre-apply-completed": 0, + "post-apply-running": 0, + "post-apply-completed": 0, + "assessing": 0, + "assessed": 0, + "pre-plan-awaiting-decision": 0, + "post-plan-awaiting-decision": 0, + "pre-apply-awaiting-decision": 0, + "total": 3 + } + } + } + }, + "IndicatorTimeline": [], + "IgnoreAutoExtract": false, + "Note": false, + "Relationships": [] + } +} \ No newline at end of file diff --git a/Packs/HashiCorpTerraform/README.md b/Packs/HashiCorpTerraform/README.md new file mode 100644 index 000000000000..c25acf97fe4f --- /dev/null +++ b/Packs/HashiCorpTerraform/README.md @@ -0,0 +1,8 @@ +HashiCorp Terraform is an Infrastructure as Code (IaC) tool designed to streamline and automate the deployment and management of infrastructure across diverse environments. + +## What does this pack do? +- List runs in a workspace. +- Perform actions on a run such as: apply, cancel, discard, etc. +- Show a plan. +- List a policy's policy sets and policy checks. + diff --git a/Packs/HashiCorpTerraform/TestPlaybooks/HasiCoprTerraformTest.yml b/Packs/HashiCorpTerraform/TestPlaybooks/HasiCoprTerraformTest.yml new file mode 100644 index 000000000000..95e3b9be8c52 --- /dev/null +++ b/Packs/HashiCorpTerraform/TestPlaybooks/HasiCoprTerraformTest.yml @@ -0,0 +1,590 @@ +id: HasiCoprTerraformTest +version: -1 +name: HasiCoprTerraformTest +fromversion: 6.10.0 +starttaskid: "0" +tasks: + "0": + id: "0" + taskid: 6375b828-bb18-4371-815f-ca382522a88f + type: start + task: + id: 6375b828-bb18-4371-815f-ca382522a88f + version: -1 + name: "" + iscommand: false + brand: "" + description: '' + nexttasks: + '#none#': + - "1" + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 480, + "y": 50 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "1": + id: "1" + taskid: 626a14eb-fddc-441a-832b-89c6e2f89388 + type: regular + task: + id: 626a14eb-fddc-441a-832b-89c6e2f89388 + version: -1 + name: Delete Context + description: |- + Delete field from context. + + This automation runs using the default Limited User role, unless you explicitly change the permissions. + For more information, see the section about permissions here: + https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/6.10/Cortex-XSOAR-Administrator-Guide/Automations + scriptName: DeleteContext + type: regular + iscommand: false + brand: "" + nexttasks: + '#none#': + - "2" + - "5" + - "7" + scriptarguments: + all: + simple: "yes" + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 480, + "y": 195 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "2": + id: "2" + taskid: 5bb5eb7e-4a8c-458a-8672-35ba16b45603 + type: regular + task: + id: 5bb5eb7e-4a8c-458a-8672-35ba16b45603 + version: -1 + name: Get runs + description: List Runs in a Workspace. + script: HashicorpTerraform|||terraform-runs-list + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "3" + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 1237.5, + "y": 370 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "3": + id: "3" + taskid: d56a6240-1a27-4a0b-8f81-c54d4e593a3e + type: condition + task: + id: d56a6240-1a27-4a0b-8f81-c54d4e593a3e + version: -1 + name: Check results + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "9" + - "14" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isNotEmpty + left: + value: + simple: Terraform.Run.data.id + iscontext: true + continueonerrortype: "" + view: |- + { + "position": { + "x": 1237.5, + "y": 545 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "4": + id: "4" + taskid: bf005cc4-5bbf-4753-8bae-4ed9daa6944e + type: condition + task: + id: bf005cc4-5bbf-4753-8bae-4ed9daa6944e + version: -1 + name: Check results + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "6" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isNotEmpty + left: + value: + simple: Terraform.Policy.id + iscontext: true + right: + value: {} + continueonerrortype: "" + view: |- + { + "position": { + "x": 50, + "y": 1245 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "5": + id: "5" + taskid: 32d0a14c-8316-40f9-863b-480cbf3ed08c + type: regular + task: + id: 32d0a14c-8316-40f9-863b-480cbf3ed08c + version: -1 + name: Get policies + description: List the policies for an organization or get a specific policy. + script: HashicorpTerraform|||terraform-policies-list + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "4" + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 50, + "y": 1070 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "6": + id: "6" + taskid: 76a15b24-c939-4b4e-8776-ff9b48f8b023 + type: title + task: + id: 76a15b24-c939-4b4e-8776-ff9b48f8b023 + version: -1 + name: Done + type: title + iscommand: false + brand: "" + description: '' + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 910, + "y": 1420 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "7": + id: "7" + taskid: ceaa78e4-a2bd-4d32-8678-787fde152023 + type: regular + task: + id: ceaa78e4-a2bd-4d32-8678-787fde152023 + version: -1 + name: Get policies set + description: List the policy sets for an organization or get a specific policy set. + script: HashicorpTerraform|||terraform-policy-set-list + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "8" + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 480, + "y": 1070 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "8": + id: "8" + taskid: 53b3c8d0-49b6-435c-81b9-eb6287adcd7b + type: condition + task: + id: 53b3c8d0-49b6-435c-81b9-eb6287adcd7b + version: -1 + name: Check results + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "6" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isNotEmpty + left: + value: + simple: Terraform.PolicySet.id + iscontext: true + right: + value: {} + - - operator: isNotEmpty + left: + value: + simple: Terraform.PolicySet.relationships.policies.data.id + iscontext: true + continueonerrortype: "" + view: |- + { + "position": { + "x": 480, + "y": 1245 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "9": + id: "9" + taskid: 3a9c20ab-f588-4c89-8028-417d2ecc037f + type: regular + task: + id: 3a9c20ab-f588-4c89-8028-417d2ecc037f + version: -1 + name: Get policies checks + description: List the policy checks for a Terraform run. + script: HashicorpTerraform|||terraform-policies-checks-list + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "10" + scriptarguments: + run_id: + complex: + root: ${Terraform.Run.data + accessor: id} + transformers: + - operator: FirstArrayElement + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 910, + "y": 720 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "10": + id: "10" + taskid: 281f4176-8cde-472b-8bfa-587300ee929d + type: regular + task: + id: 281f4176-8cde-472b-8bfa-587300ee929d + version: -1 + name: Get plan meta + description: Get plan JSON file or the plan meta data. + script: HashicorpTerraform|||terraform-plan-get + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "11" + scriptarguments: + plan_id: + complex: + root: Terraform.Run.data.relationships.plan.data + accessor: id + transformers: + - operator: FirstArrayElement + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 910, + "y": 895 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "11": + id: "11" + taskid: 1881c39a-2d9a-4b1d-868f-ec2296b3164c + type: condition + task: + id: 1881c39a-2d9a-4b1d-868f-ec2296b3164c + version: -1 + name: Check response + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "12" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isNotEmpty + left: + value: + simple: Terraform.Plan.attributes.status + iscontext: true + continueonerrortype: "" + view: |- + { + "position": { + "x": 910, + "y": 1070 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "12": + id: "12" + taskid: b318ab98-ca6c-4bbc-8c75-0c70d045ea5c + type: regular + task: + id: b318ab98-ca6c-4bbc-8c75-0c70d045ea5c + version: -1 + name: Get plan file result + description: Get plan JSON file or the plan meta data. + script: HashicorpTerraform|||terraform-plan-get + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "6" + scriptarguments: + json_output: + simple: "true" + plan_id: + complex: + root: Terraform.Plan + accessor: id + transformers: + - operator: FirstArrayElement + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 910, + "y": 1245 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "13": + id: "13" + taskid: 9675207f-b3a6-4a2b-80d6-9b7706157b1c + type: regular + task: + id: 9675207f-b3a6-4a2b-80d6-9b7706157b1c + version: -1 + name: Run action + description: 'Perform an action on a Terraform run. The available actions are: apply, cancel, discard, force-cancel, force-execute.' + script: HashicorpTerraform|||terraform-run-action + type: regular + iscommand: true + brand: HashicorpTerraform + nexttasks: + '#none#': + - "6" + scriptarguments: + action: + simple: discard + comment: + simple: comment from TPB + run_id: + complex: + root: Terraform.Run.data + filters: + - - operator: isEqualString + left: + value: + simple: Terraform.Run.data.attributes.actions.is-discardable + iscontext: true + right: + value: + simple: "true" + accessor: id + transformers: + - operator: FirstArrayElement + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 1340, + "y": 1245 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "14": + id: "14" + taskid: 7fd5e23d-089a-4003-8bab-faf19a556929 + type: condition + task: + id: 7fd5e23d-089a-4003-8bab-faf19a556929 + version: -1 + name: There are run to discard + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "6" + "yes": + - "13" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isTrue + left: + value: + simple: Terraform.Run.data.attributes.actions.is-discardable + iscontext: true + continueonerrortype: "" + view: |- + { + "position": { + "x": 1452.5, + "y": 1070 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false +view: |- + { + "linkLabelsPosition": {}, + "paper": { + "dimensions": { + "height": 1435, + "width": 1782.5, + "x": 50, + "y": 50 + } + } + } +inputs: [] +outputs: [] +description: '' diff --git a/Packs/HashiCorpTerraform/pack_metadata.json b/Packs/HashiCorpTerraform/pack_metadata.json new file mode 100644 index 000000000000..4e9ffbaefb84 --- /dev/null +++ b/Packs/HashiCorpTerraform/pack_metadata.json @@ -0,0 +1,19 @@ +{ + "name": "HashiCorp Terraform", + "description": "Hashicorp Terraform provide infrastructure automation to provision and manage resources in any cloud or data center with Terraform.", + "support": "xsoar", + "currentVersion": "1.0.0", + "author": "Cortex XSOAR", + "url": "https://www.paloaltonetworks.com/cortex", + "email": "", + "categories": [ + "IT Services" + ], + "tags": [], + "useCases": [], + "keywords": [], + "marketplaces": [ + "xsoar", + "marketplacev2" + ] +} \ No newline at end of file diff --git a/Tests/conf.json b/Tests/conf.json index c7952f72b202..451df39c4995 100644 --- a/Tests/conf.json +++ b/Tests/conf.json @@ -3514,6 +3514,11 @@ "integrations": "Code42", "fromversion": "6.10.0" }, + { + "playbookID": "HasiCoprTerraformTest", + "integrations": "HashicorpTerraform", + "fromversion": "6.10.0" + }, { "playbookID": "FetchIndicatorsFromFile-test", "fromversion": "5.5.0"