Skip to content

Commit 891d9b7

Browse files
refeedAkshat0694
authored andcommitted
terraform_plan: Add direct_references and direct_dependencies
Closes #102
1 parent 8056318 commit 891d9b7

File tree

7 files changed

+1742
-1
lines changed

7 files changed

+1742
-1
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,30 @@ optional arguments:
151151
}
152152
```
153153

154+
4. Make sure that AWS ELBs are attached to security group (using Terraform plan provider)
155+
```json
156+
{
157+
"meta": {
158+
"version": "v1",
159+
"required_provider": "stackguardian/terraform_plan"
160+
},
161+
"evaluators": [
162+
{
163+
"id": "aws_elbs_have_direct_references_to_security_group",
164+
"provider_args": {
165+
"operation_type": "direct_references",
166+
"terraform_resource_type": "aws_elb"
167+
},
168+
"condition": {
169+
"type": "Contains",
170+
"value": "aws_security_group",
171+
"error_tolerance": 2
172+
}
173+
}
174+
],
175+
"eval_expression": "aws_elbs_have_direct_references_to_security_group"
176+
}
177+
```
154178
<!-- ## Local Development Environment
155179
156180
- [Python 3.6 or higher](https://www.python.org/downloads/) is required.

src/tirith/providers/terraform_plan/handler.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,89 @@ def provide(provider_inputs, input_data):
159159
)
160160
return outputs
161161
# CASE 4
162-
# TODO: Get relationship between resources
162+
elif input_type == "direct_dependencies":
163+
direct_dependencies_operator(input_data, provider_inputs, outputs)
164+
elif input_type == "direct_references":
165+
direct_references_operator(input_data, provider_inputs, outputs)
166+
else:
167+
outputs.append(
168+
{
169+
"value": ProviderError(severity_value=99),
170+
"err": f"operation_type: '{input_type}' is not supported (severity_value: 99)",
171+
}
172+
)
163173
return outputs
174+
175+
176+
def direct_dependencies_operator(input_data: dict, provider_inputs: dict, outputs: list):
177+
config_resources = input_data.get("configuration", {}).get("root_module", {}).get("resources", [])
178+
resource_type = provider_inputs.get("terraform_resource_type")
179+
180+
if not resource_type:
181+
outputs.append(
182+
{
183+
"value": ProviderError(severity_value=99),
184+
"err": "`terraform_resource_type` must be provided in the provider input (severity_value: 99))",
185+
}
186+
)
187+
return
188+
189+
is_resource_found = False
190+
191+
for resource in config_resources:
192+
if resource.get("type") != resource_type:
193+
continue
194+
is_resource_found = True
195+
deps_resource_type = {resource_id.split(".")[0] for resource_id in resource.get("depends_on", [])}
196+
outputs.append({"value": list(deps_resource_type), "meta": config_resources})
197+
198+
if not is_resource_found:
199+
outputs.append(
200+
{
201+
"value": ProviderError(severity_value=1),
202+
"err": f"resource_type: '{resource_type}' is not found",
203+
"meta": config_resources,
204+
}
205+
)
206+
207+
208+
def direct_references_operator(input_data: dict, provider_inputs: dict, outputs: list):
209+
config_resources = input_data.get("configuration", {}).get("root_module", {}).get("resources", [])
210+
resource_type = provider_inputs.get("terraform_resource_type")
211+
212+
if not resource_type:
213+
outputs.append(
214+
{
215+
"value": ProviderError(severity_value=99),
216+
"err": "`terraform_resource_type` must be provided in the provider input (severity_value: 99))",
217+
}
218+
)
219+
return
220+
221+
is_resource_found = False
222+
223+
for resource in config_resources:
224+
if resource.get("type") != resource_type:
225+
continue
226+
is_resource_found = True
227+
resource_references = set()
228+
for expressions_val in resource.get("expressions", {}).values():
229+
# Currently we don't support expressions other than dict
230+
# Might be needed in the future to search references in lists
231+
# Ideally we should do `*.references`
232+
if not isinstance(expressions_val, dict):
233+
continue
234+
for reference in expressions_val.get("references", []):
235+
# Only get the resource type
236+
resource_references.add(reference.split(".")[0])
237+
238+
outputs.append({"value": list(resource_references), "meta": resource})
239+
240+
if not is_resource_found:
241+
outputs.append(
242+
{
243+
"value": ProviderError(severity_value=1),
244+
"err": f"resource_type: '{resource_type}' is not found",
245+
"meta": config_resources,
246+
}
247+
)

0 commit comments

Comments
 (0)