Skip to content

Commit 590764d

Browse files
committed
cleaner
1 parent d684d75 commit 590764d

4 files changed

Lines changed: 72 additions & 75 deletions

File tree

v1/providers/nebius/instance.go

Lines changed: 35 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package v1
22

33
import (
44
"context"
5+
_ "embed"
6+
"encoding/base64"
57
"fmt"
68
"strings"
79
"time"
@@ -20,6 +22,12 @@ const (
2022
nebiusCPUImageFamily = "ubuntu24.04-driverless"
2123
)
2224

25+
//go:embed scripts/brev-apply-docker-firewall.sh
26+
var dockerFirewallScript string
27+
28+
//go:embed scripts/10-brev-firewall.conf
29+
var dockerFirewallDropIn string
30+
2331
//nolint:gocyclo,funlen // Complex instance creation with resource management
2432
func (c *NebiusClient) CreateInstance(ctx context.Context, attrs v1.CreateInstanceAttrs) (*v1.Instance, error) {
2533
// Track created resources for automatic cleanup on failure
@@ -1576,7 +1584,7 @@ func (c *NebiusClient) cleanupOrphanedBootDisks(ctx context.Context, testID stri
15761584
}
15771585

15781586
// generateCloudInitUserData generates a cloud-init user-data script for SSH key injection and firewall configuration
1579-
// This is inspired by Shadeform's LaunchConfiguration approach but uses cloud-init instead of base64 scripts
1587+
// This is inspired by Shadeform's LaunchConfiguration approach but uses cloud-init directly.
15801588
func generateCloudInitUserData(publicKey string, firewallRules v1.FirewallRules) string {
15811589
// Start with cloud-init header
15821590
script := `#cloud-config
@@ -1591,13 +1599,11 @@ packages:
15911599
`, publicKey)
15921600
}
15931601

1602+
script += generateDockerFirewallWriteFiles()
1603+
15941604
var commands []string
15951605

1596-
// Install an idempotent Docker firewall hook before enabling UFW. Some
1597-
// Nebius images start Docker after cloud-init runcmd; Docker creates or
1598-
// resets DOCKER-USER during startup, so the rules need to be re-applied after
1599-
// docker.service starts instead of only once during runcmd.
1600-
commands = append(commands, generateDockerFirewallInstallCommands()...)
1606+
commands = append(commands, "sudo systemctl daemon-reload")
16011607

16021608
// Generate UFW firewall commands (similar to Shadeform's approach)
16031609
// UFW (Uncomplicated Firewall) is available on Ubuntu/Debian instances
@@ -1648,14 +1654,18 @@ func generateUFWCommands(firewallRules v1.FirewallRules) []string {
16481654
}
16491655

16501656
const (
1651-
// Keep these paths stable: they are useful operator touchpoints when
1652-
// debugging instance firewall state with systemctl/cat/iptables.
1657+
// Keep these generated paths stable: cloud-init, systemd, and validation
1658+
// tests all depend on this Docker firewall handoff.
16531659
dockerFirewallScriptPath = "/usr/local/sbin/brev-apply-docker-firewall.sh"
16541660
dockerServiceDropInDir = "/etc/systemd/system/docker.service.d"
16551661
dockerFirewallDropInPath = dockerServiceDropInDir + "/10-brev-firewall.conf"
16561662
)
16571663

1658-
func generateDockerFirewallInstallCommands() []string {
1664+
func generateDockerFirewallWriteFiles() string {
1665+
// This function emits the only write_files block in this cloud-config. If
1666+
// another generated file is added later, merge it into this block instead of
1667+
// adding a second top-level write_files key.
1668+
//
16591669
// Docker published ports are not governed by UFW's INPUT policy. Docker adds
16601670
// NAT/FORWARD rules that can make `docker run -p host:container` reachable
16611671
// from the public internet even when UFW says incoming traffic is denied.
@@ -1671,65 +1681,22 @@ func generateDockerFirewallInstallCommands() []string {
16711681
// because failing Docker startup would be worse operationally. Validation
16721682
// tests assert that the rule set is actually present and blocks published
16731683
// ports.
1674-
scriptLines := append([]string{
1675-
"#!/bin/sh",
1676-
"set +e",
1677-
}, generateIPTablesCommands()...)
1678-
scriptLines = append(scriptLines, "exit 0")
1679-
1680-
return []string{
1681-
generatePrintfToFileCommand(scriptLines, dockerFirewallScriptPath),
1682-
"sudo chmod 0755 " + dockerFirewallScriptPath,
1683-
"sudo mkdir -p " + dockerServiceDropInDir,
1684-
generatePrintfToFileCommand([]string{
1685-
"[Service]",
1686-
"ExecStartPost=" + dockerFirewallScriptPath,
1687-
}, dockerFirewallDropInPath),
1688-
"sudo systemctl daemon-reload",
1689-
}
1690-
}
1691-
1692-
func generatePrintfToFileCommand(lines []string, path string) string {
1693-
quotedLines := make([]string, 0, len(lines))
1694-
for _, line := range lines {
1695-
quotedLines = append(quotedLines, shellSingleQuote(line))
1696-
}
1697-
1698-
return fmt.Sprintf("printf '%%s\\n' %s | sudo tee %s > /dev/null", strings.Join(quotedLines, " "), path)
1699-
}
1700-
1701-
func shellSingleQuote(value string) string {
1702-
return "'" + strings.ReplaceAll(value, "'", `'\''`) + "'"
1703-
}
1704-
1705-
// generateIPTablesCommands generates IPTables firewall commands to ensure docker ports are not made immediately
1706-
// accessible from the internet by default.
1707-
func generateIPTablesCommands() []string {
1708-
commands := []string{
1709-
// CPU images can run cloud-init before Docker has created DOCKER-USER.
1710-
// Create it first so the immediate cloud-init run succeeds; when Docker
1711-
// starts later, the systemd ExecStartPost hook above re-applies the same
1712-
// rules after Docker has finished creating/resetting its own chains.
1713-
"iptables -N DOCKER-USER 2>/dev/null || true",
1714-
"iptables -F DOCKER-USER || true",
1715-
1716-
// Preserve already-established connections, then allow container bridge
1717-
// egress and intra-bridge traffic. The final DROP below is what prevents
1718-
// externally-published Docker ports from being reachable by default.
1719-
"iptables -A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT",
1720-
"iptables -A DOCKER-USER -i docker0 ! -o docker0 -j ACCEPT",
1721-
"iptables -A DOCKER-USER -i br+ ! -o br+ -j ACCEPT",
1722-
"iptables -A DOCKER-USER -i cni+ ! -o cni+ -j ACCEPT", // TODO: add these back in when we have a way to test it
1723-
"iptables -A DOCKER-USER -i cali+ ! -o cali+ -j ACCEPT",
1724-
"iptables -A DOCKER-USER -i docker0 -o docker0 -j ACCEPT",
1725-
"iptables -A DOCKER-USER -i br+ -o br+ -j ACCEPT",
1726-
"iptables -A DOCKER-USER -i cni+ -o cni+ -j ACCEPT",
1727-
"iptables -A DOCKER-USER -i cali+ -o cali+ -j ACCEPT",
1728-
"iptables -A DOCKER-USER -i lo -j ACCEPT",
1729-
"iptables -A DOCKER-USER -j DROP",
1730-
"iptables -A DOCKER-USER -j RETURN", // Expected by Docker
1731-
}
1732-
return commands
1684+
//
1685+
// UFW persists its own rules in /etc/ufw; only DOCKER-USER needed a Docker
1686+
// startup hook after removing netfilter-persistent.
1687+
return fmt.Sprintf(`
1688+
write_files:
1689+
- path: %s
1690+
owner: root:root
1691+
permissions: '0755'
1692+
encoding: b64
1693+
content: %s
1694+
- path: %s
1695+
owner: root:root
1696+
permissions: '0644'
1697+
encoding: b64
1698+
content: %s
1699+
`, dockerFirewallScriptPath, base64.StdEncoding.EncodeToString([]byte(dockerFirewallScript)), dockerFirewallDropInPath, base64.StdEncoding.EncodeToString([]byte(dockerFirewallDropIn)))
17331700
}
17341701

17351702
// convertIngressRuleToUFW converts an ingress firewall rule to UFW command(s)

v1/providers/nebius/instance_test.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,29 @@ func TestGenerateCloudInitUserDataInstallsDockerFirewallHook(t *testing.T) {
8989

9090
assert.NotContains(t, script, "iptables-persistent")
9191
assert.NotContains(t, script, "netfilter-persistent")
92+
assert.Contains(t, script, "write_files:")
93+
assert.Contains(t, script, "encoding: b64")
9294
assert.Contains(t, script, "/usr/local/sbin/brev-apply-docker-firewall.sh")
9395
assert.Contains(t, script, "/etc/systemd/system/docker.service.d")
94-
assert.Contains(t, script, "ExecStartPost=/usr/local/sbin/brev-apply-docker-firewall.sh")
9596
assert.Contains(t, script, "sudo /usr/local/sbin/brev-apply-docker-firewall.sh || true")
97+
assert.NotContains(t, script, "content: |")
98+
assert.NotContains(t, script, " #!/bin/sh")
99+
assert.NotContains(t, script, "ExecStartPost=/usr/local/sbin/brev-apply-docker-firewall.sh")
100+
assert.NotContains(t, script, "printf '%s\\n'")
101+
assert.NotContains(t, script, "| sudo tee")
96102
}
97103

98-
func TestGenerateIPTablesCommandsCreateDockerUserChainBeforeFlush(t *testing.T) {
99-
commands := generateIPTablesCommands()
104+
func TestDockerFirewallScriptCreatesDockerUserChainBeforeFlush(t *testing.T) {
105+
createChainIndex := strings.Index(dockerFirewallScript, "iptables -N DOCKER-USER")
106+
flushChainIndex := strings.Index(dockerFirewallScript, "iptables -F DOCKER-USER")
100107

101-
assert.GreaterOrEqual(t, len(commands), 2)
102-
assert.Equal(t, "iptables -N DOCKER-USER 2>/dev/null || true", commands[0])
103-
assert.Equal(t, "iptables -F DOCKER-USER || true", commands[1])
104-
assert.Contains(t, strings.Join(commands, "\n"), "iptables -A DOCKER-USER -j DROP")
108+
assert.Greater(t, createChainIndex, -1)
109+
assert.Greater(t, flushChainIndex, createChainIndex)
110+
assert.Contains(t, dockerFirewallScript, "iptables -A DOCKER-USER -j DROP")
111+
}
112+
113+
func TestDockerFirewallDropInIgnoresExecStartPostFailure(t *testing.T) {
114+
assert.Contains(t, dockerFirewallDropIn, "ExecStartPost=-/usr/local/sbin/brev-apply-docker-firewall.sh")
105115
}
106116

107117
// BenchmarkCreateInstance benchmarks the CreateInstance method
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[Service]
2+
ExecStartPost=-/usr/local/sbin/brev-apply-docker-firewall.sh
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
iptables -N DOCKER-USER 2>/dev/null || true
4+
iptables -F DOCKER-USER || true
5+
iptables -A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
6+
iptables -A DOCKER-USER -i docker0 ! -o docker0 -j ACCEPT
7+
iptables -A DOCKER-USER -i br+ ! -o br+ -j ACCEPT
8+
iptables -A DOCKER-USER -i cni+ ! -o cni+ -j ACCEPT
9+
iptables -A DOCKER-USER -i cali+ ! -o cali+ -j ACCEPT
10+
iptables -A DOCKER-USER -i docker0 -o docker0 -j ACCEPT
11+
iptables -A DOCKER-USER -i br+ -o br+ -j ACCEPT
12+
iptables -A DOCKER-USER -i cni+ -o cni+ -j ACCEPT
13+
iptables -A DOCKER-USER -i cali+ -o cali+ -j ACCEPT
14+
iptables -A DOCKER-USER -i lo -j ACCEPT
15+
iptables -A DOCKER-USER -j DROP
16+
iptables -A DOCKER-USER -j RETURN
17+
18+
exit 0

0 commit comments

Comments
 (0)