Have Runner support sending context to firewall (if its running)#4537
Have Runner support sending context to firewall (if its running)#4537steiza wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an extension point to SecretMasker so the runner can (optionally) notify an external component when new secrets/regexes are registered—intended to forward masking context to a host-side egress firewall over vsock on Linux.
Changes:
- Introduces
ISecretRegistrationNotifierwith a default no-op implementation. - Extends
SecretMaskerto accept a notifier and emit notifications fromAddValue/AddRegex. - Adds
RunnerSecretRegistrationNotifierthat best-effort connects to a host vsock endpoint and sends secret registration payloads; wires it intoHostContext.
Show a summary per file
| File | Description |
|---|---|
| src/Sdk/DTLogging/Logging/SecretMasker.cs | Adds notifier injection and emits secret/regex registration notifications. |
| src/Sdk/DTLogging/Logging/ISecretRegistrationNotifier.cs | Defines notifier interface plus a no-op default implementation. |
| src/Runner.Common/RunnerSecretRegistrationNotifier.cs | Implements runner-side vsock-based notification delivery to the host. |
| src/Runner.Common/HostContext.cs | Instantiates SecretMasker with the new runner notifier. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 8
- Review effort level: Low
| } | ||
| } | ||
|
|
||
| NotifySecretRegistration(new List<string> { value }, new List<string>()); |
| } | ||
| } | ||
|
|
||
| NotifySecretRegistration(new List<string>(), new List<string> { pattern }); | ||
| } |
| private readonly Socket _vsock; | ||
| private readonly object _vsockSendLock = new object(); | ||
| private static readonly object _debugFileLock = new object(); |
| catch (SocketException ex) | ||
| { | ||
| socket?.Dispose(); | ||
| return null; | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| socket?.Dispose(); | ||
| return null; | ||
| } |
|
|
||
| public override SocketAddress Serialize() | ||
| { | ||
| SocketAddress socketAddress = new SocketAddress(AddressFamily.Unspecified, SocketAddressSize); |
| private readonly ConcurrentDictionary<Type, object> _serviceInstances = new(); | ||
| private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new(); | ||
| private readonly ISecretMasker _secretMasker = new SecretMasker(); | ||
| private readonly ISecretMasker _secretMasker = new SecretMasker(new RunnerSecretRegistrationNotifier()); |
| private void NotifySecretRegistration(List<string> secretValues, List<string> secretRegexes) | ||
| { | ||
| try | ||
| { | ||
| m_secretRegistrationNotifier.NotifySecretRegistration(secretValues, secretRegexes); |
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using Microsoft.Win32.SafeHandles; | ||
| using System.Net; | ||
| using System.Net.Sockets; | ||
| using System.Runtime.InteropServices; | ||
| using System.Text; | ||
| using System.Text.Json; | ||
| using GitHub.DistributedTask.Logging; |
| private readonly ConcurrentDictionary<Type, object> _serviceInstances = new(); | ||
| private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new(); | ||
| private readonly ISecretMasker _secretMasker = new SecretMasker(); | ||
| private readonly ISecretMasker _secretMasker = new SecretMasker(new RunnerSecretRegistrationNotifier()); |
There was a problem hiding this comment.
there might be a better approach for doing this, we probably just want to send over the data after we get them from the job message, so we don't have to touch secretmasker since its job is to mask.
There was a problem hiding this comment.
There's a couple of different secrets I'm worried about, which I think come from different places:
- Secrets GitHub provides as part of Actions (like
GITHUB_TOKEN) - Secrets a user provides for a workflow run (like things set at https://github.com/my-org/my-repo/settings/secrets/actions)
- Secrets set during the workflow run (e.g.
echo "::add-mask::$SOME_SECRET_VALUE")
I think we want to make sure we're getting context from all 3 sources, but also I'm very new to this codebase.
| } | ||
|
|
||
| socket = new Socket(nativeSocket); | ||
| socket.Connect(new HostVsockEndPoint(2, 9999)); |
There was a problem hiding this comment.
we probably want to use some input to provide the value, so it's not hardcoded.
With https://github.com/github-early-access/actions-native-egress-firewall/, sometimes Runner is running in a guest VM with a firewall process listening on a vsock on the host.
This change makes it so that Runner checks to see if it's running a Linux environment, if so if there's a vsock present, and if so send context to the vsock so it makes its way to the firewall (like what patterns of secrets should be masked from the log).
This is my first time writing C# code, so feedback is welcome! I was able to run this successfully as a self-hosted runner.