Skip to content

Latest commit

 

History

History
115 lines (85 loc) · 4.64 KB

args.md

File metadata and controls

115 lines (85 loc) · 4.64 KB

Customizing Your TTPs with Command-Line Arguments

Note: to run the examples in this section, make sure you have the examples repository installed with ttpforge list repos and if not run:

ttpforge install repo https://github.com/facebookincubator/TTPForge --name examples

Basics of Command-Line Arguments

TTPForge allows users to control TTP execution through its support for command-line arguments - check out the TTP below to see how it works:

---
name: Basic Command-Line Arguments
description: |
TTPForge allows users to configure their TTPs' expected command-line
arguments in various ways. This TTP demonstrates the following
basic command-line argument options:
* Support for Various Argument Types (string, int, bool, etc)
* Default Values for Arguments
args:
- name: str_to_print
description: this argument is of the default type `string`
- name: has_a_default_value
description: |
the default value will be used if the user does not explicitly
specify a value
default: this_is_the_default
- name: run_second_step
type: bool
default: false
- name: int_arg
type: int
default: 1337
steps:
- name: first_Step
print_str: |
Value of argument `str_to_print`: {{.Args.str_to_print}}
Value of argument `has_a_default_value`: {{.Args.has_a_default_value}}
{{ if .Args.run_second_step }}
- name: second_step
print_str: |
You must have passed `--run_second_step=true`
Doing some math : {{add .Args.int_arg 5}}
{{ end }}

You can run this TTP and provide values for all relevant arguments as follows:

ttpforge run examples//args/basic.yaml \
  --arg str_to_print=hello \
  --arg run_second_step=true

Try out the following exercises to increase your understanding of how arguments work in TTPForge:

  • Remove --arg str_to_print="..." - the TTP will now refuse to run because the user is required to specify a value for that argument since it has no default value specified.
  • Explicitly set int_arg with --arg int_arg=5 - the default value will be overridden.
  • Try to pass values with invalid types, such as --arg int_arg=foo or --arg run_second_step=bar. TTPForge validates argument types and should throw an error for both of these cases. Note that string type arguments (the default) will pretty much accept anything.
  • Disable the second step by removing the --arg run_second_step=true line.

Focus in particular on the last item above, concerning run_second_step=true. TTPForge TTP files are processed using Golang's text/template package to expand all argument values prior to execution. We can use advanced templating features, such as the if-else-end shown above, to precisely control execution based on argument values.

Argument Types

TTPForge supports the following argument types (which you can specify with the type: field as shown in the example above):

  • string (this is the default if no type is specified)
  • int
  • bool
  • path (a very important one - see below)

The path Argument Type

If your TTP will accept arguments that refer to file paths on disk, you should almost always use type: path when declaring those arguments, as shown in the example below (just focus on the args: section for now, though you can check out the edit_file documentation if you are curious):

---
name: edit_file_append_delete
description: |
Learn how to append and delete lines
with the edit_file action.
args:
- name: test_file_path
type: path
description: The path at which the temporary test file should be created
default: /tmp/ttpforge_edit_file_append_delete
steps:
- name: create-tmp-file
create_file: {{.Args.test_file_path}}
contents: |
this_will_be_deleted
and also this_will_be_deleted
this will survive
// all of these
// lines will be
// deleted by a regexp
and this will also survive
overwrite: true
- name: edit_test_file
edit_file: {{.Args.test_file_path}}
edits:
- description: |
Delete all occurrences of a string literal
delete: this_will_be_deleted
- description: You can also delete regular expressions matches
delete: (?m://.*$)
regexp: true
- description: Append a line to the file
append: this will be appended to the end of the file
- name: display_result
inline: cat {{.Args.test_file_path}}

You must use type: path because when you execute ttpforge run [ttp], TTPForge changes its working directory to the folder containing the TTP. This means that relative paths such as foo/bar won't retain their original meaning by default - however, when you declare your argument using type: path, TTPForge knows to expand its value to an absolute path prior to changing directories, ensuring that everything will work as intended.

Predefined Choices for Argument Values

Sometimes only certain specific values make sense for a given argument. TTPForge lets you restrict the allowed values for an argument using the choices: keyword, as shown below

---
name: Explicitly Allowed Choices for Command-Line Arguments
description: |
Sometimes, you might need a TTP to only accept
certain specific values of a given command-line argument.
The `choices:` field of the argument spec format provides
you with this capability.
args:
- name: arg_with_choices
description: you must pass one of these values in order to avoid an error
choices:
- A
- B
- C
- name: with_default
type: int
description: |
arguments with `choices` can have default values to,
but the default value must be one of the choices.
choices:
- 1
- 2
- 3
default: 3
steps:
- name: first_Step
print_str: "You must have selected a valid choice: {{.Args.arg_with_choices}}"
- name: second_step
print_str: "Value for argument `with_default`: {{.Args.with_default}}"

You can run the above TTP as follows:

ttpforge run examples//args/choices.yaml \
  --arg arg_with_choices=C

Notice the following key aspects of the choices feature:

  • TTPForge will reject your arguments if you specify an invalid choice such as arg_with_choices=D.
  • If you use choices and default together, the default value must be one of the valid choices.

Validating Arguments with Regular Expressions

In order to require user-provided argument values to match a particular regular expression (which is useful for ensuring that you don't get strange errors halfway through a TTP due to user error) you can use the regexp: syntax demonstrated below:

---
name: Regular Expression Validation for Command-Line Arguments
description: |
You can require user-provided command-line arguments
to match a provided regular expression.
Golang regexp syntax documentation: https://pkg.go.dev/regexp/syntax
NOTE: `regexp` is only supported for arguments of type `string` (the default)
args:
- name: must_contain_ab
description: requirement satisfied if `ab` occurs anywhere in the string
regexp: ab
- name: must_start_with_1_end_with_7
type: string
description: requirement satisfied if argument starts with `1` and ends with `7`
regexp: ^1.*7$
steps:
- name: valid_args_provided
print_str: |
Valid value for arg `must_contain_ab`: {{.Args.must_contain_ab}}
Valid value for arg `must_start_with_1_end_with_9`: {{.Args.must_start_with_1_end_with_7}}

You can use any regular expression allowed by the Golang regular expression syntax, although if you use YAML metacharacters such as : you are advised to put quotes around your regexp to ensure that your TTP YAML remains valid.

You can run the above TTP as follows:

ttpforge run examples//args/regexp.yaml \
  --arg must_contain_ab=xabyabz \
  --arg must_start_with_1_end_with_7=1337