Terraform and OPA

Hi , I’m running a terraform plan and want to ensure that only certain IAM users/roles are allowed to do a terraform apply on certain resources.
I’m trying to figure out where does terraform store the information regarding who is creating these resources and can we block if the user/role doesn’t match in the opa policy we defined ?
Below is the opa policy that i’ve in place , this is checking for aws resources and only if the request is from certain users/roles then it should pass, in this policy i’m checking prior_state , but this configuration block isn’t present in all terraform plan (json file)

package terraform.network

import future.keywords
import input.plan

resources_to_check := [
	"aws_ec2_transit_gateway_peering_attachment_accepter",
	"aws_ec2_transit_gateway_route",
	"aws_ec2_transit_gateway_route_table_association",
	"aws_ec2_transit_gateway_peering_attachment",
	"aws_ssm_parameter",
	"aws_ec2_transit_gateway",
  "aws_iam_policy",
  "aws_vpc"
]
allowed_roles := ["AWSCloudFormationStackSetExecutionRole", "AWSReservedSSO_AdministratorAccess_"]


array_contains(arr, elem) if {
	arr[_] = elem
}

# allowed_actions := {"create", "update"}

deny contains msg if {
	r := plan.resource_changes[_]
	action := r.change.actions[count(r.change.actions) - 1]
	array_contains(["create", "update"], action)
	not array_contains(resources_to_check, r.type)
  
  ar := input.prior_state.values.root_module.child_modules[_].resources[_]
  roles := ar.values.arn
  roles
  role_split := split(roles, "/")
  
  some ro in allowed_roles
  role := role_split[1]
  not startswith(role, ro)
	

	msg := sprintf("Resource: %s can not be created/updated with %s role.", [r.type, role])
}

this is the sample terraform out json file

