mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-04-17 05:53:15 +02:00
Autocreate alias if not exist on PFSense and enhance the alias IP function
This commit is contained in:
@@ -88,8 +88,28 @@ func (p *pfSenseIntegration) modifyAliasIP(req Request, ip, description string,
|
||||
// GET the alias by name
|
||||
alias, err := p.getAliasByName(httpClient, baseURL, cfg.APIToken, cfg.Alias, req.Logger)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// Modify the address array
|
||||
if add {
|
||||
@@ -224,12 +244,77 @@ func (p *pfSenseIntegration) getAliasByName(client *http.Client, baseURL, apiTok
|
||||
return nil, fmt.Errorf("alias %s not found", aliasName)
|
||||
}
|
||||
|
||||
// updateAlias updates a firewall alias using PATCH /api/v2/firewall/alias/{id}
|
||||
func (p *pfSenseIntegration) updateAlias(client *http.Client, baseURL, apiToken string, alias *FirewallAlias, logger func(string, ...interface{})) error {
|
||||
apiURL := fmt.Sprintf("%s/api/v2/firewall/alias/%d", baseURL, alias.ID)
|
||||
// createAlias creates a new firewall alias using POST /api/v2/firewall/alias
|
||||
func (p *pfSenseIntegration) createAlias(client *http.Client, baseURL, apiToken string, alias *FirewallAlias, logger func(string, ...interface{})) (*FirewallAlias, error) {
|
||||
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{}{
|
||||
"id": alias.ID,
|
||||
"name": alias.Name,
|
||||
"type": alias.Type,
|
||||
"descr": alias.Descr,
|
||||
|
||||
Reference in New Issue
Block a user