github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/appsec/match_target.go (about) 1 package appsec 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 9 validation "github.com/go-ozzo/ozzo-validation/v4" 10 ) 11 12 type ( 13 // The MatchTarget interface supports creating, retrieving, updating and removing match targets. 14 // 15 // https://developer.akamai.com/api/cloud_security/application_security/v1.html#matchtarget 16 MatchTarget interface { 17 // https://developer.akamai.com/api/cloud_security/application_security/v1.html#getmatchtargets 18 GetMatchTargets(ctx context.Context, params GetMatchTargetsRequest) (*GetMatchTargetsResponse, error) 19 20 // https://developer.akamai.com/api/cloud_security/application_security/v1.html#getmatchtargetid 21 GetMatchTarget(ctx context.Context, params GetMatchTargetRequest) (*GetMatchTargetResponse, error) 22 23 // https://developer.akamai.com/api/cloud_security/application_security/v1.html#getmatchtargetid 24 CreateMatchTarget(ctx context.Context, params CreateMatchTargetRequest) (*CreateMatchTargetResponse, error) 25 26 // https://developer.akamai.com/api/cloud_security/application_security/v1.html#putmatchtargetid 27 UpdateMatchTarget(ctx context.Context, params UpdateMatchTargetRequest) (*UpdateMatchTargetResponse, error) 28 29 // https://developer.akamai.com/api/cloud_security/application_security/v1.html#deletematchtargetid 30 RemoveMatchTarget(ctx context.Context, params RemoveMatchTargetRequest) (*RemoveMatchTargetResponse, error) 31 } 32 33 // GetMatchTargetsRequest is used to retrieve the match targets for a configuration. 34 GetMatchTargetsRequest struct { 35 ConfigID int `json:"configId"` 36 ConfigVersion int `json:"configVersion"` 37 TargetID int `json:"targetId"` 38 } 39 40 // GetMatchTargetsResponse is returned from a call to GetMatchTargets. 41 GetMatchTargetsResponse struct { 42 MatchTargets struct { 43 APITargets []struct { 44 Type string `json:"type,omitempty"` 45 Apis []struct { 46 ID int `json:"id"` 47 Name string `json:"name"` 48 } `json:"apis"` 49 Sequence int `json:"sequence"` 50 TargetID int `json:"targetId"` 51 ConfigID int `json:"configId,omitempty"` 52 ConfigVersion int `json:"configVersion,omitempty"` 53 54 SecurityPolicy struct { 55 PolicyID string `json:"policyId,omitempty"` 56 } `json:"securityPolicy,omitempty"` 57 58 BypassNetworkLists []struct { 59 Name string `json:"name,omitempty"` 60 ID string `json:"id,omitempty"` 61 } `json:"bypassNetworkLists,omitempty"` 62 } `json:"apiTargets,omitempty"` 63 WebsiteTargets []struct { 64 ConfigID int `json:"configId,omitempty"` 65 ConfigVersion int `json:"configVersion,omitempty"` 66 DefaultFile string `json:"defaultFile,omitempty"` 67 IsNegativeFileExtensionMatch bool `json:"isNegativeFileExtensionMatch,omitempty"` 68 IsNegativePathMatch *json.RawMessage `json:"isNegativePathMatch,omitempty"` 69 Sequence int `json:"-"` 70 TargetID int `json:"targetId,omitempty"` 71 Type string `json:"type,omitempty"` 72 FileExtensions []string `json:"fileExtensions,omitempty"` 73 FilePaths []string `json:"filePaths,omitempty"` 74 Hostnames []string `json:"hostnames,omitempty"` 75 SecurityPolicy struct { 76 PolicyID string `json:"policyId,omitempty"` 77 } `json:"securityPolicy,omitempty"` 78 BypassNetworkLists []struct { 79 Name string `json:"name,omitempty"` 80 ID string `json:"id,omitempty"` 81 } `json:"bypassNetworkLists,omitempty"` 82 } `json:"websiteTargets,omitempty"` 83 } `json:"matchTargets,omitempty"` 84 } 85 86 // GetMatchTargetRequest is used to retrieve a match target. 87 GetMatchTargetRequest struct { 88 ConfigID int `json:"configId"` 89 ConfigVersion int `json:"configVersion"` 90 TargetID int `json:"targetId"` 91 } 92 93 // GetMatchTargetResponse is returned from a call to GetMatchTarget. 94 GetMatchTargetResponse struct { 95 Type string `json:"type,omitempty"` 96 Apis []struct { 97 ID int `json:"id"` 98 Name string `json:"name"` 99 } `json:"apis,omitempty"` 100 DefaultFile string `json:"defaultFile,omitempty"` 101 Hostnames []string `json:"hostnames,omitempty"` 102 IsNegativeFileExtensionMatch bool `json:"isNegativeFileExtensionMatch,omitempty"` 103 IsNegativePathMatch *json.RawMessage `json:"isNegativePathMatch,omitempty"` 104 FilePaths []string `json:"filePaths,omitempty"` 105 FileExtensions []string `json:"fileExtensions,omitempty"` 106 SecurityPolicy struct { 107 PolicyID string `json:"policyId,omitempty"` 108 } `json:"securityPolicy,omitempty"` 109 Sequence int `json:"-"` 110 TargetID int `json:"targetId"` 111 BypassNetworkLists []struct { 112 Name string `json:"name,omitempty"` 113 ID string `json:"id,omitempty"` 114 } `json:"bypassNetworkLists,omitempty"` 115 } 116 117 // CreateMatchTargetRequest is used to create a match target. 118 CreateMatchTargetRequest struct { 119 Type string `json:"type"` 120 ConfigID int `json:"configId"` 121 ConfigVersion int `json:"configVersion"` 122 JsonPayloadRaw json.RawMessage `json:"-"` 123 } 124 125 // CreateMatchTargetResponse is returned from a call to CreateMatchTarget. 126 CreateMatchTargetResponse struct { 127 MType string `json:"type"` 128 Apis []struct { 129 ID int `json:"id"` 130 Name string `json:"name"` 131 } `json:"apis,omitempty"` 132 DefaultFile string `json:"defaultFile"` 133 Hostnames []string `json:"hostnames"` 134 IsNegativeFileExtensionMatch bool `json:"isNegativeFileExtensionMatch"` 135 IsNegativePathMatch *json.RawMessage `json:"isNegativePathMatch,omitempty"` 136 FilePaths []string `json:"filePaths"` 137 FileExtensions []string `json:"fileExtensions"` 138 SecurityPolicy struct { 139 PolicyID string `json:"policyId"` 140 } `json:"securityPolicy"` 141 Sequence int `json:"-"` 142 TargetID int `json:"targetId"` 143 BypassNetworkLists []struct { 144 Name string `json:"name"` 145 ID string `json:"id"` 146 } `json:"bypassNetworkLists"` 147 } 148 149 // UpdateMatchTargetRequest is used to modify an existing match target. 150 UpdateMatchTargetRequest struct { 151 ConfigID int `json:"configId"` 152 ConfigVersion int `json:"configVersion"` 153 JsonPayloadRaw json.RawMessage `json:"-"` 154 TargetID int `json:"targetId"` 155 } 156 157 // UpdateMatchTargetResponse is returned from a call to UpdateMatchTarget. 158 UpdateMatchTargetResponse struct { 159 Type string `json:"type"` 160 ConfigID int `json:"configId"` 161 ConfigVersion int `json:"configVersion"` 162 DefaultFile string `json:"defaultFile"` 163 Hostnames []string `json:"hostnames"` 164 IsNegativeFileExtensionMatch bool `json:"isNegativeFileExtensionMatch"` 165 IsNegativePathMatch *json.RawMessage `json:"isNegativePathMatch,omitempty"` 166 FilePaths []string `json:"filePaths"` 167 FileExtensions []string `json:"fileExtensions"` 168 SecurityPolicy struct { 169 PolicyID string `json:"policyId"` 170 } `json:"securityPolicy"` 171 Sequence int `json:"-"` 172 TargetID int `json:"targetId"` 173 BypassNetworkLists []struct { 174 Name string `json:"name"` 175 ID string `json:"id"` 176 } `json:"bypassNetworkLists"` 177 } 178 179 // RemoveMatchTargetRequest is used to remove a match target. 180 RemoveMatchTargetRequest struct { 181 ConfigID int `json:"configId"` 182 ConfigVersion int `json:"configVersion"` 183 TargetID int `json:"targetId"` 184 } 185 186 // RemoveMatchTargetResponse is returned from a call to RemoveMatchTarget. 187 RemoveMatchTargetResponse struct { 188 Type string `json:"type"` 189 ConfigID int `json:"configId"` 190 ConfigVersion int `json:"configVersion"` 191 DefaultFile string `json:"defaultFile"` 192 Hostnames []string `json:"hostnames"` 193 IsNegativeFileExtensionMatch bool `json:"isNegativeFileExtensionMatch"` 194 IsNegativePathMatch bool `json:"isNegativePathMatch"` 195 FilePaths []string `json:"filePaths"` 196 FileExtensions []string `json:"fileExtensions"` 197 SecurityPolicy struct { 198 PolicyID string `json:"policyId"` 199 } `json:"securityPolicy"` 200 Sequence int `json:"sequence"` 201 TargetID int `json:"targetId"` 202 BypassNetworkLists []struct { 203 Name string `json:"name"` 204 ID string `json:"id"` 205 } `json:"bypassNetworkLists"` 206 } 207 208 // BypassNetworkList describes a network list used in the bypass network lists for the specified configuration. 209 BypassNetworkList struct { 210 Name string `json:"name"` 211 ID string `json:"id"` 212 } 213 214 // Hostnames contains one or more hostnames. 215 Hostnames struct { 216 Hostnames string `json:"hostnames"` 217 } 218 219 // AutoGenerated is currently unused. 220 AutoGenerated struct { 221 Type string `json:"type"` 222 Apis []struct { 223 ID int `json:"id"` 224 Name string `json:"name"` 225 } `json:"apis"` 226 BypassNetworkLists []struct { 227 ID string `json:"id"` 228 Name string `json:"name"` 229 } `json:"bypassNetworkLists"` 230 ConfigID int `json:"configId"` 231 ConfigVersion int `json:"configVersion"` 232 SecurityPolicy struct { 233 PolicyID string `json:"policyId"` 234 } `json:"securityPolicy"` 235 Sequence int `json:"-"` 236 TargetID int `json:"targetId"` 237 } 238 ) 239 240 // Validate validates a GetMatchTargetRequest. 241 func (v GetMatchTargetRequest) Validate() error { 242 return validation.Errors{ 243 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 244 "ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required), 245 "TargetID": validation.Validate(v.TargetID, validation.Required), 246 }.Filter() 247 } 248 249 // Validate validates a GetMatchTargetsRequest. 250 func (v GetMatchTargetsRequest) Validate() error { 251 return validation.Errors{ 252 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 253 "ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required), 254 }.Filter() 255 } 256 257 // Validate validates a CreateMatchTargetRequest. 258 func (v CreateMatchTargetRequest) Validate() error { 259 return validation.Errors{ 260 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 261 "ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required), 262 }.Filter() 263 } 264 265 // Validate validates an UpdateMatchTargetRequest. 266 func (v UpdateMatchTargetRequest) Validate() error { 267 return validation.Errors{ 268 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 269 "ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required), 270 "TargetID": validation.Validate(v.TargetID, validation.Required), 271 }.Filter() 272 } 273 274 // Validate validates a RemoveMatchTargetRequest. 275 func (v RemoveMatchTargetRequest) Validate() error { 276 return validation.Errors{ 277 "ConfigID": validation.Validate(v.ConfigID, validation.Required), 278 "ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required), 279 "TargetID": validation.Validate(v.TargetID, validation.Required), 280 }.Filter() 281 } 282 283 func (p *appsec) GetMatchTarget(ctx context.Context, params GetMatchTargetRequest) (*GetMatchTargetResponse, error) { 284 logger := p.Log(ctx) 285 logger.Debug("GetMatchTarget") 286 287 if err := params.Validate(); err != nil { 288 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 289 } 290 291 uri := fmt.Sprintf( 292 "/appsec/v1/configs/%d/versions/%d/match-targets/%d?includeChildObjectName=true", 293 params.ConfigID, 294 params.ConfigVersion, 295 params.TargetID, 296 ) 297 298 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 299 if err != nil { 300 return nil, fmt.Errorf("failed to create GetMatchTarget request: %w", err) 301 } 302 303 var result GetMatchTargetResponse 304 resp, err := p.Exec(req, &result) 305 if err != nil { 306 return nil, fmt.Errorf("get match target request failed: %w", err) 307 } 308 if resp.StatusCode != http.StatusOK { 309 return nil, p.Error(resp) 310 } 311 312 return &result, nil 313 } 314 315 func (p *appsec) GetMatchTargets(ctx context.Context, params GetMatchTargetsRequest) (*GetMatchTargetsResponse, error) { 316 logger := p.Log(ctx) 317 logger.Debug("GetMatchTargets") 318 319 if err := params.Validate(); err != nil { 320 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 321 } 322 323 uri := fmt.Sprintf( 324 "/appsec/v1/configs/%d/versions/%d/match-targets", 325 params.ConfigID, 326 params.ConfigVersion, 327 ) 328 329 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 330 if err != nil { 331 return nil, fmt.Errorf("failed to create GetMatchTargets request: %w", err) 332 } 333 334 var result GetMatchTargetsResponse 335 resp, err := p.Exec(req, &result) 336 if err != nil { 337 return nil, fmt.Errorf("get match targets request failed: %w", err) 338 } 339 if resp.StatusCode != http.StatusOK { 340 return nil, p.Error(resp) 341 } 342 343 if params.TargetID != 0 { 344 var filteredResult GetMatchTargetsResponse 345 for _, val := range result.MatchTargets.WebsiteTargets { 346 if val.TargetID == params.TargetID { 347 filteredResult.MatchTargets.WebsiteTargets = append(filteredResult.MatchTargets.WebsiteTargets, val) 348 } 349 } 350 for _, val := range result.MatchTargets.APITargets { 351 if val.TargetID == params.TargetID { 352 filteredResult.MatchTargets.APITargets = append(filteredResult.MatchTargets.APITargets, val) 353 } 354 } 355 return &filteredResult, nil 356 } 357 358 return &result, nil 359 } 360 361 func (p *appsec) UpdateMatchTarget(ctx context.Context, params UpdateMatchTargetRequest) (*UpdateMatchTargetResponse, error) { 362 logger := p.Log(ctx) 363 logger.Debug("UpdateMatchTarget") 364 365 if err := params.Validate(); err != nil { 366 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 367 } 368 369 uri := fmt.Sprintf( 370 "/appsec/v1/configs/%d/versions/%d/match-targets/%d", 371 params.ConfigID, 372 params.ConfigVersion, 373 params.TargetID, 374 ) 375 376 req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil) 377 if err != nil { 378 return nil, fmt.Errorf("failed to create UpdateMatchTarget request: %w", err) 379 } 380 381 var result UpdateMatchTargetResponse 382 req.Header.Set("Content-Type", "application/json") 383 resp, err := p.Exec(req, &result, params.JsonPayloadRaw) 384 if err != nil { 385 return nil, fmt.Errorf("update match target request failed: %w", err) 386 } 387 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { 388 return nil, p.Error(resp) 389 } 390 391 return &result, nil 392 } 393 394 func (p *appsec) CreateMatchTarget(ctx context.Context, params CreateMatchTargetRequest) (*CreateMatchTargetResponse, error) { 395 logger := p.Log(ctx) 396 logger.Debug("CreateMatchTarget") 397 398 if err := params.Validate(); err != nil { 399 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 400 } 401 402 uri := fmt.Sprintf( 403 "/appsec/v1/configs/%d/versions/%d/match-targets", 404 params.ConfigID, 405 params.ConfigVersion, 406 ) 407 408 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil) 409 if err != nil { 410 return nil, fmt.Errorf("failed to create CreateMatchTarget request: %w", err) 411 } 412 413 var result CreateMatchTargetResponse 414 req.Header.Set("Content-Type", "application/json") 415 resp, err := p.Exec(req, &result, params.JsonPayloadRaw) 416 if err != nil { 417 return nil, fmt.Errorf("create match target request failed: %w", err) 418 } 419 if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK { 420 return nil, p.Error(resp) 421 } 422 423 return &result, nil 424 } 425 426 func (p *appsec) RemoveMatchTarget(ctx context.Context, params RemoveMatchTargetRequest) (*RemoveMatchTargetResponse, error) { 427 logger := p.Log(ctx) 428 logger.Debug("RemoveMatchTarget") 429 430 if err := params.Validate(); err != nil { 431 return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error()) 432 } 433 434 uri := fmt.Sprintf("/appsec/v1/configs/%d/versions/%d/match-targets/%d", params.ConfigID, params.ConfigVersion, params.TargetID) 435 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil) 436 if err != nil { 437 return nil, fmt.Errorf("failed to create RemoveMatchTarget request: %w", err) 438 } 439 440 var result RemoveMatchTargetResponse 441 resp, errd := p.Exec(req, nil) 442 if errd != nil { 443 return nil, fmt.Errorf("remove match target request failed: %w", err) 444 } 445 446 if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK { 447 return nil, p.Error(resp) 448 } 449 450 return &result, nil 451 }