Autocreate alias if not exist on PFSense and enhance the alias IP function

This commit is contained in:
2026-01-28 13:25:54 +01:00
parent 76b5a332de
commit fd1f26a1a6

View File

@@ -88,8 +88,28 @@ func (p *pfSenseIntegration) modifyAliasIP(req Request, ip, description string,
// GET the alias by name // GET the alias by name
alias, err := p.getAliasByName(httpClient, baseURL, cfg.APIToken, cfg.Alias, req.Logger) alias, err := p.getAliasByName(httpClient, baseURL, cfg.APIToken, cfg.Alias, req.Logger)
if err != nil { if err != nil {
// If alias doesn't exist, create it automatically
if strings.Contains(err.Error(), "not found") {
if req.Logger != nil {
req.Logger("Alias %s not found, creating it automatically", cfg.Alias)
}
// Create a new alias with default values
newAlias := &FirewallAlias{
Name: cfg.Alias,
Type: "host",
Descr: "Fail2ban-UI alias",
Address: []string{},
Detail: []string{},
}
createdAlias, createErr := p.createAlias(httpClient, baseURL, cfg.APIToken, newAlias, req.Logger)
if createErr != nil {
return fmt.Errorf("failed to create alias %s: %w", cfg.Alias, createErr)
}
alias = createdAlias
} else {
return fmt.Errorf("failed to get alias %s: %w", cfg.Alias, err) return fmt.Errorf("failed to get alias %s: %w", cfg.Alias, err)
} }
}
// Modify the address array // Modify the address array
if add { if add {
@@ -224,12 +244,77 @@ func (p *pfSenseIntegration) getAliasByName(client *http.Client, baseURL, apiTok
return nil, fmt.Errorf("alias %s not found", aliasName) return nil, fmt.Errorf("alias %s not found", aliasName)
} }
// updateAlias updates a firewall alias using PATCH /api/v2/firewall/alias/{id} // createAlias creates a new firewall alias using POST /api/v2/firewall/alias
func (p *pfSenseIntegration) updateAlias(client *http.Client, baseURL, apiToken string, alias *FirewallAlias, logger func(string, ...interface{})) error { func (p *pfSenseIntegration) createAlias(client *http.Client, baseURL, apiToken string, alias *FirewallAlias, logger func(string, ...interface{})) (*FirewallAlias, error) {
apiURL := fmt.Sprintf("%s/api/v2/firewall/alias/%d", baseURL, alias.ID) apiURL := baseURL + "/api/v2/firewall/alias"
// Prepare PATCH payload - only include fields that can be updated // Prepare POST payload - exclude ID as it will be generated by pfSense
postPayload := map[string]interface{}{
"name": alias.Name,
"type": alias.Type,
"descr": alias.Descr,
"address": alias.Address,
}
if len(alias.Detail) > 0 {
postPayload["detail"] = alias.Detail
}
data, err := json.Marshal(postPayload)
if err != nil {
return nil, fmt.Errorf("failed to encode pfSense POST payload: %w", err)
}
if logger != nil {
logger("Calling pfSense API POST %s payload=%s", apiURL, string(data))
}
httpReq, err := http.NewRequest(http.MethodPost, apiURL, bytes.NewReader(data))
if err != nil {
return nil, fmt.Errorf("failed to create pfSense POST request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("x-api-key", apiToken)
resp, err := client.Do(httpReq)
if err != nil {
if netErr, ok := err.(interface {
Timeout() bool
Error() string
}); ok && netErr.Timeout() {
return nil, fmt.Errorf("pfSense API request to %s timed out: %w", apiURL, err)
}
return nil, fmt.Errorf("pfSense API request to %s failed: %w", apiURL, err)
}
defer resp.Body.Close()
bodyBytes, _ := io.ReadAll(resp.Body)
bodyStr := strings.TrimSpace(string(bodyBytes))
if resp.StatusCode >= 300 {
return nil, fmt.Errorf("pfSense API POST failed: status %s, response: %s", resp.Status, bodyStr)
}
// Parse the response to get the created alias with its ID
var createResp FirewallAliasResponse
if err := json.Unmarshal(bodyBytes, &createResp); err != nil {
return nil, fmt.Errorf("failed to decode pfSense alias creation response: %w", err)
}
if logger != nil {
logger("pfSense API POST succeeded: alias %s created with ID %d", createResp.Data.Name, createResp.Data.ID)
}
return &createResp.Data, nil
}
// updateAlias updates a firewall alias using PATCH /api/v2/firewall/alias
// The id must be included in the request body, not in the URL path
func (p *pfSenseIntegration) updateAlias(client *http.Client, baseURL, apiToken string, alias *FirewallAlias, logger func(string, ...interface{})) error {
apiURL := baseURL + "/api/v2/firewall/alias"
// Prepare PATCH payload - include id in the request body
patchPayload := map[string]interface{}{ patchPayload := map[string]interface{}{
"id": alias.ID,
"name": alias.Name, "name": alias.Name,
"type": alias.Type, "type": alias.Type,
"descr": alias.Descr, "descr": alias.Descr,