1. Overview

Twistlock rules have granular pattern matching capabilities. For example, you could apply a rule to any image with the name ubuntu*. Or you could apply a rule to all hosts, except those named test. This article describes how filtering and pattern matching works in Twistlock.

2. Pattern matching

All rules in Twistlock include an applies to field that looks like this:

rule ordering 763992

This allows you to apply rules based on container name, image name, host name, or Docker labels. By default, these rules apply to the object, which means *any object of this type:

However, you can also be more specific about exactly where rules are applied by replacing the object with specific strings. When Twistlock sees a wildcard in a resource name, it evaluates that name with *string contains logic. For example, if you specify a resource of foo-resource*, Twistlock matches that resource to any value that contains the string, such as example-foo-resource and foo-resource-1. Twistlock matching logic is case insensitive.

rule ordering 763994

These fields are combined using AND logic. For example, if a rule is configured to apply to hosts called foo-hosts* and images called foo-images*, it will apply only to images with names containing foo-images* on hosts with host-names containing foo-hosts*.

The asterisk results in the rule applying to any object of a given type, which is then further constrained by the other filters you have in the rule.

Note in the following example, that the rule is configured to apply to hosts called foo-hosts* and images called foo-images*, and that the filters for containers and labels are left with the default value. The effective result is *apply this rule anytime the host name contains foo-hosts and image name contains foo-images, regardless of what the container or label is.

rule ordering 763995

If wildcard characters are not used, Twistlock matches the value provided against the ending of the resource string. This allows you to have precise control over exactly what values are matched simply by providing a more complete string. For example:

  • /ubuntu:latest will match /library/ubuntu:latest or docker.io/library/ubuntu:latest.

  • :latest will match ubuntu:latest or debian:latest.

  • If you want to explicitly target just ubuntu:latest from Docker Hub, use docker.io/library/ubuntu:latest. Because the value provided is the complete name of the resource, Twistlock will match it exactly.

  • _test will match host_sandbox_test and host_preprod_test but will not match host_test_server because _test is not the final suffix of the string.

rule ordering 763996

For DNS filtering, Twistlock doesn’t prevent you from entering multiple wildcards per string, but it’s treated the same as if you simply entered the right-most wildcard. The following patterns are equivalent:

*.*.b.a == *.b.a

3. Exemptions

While the above process makes it very easy to manage rules for most scenarios, you may have more sophisticated needs that require you to exempt certain objects from a given rule. Twistlock uses the - (minus sign) character to specify objects to filter out. From our example, if we wanted a rule to apply to all hosts containing foo-hosts, except those containing foo-hosts-exempt*, you could create it like this:

rule ordering 763997

When Twistlock evaluates an object against rule that uses a minus sign, we first skip any object for which there is a match with the subtracted object. So, from our example:

  1. If the host name contains foo-hosts-exempt, skip

  2. If the host name contains foo-hosts AND the image name contains foo-images, apply.

4. Rule ordering

For any given feature area, such as vulnerability management or compliance, you might have multiple rules, such as test 1 and test 2.

rule ordering two rules

The entire set of rules in a given feature area is called the policy. The rules in the policy are evaluated from top to bottom, making it easy to understand how policy is applied. When evaluating whether to apply a rule to a given object, Twistlock uses the following logic:

  1. Does rule 1 apply to object? If yes, apply action(s) defined in rule and stop. If no, go to 2.

  2. Does rule 2 apply to object? If yes, apply action(s) defined in rule and stop. If no, go to 3.

  3. …​

  4. Apply the built-in Default rule (unless it was removed or modified).

Twistlock evaluates the rule list from top to bottom until it finds a match based on the object filters. When a match is found, it applies the actions in the rule and stops processing further rules. If no match is found, then no action is applied. Sometimes this could mean that an attempted action is blocked (e.g. if no access control rule is matched that allows a user to run a container).

To reorder rules, click on a rule’s hamburger button and drag it to a new position in the list.

rule ordering drag and drop

5. Disabling rules

If you want to test how the system behaves without a particular rule, you can temporarily disable it. Disabling a rule gives you a way to preserve the rule and its configuration, but take it out of service, so that it’s ignored when Twistlock evaluates events against your policy.

To disable a rule, click Actions > Disable.

rule ordering disable rule

6. Image names

The canonical name of an image is it’s full name in a format like registry/repo/image-name. For example: 1234.dkr.ecr.us-east-1.amazonaws.com/morello:foo-images. Within Docker itself, these canonical names can be seen by inspecting any given image, like this:

$ sudo docker inspect morello/foo-images | grep Repo -A 3
      "RepoTags": [
          "1234.dkr.ecr.us-east-1.amazonaws.com/morello:foo-images",

However, there’s a special case to be aware of with images sourced from Docker Hub. For those images, the Docker Engine and client do not show the full path in the canonical name; instead it only shows the ‘short name’ that can be used with Docker Hub and the full name is implied. For example, compare the previous example of an image on AWS ECR, with this image on Docker Hub:

$ sudo docker inspect morello/docker-whale | grep Repo -A 3
      "RepoTags": [
          "morello/docker-whale:latest",

Note that when the image is from Hub, the canonical name is listed as just the short name (the same name you could use with the Docker client to issue a command like ‘docker run morello/docker-whale’). For images like this, Twistlock automatically prepends the actual address of the Docker Hub registry (docker.io) and, if necessary, the library repo name as well, even though these values are not shown by Docker itself.

For example, you can run the Alpine image from Docker Hub simply by issuing a Docker client command like ‘docker run -ti alpine /bin/sh’. The Docker client automatically knows that this means to pull and run the image that has a canonical name of docker.io/library/alpine:latest. However, this full canonical name is not exposed by the Docker client when inspecting the image:

$ sudo docker inspect alpine | grep Repo -A 2
      "RepoTags": [
          "alpine:latest"
      ],
      "RepoDigests": [
          "alpine@sha256:1354db23ff5478120c980eca1611a51c9f2b88b61f24283ee8200bf9a54f2e5c"
      ],

But because Twistlock automatically prepends the proper values to compose the canonical name, a rule like this blocks images from Hub from running:

rule ordering 764008
$ docker -H :9998 --tls run -ti alpine /bin/sh
docker: Error response from daemon: [Twistlock] The command container_create denied for user admin by rule Deny - deny all docker.io images.