add firewall rules option
This commit is contained in:
55
README.md
55
README.md
@@ -10,7 +10,8 @@ Tool untuk membuat **template** di Proxmox menggunakan cloud image (Ubuntu, Debi
|
||||
- Support konfigurasi via CLI flags atau YAML file
|
||||
- Progress bar untuk download
|
||||
- **QEMU Guest Agent support** (auto-enable)
|
||||
- **Firewall configuration** (enable/disable)
|
||||
- **Firewall configuration** (enable/disable + custom rules)
|
||||
- **Batch mode** untuk create multiple templates sekaligus
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -113,6 +114,17 @@ proxmox_user: "root@pam"
|
||||
proxmox_pass: ""
|
||||
guest_agent: true
|
||||
firewall: true
|
||||
firewall_rules:
|
||||
- type: in
|
||||
action: accept
|
||||
protocol: tcp
|
||||
dport: "22"
|
||||
comment: "SSH"
|
||||
- type: in
|
||||
action: accept
|
||||
protocol: tcp
|
||||
dport: "80,443"
|
||||
comment: "HTTP/HTTPS"
|
||||
```
|
||||
|
||||
### Batch mode (multiple templates):
|
||||
@@ -185,7 +197,8 @@ proxmox-cloud-image -batch batch.txt
|
||||
6. Setup cloud-init
|
||||
7. **Enable QEMU Guest Agent** (jika di-enable)
|
||||
8. **Enable Proxmox firewall** (jika di-enable)
|
||||
9. **Convert VM menjadi template** dengan `qm template`
|
||||
9. **Configure firewall rules** (jika ada rules yang di-define)
|
||||
10. **Convert VM menjadi template** dengan `qm template`
|
||||
|
||||
## QEMU Guest Agent
|
||||
|
||||
@@ -207,6 +220,44 @@ Proxmox firewall bisa di-enable untuk template dengan flag `-firewall` atau di c
|
||||
firewall: true
|
||||
```
|
||||
|
||||
### Firewall Rules
|
||||
|
||||
Kamu juga bisa define firewall rules langsung di config file:
|
||||
|
||||
```yaml
|
||||
firewall: true
|
||||
firewall_rules:
|
||||
- type: in
|
||||
action: accept
|
||||
protocol: tcp
|
||||
dport: "22"
|
||||
comment: "SSH"
|
||||
- type: in
|
||||
action: accept
|
||||
protocol: tcp
|
||||
dport: "80,443"
|
||||
comment: "HTTP/HTTPS"
|
||||
- type: in
|
||||
action: accept
|
||||
protocol: icmp
|
||||
comment: "ICMP/Ping"
|
||||
- type: in
|
||||
action: drop
|
||||
comment: "Drop all other incoming"
|
||||
```
|
||||
|
||||
**Firewall Rule Fields:**
|
||||
- `type`: `in` (incoming) atau `out` (outgoing)
|
||||
- `action`: `accept`, `drop`, atau `reject`
|
||||
- `protocol`: `tcp`, `udp`, `icmp`, dll (optional)
|
||||
- `dport`: destination port atau port range, contoh: `22`, `80,443`, `8000:9000` (optional)
|
||||
- `sport`: source port (optional)
|
||||
- `source`: source IP/CIDR, contoh: `192.168.1.0/24` (optional)
|
||||
- `dest`: destination IP/CIDR (optional)
|
||||
- `comment`: komentar untuk rule (optional)
|
||||
|
||||
Rules akan ditulis ke `/etc/pve/firewall/<vmid>.fw` di Proxmox host.
|
||||
|
||||
Firewall akan di-enable di network interface VM.
|
||||
|
||||
## Clone Template
|
||||
|
||||
42
main.go
42
main.go
@@ -6,22 +6,34 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type FirewallRule struct {
|
||||
Type string `yaml:"type"`
|
||||
Action string `yaml:"action"`
|
||||
Protocol string `yaml:"protocol"`
|
||||
Dport string `yaml:"dport"`
|
||||
Sport string `yaml:"sport"`
|
||||
Source string `yaml:"source"`
|
||||
Dest string `yaml:"dest"`
|
||||
Comment string `yaml:"comment"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ImageURL string `yaml:"image_url"`
|
||||
VMName string `yaml:"vm_name"`
|
||||
VMID int `yaml:"vm_id"`
|
||||
Storage string `yaml:"storage"`
|
||||
Memory int `yaml:"memory"`
|
||||
Cores int `yaml:"cores"`
|
||||
DiskSize string `yaml:"disk_size"`
|
||||
Bridge string `yaml:"bridge"`
|
||||
VlanTag int `yaml:"vlan_tag"`
|
||||
SSHKey string `yaml:"ssh_key"`
|
||||
ProxmoxHost string `yaml:"proxmox_host"`
|
||||
ProxmoxUser string `yaml:"proxmox_user"`
|
||||
ProxmoxPass string `yaml:"proxmox_pass"`
|
||||
GuestAgent bool `yaml:"guest_agent"`
|
||||
Firewall bool `yaml:"firewall"`
|
||||
ImageURL string `yaml:"image_url"`
|
||||
VMName string `yaml:"vm_name"`
|
||||
VMID int `yaml:"vm_id"`
|
||||
Storage string `yaml:"storage"`
|
||||
Memory int `yaml:"memory"`
|
||||
Cores int `yaml:"cores"`
|
||||
DiskSize string `yaml:"disk_size"`
|
||||
Bridge string `yaml:"bridge"`
|
||||
VlanTag int `yaml:"vlan_tag"`
|
||||
SSHKey string `yaml:"ssh_key"`
|
||||
ProxmoxHost string `yaml:"proxmox_host"`
|
||||
ProxmoxUser string `yaml:"proxmox_user"`
|
||||
ProxmoxPass string `yaml:"proxmox_pass"`
|
||||
GuestAgent bool `yaml:"guest_agent"`
|
||||
Firewall bool `yaml:"firewall"`
|
||||
FirewallRules []FirewallRule `yaml:"firewall_rules"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
62
proxmox.go
62
proxmox.go
@@ -194,9 +194,16 @@ func createProxmoxVM(config *Config) error {
|
||||
"--serial0", "socket",
|
||||
"--vga", "serial0",
|
||||
},
|
||||
}
|
||||
|
||||
if config.Firewall {
|
||||
commands = append(commands, []string{"qm", "set", fmt.Sprintf("%d", config.VMID), "--firewall", "1"})
|
||||
}
|
||||
|
||||
commands = append(commands, [][]string{
|
||||
{"qm", "template", fmt.Sprintf("%d", config.VMID)},
|
||||
{"rm", "-f", remotePath},
|
||||
}
|
||||
}...)
|
||||
|
||||
for _, cmdArgs := range commands {
|
||||
fmt.Printf("Running: %s\n", strings.Join(cmdArgs, " "))
|
||||
@@ -232,12 +239,65 @@ func createProxmoxVM(config *Config) error {
|
||||
}
|
||||
}
|
||||
|
||||
if config.Firewall && len(config.FirewallRules) > 0 {
|
||||
if err := configureFirewallRules(config, sshCmd); err != nil {
|
||||
return fmt.Errorf("failed to configure firewall rules: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\nTemplate %s (ID: %d) created successfully!\n", config.VMName, config.VMID)
|
||||
fmt.Printf("You can clone it with: qm clone %d <new-vm-id> --name <new-vm-name>\n", config.VMID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureFirewallRules(config *Config, sshCmd func(args ...string) *exec.Cmd) error {
|
||||
fmt.Println("Configuring firewall rules...")
|
||||
|
||||
firewallConfig := "[OPTIONS]\nenable: 1\n\n[RULES]\n"
|
||||
|
||||
for _, rule := range config.FirewallRules {
|
||||
ruleLine := fmt.Sprintf("%s %s", strings.ToUpper(rule.Type), strings.ToUpper(rule.Action))
|
||||
|
||||
if rule.Protocol != "" {
|
||||
ruleLine += fmt.Sprintf(" -p %s", rule.Protocol)
|
||||
}
|
||||
if rule.Dport != "" {
|
||||
ruleLine += fmt.Sprintf(" -dport %s", rule.Dport)
|
||||
}
|
||||
if rule.Sport != "" {
|
||||
ruleLine += fmt.Sprintf(" -sport %s", rule.Sport)
|
||||
}
|
||||
if rule.Source != "" {
|
||||
ruleLine += fmt.Sprintf(" -source %s", rule.Source)
|
||||
}
|
||||
if rule.Dest != "" {
|
||||
ruleLine += fmt.Sprintf(" -dest %s", rule.Dest)
|
||||
}
|
||||
if rule.Comment != "" {
|
||||
ruleLine += fmt.Sprintf(" -log nolog # %s", rule.Comment)
|
||||
}
|
||||
|
||||
firewallConfig += ruleLine + "\n"
|
||||
}
|
||||
|
||||
firewallPath := fmt.Sprintf("/etc/pve/firewall/%d.fw", config.VMID)
|
||||
|
||||
createCmd := sshCmd("bash", "-c", fmt.Sprintf("cat > %s << 'EOF'\n%sEOF", firewallPath, firewallConfig))
|
||||
var stdout, stderr bytes.Buffer
|
||||
createCmd.Stdout = &stdout
|
||||
createCmd.Stderr = &stderr
|
||||
|
||||
if err := createCmd.Run(); err != nil {
|
||||
fmt.Println(stdout.String())
|
||||
fmt.Println(stderr.String())
|
||||
return fmt.Errorf("failed to create firewall config: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Firewall rules configured: %s\n", firewallPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func listAvailableStorage(config *Config) error {
|
||||
fmt.Printf("Detecting available storage on %s...\n", config.ProxmoxHost)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user