{
    "format_version":"1.2",
    "terraform_version":"1.5.2",
    "planned_values":{
       "root_module":{
          "resources":[
             {
                "address":"aws_iam_policy.policy",
                "mode":"managed",
                "type":"aws_iam_policy",
                "name":"policy",
                "provider_name":"registry.terraform.io/hashicorp/aws",
                "schema_version":0,
                "values":{
                   "description":"My test policy",
                   "name":"test_policy",
                   "path":"/",
                   "policy":"{\"Statement\":[{\"Action\":[\"ec2:Describe*\"],\"Effect\":\"Allow\",\"Resource\":\"*\"}],\"Version\":\"2012-10-17\"}",
                   "tags":null
                },
                "sensitive_values":{
                   "tags_all":{
                      
                   }
                }
             },
             {
                "address":"aws_s3_bucket.b",
                "mode":"managed",
                "type":"aws_s3_bucket",
                "name":"b",
                "provider_name":"registry.terraform.io/hashicorp/aws",
                "schema_version":0,
                "values":{
                   "acl":"private",
                   "bucket":"my-tf-test-bucket",
                   "force_destroy":false,
                   "tags":{
                      "Environment":"Dev",
                      "Name":"My bucket"
                   },
                   "tags_all":{
                      "Environment":"Dev",
                      "Name":"My bucket"
                   },
                   "timeouts":null
                },
                "sensitive_values":{
                   "cors_rule":[
                      
                   ],
                   "grant":[
                      
                   ],
                   "lifecycle_rule":[
                      
                   ],
                   "logging":[
                      
                   ],
                   "object_lock_configuration":[
                      
                   ],
                   "replication_configuration":[
                      
                   ],
                   "server_side_encryption_configuration":[
                      
                   ],
                   "tags":{
                      
                   },
                   "tags_all":{
                      
                   },
                   "versioning":[
                      
                   ],
                   "website":[
                      
                   ]
                }
             }
          ]
       }
    },
    "resource_changes":[
       {
          "address":"aws_iam_policy.policy",
          "mode":"managed",
          "type":"aws_iam_policy",
          "name":"policy",
          "provider_name":"registry.terraform.io/hashicorp/aws",
          "change":{
             "actions":[
                "create"
             ],
             "before":null,
             "after":{
                "description":"My test policy",
                "name":"test_policy",
                "path":"/",
                "policy":"{\"Statement\":[{\"Action\":[\"ec2:Describe*\"],\"Effect\":\"Allow\",\"Resource\":\"*\"}],\"Version\":\"2012-10-17\"}",
                "tags":null
             },
             "after_unknown":{
                "arn":true,
                "id":true,
                "name_prefix":true,
                "policy_id":true,
                "tags_all":true
             },
             "before_sensitive":false,
             "after_sensitive":{
                "tags_all":{
                   
                }
             }
          }
       },
       {
          "address":"aws_s3_bucket.b",
          "mode":"managed",
          "type":"aws_s3_bucket",
          "name":"b",
          "provider_name":"registry.terraform.io/hashicorp/aws",
          "change":{
             "actions":[
                "create"
             ],
             "before":null,
             "after":{
                "acl":"private",
                "bucket":"my-tf-test-bucket",
                "force_destroy":false,
                "tags":{
                   "Environment":"Dev",
                   "Name":"My bucket"
                },
                "tags_all":{
                   "Environment":"Dev",
                   "Name":"My bucket"
                },
                "timeouts":null
             },
             "after_unknown":{
                "acceleration_status":true,
                "arn":true,
                "bucket_domain_name":true,
                "bucket_prefix":true,
                "bucket_regional_domain_name":true,
                "cors_rule":true,
                "grant":true,
                "hosted_zone_id":true,
                "id":true,
                "lifecycle_rule":true,
                "logging":true,
                "object_lock_configuration":true,
                "object_lock_enabled":true,
                "policy":true,
                "region":true,
                "replication_configuration":true,
                "request_payer":true,
                "server_side_encryption_configuration":true,
                "tags":{
                   
                },
                "tags_all":{
                   
                },
                "versioning":true,
                "website":true,
                "website_domain":true,
                "website_endpoint":true
             },
             "before_sensitive":false,
             "after_sensitive":{
                "cors_rule":[
                   
                ],
                "grant":[
                   
                ],
                "lifecycle_rule":[
                   
                ],
                "logging":[
                   
                ],
                "object_lock_configuration":[
                   
                ],
                "replication_configuration":[
                   
                ],
                "server_side_encryption_configuration":[
                   
                ],
                "tags":{
                   
                },
                "tags_all":{
                   
                },
                "versioning":[
                   
                ],
                "website":[
                   
                ]
             }
          }
       }
    ],
    "configuration":{
       "provider_config":{
          "aws":{
             "name":"aws",
             "full_name":"registry.terraform.io/hashicorp/aws",
             "expressions":{
                "access_key":{
                   "constant_value":"AKIA3REMOVED"
                },
                "region":{
                   "constant_value":"ap-south-1"
                },
                "secret_key":{
                   "constant_value":"wq5of/I+M3euRglREMOVED"
                }
             }
          }
       },
       "root_module":{
          "resources":[
             {
                "address":"aws_iam_policy.policy",
                "mode":"managed",
                "type":"aws_iam_policy",
                "name":"policy",
                "provider_config_key":"aws",
                "expressions":{
                   "description":{
                      "constant_value":"My test policy"
                   },
                   "name":{
                      "constant_value":"test_policy"
                   },
                   "path":{
                      "constant_value":"/"
                   },
                   "policy":{
                      
                   }
                },
                "schema_version":0
             },
             {
                "address":"aws_s3_bucket.b",
                "mode":"managed",
                "type":"aws_s3_bucket",
                "name":"b",
                "provider_config_key":"aws",
                "expressions":{
                   "acl":{
                      "constant_value":"private"
                   },
                   "bucket":{
                      "constant_value":"my-tf-test-bucket"
                   },
                   "tags":{
                      "constant_value":{
                         "Environment":"Dev",
                         "Name":"My bucket"
                      }
                   }
                },
                "schema_version":0
             }
          ]
       }
    },
    "timestamp":"2023-07-11T08:05:04Z"
 }```

It doesn’t.

Terraform itself is unconcerned with who or what is running it. Any information about that needs to come from whatever tool is causing Terraform to be run, not from Terraform itself.

so I’m using terraform cloud to create these resources, so it should come from terraform cloud ?
so basically i’m trying to mimic what is there in our existing aws scp policy
Example : Example SCPs for Amazon Virtual Private Cloud (Amazon VPC) - AWS Organizations

we enabling users to delete vpc flow logs only if they are administrators of that aws account.
we can achieve this using aws scp.
so can we use hashicorp sentinel instead of opa ? or it’s not possible through policies ?

User information may be available in the policy evaluation context in Terraform Cloud, however it will be somewhere specific to Terraform Cloud, and not something you can see in any JSON format you reproduce locally using Terraform itself.

I, personally, am unaware of what Terraform Cloud may or may not offer in this regard, never having had to use that particular feature myself.

When you use OPA in Terraform Cloud, the input includes both the JSON plan information you previously mentioned, and another object called Run Data which includes various metadata Terraform Cloud knows about this particular run.

That object does include information about which Terraform Cloud user created the run, but I believe that will only be dependable for runs created explicitly by a user, such as by running Terraform CLI in remote operations mode or by starting a run from the web UI.

When runs are created based on push notifications from a version control system they are not necessarily attributable to a particular Terraform Cloud user, and so if you will be using version control I’d encourage you to experiment to see how that field gets populated when you try each of the ways you will typically be starting new runs.