github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/appsec/tuning_recommendations.go (about) 1 package appsec 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "time" 8 9 validation "github.com/go-ozzo/ozzo-validation/v4" 10 ) 11 12 type ( 13 // The TuningRecommendations interface supports retrieving tuning recommendations for a security policy, a specific attack group or a rule 14 // 15 // https://techdocs.akamai.com/application-security/reference/get-recommendations 16 TuningRecommendations interface { 17 // https://techdocs.akamai.com/application-security/reference/get-recommendations 18 GetTuningRecommendations(ctx context.Context, params GetTuningRecommendationsRequest) (*GetTuningRecommendationsResponse, error) 19 // https://techdocs.akamai.com/application-security/reference/get-recommendations-attack-group 20 GetAttackGroupRecommendations(ctx context.Context, params GetAttackGroupRecommendationsRequest) (*GetAttackGroupRecommendationsResponse, error) 21 // https://techdocs.akamai.com/application-security/reference/get-recommendations-rule 22 GetRuleRecommendations(ctx context.Context, params GetRuleRecommendationsRequest) (*GetRuleRecommendationsResponse, error) 23 } 24 25 // GetTuningRecommendationsRequest is used to retrieve tuning recommendations for a security policy. 26 GetTuningRecommendationsRequest struct { 27 ConfigID int 28 Version int 29 PolicyID string 30 RulesetType RulesetType 31 } 32 33 // GetAttackGroupRecommendationsRequest is used to retrieve tuning recommendations for a specific attack group. 34 GetAttackGroupRecommendationsRequest struct { 35 ConfigID int 36 Version int 37 PolicyID string 38 Group string 39 RulesetType RulesetType 40 } 41 42 // GetRuleRecommendationsRequest is used to retrieve tuning recommendations for a specific rule. 43 GetRuleRecommendationsRequest struct { 44 ConfigID int 45 Version int 46 PolicyID string 47 RuleID int 48 RulesetType RulesetType 49 } 50 51 // GetTuningRecommendationsResponse is returned from a call to GetTuningRecommendations. 52 GetTuningRecommendationsResponse struct { 53 AttackGroupRecommendations []AttackGroupRecommendation `json:"attackGroupRecommendations,omitempty"` 54 RuleRecommendations []RuleRecommendation `json:"ruleRecommendations,omitempty"` 55 EvaluationPeriodStart time.Time `json:"evaluationPeriodStart,omitempty"` 56 EvaluationPeriodEnd time.Time `json:"evaluationPeriodEnd,omitempty"` 57 } 58 59 // GetAttackGroupRecommendationsResponse is returned from a call to GetAttackGroupRecommendations. 60 GetAttackGroupRecommendationsResponse AttackGroupRecommendation 61 62 // GetRuleRecommendationsResponse is returned from a call to GetRuleRecommendations. 63 GetRuleRecommendationsResponse RuleRecommendation 64 65 // AttackGroupRecommendation is used to describe a recommendation for an attack group. 66 AttackGroupRecommendation struct { 67 Description string `json:"description,omitempty"` 68 Evidence *Evidences `json:"evidences,omitempty"` 69 Exception *AttackGroupException `json:"exception,omitempty"` 70 Group string `json:"group,omitempty"` 71 } 72 // RuleRecommendation is used to describe a recommendation for a rule. 73 RuleRecommendation struct { 74 Description string `json:"description,omitempty"` 75 Evidence *Evidences `json:"evidences,omitempty"` 76 Exception *AttackGroupException `json:"exception,omitempty"` 77 RuleId int `json:"ruleId,omitempty"` 78 } 79 80 // Evidences is used to describe evidences for a recommendation. 81 Evidences []struct { 82 HostEvidences []string `json:"hostEvidences,omitempty"` 83 PathEvidences []string `json:"pathEvidences,omitempty"` 84 UserDataEvidences []string `json:"userDataEvidences,omitempty"` 85 } 86 ) 87 88 // Validate validates a GetTuningRecommendationsRequest. 89 func (v GetTuningRecommendationsRequest) Validate() error { 90 return validation.Errors{ 91 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 92 "Version": validation.Validate(v.Version, validation.Required), 93 "PolicyID": validation.Validate(v.PolicyID, validation.Required), 94 "RulesetType": validation.Validate(v.RulesetType, validation.In(RulesetTypeActive, RulesetTypeEvaluation).Error( 95 fmt.Sprintf("value '%s' is invalid. Must be one of: 'active', 'evaluation' or '' (empty)", v.RulesetType))), 96 }.Filter() 97 } 98 99 // Validate validates a GetAttackGroupRecommendationsRequest. 100 func (v GetAttackGroupRecommendationsRequest) Validate() error { 101 return validation.Errors{ 102 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 103 "Version": validation.Validate(v.Version, validation.Required), 104 "PolicyID": validation.Validate(v.PolicyID, validation.Required), 105 "Group": validation.Validate(v.Group, validation.Required), 106 "RulesetType": validation.Validate(v.RulesetType, validation.In(RulesetTypeActive, RulesetTypeEvaluation).Error( 107 fmt.Sprintf("value '%s' is invalid. Must be one of: 'active', 'evaluation' or '' (empty)", v.RulesetType))), 108 }.Filter() 109 } 110 111 // Validate validates a GetAttackGroupRecommendationsRequest. 112 func (v GetRuleRecommendationsRequest) Validate() error { 113 return validation.Errors{ 114 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 115 "Version": validation.Validate(v.Version, validation.Required), 116 "PolicyID": validation.Validate(v.PolicyID, validation.Required), 117 "RuleID": validation.Validate(v.RuleID, validation.Required), 118 "RulesetType": validation.Validate(v.RulesetType, validation.In(RulesetTypeActive, RulesetTypeEvaluation).Error( 119 fmt.Sprintf("value '%s' is invalid. Must be one of: 'active', 'evaluation' or '' (empty)", v.RulesetType))), 120 }.Filter() 121 } 122 123 func (p *appsec) GetTuningRecommendations(ctx context.Context, params GetTuningRecommendationsRequest) (*GetTuningRecommendationsResponse, error) { 124 logger := p.Log(ctx) 125 logger.Debug("GetTuningRecommendations") 126 127 if err := params.Validate(); err != nil { 128 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 129 } 130 131 uri := fmt.Sprintf( 132 "/appsec/v1/configs/%d/versions/%d/security-policies/%s/recommendations?standardException=true&type=%s", 133 params.ConfigID, 134 params.Version, 135 params.PolicyID, 136 params.RulesetType) 137 138 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 139 if err != nil { 140 return nil, fmt.Errorf("failed to create GetTuningRecommendations request: %w", err) 141 } 142 req.Header.Set("Content-Type", "application/json") 143 144 var result GetTuningRecommendationsResponse 145 resp, err := p.Exec(req, &result) 146 if err != nil { 147 return nil, fmt.Errorf("get tuning recommendations request failed: %w", err) 148 } 149 if resp.StatusCode != http.StatusOK { 150 return nil, p.Error(resp) 151 } 152 153 return &result, nil 154 } 155 156 func (p *appsec) GetAttackGroupRecommendations(ctx context.Context, params GetAttackGroupRecommendationsRequest) (*GetAttackGroupRecommendationsResponse, error) { 157 logger := p.Log(ctx) 158 logger.Debug("GetAttackGroupRecommendations") 159 160 if err := params.Validate(); err != nil { 161 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 162 } 163 164 uri := fmt.Sprintf( 165 "/appsec/v1/configs/%d/versions/%d/security-policies/%s/recommendations/attack-groups/%s?standardException=true&type=%s", 166 params.ConfigID, 167 params.Version, 168 params.PolicyID, 169 params.Group, 170 params.RulesetType, 171 ) 172 173 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 174 if err != nil { 175 return nil, fmt.Errorf("failed to create GetAttackGroupRecommendations request: %w", err) 176 } 177 178 req.Header.Set("Content-Type", "application/json") 179 180 var result GetAttackGroupRecommendationsResponse 181 resp, err := p.Exec(req, &result) 182 if err != nil { 183 return nil, fmt.Errorf("get attack group recommendations request failed: %w", err) 184 } 185 if resp.StatusCode != http.StatusOK { 186 return nil, p.Error(resp) 187 } 188 189 return &result, nil 190 } 191 192 func (p *appsec) GetRuleRecommendations(ctx context.Context, params GetRuleRecommendationsRequest) (*GetRuleRecommendationsResponse, error) { 193 logger := p.Log(ctx) 194 logger.Debug("GetRuleRecommendations") 195 196 if err := params.Validate(); err != nil { 197 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 198 } 199 200 uri := fmt.Sprintf( 201 "/appsec/v1/configs/%d/versions/%d/security-policies/%s/recommendations/rules/%d?standardException=true&type=%s", 202 params.ConfigID, 203 params.Version, 204 params.PolicyID, 205 params.RuleID, 206 params.RulesetType, 207 ) 208 209 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 210 if err != nil { 211 return nil, fmt.Errorf("failed to create GetRuleRecommendations request: %w", err) 212 } 213 214 req.Header.Set("Content-Type", "application/json") 215 216 var result GetRuleRecommendationsResponse 217 resp, err := p.Exec(req, &result) 218 if err != nil { 219 return nil, fmt.Errorf("get rule recommendations request failed: %w", err) 220 } 221 if resp.StatusCode != http.StatusOK { 222 return nil, p.Error(resp) 223 } 224 225 return &result, nil 226 }