How to write Sentinel policies

Not sure why but it keeps changing the mock title to mock-tfplan-functions.sentinel

@wblanchard-concurren the mock- prefix is correct and is what Sentinel is expecting. It will automagically discover the mock as the tfplan-functions module. I am actually cheating a little as the playground does not currently support modules, so I am using a mock to mimic the behavior of a module.

Regarding the mock-tfplan-functions.sentinel:16:23: Import “tfplan/v2” is not available error, make sure that you have added a tfplan-v2 mock to the playground as this is a prerequisite for the tfplan-functions mock.

1 Like

@hcrhall I was able to get the playground to run by changing the mock from tfplan/v2 to tfplan-v2 (as you show). Thank you!

1 Like

If I want to run sentinel test locally, how do I use tfplan-functions? I’m getting the following…

Import “tfplan-functions” is not available

I was able to get this one figured out but now I’m getting an error on the Strings import

@wblanchard-concurren it’s probably best if you upload an archive of the policy so that I can help further

1 Like

Hey @hcrhall, Thanks for responding. I was able to figure it out. Noob issue.

Can we write sentinel Policies to check specific VM agents is getting installed or not using user-data on AWS, custom data on VMs? I can still check if an extension i want is added to VM using azurerm_virtual_machine_extension but this still doesn’t help me to parse the init file for a specific agent.

@jhabikal21 it really depends on how you have set the user_data. Are you doing it inline or are you using a file resource to provide the contents of a script?

@hcrhall Using file resource like base64encode(file(“cloud-init.yaml”)).

@hcrhall I found your response here very helpful. May I know if we have other sentinel policy examples too.

Sure, we have two great resources for policy examples:

@hcrhall Thanks for those links, I have gone through the docs there but doesn’t covers lot of things.

Lets say for below code:
main = rule {

map allLinuxVMsUnzipCustomDataResources as _, resource {

{

  "message":          "Supported custom_data value supplied",

  "name":             resource.change.after.name,

  "address":          resource.address,

  "custom_data":      base64.decode(resource.change.after.custom_data),

}

}

map allLinuxsVMsSSUnzipCustomDataResources as _, resource {

{

  "message":          "Supported custom_data value supplied",

  "name":             resource.change.after.name,

  "address":          resource.address,

  "custom_data":      base64.decode(resource.change.after.custom_data),

}

}

map allVMsUnzipCustomDataResources as _, resource {

{

  "message":          "Supported custom_data value supplied",

  "name":             resource.change.after.name,

  "address":          resource.address,

  "custom_data":      base64.decode(resource.change.after.custom_data),

}

}

map allVMsSSUnzipCustomDataResources as _, resource {

{

  "message":          "Supported custom_data value supplied",

  "name":             resource.change.after.name,

  "address":          resource.address,

  "custom_data":      base64.decode(resource.change.after.custom_data),

}

}

}
I am unable to use and condition

I am trying to fetch the same information for resource azurerm_virtual_machine

allVMsUnzipCujdkstomDataResources = rule {
all allVMs as _, initscriptcheck {
all initscriptcheck.change.after.os_profile as os_profile {
base64.decode(os_profile.custom_data) matches “apt install -y unzip”
}
}
}

You haven’t included the error that you are receiving, but I think you will find that your rule is the following:

allVMsUnzipCujdkstomDataResources = rule {
	all allVMs as _, initscriptcheck {
		base64.decode(initscriptcheck.change.after.os_profile.custom_data) matches "apt install -y unzip"
	}
}

An error occurred evaluating the policy:

policy.sentinel:27:17: selectors only available for imports, maps, and modules, got list

@hcrhall
“after”: {

                "additional_capabilities":          [],

                "boot_diagnostics":                 [],

                "delete_data_disks_on_termination": false,

                "delete_os_disk_on_termination":    false,

                "location":                         "eastus",

                "name":                             "Test-bikal-vm",

                "os_profile": [

                    {

                        "admin_password": "Password1234!",

                        "admin_username": "testadmin",

                        "computer_name":  "hostname",

                        "custom_data":    "YXB0IGluc3RhbGwgLXkgdW56aXA",

                    },

                ],

@hcrhall If I use like below:
allVMsUnzipCujdkstomDataResources = rule {
all allVMs as _, initscriptcheck {
all initscriptcheck.change.after.os_profile as os_profile {
base64.decode(os_profile.custom_data) matches “apt install -y unzip”
}
}
}

I get
An error occurred evaluating the policy:

Result value was ‘undefined’.

This means that undefined behavior was experienced at one or more locations
and the result of your policy ultimately resulted in “undefined”. This usually
represents a policy which doesn’t handle all possible cases and should be
corrected.

The locations where the undefined behavior happened are:

policy.sentinel:33:4

I guess the base64.decode doesn’t work well with azurerm_virtual_machine_scale_set or azurerm_virtual_machine

You need to structure your rule as follows:

allVMsUnzipCujdkstomDataResources = rule {
	all allVMs as _, initscriptcheck {
		all initscriptcheck.change.after.os_profile as _, os_profile {
			base64.decode(os_profile.custom_data) matches "apt install -y unzip"
    }
  }
}

You also need to change to value of custom_data to YXB0IGluc3RhbGwgLXkgdW56aXA= as the value you have set is not a base64 encoded value