Skip to content

Commit 29227df

Browse files
authored
DXE-6511 Merge pull request #237 from akamai/release/v13.2.0
DXE-6511 Release/v13.2.0
2 parents 4d4465d + c8d771f commit 29227df

30 files changed

Lines changed: 5481 additions & 118 deletions

CHANGELOG.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,72 @@
11
# RELEASE NOTES
22

3+
## 13.2.0 (May 11, 2026)
4+
5+
### FEATURES/ENHANCEMENTS:
6+
7+
* Appsec
8+
* Relaxed validation of the `UpdatePenaltyBoxRequest` structure to allow the `deny_custom_{custom_deny_id}` value.
9+
* Added the `ApplyAccountProtectionControls` field to the `UpdatePolicyProtectionsRequest` structure.
10+
11+
* Edgeworkers
12+
* Added support for the `autoPin` attribute in the Edgeworkers activation requests.
13+
14+
* mTLS Truststore
15+
* Added the `CASetStatuses` field to the `ListCASetsRequest` structure that allows filtering CA sets by their statuses, including `NOT_DELETED`, `DELETING`, and `DELETED`.
16+
* Added support for the `RemovalDate` field to the following structures:
17+
* `CASetResponse`
18+
* `CreateCASetResponse`
19+
* `GetCASetResponse`
20+
* `ListCASetResponse`
21+
* `CloneCASetResponse`
22+
* `GetCASetDeletionStatusResponse`
23+
* `CASetVersion`
24+
* `CreateCASetVersionResponse`
25+
* `GetCASetVersionResponse`
26+
* `CloneCASetVersionResponse`
27+
* `ListCASetVersionsResponse`
28+
* `UpdateCASetVersionResponse`
29+
* Added support for the `CASetVersionStatus` field to the following structures:
30+
* `CASetVersion`
31+
* `CreateCASetVersionResponse`
32+
* `GetCASetVersionResponse`
33+
* `CloneCASetVersionResponse`
34+
* `ListCASetVersionsResponse`
35+
* `UpdateCASetVersionResponse`
36+
* Added support for the `CASetVersionStatuses` query parameter to the `ListCASetVersions` method to filter CA set versions by their statuses, either `NOT_DELETED` or `DELETED`.
37+
* Added support for the [DeleteCASetVersion](https://techdocs.akamai.com/mtls-edge-truststore/reference/delete-ca-set-version) endpoint.
38+
39+
* PAPI
40+
* Added the `AccessGroup` field to the `CPCodeDetailResponse` structure, returned by the following methods:
41+
* `GetCPCodeDetail`
42+
* `UpdateCPCode`
43+
44+
* Reporting Groups (Beta)
45+
* Added support for the Reporting Groups API:
46+
* [CreateReportingGroup](https://techdocs.akamai.com/cp-codes/reference/post-reporting-groups) - Creates a new reporting group.
47+
* [GetReportingGroup](https://techdocs.akamai.com/cp-codes/reference/get-reporting-group) - Gets details of a specific reporting group.
48+
* [ListReportingGroups](https://techdocs.akamai.com/cp-codes/reference/get-reporting-groups) - Lists all reporting groups.
49+
* [ListProducts](https://techdocs.akamai.com/cp-codes/reference/get-reporting-group-products) - Lists products and services assigned to a specific reporting group.
50+
* [UpdateReportingGroup](https://techdocs.akamai.com/cp-codes/reference/put-reporting-group) - Updates an existing reporting group.
51+
* [DeleteReportingGroup](https://techdocs.akamai.com/cp-codes/reference/delete-reporting-group) - Deletes a reporting group.
52+
* [GetReportingGroupsWaterMarkLimits](https://techdocs.akamai.com/cp-codes/reference/get-reporting-groups-watermark-limits) - Gets water-mark limits for reporting groups.
53+
* [GetCPCodesWaterMarkLimits](https://techdocs.akamai.com/cp-codes/reference/get-cpcodes-watermark-limits) - Gets water-mark limits for CP codes.
54+
* Added support for the CP Codes API:
55+
* [ListCPCodes](https://techdocs.akamai.com/cp-codes/reference/get-cpcodes) - Lists CP codes.
56+
* [GetCPCode](https://techdocs.akamai.com/cp-codes/reference/get-cpcode) - Gets details of a specific CP code.
57+
* [UpdateCPCode](https://techdocs.akamai.com/cp-codes/reference/put-cpcode) - Updates a specific CP code.
58+
59+
### BUG FIXES:
60+
61+
* Appsec
62+
* Removed the incorrectly allowed `StatusCreated` response status from the `UpdatePolicyProtections` method.
63+
64+
### Deprecations:
65+
66+
* PAPI
67+
* Deprecated `GetCPCodeDetail`. Use `reportinggroups.GetCPCode` instead.
68+
* Deprecated `UpdateCPCode`. Use `reportinggroups.UpdateCPCode` instead.
69+
370
## 13.1.0 (Mar 30, 2026)
471

572
### FEATURES/ENHANCEMENTS:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ To see what methods you can use within a given package, go to the `pkg` director
789789
| [Network Lists](./pkg/networklists/) | Automate the creation, deployment, and management of lists used in ​Akamai​ security products. |
790790
| [Pointer Record](./pkg/ptr/) | Create pointers to values of any type. |
791791
| [Property Manager](./pkg/papi/) | Define rules and behaviors that govern your website delivery based on match criteria. |
792+
| [Reporting Groups](./pkg/reportinggroups/) | Break down your invoices and reports on your site's traffic by reporting groups rather than by contracts or products only. |
792793
| [Session](./pkg/session/) | Manage the base secure HTTP client and requests for Akamai APIs. |
793794

794795
### Example

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/stretchr/testify v1.10.0
1313
github.com/wk8/go-ordered-map/v2 v2.1.8
1414
go.uber.org/ratelimit v0.3.1
15-
golang.org/x/net v0.49.0
15+
golang.org/x/net v0.53.0
1616
gopkg.in/ini.v1 v1.67.0
1717
)
1818

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
6464
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
6565
go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0=
6666
go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk=
67-
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
68-
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
69-
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
70-
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
67+
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
68+
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
69+
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
70+
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
7171
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
7272
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
7373
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

pkg/appsec/penalty_box.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net/http"
7+
"strings"
78

89
"github.com/akamai/AkamaiOPEN-edgegrid-golang/v13/pkg/session"
910
validation "github.com/go-ozzo/ozzo-validation/v4"
@@ -70,8 +71,7 @@ func (v UpdatePenaltyBoxRequest) Validate() error {
7071
"ConfigID": validation.Validate(v.ConfigID, validation.Required),
7172
"Version": validation.Validate(v.Version, validation.Required),
7273
"PolicyID": validation.Validate(v.PolicyID, validation.Required),
73-
"Action": validation.Validate(v.Action, validation.Required, validation.In(string(ActionTypeAlert), string(ActionTypeDeny), string(ActionTypeNone)).Error(
74-
fmt.Sprintf("value '%s' is invalid. Must be one of: 'alert', 'deny' or 'none'", v.Action))),
74+
"Action": validation.Validate(v.Action, validation.Required, validateActions),
7575
}.Filter()
7676
}
7777

@@ -141,3 +141,20 @@ func (p *appsec) UpdatePenaltyBox(ctx context.Context, params UpdatePenaltyBoxRe
141141

142142
return &result, nil
143143
}
144+
145+
// validateActions ensures actions are correct for API call.
146+
// Allowed values: alert, deny, deny_custom_{custom_deny_id}, none.
147+
var validateActions = validation.By(func(value interface{}) error {
148+
v, ok := value.(string)
149+
if !ok {
150+
return fmt.Errorf("value must be a string")
151+
}
152+
allowed := map[string]bool{"alert": true, "deny": true, "none": true}
153+
if allowed[v] {
154+
return nil
155+
}
156+
if !strings.HasPrefix(v, "deny_custom_") || strings.TrimPrefix(v, "deny_custom_") == "" {
157+
return fmt.Errorf("value '%s' is invalid. Must be one of: alert, deny, deny_custom_{custom_deny_id}, none", v)
158+
}
159+
return nil
160+
})

pkg/appsec/penalty_box_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,107 @@ func TestAppSec_UpdatePenaltyBox(t *testing.T) {
173173
})
174174
}
175175
}
176+
177+
func TestGetPenaltyBoxRequest_Validate(t *testing.T) {
178+
tests := map[string]struct {
179+
req GetPenaltyBoxRequest
180+
withError string
181+
}{
182+
"valid request - all fields populated": {
183+
req: GetPenaltyBoxRequest{
184+
ConfigID: 43253,
185+
Version: 15,
186+
PolicyID: "AAAA_81230",
187+
},
188+
},
189+
"missing all required fields": {
190+
req: GetPenaltyBoxRequest{},
191+
withError: "ConfigID: cannot be blank; PolicyID: cannot be blank; Version: cannot be blank.",
192+
},
193+
}
194+
195+
for name, test := range tests {
196+
t.Run(name, func(t *testing.T) {
197+
err := test.req.Validate()
198+
if test.withError != "" {
199+
assert.EqualError(t, err, test.withError)
200+
return
201+
}
202+
require.NoError(t, err)
203+
})
204+
}
205+
}
206+
207+
func TestUpdatePenaltyBoxRequest_Validate(t *testing.T) {
208+
tests := map[string]struct {
209+
req UpdatePenaltyBoxRequest
210+
withError string
211+
}{
212+
"valid request - all fields populated": {
213+
req: UpdatePenaltyBoxRequest{
214+
ConfigID: 43253,
215+
Version: 15,
216+
PolicyID: "AAAA_81230",
217+
Action: string(ActionTypeDeny),
218+
PenaltyBoxProtection: true,
219+
},
220+
},
221+
"valid request - action alert": {
222+
req: UpdatePenaltyBoxRequest{
223+
ConfigID: 43253,
224+
Version: 15,
225+
PolicyID: "AAAA_81230",
226+
Action: string(ActionTypeAlert),
227+
},
228+
},
229+
"valid request - action none": {
230+
req: UpdatePenaltyBoxRequest{
231+
ConfigID: 43253,
232+
Version: 15,
233+
PolicyID: "AAAA_81230",
234+
Action: string(ActionTypeNone),
235+
},
236+
},
237+
"valid request - deny_custom_ ": {
238+
req: UpdatePenaltyBoxRequest{
239+
ConfigID: 43253,
240+
Version: 15,
241+
PolicyID: "AAAA_81230",
242+
Action: "deny_custom_1012254",
243+
},
244+
},
245+
"invalid action": {
246+
req: UpdatePenaltyBoxRequest{
247+
ConfigID: 43253,
248+
Version: 15,
249+
PolicyID: "AAAA_81230",
250+
Action: "invalid_action",
251+
},
252+
withError: "Action: value 'invalid_action' is invalid. Must be one of: alert, deny, deny_custom_{custom_deny_id}, none.",
253+
},
254+
"invalid action - deny_custom_ with blank id": {
255+
req: UpdatePenaltyBoxRequest{
256+
ConfigID: 43253,
257+
Version: 15,
258+
PolicyID: "AAAA_81230",
259+
Action: "deny_custom_",
260+
},
261+
withError: "Action: value 'deny_custom_' is invalid. Must be one of: alert, deny, deny_custom_{custom_deny_id}, none.",
262+
},
263+
"missing all required fields": {
264+
req: UpdatePenaltyBoxRequest{},
265+
withError: "Action: cannot be blank; ConfigID: cannot be blank; PolicyID: cannot be blank; Version: cannot be blank.",
266+
},
267+
}
268+
269+
for name, test := range tests {
270+
t.Run(name, func(t *testing.T) {
271+
err := test.req.Validate()
272+
if test.withError != "" {
273+
assert.EqualError(t, err, test.withError)
274+
return
275+
}
276+
require.NoError(t, err)
277+
})
278+
}
279+
}

pkg/appsec/security_policy_protections.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,19 @@ type (
3232

3333
// UpdatePolicyProtectionsRequest is used to modify the policy protection setting.
3434
UpdatePolicyProtectionsRequest struct {
35-
ConfigID int `json:"-"`
36-
Version int `json:"-"`
37-
PolicyID string `json:"-"`
38-
ApplyAPIConstraints bool `json:"applyApiConstraints"`
39-
ApplyApplicationLayerControls bool `json:"applyApplicationLayerControls"`
40-
ApplyBotmanControls bool `json:"applyBotmanControls"`
41-
ApplyNetworkLayerControls bool `json:"applyNetworkLayerControls"`
42-
ApplyRateControls bool `json:"applyRateControls"`
43-
ApplyReputationControls bool `json:"applyReputationControls"`
44-
ApplySlowPostControls bool `json:"applySlowPostControls"`
45-
ApplyURLProtectionControls bool `json:"applyUrlProtectionControls"`
46-
ApplyMalwareControls bool `json:"applyMalwareControls"`
35+
ConfigID int `json:"-"`
36+
Version int `json:"-"`
37+
PolicyID string `json:"-"`
38+
ApplyAPIConstraints bool `json:"applyApiConstraints"`
39+
ApplyAccountProtectionControls bool `json:"applyAccountProtectionControls"`
40+
ApplyApplicationLayerControls bool `json:"applyApplicationLayerControls"`
41+
ApplyBotmanControls bool `json:"applyBotmanControls"`
42+
ApplyNetworkLayerControls bool `json:"applyNetworkLayerControls"`
43+
ApplyRateControls bool `json:"applyRateControls"`
44+
ApplyReputationControls bool `json:"applyReputationControls"`
45+
ApplySlowPostControls bool `json:"applySlowPostControls"`
46+
ApplyURLProtectionControls bool `json:"applyUrlProtectionControls"`
47+
ApplyMalwareControls bool `json:"applyMalwareControls"`
4748
}
4849

4950
// PolicyProtectionsResponse is returned from GetPolicyProtections, UpdatePolicyProtections, and RemovePolicyProtections.
@@ -139,7 +140,7 @@ func (p *appsec) UpdatePolicyProtections(ctx context.Context, params UpdatePolic
139140
}
140141
defer session.CloseResponseBody(resp)
141142

142-
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
143+
if resp.StatusCode != http.StatusOK {
143144
return nil, p.Error(resp)
144145
}
145146

pkg/appsec/security_policy_protections_test.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,6 @@ func TestAppSec_UpdatePolicyProtections(t *testing.T) {
9393
err := json.Unmarshal([]byte(respData), &result)
9494
require.NoError(t, err)
9595

96-
req := UpdatePolicyProtectionsRequest{}
97-
98-
reqData := compactJSON(loadFixtureBytes("testdata/TestPolicyProtections/PolicyProtections.json"))
99-
err = json.Unmarshal([]byte(reqData), &req)
100-
require.NoError(t, err)
101-
10296
tests := map[string]struct {
10397
params UpdatePolicyProtectionsRequest
10498
responseStatus int
@@ -110,14 +104,24 @@ func TestAppSec_UpdatePolicyProtections(t *testing.T) {
110104
}{
111105
"200 Success": {
112106
params: UpdatePolicyProtectionsRequest{
113-
ConfigID: 43253,
114-
Version: 15,
115-
PolicyID: "AAAA_81230",
107+
ConfigID: 43253,
108+
Version: 15,
109+
PolicyID: "AAAA_81230",
110+
ApplyAPIConstraints: true,
111+
ApplyAccountProtectionControls: true,
112+
ApplyApplicationLayerControls: true,
113+
ApplyBotmanControls: true,
114+
ApplyNetworkLayerControls: true,
115+
ApplyRateControls: true,
116+
ApplyReputationControls: true,
117+
ApplySlowPostControls: true,
118+
ApplyMalwareControls: true,
119+
ApplyURLProtectionControls: true,
116120
},
117121
headers: http.Header{
118122
"Content-Type": []string{"application/json;charset=UTF-8"},
119123
},
120-
responseStatus: http.StatusCreated,
124+
responseStatus: http.StatusOK,
121125
responseBody: respData,
122126
expectedResponse: &result,
123127
expectedPath: "/appsec/v1/configs/43253/versions/15/security-policies/AAAA_81230/protections",

pkg/cloudcertificates/errors.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ var (
5252
)
5353

5454
type (
55-
// Error is a CloudCertificates error interface.
55+
// Error represents an error returned by the Cloud Certificates API.
5656
Error struct {
5757
Type string `json:"type"`
5858
Title string `json:"title"`

pkg/edgeworkers/activations.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type (
2626

2727
// ActivateVersion represents the request body used to activate a version
2828
ActivateVersion struct {
29+
AutoPin *bool `json:"autoPin,omitempty"`
2930
Network ActivationNetwork `json:"network"`
3031
Version string `json:"version"`
3132
Note string `json:"note,omitempty"`

0 commit comments

Comments
 (0)