mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 15:01:32 +00:00
7cb453a336
Mechanical reformat. The new 'gofmt drift' CI step (added in
ci-pipeline-cleanup Phase 4, commit 0f205a8) surfaced 111 files
with accumulated gofmt drift across cmd/, internal/, and deploy/test/.
Each file's diff is gofmt-standard: whitespace adjustments, intra-
group import sorting (alphabetical by import path within blank-line-
separated groups), and struct-tag column alignment. No semantic
changes — verified via 'git diff --ignore-all-space' which shows only
the line-position deltas from import reordering.
The gate stays in place after this commit. Going forward it catches
gofmt drift at PR time.
90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
package iis
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/masterzen/winrm"
|
|
)
|
|
|
|
// WinRMConfig holds WinRM connection settings for remote IIS management.
|
|
// Used when Mode is "winrm" — the proxy agent connects to a remote Windows
|
|
// server over WinRM and executes PowerShell commands remotely.
|
|
type WinRMConfig struct {
|
|
Host string `json:"winrm_host"` // WinRM target hostname or IP (required)
|
|
Port int `json:"winrm_port"` // WinRM port (default 5985 for HTTP, 5986 for HTTPS)
|
|
Username string `json:"winrm_username"` // Windows user (e.g., "Administrator")
|
|
Password string `json:"winrm_password"` // Windows password
|
|
UseHTTPS bool `json:"winrm_https"` // Use HTTPS (port 5986) instead of HTTP (port 5985)
|
|
Insecure bool `json:"winrm_insecure"` // Skip TLS certificate verification (for self-signed certs)
|
|
Timeout int `json:"winrm_timeout"` // Operation timeout in seconds (default 60)
|
|
}
|
|
|
|
// winrmExecutor implements PowerShellExecutor by running PowerShell commands
|
|
// on a remote Windows server via WinRM. This enables the proxy agent pattern:
|
|
// a Linux agent in the same network zone manages Windows IIS servers remotely.
|
|
type winrmExecutor struct {
|
|
client *winrm.Client
|
|
}
|
|
|
|
// newWinRMExecutor creates a WinRM client and returns a PowerShellExecutor.
|
|
func newWinRMExecutor(cfg *WinRMConfig) (*winrmExecutor, error) {
|
|
if cfg.Host == "" {
|
|
return nil, fmt.Errorf("winrm_host is required for WinRM mode")
|
|
}
|
|
if cfg.Username == "" {
|
|
return nil, fmt.Errorf("winrm_username is required for WinRM mode")
|
|
}
|
|
if cfg.Password == "" {
|
|
return nil, fmt.Errorf("winrm_password is required for WinRM mode")
|
|
}
|
|
|
|
port := cfg.Port
|
|
if port == 0 {
|
|
if cfg.UseHTTPS {
|
|
port = 5986
|
|
} else {
|
|
port = 5985
|
|
}
|
|
}
|
|
|
|
timeout := time.Duration(cfg.Timeout) * time.Second
|
|
if cfg.Timeout == 0 {
|
|
timeout = 60 * time.Second
|
|
}
|
|
|
|
endpoint := winrm.NewEndpoint(
|
|
cfg.Host,
|
|
port,
|
|
cfg.UseHTTPS,
|
|
cfg.Insecure,
|
|
nil, // CA cert
|
|
nil, // Client cert
|
|
nil, // Client key
|
|
timeout,
|
|
)
|
|
|
|
client, err := winrm.NewClient(endpoint, cfg.Username, cfg.Password)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create WinRM client: %w", err)
|
|
}
|
|
|
|
return &winrmExecutor{client: client}, nil
|
|
}
|
|
|
|
// Execute runs a PowerShell script on the remote Windows server via WinRM.
|
|
// The script is wrapped in powershell.exe invocation on the remote side.
|
|
func (e *winrmExecutor) Execute(ctx context.Context, script string) (string, error) {
|
|
// RunPSWithContext returns (stdout, stderr, exitCode, error)
|
|
stdout, stderr, exitCode, err := e.client.RunPSWithContext(ctx, script)
|
|
if err != nil {
|
|
return stdout + stderr, fmt.Errorf("WinRM command failed: %w", err)
|
|
}
|
|
if exitCode != 0 {
|
|
return stdout + stderr, fmt.Errorf("PowerShell exited with code %d: %s", exitCode, stdout+stderr)
|
|
}
|
|
|
|
return stdout, nil
|
|
}
|