Run a Script with the Private Action Runner
This product is not supported for your selected
Datadog site. (
).
Overview
The private action runner can run predefined scripts, which are shell commands, command-line tools, and scripts you declare ahead of time in a script configuration file. Only what you predefine can run, so the runner never runs arbitrary inline commands from a workflow or app.
You decide which commands and binaries the runner is allowed to run. Review every command you add to the script configuration, especially those that accept parameters, grant the runner only the privileges it needs, and carefully review the permissions you share through connections. See
connection security considerations.
Use cases
| Use case | Agent-based | Standalone | Notes |
|---|
Running Linux binaries (ls, rm, find, curl) | | | For standalone runners, the relevant files must be accessible to the container. |
Running CLIs (aws, terraform, kubectl) | | | For standalone runners, the CLI and credentials must be available in the image. For Agent-based runners, tools must be installed on the host. |
| Running bash scripts | | | For standalone runners, scripts can be mounted inside the container. Use the large image for a Python interpreter. |
| Running PowerShell scripts | | | Supported on Agent-based Windows runners only. |
Running privileged commands (systemctl restart) | | | For Agent-based runners, grant permissions to the runner user. Container sandboxing prevents standalone runners from privileged host access. |
Prerequisites
For Agent-based runners:
For standalone runners:
Agent-based
Edit the /etc/datadog-agent/private-action-runner/script-config.yaml file:
schemaId: script-credentials-v1
runPredefinedScript:
echo:
command: ["echo", "Hello world!"]
echo-parametrized:
command: ["echo", "{{ parameters.echoValue }}"]
restart-service:
command: ["sudo", "systemctl", "restart", "{{ parameters.service }}"]
Edit the C:\ProgramData\Datadog\private-action-runner\powershell-script-config.yaml file:
schemaId: script-credentials-v1
runPredefinedPowershellScript:
helloWorld:
script: |
Write-Output "Hello world!"
greet:
script: |
Write-Output "Run script from workflow called {{ parameters.name }} !"
parameterSchema:
properties:
name:
type: string
required:
- name
restartService:
script: |
Restart-Service -Name {{ parameters.serviceName }} -Force
parameterSchema:
properties:
serviceName:
type: string
required:
- serviceName
In a workflow or app, reference a script by the name you defined (for example, echo). Use runPredefinedScript on Linux runners and runPredefinedPowershellScript on Windows runners.
Grant permissions
The runner executes scripts as the dd-agent user. If your scripts require elevated permissions, grant them to the dd-agent user:
echo "dd-agent ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx" > /etc/sudoers.d/dd-agent
chmod 440 /etc/sudoers.d/dd-agent
The runner executes scripts as ddagentuser. If your scripts require access to certain resources, grant ddagentuser elevated permissions to them:
icacls "C:\<your-file-path>" /grant "ddagentuser:(OI)(CI)RX" /T
# Verify permissions
icacls "C:\<your-file-path>"
Ownerless runner (Execution Policy-authorized)
When a runner is enrolled as ownerless and authorized by Execution Policies, two things are required in addition to the steps above:
- The Script integration must be authorized for the runner through an Execution Policy, in addition to the predefined-script action being in the runner’s actions allowlist.
- The runner reads its predefined scripts from a fixed path, the same path used in Configure scripts above:
/etc/datadog-agent/private-action-runner/script-config.yaml
C:\ProgramData\Datadog\private-action-runner\powershell-script-config.yaml
Delivering the config on Kubernetes
On Kubernetes, provide the script configuration file to the runner in the Datadog Agent as a ConfigMap. Mount it into the runner container at the fixed path. The Cluster Agent runner uses the Linux path above.
First, create a ConfigMap that holds your script configuration:
apiVersion: v1
kind: ConfigMap
metadata:
name: par-script-config
namespace: datadog
data:
script-config.yaml: |
schemaId: script-credentials-v1
runPredefinedScript:
echo:
command: ["echo", "Hello world!"]
Then, on the DatadogAgent resource, allow the predefined-script action and mount the ConfigMap into the runner container at the fixed path:
apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
name: datadog
annotations:
agent.datadoghq.com/private-action-runner-enabled: "true"
agent.datadoghq.com/private-action-runner-configdata: |
private_action_runner:
enabled: true
api_key_only_enrollment: true
actions_allowlist:
- "com.datadoghq.script.runPredefinedScript"
- "com.datadoghq.kubernetes.*"
- "com.datadoghq.remoteaction.*"
spec:
override:
nodeAgent:
volumes:
- name: par-script-config
configMap:
name: par-script-config
containers:
private-action-runner:
volumeMounts:
- name: par-script-config
mountPath: /etc/datadog-agent/private-action-runner/script-config.yaml
subPath: script-config.yaml
readOnly: true
Finally, apply the manifest:
kubectl apply -f datadog-agent.yaml
Owned runner (Connection-based)
If you selected com.datadoghq.script.runPredefinedScript in the runner’s actions allowlist, you should already have a Script connection linked to your runner. Otherwise, create a connection and specify /etc/datadog-agent/private-action-runner/script-config.yaml as the path to file. For more information, see [Handling private action credentials][4].
If you selected com.datadoghq.script.runPredefinedPowershellScript in the runner’s actions allowlist, you should already have a Script connection linked to your runner. Otherwise, create a connection and specify C:\ProgramData\Datadog\private-action-runner\powershell-script-config.yaml as the path to file. For more information, see [Handling private action credentials][4].
Standalone
A standalone runner is always owned and authorized with Connections.
- After [setting up a runner][2], navigate to Connections.
- Click New Connection and select Script.
- Enter a connection name, and in the Private Action Runner dropdown, select your runner.
- Copy the credential file template into your runner’s configuration directory with the commands you want to run.
- In Path to file, confirm the file path matches the path on your runner’s file system (the default is sufficient in most cases).
- Click Next, Confirm Access, configure permissions, then click Create.
- Select this connection when using the script action in your workflows or apps.
Configure script actions through your runner’s config.yaml file and the script connection
(credentials/script.yaml by default):
# Add the script action to the allowlist (config.yaml)
actionsAllowlist:
- com.datadoghq.script.runPredefinedScript
# Configure your script connection (credentials/script.yaml)
schemaId: script-credentials-v1
runPredefinedScript:
echo:
command: ["echo", "Hello world"]
echo-parametrized:
command: ["echo", "{{ parameters.echoValue }}"]
parameterSchema:
properties:
echoValue:
type: string
required:
- echoValue
When deploying the runner with Helm, configure scripts through your values.yaml file:
common:
actionsAllowlist:
- com.datadoghq.script.runPredefinedScript
credentials:
script:
schemaId: script-credentials-v1
runPredefinedScript:
echo:
command: ["echo", "Hello world"]
echo-parametrized:
command: ["echo", "{{ parameters.echoValue }}"]
parameterSchema:
properties:
echoValue:
type: string
required:
- echoValue
Deploy or upgrade the runner:
helm upgrade --install <RELEASE_NAME> datadog/private-action-runner -f ./values.yaml
Runner image options
The following options are available for standalone runners only.
Large image
If you want to use tools like Python, SSH, the AWS CLI, Terraform, or the gcloud CLI, use the gcr.io/datadoghq/private-action-runner:v1.21.0-large image instead of the default image.
Custom images
For binaries not available in the Datadog-provided images, create a custom image:
FROM gcr.io/datadoghq/private-action-runner:v1.21.0
USER root
# Change the line below to install the tool of your choice
RUN apt update && apt install -y python3
USER dog
You can mount complex scripts inside the runner:
# docker-compose example
services:
runner:
build: . # if you are using a local Dockerfile
volumes:
- "./config:/etc/dd-action-runner/config" # contains credentials for actions
- "./scripts:/etc/dd-action-runner-script/scripts" # contains dependencies for script actions
# credentials/script.yaml
schemaId: script-credentials-v1
runPredefinedScript:
python:
command: ["python3", "/etc/dd-action-runner-script/scripts/script.py"]
shell:
command: ["bash", "/etc/dd-action-runner-script/scripts/script.sh"]
In your workflow or app, configure the action to use the script name you defined (for example, echo or echo-parametrized). For Linux runners, use runPredefinedScript. For Windows runners, use runPredefinedPowershellScript.
There are two levels of variable resolution: one at the workflow level and one at the action level
inside the runner.
Further reading
Additional helpful documentation, links, and articles: