From ec51561d10af18ff57b3c1f58a649bc1490b6ffc Mon Sep 17 00:00:00 2001 From: sha-e-256 <105937174+sha-e-256@users.noreply.github.com> Date: Sun, 28 Jul 2024 21:33:07 -0400 Subject: [PATCH 01/84] feat: add flag to skip the app launcher landing pg --- .changelog/2793.txt | 3 +++ access_application.go | 11 ++++++----- access_application_test.go | 5 ++++- 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 .changelog/2793.txt diff --git a/.changelog/2793.txt b/.changelog/2793.txt new file mode 100644 index 00000000000..ee91155c4a0 --- /dev/null +++ b/.changelog/2793.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/access_application: add `skip_app_launcher_login_page` flag to skip the App Launcher landing page +``` diff --git a/access_application.go b/access_application.go index bdeaf79cd8d..ec1dfcc62eb 100644 --- a/access_application.go +++ b/access_application.go @@ -250,11 +250,12 @@ type SaasApplication struct { } type AccessAppLauncherCustomization struct { - LandingPageDesign AccessLandingPageDesign `json:"landing_page_design"` - LogoURL string `json:"app_launcher_logo_url"` - HeaderBackgroundColor string `json:"header_bg_color"` - BackgroundColor string `json:"bg_color"` - FooterLinks []AccessFooterLink `json:"footer_links"` + LandingPageDesign AccessLandingPageDesign `json:"landing_page_design"` + LogoURL string `json:"app_launcher_logo_url"` + HeaderBackgroundColor string `json:"header_bg_color"` + BackgroundColor string `json:"bg_color"` + FooterLinks []AccessFooterLink `json:"footer_links"` + SkipAppLauncherLoginPage *bool `json:"skip_app_launcher_login_page,omitempty"` } type AccessFooterLink struct { diff --git a/access_application_test.go b/access_application_test.go index 1783863950b..d4308560883 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -1292,7 +1292,8 @@ func TestCreateApplicationWithAccessAppLauncherCustomization(t *testing.T) { "url": "https://somesite.com", "name": "bug" } - ] + ], + "skip_app_launcher_login_page": true } } `) @@ -1332,6 +1333,7 @@ func TestCreateApplicationWithAccessAppLauncherCustomization(t *testing.T) { Name: "bug", }, }, + SkipAppLauncherLoginPage: BoolPtr(true), }, } @@ -1357,6 +1359,7 @@ func TestCreateApplicationWithAccessAppLauncherCustomization(t *testing.T) { Name: "bug", }, }, + SkipAppLauncherLoginPage: BoolPtr(true), }, }) From 369a946b44f1d09103df0a9f42d9e0f4ae931b09 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 31 Jul 2024 12:45:41 +1000 Subject: [PATCH 02/84] Update .changelog/2793.txt --- .changelog/2793.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/2793.txt b/.changelog/2793.txt index ee91155c4a0..af48c245270 100644 --- a/.changelog/2793.txt +++ b/.changelog/2793.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -resource/access_application: add `skip_app_launcher_login_page` flag to skip the App Launcher landing page +access_application: add `skip_app_launcher_login_page` flag to skip the App Launcher landing page ``` From 64c544438be728032b6c24748e40bc7c97f3af89 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 31 Jul 2024 13:07:20 +1000 Subject: [PATCH 03/84] generate changelog --- CHANGELOG.md | 11 +++++++++++ scripts/generate-changelog.sh | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7b8fa6513e..7859c4e98a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ ## 0.101.0 (Unreleased) +ENHANCEMENTS: + +* access_application: add `skip_app_launcher_login_page` flag to skip the App Launcher landing page ([#2793](https://github.com/cloudflare/cloudflare-go/issues/2793)) +* device_posture_rule: support extended_key_usage, check_private_key, and locations for client_certificate_v2 posture rule ([#1685](https://github.com/cloudflare/cloudflare-go/issues/1685)) +* devices_policy: Add new tunnel_protocol field to policy ([#2778](https://github.com/cloudflare/cloudflare-go/issues/2778)) +* risk_score_integration: Add support for Risk Score Integrations ([#2786](https://github.com/cloudflare/cloudflare-go/issues/2786)) + +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.27.2 to 2.27.3 ([#2787](https://github.com/cloudflare/cloudflare-go/issues/2787)) + ## 0.100.0 (July 18th, 2024) BREAKING CHANGES: diff --git a/scripts/generate-changelog.sh b/scripts/generate-changelog.sh index dbd0c3775f5..a9748eef161 100755 --- a/scripts/generate-changelog.sh +++ b/scripts/generate-changelog.sh @@ -24,7 +24,7 @@ then exit 1 fi -CHANGELOG=$($(go env GOPATH)/bin/changelog-build -this-release $TARGET_SHA \ +CHANGELOG=$(changelog-build -this-release $TARGET_SHA \ -last-release $PREVIOUS_RELEASE_SHA \ -git-dir $__parent \ -entries-dir .changelog \ From 217ab498974fbfeba3fd6a967f274cc13eab8af9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 31 Jul 2024 13:07:55 +1000 Subject: [PATCH 04/84] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7859c4e98a5..c13af7ce6bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.101.0 (Unreleased) +## 0.102.0 (Unreleased) + +## 0.101.0 (July 31st, 2024) ENHANCEMENTS: From 2a55e876353f2280995e68fc3e3f5d82458fc02b Mon Sep 17 00:00:00 2001 From: Emilio Assuncao Date: Thu, 1 Aug 2024 16:58:17 -0500 Subject: [PATCH 05/84] Add support for hyperdrive workers bindings --- .changelog/2794.txt | 3 +++ workers_bindings.go | 29 +++++++++++++++++++++++++++++ workers_bindings_test.go | 20 ++++++++++++++++++-- workers_test.go | 5 +++++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 .changelog/2794.txt diff --git a/.changelog/2794.txt b/.changelog/2794.txt new file mode 100644 index 00000000000..2ab3e98f4d1 --- /dev/null +++ b/.changelog/2794.txt @@ -0,0 +1,3 @@ +```release-notes:enhancement +worker_bindings: add support for `hyperdrive` bindings +``` \ No newline at end of file diff --git a/workers_bindings.go b/workers_bindings.go index 0516c5b3f72..9a49cf865ac 100644 --- a/workers_bindings.go +++ b/workers_bindings.go @@ -46,6 +46,8 @@ const ( DispatchNamespaceBindingType WorkerBindingType = "dispatch_namespace" // WorkerD1DataseBindingType is for D1 databases. WorkerD1DataseBindingType WorkerBindingType = "d1" + // WorkerHyperdriveBindingType is for Hyperdrive config bindings. + WorkerHyperdriveBindingType WorkerBindingType = "hyperdrive" ) type ListWorkerBindingsParams struct { @@ -433,6 +435,28 @@ func (b WorkerD1DatabaseBinding) serialize(bindingName string) (workerBindingMet }, nil, nil } +// WorkerHyperdriveBinding is a binding to a Hyperdrive config. +type WorkerHyperdriveBinding struct { + ConfigID string +} + +// Type returns the type of the binding. +func (b WorkerHyperdriveBinding) Type() WorkerBindingType { + return WorkerHyperdriveBindingType +} + +func (b WorkerHyperdriveBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.ConfigID == "" { + return nil, nil, fmt.Errorf(`config ID for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "id": b.ConfigID, + }, nil, nil +} + // UnsafeBinding is for experimental or deprecated bindings, and allows specifying any binding type or property. type UnsafeBinding map[string]interface{} @@ -562,6 +586,11 @@ func (api *API) ListWorkerBindings(ctx context.Context, rc *ResourceContainer, p bindingListItem.Binding = WorkerD1DatabaseBinding{ DatabaseID: database_id, } + case WorkerHyperdriveBindingType: + id := jsonBinding["id"].(string) + bindingListItem.Binding = WorkerHyperdriveBinding{ + ConfigID: id, + } default: bindingListItem.Binding = WorkerInheritBinding{} } diff --git a/workers_bindings_test.go b/workers_bindings_test.go index bb7f141fa8b..f747eabf106 100644 --- a/workers_bindings_test.go +++ b/workers_bindings_test.go @@ -35,7 +35,7 @@ func TestListWorkerBindings(t *testing.T) { assert.NoError(t, err) assert.Equal(t, successResponse, res.Response) - assert.Equal(t, 9, len(res.BindingList)) + assert.Equal(t, 10, len(res.BindingList)) assert.Equal(t, res.BindingList[0], WorkerBindingListItem{ Name: "MY_KV", @@ -106,6 +106,14 @@ func TestListWorkerBindings(t *testing.T) { }, }) assert.Equal(t, WorkerD1DataseBindingType, res.BindingList[8].Binding.Type()) + + assert.Equal(t, res.BindingList[9], WorkerBindingListItem{ + Name: "MY_HYPERDRIVE", + Binding: WorkerHyperdriveBinding{ + ConfigID: "aaf4609248cc493cbc8d3e446e38fdfa", + }, + }) + assert.Equal(t, WorkerHyperdriveBindingType, res.BindingList[9].Binding.Type()) } func TestListWorkerBindings_Wfp(t *testing.T) { @@ -125,7 +133,7 @@ func TestListWorkerBindings_Wfp(t *testing.T) { assert.NoError(t, err) assert.Equal(t, successResponse, res.Response) - assert.Equal(t, 9, len(res.BindingList)) + assert.Equal(t, 10, len(res.BindingList)) assert.Equal(t, res.BindingList[0], WorkerBindingListItem{ Name: "MY_KV", @@ -191,6 +199,14 @@ func TestListWorkerBindings_Wfp(t *testing.T) { }, }) assert.Equal(t, WorkerD1DataseBindingType, res.BindingList[8].Binding.Type()) + + assert.Equal(t, res.BindingList[9], WorkerBindingListItem{ + Name: "MY_HYPERDRIVE", + Binding: WorkerHyperdriveBinding{ + ConfigID: "aaf4609248cc493cbc8d3e446e38fdfa", + }, + }) + assert.Equal(t, WorkerHyperdriveBindingType, res.BindingList[9].Binding.Type()) } func ExampleUnsafeBinding() { diff --git a/workers_test.go b/workers_test.go index 6175440a130..ef0e09987a6 100644 --- a/workers_test.go +++ b/workers_test.go @@ -145,6 +145,11 @@ const ( "name": "MY_DATABASE", "type": "d1", "database_id": "cef5331f-e5c7-4c8a-a415-7908ae45f92a" + }, + { + "name": "MY_HYPERDRIVE", + "type": "hyperdrive", + "id": "aaf4609248cc493cbc8d3e446e38fdfa" } ], "success": true, From bd8437df2e165a45b9a0e3df72b2345021b92fd9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 2 Aug 2024 12:32:33 +1000 Subject: [PATCH 06/84] Rename 2794.txt to 2812.txt --- .changelog/{2794.txt => 2812.txt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .changelog/{2794.txt => 2812.txt} (95%) diff --git a/.changelog/2794.txt b/.changelog/2812.txt similarity index 95% rename from .changelog/2794.txt rename to .changelog/2812.txt index 2ab3e98f4d1..f9d178c0ed5 100644 --- a/.changelog/2794.txt +++ b/.changelog/2812.txt @@ -1,3 +1,3 @@ ```release-notes:enhancement worker_bindings: add support for `hyperdrive` bindings -``` \ No newline at end of file +``` From 1de2ed68ad71a12c350b3530d70d4536d3471a67 Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Wed, 7 Aug 2024 09:42:28 -0400 Subject: [PATCH 07/84] feature(Ruleset): Add DeleteRulesetRule() --- rulesets.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rulesets.go b/rulesets.go index 8b1ad430a56..b67c3889896 100644 --- a/rulesets.go +++ b/rulesets.go @@ -886,3 +886,24 @@ func (api *API) UpdateEntrypointRuleset(ctx context.Context, rc *ResourceContain return result.Result, nil } + +// DeleteRulesetRule removes a ruleset rule based on the ruleset ID + +// ruleset rule ID. +// +// API reference: https://developers.cloudflare.com/api/operations/deleteZoneRulesetRule +func (api *API) DeleteRulesetRule(ctx context.Context, rc *ResourceContainer, rulesetID, rulesetRuleID string) error { + uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, rulesetID, rulesetRuleID) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return err + } + + // The API is not implementing the standard response blob but returns an + // empty response (204) in case of a success. So we are checking for the + // response body size here. + if len(res) > 0 { + return fmt.Errorf(errMakeRequestError+": %w", errors.New(string(res))) + } + + return nil +} From 28cd78476f47d2ffd4351e037060036bcf48d2f0 Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Wed, 7 Aug 2024 09:55:18 -0400 Subject: [PATCH 08/84] move fn to match code style --- rulesets.go | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/rulesets.go b/rulesets.go index b67c3889896..80d91996d9c 100644 --- a/rulesets.go +++ b/rulesets.go @@ -844,6 +844,27 @@ func (api *API) UpdateRuleset(ctx context.Context, rc *ResourceContainer, params return result.Result, nil } +// DeleteRulesetRule removes a ruleset rule based on the ruleset ID + +// ruleset rule ID. +// +// API reference: https://developers.cloudflare.com/api/operations/deleteZoneRulesetRule +func (api *API) DeleteRulesetRule(ctx context.Context, rc *ResourceContainer, rulesetID, rulesetRuleID string) error { + uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, rulesetID, rulesetRuleID) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return err + } + + // The API is not implementing the standard response blob but returns an + // empty response (204) in case of a success. So we are checking for the + // response body size here. + if len(res) > 0 { + return fmt.Errorf(errMakeRequestError+": %w", errors.New(string(res))) + } + + return nil +} + // GetEntrypointRuleset returns an entry point ruleset base on the phase. // // API reference: https://developers.cloudflare.com/api/operations/getAccountEntrypointRuleset @@ -886,24 +907,3 @@ func (api *API) UpdateEntrypointRuleset(ctx context.Context, rc *ResourceContain return result.Result, nil } - -// DeleteRulesetRule removes a ruleset rule based on the ruleset ID + -// ruleset rule ID. -// -// API reference: https://developers.cloudflare.com/api/operations/deleteZoneRulesetRule -func (api *API) DeleteRulesetRule(ctx context.Context, rc *ResourceContainer, rulesetID, rulesetRuleID string) error { - uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, rulesetID, rulesetRuleID) - res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) - if err != nil { - return err - } - - // The API is not implementing the standard response blob but returns an - // empty response (204) in case of a success. So we are checking for the - // response body size here. - if len(res) > 0 { - return fmt.Errorf(errMakeRequestError+": %w", errors.New(string(res))) - } - - return nil -} From ce9234bd05f2450d3e28e39d66c6014c3d5fbbb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:57:18 +0000 Subject: [PATCH 09/84] Bump golang.org/x/net from 0.27.0 to 0.28.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.27.0 to 0.28.0. - [Commits](https://github.com/golang/net/compare/v0.27.0...v0.28.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c2e4badccba..dd60915d7a6 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.3 - golang.org/x/net v0.27.0 + golang.org/x/net v0.28.0 golang.org/x/time v0.5.0 ) @@ -25,6 +25,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/text v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 09d6cc2e914..0c4773e285c 100644 --- a/go.sum +++ b/go.sum @@ -39,10 +39,10 @@ github.com/urfave/cli/v2 v2.27.3 h1:/POWahRmdh7uztQ3CYnaDddk0Rm90PyOgIxgW2rr41M= github.com/urfave/cli/v2 v2.27.3/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 591cd13b0a814be68e24cc799638132a21a8613c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 7 Aug 2024 16:57:33 +0000 Subject: [PATCH 10/84] add CHANGELOG for #2835 --- .changelog/2835.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2835.txt diff --git a/.changelog/2835.txt b/.changelog/2835.txt new file mode 100644 index 00000000000..1071fa6bcbf --- /dev/null +++ b/.changelog/2835.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.27.0 to 0.28.0 +``` From a8304bf53b4f2153b0df56f8d4fdea3347ee2c20 Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Wed, 7 Aug 2024 14:14:14 -0400 Subject: [PATCH 11/84] Add changelog --- .changelog/2833.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/2833.txt diff --git a/.changelog/2833.txt b/.changelog/2833.txt new file mode 100644 index 00000000000..25c9976db3d --- /dev/null +++ b/.changelog/2833.txt @@ -0,0 +1,2 @@ +release-note:enhancement +Add DeleteRulesetRule() From 1f9a88425c06fec96d00bd3829173b95c030059f Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Wed, 7 Aug 2024 14:19:01 -0400 Subject: [PATCH 12/84] Update changelog --- .changelog/2833.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/2833.txt b/.changelog/2833.txt index 25c9976db3d..2cdf8101e80 100644 --- a/.changelog/2833.txt +++ b/.changelog/2833.txt @@ -1,2 +1,2 @@ release-note:enhancement -Add DeleteRulesetRule() +rulesets: Add DeleteRulesetRule() function From 0ad1a1e016a751ad36eca2ef42a52a587e3a33de Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 8 Aug 2024 14:15:26 +1000 Subject: [PATCH 13/84] update changelog --- .changelog/2833.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.changelog/2833.txt b/.changelog/2833.txt index 2cdf8101e80..00633a04e66 100644 --- a/.changelog/2833.txt +++ b/.changelog/2833.txt @@ -1,2 +1,3 @@ -release-note:enhancement -rulesets: Add DeleteRulesetRule() function +```release-note:enhancement +rulesets: Add `DeleteRulesetRule` +``` From aa359a15c8688648135d7d1d65b334ae46ce25d3 Mon Sep 17 00:00:00 2001 From: Matt Provost Date: Wed, 7 Aug 2024 16:27:09 -0500 Subject: [PATCH 14/84] fix: remove empty access application attributes Signed-off-by: Matt Provost --- .changelog/2838.txt | 3 +++ access_application.go | 20 ++++++++++---------- access_application_test.go | 8 ++++---- 3 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 .changelog/2838.txt diff --git a/.changelog/2838.txt b/.changelog/2838.txt new file mode 100644 index 00000000000..4a9c03ec0e6 --- /dev/null +++ b/.changelog/2838.txt @@ -0,0 +1,3 @@ +```release-notes:bug +access_application: enable removing access application custom attributes and claims +``` diff --git a/access_application.go b/access_application.go index ec1dfcc62eb..def62c0b870 100644 --- a/access_application.go +++ b/access_application.go @@ -224,15 +224,15 @@ type SaasApplication struct { AuthType string `json:"auth_type,omitempty"` // SAML saas app - ConsumerServiceUrl string `json:"consumer_service_url,omitempty"` - SPEntityID string `json:"sp_entity_id,omitempty"` - IDPEntityID string `json:"idp_entity_id,omitempty"` - NameIDFormat string `json:"name_id_format,omitempty"` - SSOEndpoint string `json:"sso_endpoint,omitempty"` - DefaultRelayState string `json:"default_relay_state,omitempty"` - CustomAttributes []SAMLAttributeConfig `json:"custom_attributes,omitempty"` - NameIDTransformJsonata string `json:"name_id_transform_jsonata,omitempty"` - SamlAttributeTransformJsonata string `json:"saml_attribute_transform_jsonata"` + ConsumerServiceUrl string `json:"consumer_service_url,omitempty"` + SPEntityID string `json:"sp_entity_id,omitempty"` + IDPEntityID string `json:"idp_entity_id,omitempty"` + NameIDFormat string `json:"name_id_format,omitempty"` + SSOEndpoint string `json:"sso_endpoint,omitempty"` + DefaultRelayState string `json:"default_relay_state,omitempty"` + CustomAttributes *[]SAMLAttributeConfig `json:"custom_attributes"` + NameIDTransformJsonata string `json:"name_id_transform_jsonata,omitempty"` + SamlAttributeTransformJsonata string `json:"saml_attribute_transform_jsonata"` // OIDC saas app ClientID string `json:"client_id,omitempty"` @@ -242,7 +242,7 @@ type SaasApplication struct { Scopes []string `json:"scopes,omitempty"` AppLauncherURL string `json:"app_launcher_url,omitempty"` GroupFilterRegex string `json:"group_filter_regex,omitempty"` - CustomClaims []OIDCClaimConfig `json:"custom_claims,omitempty"` + CustomClaims *[]OIDCClaimConfig `json:"custom_claims"` AllowPKCEWithoutClientSecret *bool `json:"allow_pkce_without_client_secret,omitempty"` RefreshTokenOptions *RefreshTokenOptions `json:"refresh_token_options,omitempty"` HybridAndImplicitOptions *AccessApplicationHybridAndImplicitOptions `json:"hybrid_and_implicit_options,omitempty"` diff --git a/access_application_test.go b/access_application_test.go index d4308560883..50f2c7e6686 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -1011,7 +1011,7 @@ func TestCreateSAMLSaasAccessApplications(t *testing.T) { SPEntityID: "dash.example.com", NameIDFormat: "id", DefaultRelayState: "https://saas.example.com", - CustomAttributes: []SAMLAttributeConfig{ + CustomAttributes: &[]SAMLAttributeConfig{ { Name: "test1", NameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", @@ -1166,7 +1166,7 @@ func TestCreateOIDCSaasAccessApplications(t *testing.T) { AppLauncherURL: "https://saas.example.com", GroupFilterRegex: ".*", AllowPKCEWithoutClientSecret: BoolPtr(false), - CustomClaims: []OIDCClaimConfig{ + CustomClaims: &[]OIDCClaimConfig{ { Name: "test1", Source: SourceConfig{Name: "test1"}, @@ -1197,7 +1197,7 @@ func TestCreateOIDCSaasAccessApplications(t *testing.T) { AppLauncherURL: "https://saas.example.com", GroupFilterRegex: ".*", AllowPKCEWithoutClientSecret: BoolPtr(false), - CustomClaims: []OIDCClaimConfig{ + CustomClaims: &[]OIDCClaimConfig{ { Name: "test1", Source: SourceConfig{Name: "test1"}, @@ -1229,7 +1229,7 @@ func TestCreateOIDCSaasAccessApplications(t *testing.T) { AppLauncherURL: "https://saas.example.com", GroupFilterRegex: ".*", AllowPKCEWithoutClientSecret: BoolPtr(false), - CustomClaims: []OIDCClaimConfig{ + CustomClaims: &[]OIDCClaimConfig{ { Name: "test1", Source: SourceConfig{Name: "test1"}, From 4ebdf6a694c529e0a603d3a1d98cb38759c28021 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 9 Aug 2024 12:58:37 +1000 Subject: [PATCH 15/84] refactor: shuffle params into a struct --- rulesets.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rulesets.go b/rulesets.go index 80d91996d9c..b58a4eec822 100644 --- a/rulesets.go +++ b/rulesets.go @@ -741,6 +741,11 @@ type UpdateEntrypointRulesetParams struct { Rules []RulesetRule `json:"rules"` } +type DeleteRulesetRuleParams struct { + rulesetID string `json:"-"` + rulesetRuleID string `json:"-"` +} + // ListRulesets lists all Rulesets in a given zone or account depending on the // ResourceContainer type provided. // @@ -848,8 +853,8 @@ func (api *API) UpdateRuleset(ctx context.Context, rc *ResourceContainer, params // ruleset rule ID. // // API reference: https://developers.cloudflare.com/api/operations/deleteZoneRulesetRule -func (api *API) DeleteRulesetRule(ctx context.Context, rc *ResourceContainer, rulesetID, rulesetRuleID string) error { - uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, rulesetID, rulesetRuleID) +func (api *API) DeleteRulesetRule(ctx context.Context, rc *ResourceContainer, params DeleteRulesetRuleParams) error { + uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, params.rulesetID, params.rulesetRuleID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err From a36975dfd297718d47c20e6c707aa1787f5218a0 Mon Sep 17 00:00:00 2001 From: Yawar Jamal Date: Fri, 9 Aug 2024 16:49:44 -0500 Subject: [PATCH 16/84] add automatic ssl mode setting support --- .changelog/2855.txt | 3 +++ zone.go | 50 +++++++++++++++++++++++++++++++++++++++++- zone_test.go | 53 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 .changelog/2855.txt diff --git a/.changelog/2855.txt b/.changelog/2855.txt new file mode 100644 index 00000000000..614807de5c4 --- /dev/null +++ b/.changelog/2855.txt @@ -0,0 +1,3 @@ +```release-notes:enhancement +ssl: add support for ssl/tls automatic mode setting +``` diff --git a/zone.go b/zone.go index de92880a157..7be43400a51 100644 --- a/zone.go +++ b/zone.go @@ -174,8 +174,22 @@ type ZoneSSLSetting struct { CertificateStatus string `json:"certificate_status"` } +// ZoneAutomaticSSLModeSetting contains automatic ssl mode +type ZoneAutomaticSSLModeSetting struct { + ID string `json:"id"` + Editable bool `json:"editable"` + ModifiedOn string `json:"modified_on"` + Value string `json:"value"` + NextScheduledScan string `json:"next_scheduled_scan"` +} + +// ZoneAutomaticSSLModeSettingResponse represents the response from the Zone automatic SSL mode setting +type ZoneAutomaticSSLModeSettingResponse struct { + Response + Result ZoneAutomaticSSLModeSetting `json:"result"` +} + // ZoneSSLSettingResponse represents the response from the Zone SSL Setting -// endpoint. type ZoneSSLSettingResponse struct { Response Result ZoneSSLSetting `json:"result"` @@ -848,6 +862,23 @@ func (api *API) ZoneSSLSettings(ctx context.Context, zoneID string) (ZoneSSLSett return r.Result, nil } +// ZoneSSLSettings returns information about SSL setting to the specified zone. +// +// API reference: https://api.cloudflare.com/#zone-settings-get-automatic-ssl-mode-setting +func (api *API) ZoneAutomaticSSLModeSetting(ctx context.Context, zoneID string) (ZoneAutomaticSSLModeSetting, error) { + uri := fmt.Sprintf("/zones/%s/settings/ssl_automatic_mode", zoneID) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return ZoneAutomaticSSLModeSetting{}, err + } + var r ZoneAutomaticSSLModeSettingResponse + err = json.Unmarshal(res, &r) + if err != nil { + return ZoneAutomaticSSLModeSetting{}, fmt.Errorf("%s: %s %w", errUnmarshalError, string(res), err) + } + return r.Result, nil +} + // UpdateZoneSSLSettings update information about SSL setting to the specified zone. // // API reference: https://api.cloudflare.com/#zone-settings-change-ssl-setting @@ -865,6 +896,23 @@ func (api *API) UpdateZoneSSLSettings(ctx context.Context, zoneID string, sslVal return r.Result, nil } +// UpdateZoneAutomaticSSLSettingMode update information about Automatic SSL mode setting to the specified zone. +// +// API reference: https://api.cloudflare.com/[#-add-url-slug-here] +func (api *API) UpdateZoneAutomaticSSLSettingMode(ctx context.Context, zoneID, mode string) (ZoneSSLSetting, error) { + uri := fmt.Sprintf("/zones/%s/settings/ssl_automatic_mode", zoneID) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, ZoneSSLSetting{Value: mode}) + if err != nil { + return ZoneSSLSetting{}, err + } + var r ZoneSSLSettingResponse + err = json.Unmarshal(res, &r) + if err != nil { + return ZoneSSLSetting{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + // FallbackOrigin returns information about the fallback origin for the specified zone. // // API reference: https://developers.cloudflare.com/ssl/ssl-for-saas/api-calls/#fallback-origin-configuration diff --git a/zone_test.go b/zone_test.go index d8b94cd1c65..459e871fcf8 100644 --- a/zone_test.go +++ b/zone_test.go @@ -1511,6 +1511,59 @@ func TestUpdateZoneSSLSettings(t *testing.T) { } } +func TestUpdateZoneAutomaticSSLModeSetting(t *testing.T) { + setup() + defer teardown() + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) + w.Header().Set("content-type", "application/json") + // JSON data from: https://api.cloudflare.com/#zone-settings-properties + _, _ = fmt.Fprintf(w, `{ + "result": { + "id": "ssl_automatic_mode", + "value": "auto", + "editable": true, + "modified_on": "2014-01-01T05:20:00.12345Z" + } + }`) + } + mux.HandleFunc("/zones/foo/settings/ssl_automatic_mode", handler) + s, err := client.UpdateZoneAutomaticSSLSettingMode(context.Background(), "foo", "auto") + if assert.NoError(t, err) { + assert.Equal(t, s.ID, "ssl_automatic_mode") + assert.Equal(t, s.Value, "auto") + assert.Equal(t, s.Editable, true) + assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + } +} + +func TestGetZoneAutomaticSSLModeSetting(t *testing.T) { + setup() + defer teardown() + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + _, _ = fmt.Fprintf(w, `{ + "result": { + "id": "ssl_automatic_mode", + "value": "custom", + "editable": true, + "modified_on": "2014-01-01T05:20:00.12345Z", + "next_scheduled_scan": "2024-01-01T05:20:00.12345Z" + } + }`) + } + mux.HandleFunc("/zones/foo/settings/ssl_automatic_mode", handler) + s, err := client.ZoneAutomaticSSLModeSetting(context.Background(), "foo") + if assert.NoError(t, err) { + assert.Equal(t, s.ID, "ssl_automatic_mode") + assert.Equal(t, s.Value, "custom") + assert.Equal(t, s.Editable, true) + assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + assert.Equal(t, s.NextScheduledScan, "2024-01-01T05:20:00.12345Z") + } +} + func TestGetZoneSetting(t *testing.T) { setup() defer teardown() From 1fdd15f18057214e3f402adf88c49d490d5c94e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:07:19 +0000 Subject: [PATCH 17/84] Bump github.com/urfave/cli/v2 from 2.27.3 to 2.27.4 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.27.3 to 2.27.4. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.27.3...v2.27.4) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dd60915d7a6..04bdc813906 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/go-querystring v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.9.0 - github.com/urfave/cli/v2 v2.27.3 + github.com/urfave/cli/v2 v2.27.4 golang.org/x/net v0.28.0 golang.org/x/time v0.5.0 ) diff --git a/go.sum b/go.sum index 0c4773e285c..8ae0beb4a4f 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/urfave/cli/v2 v2.27.3 h1:/POWahRmdh7uztQ3CYnaDddk0Rm90PyOgIxgW2rr41M= -github.com/urfave/cli/v2 v2.27.3/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= +github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= +github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= From 2e036e7f20a26f3b9044563e46af77dc8403b3c1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 12 Aug 2024 16:07:33 +0000 Subject: [PATCH 18/84] add CHANGELOG for #2863 --- .changelog/2863.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2863.txt diff --git a/.changelog/2863.txt b/.changelog/2863.txt new file mode 100644 index 00000000000..93795789d3b --- /dev/null +++ b/.changelog/2863.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.27.3 to 2.27.4 +``` From de03d2390ce619747ccd408c42c3382f3b48a58e Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 13 Aug 2024 15:48:16 -0400 Subject: [PATCH 19/84] feature(Ruleset): Export fields of DeleteRulesetRuleParams --- rulesets.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rulesets.go b/rulesets.go index b58a4eec822..7136b8e9d80 100644 --- a/rulesets.go +++ b/rulesets.go @@ -742,8 +742,8 @@ type UpdateEntrypointRulesetParams struct { } type DeleteRulesetRuleParams struct { - rulesetID string `json:"-"` - rulesetRuleID string `json:"-"` + RulesetID string `json:"-"` + RulesetRuleID string `json:"-"` } // ListRulesets lists all Rulesets in a given zone or account depending on the From 91e8c9f166d08e5630a6f83e1c49d308ec6942a2 Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 13 Aug 2024 15:52:24 -0400 Subject: [PATCH 20/84] fixup! --- rulesets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rulesets.go b/rulesets.go index 7136b8e9d80..b9e36f8092f 100644 --- a/rulesets.go +++ b/rulesets.go @@ -854,7 +854,7 @@ func (api *API) UpdateRuleset(ctx context.Context, rc *ResourceContainer, params // // API reference: https://developers.cloudflare.com/api/operations/deleteZoneRulesetRule func (api *API) DeleteRulesetRule(ctx context.Context, rc *ResourceContainer, params DeleteRulesetRuleParams) error { - uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, params.rulesetID, params.rulesetRuleID) + uri := fmt.Sprintf("/%s/%s/rulesets/%s/rules/%s", rc.Level, rc.Identifier, params.RulesetID, params.RulesetRuleID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err From d0e24f15c4a9e9e18fa2260ea6cea8ce7a625a80 Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 13 Aug 2024 15:58:19 -0400 Subject: [PATCH 21/84] Add changelog --- .changelog/2886.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2886.txt diff --git a/.changelog/2886.txt b/.changelog/2886.txt new file mode 100644 index 00000000000..d87d819640f --- /dev/null +++ b/.changelog/2886.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +rulesets: Export `DeleteRulesetRuleParams` fields +``` From 7f0dcbc8034037f66a78ee015fee0a8f31245fe7 Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 13 Aug 2024 16:07:09 -0400 Subject: [PATCH 22/84] cosmetic(crlf): Fix CRLF line endings --- .changelog/1264.txt | 38 +++---- .changelog/1265.txt | 14 +-- .changelog/1319.txt | 118 +++++++++++----------- testdata/fixtures/tunnel/single_full.json | 50 ++++----- 4 files changed, 110 insertions(+), 110 deletions(-) diff --git a/.changelog/1264.txt b/.changelog/1264.txt index 55ed0957708..65b0d20e22d 100644 --- a/.changelog/1264.txt +++ b/.changelog/1264.txt @@ -1,19 +1,19 @@ -```release-note:breaking-change -pages_deployment: add support for auto pagination -``` - -```release-note:enchancement -pages_deployment: add Force to DeletePagesDeploymentParams -``` - -```release-note:breaking-change -pages_deployment: change DeletePagesDeploymentParams to contain all parameters -``` - -```release-note:breaking-change -pages_project: rename PagesProject to GetPagesProject -``` - -```release-note:breaking-change -pages_project: change to use ResourceContainer for account ID -``` \ No newline at end of file +```release-note:breaking-change +pages_deployment: add support for auto pagination +``` + +```release-note:enchancement +pages_deployment: add Force to DeletePagesDeploymentParams +``` + +```release-note:breaking-change +pages_deployment: change DeletePagesDeploymentParams to contain all parameters +``` + +```release-note:breaking-change +pages_project: rename PagesProject to GetPagesProject +``` + +```release-note:breaking-change +pages_project: change to use ResourceContainer for account ID +``` diff --git a/.changelog/1265.txt b/.changelog/1265.txt index f93fc420a6a..a001f26c5db 100644 --- a/.changelog/1265.txt +++ b/.changelog/1265.txt @@ -1,7 +1,7 @@ -```release-note:enhancement -r2_bucket: add support for getting a bucket -``` - -```release-note:breaking-change -r2_bucket: change creation time from string to *time.Time -``` +```release-note:enhancement +r2_bucket: add support for getting a bucket +``` + +```release-note:breaking-change +r2_bucket: change creation time from string to *time.Time +``` diff --git a/.changelog/1319.txt b/.changelog/1319.txt index be082a58648..4235c885cf0 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -1,59 +1,59 @@ -```release-note:breaking-change -access_application: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:enhancement -access_application: add support for auto pagination -``` - -```release-note:breaking-change -access_ca_certificate: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:enhancement -access_ca_certificate: add support for auto pagination -``` - -```release-note:breaking-change -access_group: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:enhancement -access_group: add support for auto pagination -``` - -```release-note:breaking-change -access_identity_provider: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:enhancement -access_identity_provider: add support for auto pagination -``` - -```release-note:breaking-change -access_mutual_tls_certificates: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:enhancement -access_mutual_tls_certificates: add support for auto pagination -``` - -```release-note:breaking-change -access_organization: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:breaking-change -access_policy: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:enhancement -access_policy: add support for auto pagination -``` - -```release-note:breaking-change -access_service_tokens: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` - -```release-note:breaking-change -access_user_token: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods -``` +```release-note:breaking-change +access_application: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:enhancement +access_application: add support for auto pagination +``` + +```release-note:breaking-change +access_ca_certificate: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:enhancement +access_ca_certificate: add support for auto pagination +``` + +```release-note:breaking-change +access_group: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:enhancement +access_group: add support for auto pagination +``` + +```release-note:breaking-change +access_identity_provider: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:enhancement +access_identity_provider: add support for auto pagination +``` + +```release-note:breaking-change +access_mutual_tls_certificates: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:enhancement +access_mutual_tls_certificates: add support for auto pagination +``` + +```release-note:breaking-change +access_organization: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:breaking-change +access_policy: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:enhancement +access_policy: add support for auto pagination +``` + +```release-note:breaking-change +access_service_tokens: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` + +```release-note:breaking-change +access_user_token: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` diff --git a/testdata/fixtures/tunnel/single_full.json b/testdata/fixtures/tunnel/single_full.json index e5178e650f1..6eb38f30ccf 100644 --- a/testdata/fixtures/tunnel/single_full.json +++ b/testdata/fixtures/tunnel/single_full.json @@ -1,25 +1,25 @@ -{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "name": "blog", - "created_at": "2009-11-10T23:00:00Z", - "deleted_at": "2009-11-10T23:00:00Z", - "connections": [ - { - "colo_name": "DFW", - "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "is_pending_reconnect": false, - "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", - "client_version": "2022.2.0", - "opened_at": "2021-01-25T18:22:34.317854Z", - "origin_ip": "198.51.100.1" - } - ], - "status": "healthy", - "tun_type": "cfd_tunnel", - "remote_config": true - } -} +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "name": "blog", + "created_at": "2009-11-10T23:00:00Z", + "deleted_at": "2009-11-10T23:00:00Z", + "connections": [ + { + "colo_name": "DFW", + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "is_pending_reconnect": false, + "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", + "client_version": "2022.2.0", + "opened_at": "2021-01-25T18:22:34.317854Z", + "origin_ip": "198.51.100.1" + } + ], + "status": "healthy", + "tun_type": "cfd_tunnel", + "remote_config": true + } +} From b3ec349121cfb4f1052db2f3a085f5cb37bd9cad Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 13 Aug 2024 16:11:42 -0400 Subject: [PATCH 23/84] add changelog --- .changelog/2887.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2887.txt diff --git a/.changelog/2887.txt b/.changelog/2887.txt new file mode 100644 index 00000000000..5015cdb00c8 --- /dev/null +++ b/.changelog/2887.txt @@ -0,0 +1,3 @@ +```release-notes:bug +cosmetic: Fix CRLF in changelog and test fixtures +``` From 8cd3d9d84e6d5fd088deed0daf65041a2d77a15b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 14 Aug 2024 04:43:39 +0000 Subject: [PATCH 24/84] Update CHANGELOG.md (Manual Trigger) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c13af7ce6bb..52d4337ebc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ ## 0.102.0 (Unreleased) +ENHANCEMENTS: + +* rulesets: Add `DeleteRulesetRule` ([#2833](https://github.com/cloudflare/cloudflare-go/issues/2833)) +* rulesets: Export `DeleteRulesetRuleParams` fields ([#2886](https://github.com/cloudflare/cloudflare-go/issues/2886)) + +DEPENDENCIES: + +* deps: bumps golang.org/x/net from 0.27.0 to 0.28.0 ([#2835](https://github.com/cloudflare/cloudflare-go/issues/2835)) + ## 0.101.0 (July 31st, 2024) ENHANCEMENTS: From 01784c5c610d9f61db09902b3273dcdedeaaae02 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 14 Aug 2024 04:46:45 +0000 Subject: [PATCH 25/84] Update CHANGELOG.md for #2797 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52d4337ebc8..ed82cd5c012 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ENHANCEMENTS: * rulesets: Add `DeleteRulesetRule` ([#2833](https://github.com/cloudflare/cloudflare-go/issues/2833)) * rulesets: Export `DeleteRulesetRuleParams` fields ([#2886](https://github.com/cloudflare/cloudflare-go/issues/2886)) +* teams_accounts: Add `disable_for_time` attribute ([#2797](https://github.com/cloudflare/cloudflare-go/issues/2797)) DEPENDENCIES: From 694d59feb96c20dce3ba0c147bb9c0a462b7b861 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Aug 2024 14:55:43 +1000 Subject: [PATCH 26/84] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed82cd5c012..29be0a72958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.102.0 (Unreleased) +## 0.103.0 (Unreleased) + +## 0.102.0 (August 14th, 2024) ENHANCEMENTS: From dcccf42a1e18e4f6ccc722fb1cbe9d25069489c1 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 21 Aug 2024 15:35:17 +1000 Subject: [PATCH 27/84] Update .goreleaser.yml --- cmd/flarectl/.goreleaser.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/flarectl/.goreleaser.yml b/cmd/flarectl/.goreleaser.yml index 131b233f2b5..86b765ad7d3 100644 --- a/cmd/flarectl/.goreleaser.yml +++ b/cmd/flarectl/.goreleaser.yml @@ -1,3 +1,4 @@ +version: 2 before: hooks: - cp ../../LICENSE . From 9df49c959b6afdf37eaf12a74b60d4bfc24dce94 Mon Sep 17 00:00:00 2001 From: Brad Date: Tue, 23 Jul 2024 11:06:01 -0500 Subject: [PATCH 28/84] add waiting_room enabled_origin_commands support --- .changelog/2931.txt | 3 +++ waiting_room.go | 1 + waiting_room_test.go | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .changelog/2931.txt diff --git a/.changelog/2931.txt b/.changelog/2931.txt new file mode 100644 index 00000000000..775a2085f47 --- /dev/null +++ b/.changelog/2931.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +waiting_room: add support for `enabled_origin_commands` +``` \ No newline at end of file diff --git a/waiting_room.go b/waiting_room.go index 7bd98d9a339..b2b85a2ba56 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -39,6 +39,7 @@ type WaitingRoom struct { CookieSuffix string `json:"cookie_suffix"` AdditionalRoutes []*WaitingRoomRoute `json:"additional_routes,omitempty"` QueueingStatusCode int `json:"queueing_status_code"` + EnabledOriginCommands []string `json:"enabled_origin_commands"` } // WaitingRoomStatus describes the status of a waiting room. diff --git a/waiting_room_test.go b/waiting_room_test.go index 4d5ccf00e04..26f729af70b 100644 --- a/waiting_room_test.go +++ b/waiting_room_test.go @@ -40,9 +40,10 @@ var waitingRoomJSON = fmt.Sprintf(` "default_template_language": "en-US", "next_event_prequeue_start_time": null, "next_event_start_time": "%s", - "cookie_suffix": "example_shop", - "additional_routes": [{"host": "shop2.example.com", "path": "/shop/checkout"}], - "queueing_status_code": 200 + "cookie_suffix": "example_shop", + "additional_routes": [{"host": "shop2.example.com", "path": "/shop/checkout"}], + "queueing_status_code": 200, + "enabled_origin_commands": ["revoke"] } `, waitingRoomID, testTimestampWaitingRoom.Format(time.RFC3339Nano), testTimestampWaitingRoom.Format(time.RFC3339Nano), testTimestampWaitingRoomEventStart.Format(time.RFC3339Nano)) @@ -129,6 +130,7 @@ var waitingRoom = WaitingRoom{ CookieSuffix: "example_shop", AdditionalRoutes: []*WaitingRoomRoute{{Host: "shop2.example.com", Path: "/shop/checkout"}}, QueueingStatusCode: 200, + EnabledOriginCommands: []string{"revoke"}, } var waitingRoomEvent = WaitingRoomEvent{ From e06aaff65795631129dec060d8ab2b5549e44513 Mon Sep 17 00:00:00 2001 From: emilio Date: Thu, 22 Aug 2024 13:59:40 -0500 Subject: [PATCH 29/84] Adjust Hyperdrive Worker binding to more align with wrangler syntax It works either way, but using "binding" instead of "name" in this API more aligns with our wrangler syntax https://developers.cloudflare.com/hyperdrive/get-started/#4-bind-your-worker-to-hyperdrive --- workers_bindings.go | 7 ++++++- workers_bindings_test.go | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/workers_bindings.go b/workers_bindings.go index 9a49cf865ac..04916ce6897 100644 --- a/workers_bindings.go +++ b/workers_bindings.go @@ -437,6 +437,7 @@ func (b WorkerD1DatabaseBinding) serialize(bindingName string) (workerBindingMet // WorkerHyperdriveBinding is a binding to a Hyperdrive config. type WorkerHyperdriveBinding struct { + Binding string ConfigID string } @@ -446,12 +447,15 @@ func (b WorkerHyperdriveBinding) Type() WorkerBindingType { } func (b WorkerHyperdriveBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.Binding == "" { + return nil, nil, fmt.Errorf(`binding name for binding "%s" cannot be empty`, bindingName) + } if b.ConfigID == "" { return nil, nil, fmt.Errorf(`config ID for binding "%s" cannot be empty`, bindingName) } return workerBindingMeta{ - "name": bindingName, + "name": b.Binding, "type": b.Type(), "id": b.ConfigID, }, nil, nil @@ -589,6 +593,7 @@ func (api *API) ListWorkerBindings(ctx context.Context, rc *ResourceContainer, p case WorkerHyperdriveBindingType: id := jsonBinding["id"].(string) bindingListItem.Binding = WorkerHyperdriveBinding{ + Binding: name, ConfigID: id, } default: diff --git a/workers_bindings_test.go b/workers_bindings_test.go index f747eabf106..bcd1b001bd5 100644 --- a/workers_bindings_test.go +++ b/workers_bindings_test.go @@ -110,6 +110,7 @@ func TestListWorkerBindings(t *testing.T) { assert.Equal(t, res.BindingList[9], WorkerBindingListItem{ Name: "MY_HYPERDRIVE", Binding: WorkerHyperdriveBinding{ + Binding: "MY_HYPERDRIVE", ConfigID: "aaf4609248cc493cbc8d3e446e38fdfa", }, }) @@ -203,6 +204,7 @@ func TestListWorkerBindings_Wfp(t *testing.T) { assert.Equal(t, res.BindingList[9], WorkerBindingListItem{ Name: "MY_HYPERDRIVE", Binding: WorkerHyperdriveBinding{ + Binding: "MY_HYPERDRIVE", ConfigID: "aaf4609248cc493cbc8d3e446e38fdfa", }, }) From ca4cd0012fde642b538be080e1ff011a57bbbf4d Mon Sep 17 00:00:00 2001 From: emilio Date: Thu, 22 Aug 2024 14:04:41 -0500 Subject: [PATCH 30/84] Add changelog --- .changelog/2932.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2932.txt diff --git a/.changelog/2932.txt b/.changelog/2932.txt new file mode 100644 index 00000000000..d9b098e61b3 --- /dev/null +++ b/.changelog/2932.txt @@ -0,0 +1,3 @@ +```release-notes:enhancement +worker_bindings: Adjust struct of `hyperdrive` bindings to better align with wrangler.toml syntax +``` From 38a8d50533376da481799468f8df5a85de31cb9b Mon Sep 17 00:00:00 2001 From: Brad Date: Mon, 26 Aug 2024 00:11:23 -0500 Subject: [PATCH 31/84] add omitempty for enabled_origin_commands --- waiting_room.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waiting_room.go b/waiting_room.go index b2b85a2ba56..0cb787b4ce5 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -39,7 +39,7 @@ type WaitingRoom struct { CookieSuffix string `json:"cookie_suffix"` AdditionalRoutes []*WaitingRoomRoute `json:"additional_routes,omitempty"` QueueingStatusCode int `json:"queueing_status_code"` - EnabledOriginCommands []string `json:"enabled_origin_commands"` + EnabledOriginCommands []string `json:"enabled_origin_commands,omitempty"` } // WaitingRoomStatus describes the status of a waiting room. From 110ccc990929e15b93f85b2270f3520117bdfd98 Mon Sep 17 00:00:00 2001 From: favonia Date: Sun, 11 Aug 2024 08:01:16 -0500 Subject: [PATCH 32/84] implement the Unwrap method for custom error types --- .changelog/2857.txt | 3 +++ errors.go | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 .changelog/2857.txt diff --git a/.changelog/2857.txt b/.changelog/2857.txt new file mode 100644 index 00000000000..f27aee94771 --- /dev/null +++ b/.changelog/2857.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +errors: implement the Unwrap method for custom error types to access the wrapped errors via errors.Is and errors.As +``` diff --git a/errors.go b/errors.go index 85fdc3efacb..93faab0dbd6 100644 --- a/errors.go +++ b/errors.go @@ -152,6 +152,10 @@ func (e RequestError) Type() ErrorType { return e.cloudflareError.Type } +func (e RequestError) Unwrap() error { + return e.cloudflareError +} + func NewRequestError(e *Error) RequestError { return RequestError{ cloudflareError: e, @@ -192,6 +196,10 @@ func (e RatelimitError) Type() ErrorType { return e.cloudflareError.Type } +func (e RatelimitError) Unwrap() error { + return e.cloudflareError +} + func NewRatelimitError(e *Error) RatelimitError { return RatelimitError{ cloudflareError: e, @@ -231,6 +239,10 @@ func (e ServiceError) Type() ErrorType { return e.cloudflareError.Type } +func (e ServiceError) Unwrap() error { + return e.cloudflareError +} + func NewServiceError(e *Error) ServiceError { return ServiceError{ cloudflareError: e, @@ -270,6 +282,10 @@ func (e AuthenticationError) Type() ErrorType { return e.cloudflareError.Type } +func (e AuthenticationError) Unwrap() error { + return e.cloudflareError +} + func NewAuthenticationError(e *Error) AuthenticationError { return AuthenticationError{ cloudflareError: e, @@ -309,6 +325,10 @@ func (e AuthorizationError) Type() ErrorType { return e.cloudflareError.Type } +func (e AuthorizationError) Unwrap() error { + return e.cloudflareError +} + func NewAuthorizationError(e *Error) AuthorizationError { return AuthorizationError{ cloudflareError: e, @@ -348,6 +368,10 @@ func (e NotFoundError) Type() ErrorType { return e.cloudflareError.Type } +func (e NotFoundError) Unwrap() error { + return e.cloudflareError +} + func NewNotFoundError(e *Error) NotFoundError { return NotFoundError{ cloudflareError: e, From daafdee27e773c5ef94e23fb00fc8dc275169a4e Mon Sep 17 00:00:00 2001 From: Anthony Turcios Date: Tue, 27 Aug 2024 11:48:43 -0400 Subject: [PATCH 33/84] add "contains" field to custom cache key --- .changelog/2935.txt | 3 +++ rulesets.go | 3 ++- rulesets_test.go | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changelog/2935.txt diff --git a/.changelog/2935.txt b/.changelog/2935.txt new file mode 100644 index 00000000000..dca04d79bbb --- /dev/null +++ b/.changelog/2935.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +add "contains" field to custom cache key header +``` diff --git a/rulesets.go b/rulesets.go index b9e36f8092f..1573bebb00d 100644 --- a/rulesets.go +++ b/rulesets.go @@ -334,7 +334,8 @@ type RulesetRuleActionParametersCustomKey struct { type RulesetRuleActionParametersCustomKeyHeader struct { RulesetRuleActionParametersCustomKeyFields - ExcludeOrigin *bool `json:"exclude_origin,omitempty"` + ExcludeOrigin *bool `json:"exclude_origin,omitempty"` + Contains map[string][]string `json:"contains,omitempty"` } type RulesetRuleActionParametersCustomKeyCookie RulesetRuleActionParametersCustomKeyFields diff --git a/rulesets_test.go b/rulesets_test.go index dbaf2b4f139..941f935b1de 100644 --- a/rulesets_test.go +++ b/rulesets_test.go @@ -229,7 +229,7 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) { "ignore_query_strings_order":true, "custom_key": { "query_string":{"include":"*"}, - "header":{"include":["habc","hdef"],"check_presence":["hfizz","hbuzz"],"exclude_origin":true}, + "header":{"include":["habc","hdef"],"check_presence":["hfizz","hbuzz"],"exclude_origin":true,"contains":{"accept":["image/web", "image/png"]}}, "cookie":{"include":["cabc","cdef"],"check_presence":["cfizz","cbuzz"]}, "user":{ "device_type":true, @@ -316,6 +316,9 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) { CheckPresence: []string{"hfizz", "hbuzz"}, }, ExcludeOrigin: BoolPtr(true), + Contains: map[string][]string{ + "accept": {"image/web", "image/png"}, + }, }, Cookie: &RulesetRuleActionParametersCustomKeyCookie{ Include: []string{"cabc", "cdef"}, From 3a855918bbb3e81b89accbb46373f54028c2d375 Mon Sep 17 00:00:00 2001 From: Alyssa Wang Date: Tue, 27 Aug 2024 14:14:30 -0700 Subject: [PATCH 34/84] rename enabled to in use for gateway certificates --- .changelog/2937.txt | 3 +++ teams_certificates.go | 2 +- teams_certificates_test.go | 14 +++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 .changelog/2937.txt diff --git a/.changelog/2937.txt b/.changelog/2937.txt new file mode 100644 index 00000000000..28a6295477a --- /dev/null +++ b/.changelog/2937.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +GIN-341: renamed enabled to in use for gateway certificates +``` diff --git a/teams_certificates.go b/teams_certificates.go index 74267866944..00e6f1063ad 100644 --- a/teams_certificates.go +++ b/teams_certificates.go @@ -10,7 +10,7 @@ import ( ) type TeamsCertificate struct { - Enabled *bool `json:"enabled"` + InUse *bool `json:"in_use"` ID string `json:"id"` BindingStatus string `json:"binding_status"` QsPackId string `json:"qs_pack_id"` diff --git a/teams_certificates_test.go b/teams_certificates_test.go index 8fc7155bbf4..6a9d57a75f2 100644 --- a/teams_certificates_test.go +++ b/teams_certificates_test.go @@ -23,7 +23,7 @@ func TestTeamsCertificate(t *testing.T) { "errors": [], "messages": [], "result": { - "enabled": false, + "in_use": false, "id": "80c8a54e-d55c-46c6-86bb-e8a3c90472f4", "binding_status": "inactive", "qs_pack_id": "00000000-0000-0000-0000-000000000000", @@ -42,7 +42,7 @@ func TestTeamsCertificate(t *testing.T) { actual, err := client.TeamsCertificate(context.Background(), testAccountID, testCertID) if assert.NoError(t, err) { - assert.Equal(t, *actual.Enabled, false) + assert.Equal(t, *actual.InUse, false) assert.Equal(t, actual.ID, testCertID) assert.Equal(t, actual.BindingStatus, "inactive") assert.Equal(t, actual.Type, "gateway_managed") @@ -62,7 +62,7 @@ func TestTeamsCertificatesList(t *testing.T) { "messages": [], "result": [ { - "enabled": false, + "in_use": false, "id": "43a36083-987b-4321-95ab-4052771c4e6f", "binding_status": "inactive", "qs_pack_id": "00000000-0000-0000-0000-000000000000", @@ -73,7 +73,7 @@ func TestTeamsCertificatesList(t *testing.T) { "expires_on": "2122-10-29T16:59:47Z" }, { - "enabled": false, + "in_use": false, "id": "4a9d6ecf-0fdd-4676-818a-ee6b45f17f9b", "binding_status": "inactive", "qs_pack_id": "00000000-0000-0000-0000-000000000000", @@ -111,7 +111,7 @@ func TestTeamsAccountGenerateCertificate(t *testing.T) { "errors": [], "messages": [], "result": { - "enabled": false, + "in_use": false, "id": "80c8a54e-d55c-46c6-86bb-e8a3c90472f4", "binding_status": "inactive", "qs_pack_id": "00000000-0000-0000-0000-000000000000", @@ -149,7 +149,7 @@ func TestTeamsActivateCertificate(t *testing.T) { "errors": [], "messages": [], "result": { - "enabled": false, + "in_use": false, "id": "80c8a54e-d55c-46c6-86bb-e8a3c90472f4", "binding_status": "pending_deployment", "qs_pack_id": "00000000-0000-0000-0000-000000000000", @@ -183,7 +183,7 @@ func TestTeamsDeactivateCertificate(t *testing.T) { "errors": [], "messages": [], "result": { - "enabled": false, + "in_use": false, "id": "80c8a54e-d55c-46c6-86bb-e8a3c90472f4", "binding_status": "pending_deletion", "qs_pack_id": "00000000-0000-0000-0000-000000000000", From 3fb03621be86ad2dbec9c5fb2835277b8b1432c5 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Aug 2024 10:44:28 +1000 Subject: [PATCH 35/84] Update .changelog/2935.txt --- .changelog/2935.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/2935.txt b/.changelog/2935.txt index dca04d79bbb..bcf3ae09457 100644 --- a/.changelog/2935.txt +++ b/.changelog/2935.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -add "contains" field to custom cache key header +rulesets: add "contains" field to custom cache key header ``` From b7939eb66ab341883ce96e284b2123b814e06051 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Aug 2024 10:54:46 +1000 Subject: [PATCH 36/84] Update .changelog/2937.txt --- .changelog/2937.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/2937.txt b/.changelog/2937.txt index 28a6295477a..a2c91801be9 100644 --- a/.changelog/2937.txt +++ b/.changelog/2937.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -GIN-341: renamed enabled to in use for gateway certificates +teams_certificates: renamed `enabled` to `in_use` ``` From f484daa94b7151118702483ac40baf3e2655bf69 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Aug 2024 11:21:50 +1000 Subject: [PATCH 37/84] generate changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29be0a72958..035bfdc7a4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ ## 0.103.0 (Unreleased) +ENHANCEMENTS: + +* errors: implement the Unwrap method for custom error types to access the wrapped errors via errors.Is and errors.As ([#2857](https://github.com/cloudflare/cloudflare-go/issues/2857)) +* rulesets: add "contains" field to custom cache key header ([#2935](https://github.com/cloudflare/cloudflare-go/issues/2935)) +* teams_certificates: renamed `enabled` to `in_use` ([#2937](https://github.com/cloudflare/cloudflare-go/issues/2937)) +* waiting_room: add support for `enabled_origin_commands` ([#2931](https://github.com/cloudflare/cloudflare-go/issues/2931)) + +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.27.3 to 2.27.4 ([#2863](https://github.com/cloudflare/cloudflare-go/issues/2863)) + ## 0.102.0 (August 14th, 2024) ENHANCEMENTS: From c8841b9dffddce994775dc853a36b96f162b249b Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Aug 2024 11:22:50 +1000 Subject: [PATCH 38/84] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 035bfdc7a4f..c208e1b2d20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.103.0 (Unreleased) +## 0.104.0 (Unreleased) + +## 0.103.0 (August 28th, 2024) ENHANCEMENTS: From d5859a35dfc3b049505ddf851952c359fd10a75d Mon Sep 17 00:00:00 2001 From: Yawar Jamal Date: Wed, 28 Aug 2024 16:45:01 -0500 Subject: [PATCH 39/84] use existing zone setting for automatic ssl mode --- zone.go | 60 ++++++---------------------------------------------- zone_test.go | 20 ++++++++++++------ 2 files changed, 19 insertions(+), 61 deletions(-) diff --git a/zone.go b/zone.go index 7be43400a51..714c0edc8bf 100644 --- a/zone.go +++ b/zone.go @@ -146,11 +146,12 @@ type ZoneRatePlanResponse struct { // ZoneSetting contains settings for a zone. type ZoneSetting struct { - ID string `json:"id"` - Editable bool `json:"editable"` - ModifiedOn string `json:"modified_on,omitempty"` - Value interface{} `json:"value"` - TimeRemaining int `json:"time_remaining"` + ID string `json:"id"` + Editable bool `json:"editable"` + ModifiedOn string `json:"modified_on,omitempty"` + Value interface{} `json:"value"` + TimeRemaining int `json:"time_remaining"` + NextScheduledScan string `json:"next_scheduled_scan,omitempty"` } // ZoneSettingResponse represents the response from the Zone Setting endpoint. @@ -174,21 +175,6 @@ type ZoneSSLSetting struct { CertificateStatus string `json:"certificate_status"` } -// ZoneAutomaticSSLModeSetting contains automatic ssl mode -type ZoneAutomaticSSLModeSetting struct { - ID string `json:"id"` - Editable bool `json:"editable"` - ModifiedOn string `json:"modified_on"` - Value string `json:"value"` - NextScheduledScan string `json:"next_scheduled_scan"` -} - -// ZoneAutomaticSSLModeSettingResponse represents the response from the Zone automatic SSL mode setting -type ZoneAutomaticSSLModeSettingResponse struct { - Response - Result ZoneAutomaticSSLModeSetting `json:"result"` -} - // ZoneSSLSettingResponse represents the response from the Zone SSL Setting type ZoneSSLSettingResponse struct { Response @@ -862,23 +848,6 @@ func (api *API) ZoneSSLSettings(ctx context.Context, zoneID string) (ZoneSSLSett return r.Result, nil } -// ZoneSSLSettings returns information about SSL setting to the specified zone. -// -// API reference: https://api.cloudflare.com/#zone-settings-get-automatic-ssl-mode-setting -func (api *API) ZoneAutomaticSSLModeSetting(ctx context.Context, zoneID string) (ZoneAutomaticSSLModeSetting, error) { - uri := fmt.Sprintf("/zones/%s/settings/ssl_automatic_mode", zoneID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return ZoneAutomaticSSLModeSetting{}, err - } - var r ZoneAutomaticSSLModeSettingResponse - err = json.Unmarshal(res, &r) - if err != nil { - return ZoneAutomaticSSLModeSetting{}, fmt.Errorf("%s: %s %w", errUnmarshalError, string(res), err) - } - return r.Result, nil -} - // UpdateZoneSSLSettings update information about SSL setting to the specified zone. // // API reference: https://api.cloudflare.com/#zone-settings-change-ssl-setting @@ -896,23 +865,6 @@ func (api *API) UpdateZoneSSLSettings(ctx context.Context, zoneID string, sslVal return r.Result, nil } -// UpdateZoneAutomaticSSLSettingMode update information about Automatic SSL mode setting to the specified zone. -// -// API reference: https://api.cloudflare.com/[#-add-url-slug-here] -func (api *API) UpdateZoneAutomaticSSLSettingMode(ctx context.Context, zoneID, mode string) (ZoneSSLSetting, error) { - uri := fmt.Sprintf("/zones/%s/settings/ssl_automatic_mode", zoneID) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, ZoneSSLSetting{Value: mode}) - if err != nil { - return ZoneSSLSetting{}, err - } - var r ZoneSSLSettingResponse - err = json.Unmarshal(res, &r) - if err != nil { - return ZoneSSLSetting{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - // FallbackOrigin returns information about the fallback origin for the specified zone. // // API reference: https://developers.cloudflare.com/ssl/ssl-for-saas/api-calls/#fallback-origin-configuration diff --git a/zone_test.go b/zone_test.go index 459e871fcf8..d5a28fa4f28 100644 --- a/zone_test.go +++ b/zone_test.go @@ -1520,20 +1520,26 @@ func TestUpdateZoneAutomaticSSLModeSetting(t *testing.T) { // JSON data from: https://api.cloudflare.com/#zone-settings-properties _, _ = fmt.Fprintf(w, `{ "result": { - "id": "ssl_automatic_mode", + "id": "ssl_tls_configuration_mode", "value": "auto", "editable": true, - "modified_on": "2014-01-01T05:20:00.12345Z" + "modified_on": "2014-01-01T05:20:00.12345Z", + "next_scheduled_scan": "2014-01-01T05:20:00.12345Z" } }`) } mux.HandleFunc("/zones/foo/settings/ssl_automatic_mode", handler) - s, err := client.UpdateZoneAutomaticSSLSettingMode(context.Background(), "foo", "auto") + s, err := client.UpdateZoneSetting(context.Background(), ZoneIdentifier("foo"), UpdateZoneSettingParams{ + Name: "ssl_automatic_mode", + Value: "auto", + }) + if assert.NoError(t, err) { - assert.Equal(t, s.ID, "ssl_automatic_mode") + assert.Equal(t, s.ID, "ssl_tls_configuration_mode") assert.Equal(t, s.Value, "auto") assert.Equal(t, s.Editable, true) assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + assert.Equal(t, s.NextScheduledScan, "2014-01-01T05:20:00.12345Z") } } @@ -1545,7 +1551,7 @@ func TestGetZoneAutomaticSSLModeSetting(t *testing.T) { w.Header().Set("content-type", "application/json") _, _ = fmt.Fprintf(w, `{ "result": { - "id": "ssl_automatic_mode", + "id": "ssl_tls_configuration_mode", "value": "custom", "editable": true, "modified_on": "2014-01-01T05:20:00.12345Z", @@ -1554,9 +1560,9 @@ func TestGetZoneAutomaticSSLModeSetting(t *testing.T) { }`) } mux.HandleFunc("/zones/foo/settings/ssl_automatic_mode", handler) - s, err := client.ZoneAutomaticSSLModeSetting(context.Background(), "foo") + s, err := client.GetZoneSetting(context.Background(), ZoneIdentifier("foo"), GetZoneSettingParams{Name: "ssl_automatic_mode"}) if assert.NoError(t, err) { - assert.Equal(t, s.ID, "ssl_automatic_mode") + assert.Equal(t, s.ID, "ssl_tls_configuration_mode") assert.Equal(t, s.Value, "custom") assert.Equal(t, s.Editable, true) assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") From 24713ffbd4b769b5d222a46587453875cdaac391 Mon Sep 17 00:00:00 2001 From: Gauri Baraskar Date: Thu, 29 Aug 2024 13:55:11 -0400 Subject: [PATCH 40/84] Add ai_bots_protection to bot management public API --- .changelog/2973.txt | 3 +++ bot_management.go | 2 ++ bot_management_test.go | 13 +++++++++---- 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 .changelog/2973.txt diff --git a/.changelog/2973.txt b/.changelog/2973.txt new file mode 100644 index 00000000000..ff0f072ef6a --- /dev/null +++ b/.changelog/2973.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +bot_management: add ai_bots_protection to public API +``` diff --git a/bot_management.go b/bot_management.go index f77968f4599..51205a6aea9 100644 --- a/bot_management.go +++ b/bot_management.go @@ -20,6 +20,7 @@ type BotManagement struct { SuppressSessionScore *bool `json:"suppress_session_score,omitempty"` AutoUpdateModel *bool `json:"auto_update_model,omitempty"` UsingLatestModel *bool `json:"using_latest_model,omitempty"` + AIBotsProtection *string `json:"ai_bots_protection,omitempty"` } // BotManagementResponse represents the response from the bot_management endpoint. @@ -38,6 +39,7 @@ type UpdateBotManagementParams struct { OptimizeWordpress *bool `json:"optimize_wordpress,omitempty"` SuppressSessionScore *bool `json:"suppress_session_score,omitempty"` AutoUpdateModel *bool `json:"auto_update_model,omitempty"` + AIBotsProtection *string `json:"ai_bots_protection,omitempty"` } // GetBotManagement gets a zone API shield configuration. diff --git a/bot_management_test.go b/bot_management_test.go index e0837804e5e..46ff1cff7f7 100644 --- a/bot_management_test.go +++ b/bot_management_test.go @@ -24,7 +24,8 @@ func TestGetBotManagement(t *testing.T) { "result": { "enable_js": false, "fight_mode": true, - "using_latest_model": true + "using_latest_model": true, + "ai_bots_protection": "disabled" } } `) @@ -36,6 +37,7 @@ func TestGetBotManagement(t *testing.T) { EnableJS: BoolPtr(false), FightMode: BoolPtr(true), UsingLatestModel: BoolPtr(true), + AIBotsProtection: StringPtr("disabled"), } actual, err := client.GetBotManagement(context.Background(), ZoneIdentifier(testZoneID)) @@ -60,7 +62,8 @@ func TestUpdateBotManagement(t *testing.T) { "result": { "enable_js": false, "fight_mode": true, - "using_latest_model": true + "using_latest_model": true, + "ai_bots_protection": "block" } } `) @@ -69,14 +72,16 @@ func TestUpdateBotManagement(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/bot_management", handler) bmData := UpdateBotManagementParams{ - EnableJS: BoolPtr(false), - FightMode: BoolPtr(true), + EnableJS: BoolPtr(false), + FightMode: BoolPtr(true), + AIBotsProtection: StringPtr("block"), } want := BotManagement{ EnableJS: BoolPtr(false), FightMode: BoolPtr(true), UsingLatestModel: BoolPtr(true), + AIBotsProtection: StringPtr("block"), } actual, err := client.UpdateBotManagement(context.Background(), ZoneIdentifier(testZoneID), bmData) From b109bc30efe018fb81dbd4e135408206bd9da95c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 30 Aug 2024 10:42:48 +1000 Subject: [PATCH 41/84] Rename 2973.txt to 2974.txt --- .changelog/{2973.txt => 2974.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{2973.txt => 2974.txt} (100%) diff --git a/.changelog/2973.txt b/.changelog/2974.txt similarity index 100% rename from .changelog/2973.txt rename to .changelog/2974.txt From 05d36f986333f2809691ae8b03edebba70a52d42 Mon Sep 17 00:00:00 2001 From: Janik Rabe Date: Fri, 30 Aug 2024 12:40:39 +0100 Subject: [PATCH 42/84] Remove deprecated zone fields on DNS records References: --- .changelog/2986.txt | 3 +++ dns.go | 4 ---- dns_test.go | 24 ------------------------ testdata/fixtures/dns/list_page_1.json | 6 ------ testdata/fixtures/dns/list_page_2.json | 4 ---- 5 files changed, 3 insertions(+), 38 deletions(-) create mode 100644 .changelog/2986.txt diff --git a/.changelog/2986.txt b/.changelog/2986.txt new file mode 100644 index 00000000000..e214ddced6b --- /dev/null +++ b/.changelog/2986.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +dns: removed deprecated ZoneID and ZoneName fields on DNS records +``` diff --git a/dns.go b/dns.go index 14dbe2d4b3e..0c36efd429a 100644 --- a/dns.go +++ b/dns.go @@ -27,8 +27,6 @@ type DNSRecord struct { Meta interface{} `json:"meta,omitempty"` Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC ID string `json:"id,omitempty"` - ZoneID string `json:"zone_id,omitempty"` - ZoneName string `json:"zone_name,omitempty"` Priority *uint16 `json:"priority,omitempty"` TTL int `json:"ttl,omitempty"` Proxied *bool `json:"proxied,omitempty"` @@ -185,8 +183,6 @@ type CreateDNSRecordParams struct { Meta interface{} `json:"meta,omitempty"` Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC ID string `json:"id,omitempty"` - ZoneID string `json:"zone_id,omitempty"` - ZoneName string `json:"zone_name,omitempty"` Priority *uint16 `json:"priority,omitempty"` TTL int `json:"ttl,omitempty"` Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` diff --git a/dns_test.go b/dns_test.go index 43546dcc942..01af5c1b702 100644 --- a/dns_test.go +++ b/dns_test.go @@ -98,8 +98,6 @@ func TestCreateDNSRecord(t *testing.T) { "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -123,8 +121,6 @@ func TestCreateDNSRecord(t *testing.T) { Proxiable: true, Proxied: asciiInput.Proxied, TTL: asciiInput.TTL, - ZoneID: testZoneID, - ZoneName: "example.com", CreatedOn: createdOn, ModifiedOn: modifiedOn, Data: map[string]interface{}{}, @@ -179,8 +175,6 @@ func TestListDNSRecords(t *testing.T) { "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -212,8 +206,6 @@ func TestListDNSRecords(t *testing.T) { Proxiable: true, Proxied: &proxied, TTL: 120, - ZoneID: testZoneID, - ZoneName: "example.com", CreatedOn: createdOn, ModifiedOn: modifiedOn, Data: map[string]interface{}{}, @@ -272,8 +264,6 @@ func TestListDNSRecordsSearch(t *testing.T) { "proxiable": true, "proxied": true, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -306,8 +296,6 @@ func TestListDNSRecordsSearch(t *testing.T) { Proxiable: true, Proxied: &proxied, TTL: 120, - ZoneID: testZoneID, - ZoneName: "example.com", CreatedOn: createdOn, ModifiedOn: modifiedOn, Data: map[string]interface{}{}, @@ -403,8 +391,6 @@ func TestListDNSRecordsPagination(t *testing.T) { assert.Equal(t, expected["proxiable"].(bool), actualRecord.Proxiable) assert.Equal(t, expected["proxied"].(bool), *actualRecord.Proxied) assert.Equal(t, int(expected["ttl"].(float64)), actualRecord.TTL) - assert.Equal(t, expected["zone_id"].(string), actualRecord.ZoneID) - assert.Equal(t, expected["zone_name"].(string), actualRecord.ZoneName) assert.Equal(t, expected["data"], actualRecord.Data) assert.Equal(t, expected["meta"], actualRecord.Meta) } @@ -430,8 +416,6 @@ func TestGetDNSRecord(t *testing.T) { "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -460,8 +444,6 @@ func TestGetDNSRecord(t *testing.T) { Proxiable: true, Proxied: &proxied, TTL: 120, - ZoneID: testZoneID, - ZoneName: "example.com", CreatedOn: createdOn, ModifiedOn: modifiedOn, Data: map[string]interface{}{}, @@ -521,8 +503,6 @@ func TestUpdateDNSRecord(t *testing.T) { "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -586,8 +566,6 @@ func TestUpdateDNSRecord_ClearComment(t *testing.T) { "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "comment":null, @@ -642,8 +620,6 @@ func TestUpdateDNSRecord_KeepComment(t *testing.T) { "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "comment":null, diff --git a/testdata/fixtures/dns/list_page_1.json b/testdata/fixtures/dns/list_page_1.json index 5ff33aac68c..ce6ef07b698 100644 --- a/testdata/fixtures/dns/list_page_1.json +++ b/testdata/fixtures/dns/list_page_1.json @@ -11,8 +11,6 @@ "proxiable": true, "proxied": true, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -33,8 +31,6 @@ "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -55,8 +51,6 @@ "proxiable": true, "proxied": true, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, diff --git a/testdata/fixtures/dns/list_page_2.json b/testdata/fixtures/dns/list_page_2.json index f783aa44971..73cf683e749 100644 --- a/testdata/fixtures/dns/list_page_2.json +++ b/testdata/fixtures/dns/list_page_2.json @@ -11,8 +11,6 @@ "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, @@ -33,8 +31,6 @@ "proxiable": true, "proxied": false, "ttl": 120, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", "created_on": "2014-01-01T05:20:00Z", "modified_on": "2014-01-01T05:20:00Z", "data": {}, From fe15c7b6614a504a72162bcf72efc2a10951b5b9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 2 Sep 2024 11:03:54 +1000 Subject: [PATCH 43/84] Update 2986.txt --- .changelog/2986.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/2986.txt b/.changelog/2986.txt index e214ddced6b..a717be7508f 100644 --- a/.changelog/2986.txt +++ b/.changelog/2986.txt @@ -1,3 +1,3 @@ ```release-note:breaking-change -dns: removed deprecated ZoneID and ZoneName fields on DNS records +dns: removed deprecated `ZoneID` and `ZoneName` fields ``` From b6c1ddaef70a49928a9df2546603d1256008f00d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:06:41 +0000 Subject: [PATCH 44/84] Bump golang.org/x/net from 0.28.0 to 0.29.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.28.0 to 0.29.0. - [Commits](https://github.com/golang/net/compare/v0.28.0...v0.29.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 04bdc813906..b64ca565af2 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.4 - golang.org/x/net v0.28.0 + golang.org/x/net v0.29.0 golang.org/x/time v0.5.0 ) @@ -25,6 +25,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/text v0.18.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8ae0beb4a4f..7a67d956d66 100644 --- a/go.sum +++ b/go.sum @@ -39,10 +39,10 @@ github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 18cdb17241c8efec8a723a621e633176f88fef7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Sep 2024 16:06:54 +0000 Subject: [PATCH 45/84] add CHANGELOG for #3030 --- .changelog/3030.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/3030.txt diff --git a/.changelog/3030.txt b/.changelog/3030.txt new file mode 100644 index 00000000000..1d25b5739ab --- /dev/null +++ b/.changelog/3030.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.28.0 to 0.29.0 +``` From 293941f1c055f5d7426a6f4ec8069f3d8dbb6d9e Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Sat, 7 Sep 2024 08:48:57 -0700 Subject: [PATCH 46/84] add support for custom_s2s posture rule --- .changelog/3031.txt | 3 +++ device_posture_rule.go | 1 + 2 files changed, 4 insertions(+) create mode 100644 .changelog/3031.txt diff --git a/.changelog/3031.txt b/.changelog/3031.txt new file mode 100644 index 00000000000..aa5e89ebb08 --- /dev/null +++ b/.changelog/3031.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +device_posture_rule: add score field for custom_s2s posture rule +``` \ No newline at end of file diff --git a/device_posture_rule.go b/device_posture_rule.go index fc4e0657a51..0c24fd9a825 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -203,6 +203,7 @@ type DevicePostureRuleInput struct { ExtendedKeyUsage []string `json:"extended_key_usage,omitempty"` CheckPrivateKey *bool `json:"check_private_key,omitempty"` Locations CertificateLocations `json:"locations,omitempty"` + Score int `json:"score,omitempty"` } // Locations struct for client certificate rule v2. From 53fad581c10725bd377cd0ccd24a0ffedd6246f7 Mon Sep 17 00:00:00 2001 From: Timothy W Polich Date: Thu, 5 Sep 2024 16:36:10 -0700 Subject: [PATCH 47/84] added basic support for upcomming account level load balancers --- .changelog/3027.txt | 3 + load_balancing.go | 65 +- load_balancing_test.go | 1332 +++++++++++++++++++++++++++++++++------- 3 files changed, 1159 insertions(+), 241 deletions(-) create mode 100644 .changelog/3027.txt diff --git a/.changelog/3027.txt b/.changelog/3027.txt new file mode 100644 index 00000000000..a6d75bb371a --- /dev/null +++ b/.changelog/3027.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +load_balancing: add account load balancer support +``` \ No newline at end of file diff --git a/load_balancing.go b/load_balancing.go index 44d7fd9fa33..107a49f9d95 100644 --- a/load_balancing.go +++ b/load_balancing.go @@ -101,7 +101,7 @@ type LoadBalancer struct { CreatedOn *time.Time `json:"created_on,omitempty"` ModifiedOn *time.Time `json:"modified_on,omitempty"` Description string `json:"description"` - Name string `json:"name"` + Name string `json:"name,omitempty"` TTL int `json:"ttl,omitempty"` FallbackPool string `json:"fallback_pool"` DefaultPools []string `json:"default_pools"` @@ -144,6 +144,11 @@ type LoadBalancer struct { // // "": Maps to "geo" if RegionPools or PopPools or CountryPools have entries otherwise "off". SteeringPolicy string `json:"steering_policy,omitempty"` + + // TunnelID is the ID of the tunnel associated with this load balancer. + // It is only used for account load balancers and has no relation to any + // tunnels used as origins for this load balancer. + TunnelID string `json:"tunnel_id,omitempty"` } // LoadBalancerLoadShedding contains the settings for controlling load shedding. @@ -681,12 +686,17 @@ func (api *API) UpdateLoadBalancerMonitor(ctx context.Context, rc *ResourceConta // // API reference: https://api.cloudflare.com/#load-balancers-create-load-balancer func (api *API) CreateLoadBalancer(ctx context.Context, rc *ResourceContainer, params CreateLoadBalancerParams) (LoadBalancer, error) { - if rc.Level != ZoneRouteLevel { + + var uri string + switch rc.Level { + case ZoneRouteLevel: + uri = fmt.Sprintf("/zones/%s/load_balancers", rc.Identifier) + case AccountRouteLevel: + uri = fmt.Sprintf("/accounts/%s/load_balancers", rc.Identifier) + default: return LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } - uri := fmt.Sprintf("/zones/%s/load_balancers", rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params.LoadBalancer) if err != nil { return LoadBalancer{}, err @@ -702,11 +712,19 @@ func (api *API) CreateLoadBalancer(ctx context.Context, rc *ResourceContainer, p // // API reference: https://api.cloudflare.com/#load-balancers-list-load-balancers func (api *API) ListLoadBalancers(ctx context.Context, rc *ResourceContainer, params ListLoadBalancerParams) ([]LoadBalancer, error) { - if rc.Level != ZoneRouteLevel { - return []LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + + var uri string + switch rc.Level { + case ZoneRouteLevel: + uri = fmt.Sprintf("/zones/%s/load_balancers", rc.Identifier) + case AccountRouteLevel: + uri = fmt.Sprintf("/accounts/%s/load_balancers", rc.Identifier) + default: + return nil, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } - uri := buildURI(fmt.Sprintf("/zones/%s/load_balancers", rc.Identifier), params.PaginationOptions) + // add pagination options to the URI + uri = buildURI(uri, params.PaginationOptions) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -723,7 +741,14 @@ func (api *API) ListLoadBalancers(ctx context.Context, rc *ResourceContainer, pa // // API reference: https://api.cloudflare.com/#load-balancers-load-balancer-details func (api *API) GetLoadBalancer(ctx context.Context, rc *ResourceContainer, loadbalancerID string) (LoadBalancer, error) { - if rc.Level != ZoneRouteLevel { + + var uri string + switch rc.Level { + case ZoneRouteLevel: + uri = fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, loadbalancerID) + case AccountRouteLevel: + uri = fmt.Sprintf("/accounts/%s/load_balancers/%s", rc.Identifier, loadbalancerID) + default: return LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -731,8 +756,6 @@ func (api *API) GetLoadBalancer(ctx context.Context, rc *ResourceContainer, load return LoadBalancer{}, ErrMissingLoadBalancerID } - uri := fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, loadbalancerID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return LoadBalancer{}, err @@ -748,7 +771,14 @@ func (api *API) GetLoadBalancer(ctx context.Context, rc *ResourceContainer, load // // API reference: https://api.cloudflare.com/#load-balancers-delete-load-balancer func (api *API) DeleteLoadBalancer(ctx context.Context, rc *ResourceContainer, loadbalancerID string) error { - if rc.Level != ZoneRouteLevel { + + var uri string + switch rc.Level { + case ZoneRouteLevel: + uri = fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, loadbalancerID) + case AccountRouteLevel: + uri = fmt.Sprintf("/accounts/%s/load_balancers/%s", rc.Identifier, loadbalancerID) + default: return fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -756,8 +786,6 @@ func (api *API) DeleteLoadBalancer(ctx context.Context, rc *ResourceContainer, l return ErrMissingLoadBalancerID } - uri := fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, loadbalancerID) - if _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil); err != nil { return err } @@ -768,7 +796,14 @@ func (api *API) DeleteLoadBalancer(ctx context.Context, rc *ResourceContainer, l // // API reference: https://api.cloudflare.com/#load-balancers-update-load-balancer func (api *API) UpdateLoadBalancer(ctx context.Context, rc *ResourceContainer, params UpdateLoadBalancerParams) (LoadBalancer, error) { - if rc.Level != ZoneRouteLevel { + + var uri string + switch rc.Level { + case ZoneRouteLevel: + uri = fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, params.LoadBalancer.ID) + case AccountRouteLevel: + uri = fmt.Sprintf("/accounts/%s/load_balancers/%s", rc.Identifier, params.LoadBalancer.ID) + default: return LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -776,8 +811,6 @@ func (api *API) UpdateLoadBalancer(ctx context.Context, rc *ResourceContainer, p return LoadBalancer{}, ErrMissingLoadBalancerID } - uri := fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, params.LoadBalancer.ID) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.LoadBalancer) if err != nil { return LoadBalancer{}, err diff --git a/load_balancing_test.go b/load_balancing_test.go index 3a9ab5afb5b..e4e2ae20431 100644 --- a/load_balancing_test.go +++ b/load_balancing_test.go @@ -1449,17 +1449,815 @@ func TestCreateLoadBalancer(t *testing.T) { } } -func TestCreateLoadBalancer_AccountIsNotSupported(t *testing.T) { +func TestCreateAccountLoadBalancer(t *testing.T) { setup() defer teardown() - _, err := client.CreateLoadBalancer(context.Background(), AccountIdentifier(testAccountID), CreateLoadBalancerParams{}) - if assert.Error(t, err) { - assert.Equal(t, fmt.Sprintf(errInvalidResourceContainerAccess, AccountRouteLevel), err.Error()) + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + b, err := io.ReadAll(r.Body) + defer r.Body.Close() + if assert.NoError(t, err) { + assert.JSONEq(t, `{ + "description": "Account Load Balancer", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "abd90f38ced07c2e2f4df50b1f61d4194" + ] + }, + "pop_pools": { + "LAX": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.2, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + } + }, + "adaptive_routing": { + "failover_across_pools": true + }, + "location_strategy": { + "prefer_ecs": "always", + "mode": "resolver_ip" + }, + "rules": [ + { + "name": "example rule", + "condition": "cf.load_balancer.region == \"SAF\"", + "disabled": false, + "priority": 0, + "overrides": { + "region_pools": { + "SAF": ["de90f38ced07c2e2f4df50b1f61d4194"] + }, + "adaptive_routing": { + "failover_across_pools": false + }, + "location_strategy": { + "prefer_ecs": "never", + "mode": "pop" + } + } + } + ], + "proxied": true, + "session_affinity": "cookie", + "session_affinity_ttl": 5000, + "session_affinity_attributes": { + "samesite": "Strict", + "secure": "Always", + "drain_duration": 60, + "zero_downtime_failover": "sticky" + } + }`, string(b)) + } + + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "699d98642c564d2e855e9661899b7252", + "created_on": "2014-01-01T05:20:00.12345Z", + "modified_on": "2014-02-01T05:20:00.12345Z", + "description": "Account Load Balancer", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "abd90f38ced07c2e2f4df50b1f61d4194" + ] + }, + "pop_pools": { + "LAX": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.2, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + } + }, + "adaptive_routing": { + "failover_across_pools": true + }, + "location_strategy": { + "prefer_ecs": "always", + "mode": "resolver_ip" + }, + "rules": [ + { + "name": "example rule", + "condition": "cf.load_balancer.region == \"SAF\"", + "overrides": { + "region_pools": { + "SAF": ["de90f38ced07c2e2f4df50b1f61d4194"] + }, + "adaptive_routing": { + "failover_across_pools": false + }, + "location_strategy": { + "prefer_ecs": "never", + "mode": "pop" + } + } + } + ], + "proxied": true, + "session_affinity": "cookie", + "session_affinity_ttl": 5000, + "session_affinity_attributes": { + "samesite": "Strict", + "secure": "Always", + "drain_duration": 60, + "zero_downtime_failover": "sticky" + } + } + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/load_balancers", handler) + createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2014-02-01T05:20:00.12345Z") + want := LoadBalancer{ + ID: "699d98642c564d2e855e9661899b7252", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + Description: "Account Load Balancer", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + CountryPools: map[string][]string{ + "US": { + "de90f38ced07c2e2f4df50b1f61d4194", + }, + "GB": { + "abd90f38ced07c2e2f4df50b1f61d4194", + }, + }, + PopPools: map[string][]string{ + "LAX": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "LHR": { + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", + }, + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.2, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4, + }, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(true), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "always", + Mode: "resolver_ip", + }, + Rules: []*LoadBalancerRule{ + { + Name: "example rule", + Condition: "cf.load_balancer.region == \"SAF\"", + Overrides: LoadBalancerRuleOverrides{ + RegionPools: map[string][]string{ + "SAF": {"de90f38ced07c2e2f4df50b1f61d4194"}, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(false), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "never", + Mode: "pop", + }, + }, + }, + }, + Proxied: true, + Persistence: "cookie", + PersistenceTTL: 5000, + SessionAffinityAttributes: &SessionAffinityAttributes{ + SameSite: "Strict", + Secure: "Always", + DrainDuration: 60, + ZeroDowntimeFailover: "sticky", + }, + } + request := LoadBalancer{ + Description: "Account Load Balancer", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + CountryPools: map[string][]string{ + "US": { + "de90f38ced07c2e2f4df50b1f61d4194", + }, + "GB": { + "abd90f38ced07c2e2f4df50b1f61d4194", + }, + }, + PopPools: map[string][]string{ + "LAX": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "LHR": { + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", + }, + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.2, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4, + }, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(true), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "always", + Mode: "resolver_ip", + }, + Rules: []*LoadBalancerRule{ + { + Name: "example rule", + Condition: "cf.load_balancer.region == \"SAF\"", + Overrides: LoadBalancerRuleOverrides{ + RegionPools: map[string][]string{ + "SAF": {"de90f38ced07c2e2f4df50b1f61d4194"}, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(false), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "never", + Mode: "pop", + }, + }, + }, + }, + Proxied: true, + Persistence: "cookie", + PersistenceTTL: 5000, + SessionAffinityAttributes: &SessionAffinityAttributes{ + SameSite: "Strict", + Secure: "Always", + DrainDuration: 60, + ZeroDowntimeFailover: "sticky", + }, + } + + actual, err := client.CreateLoadBalancer(context.Background(), AccountIdentifier(testAccountID), CreateLoadBalancerParams{LoadBalancer: request}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListLoadBalancers(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "699d98642c564d2e855e9661899b7252", + "created_on": "2014-01-01T05:20:00.12345Z", + "modified_on": "2014-02-01T05:20:00.12345Z", + "description": "Load Balancer for www.example.com", + "name": "www.example.com", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "abd90f38ced07c2e2f4df50b1f61d4194" + ] + }, + "pop_pools": { + "LAX": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.2, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + } + }, + "adaptive_routing": { + "failover_across_pools": true + }, + "location_strategy": { + "prefer_ecs": "always", + "mode": "resolver_ip" + }, + "proxied": true + } + ], + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 1 + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/load_balancers", handler) + createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2014-02-01T05:20:00.12345Z") + want := []LoadBalancer{ + { + ID: "699d98642c564d2e855e9661899b7252", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + Description: "Load Balancer for www.example.com", + Name: "www.example.com", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + CountryPools: map[string][]string{ + "US": { + "de90f38ced07c2e2f4df50b1f61d4194", + }, + "GB": { + "abd90f38ced07c2e2f4df50b1f61d4194", + }, + }, + PopPools: map[string][]string{ + "LAX": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "LHR": { + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", + }, + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.2, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4, + }, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(true), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "always", + Mode: "resolver_ip", + }, + Proxied: true, + }, + } + + actual, err := client.ListLoadBalancers(context.Background(), ZoneIdentifier(testZoneID), ListLoadBalancerParams{}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListAccountLoadBalancers(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "699d98642c564d2e855e9661899b7252", + "created_on": "2014-01-01T05:20:00.12345Z", + "modified_on": "2014-02-01T05:20:00.12345Z", + "description": "Account Load Balancer", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "abd90f38ced07c2e2f4df50b1f61d4194" + ] + }, + "pop_pools": { + "LAX": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.2, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + } + }, + "adaptive_routing": { + "failover_across_pools": true + }, + "location_strategy": { + "prefer_ecs": "always", + "mode": "resolver_ip" + }, + "proxied": true + } + ], + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 1 + } + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/load_balancers", handler) + createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2014-02-01T05:20:00.12345Z") + want := []LoadBalancer{ + { + ID: "699d98642c564d2e855e9661899b7252", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + Description: "Account Load Balancer", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + CountryPools: map[string][]string{ + "US": { + "de90f38ced07c2e2f4df50b1f61d4194", + }, + "GB": { + "abd90f38ced07c2e2f4df50b1f61d4194", + }, + }, + PopPools: map[string][]string{ + "LAX": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "LHR": { + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", + }, + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.2, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4, + }, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(true), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "always", + Mode: "resolver_ip", + }, + Proxied: true, + }, + } + + actual, err := client.ListLoadBalancers(context.Background(), AccountIdentifier(testAccountID), ListLoadBalancerParams{}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestGetLoadBalancer(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "699d98642c564d2e855e9661899b7252", + "created_on": "2014-01-01T05:20:00.12345Z", + "modified_on": "2014-02-01T05:20:00.12345Z", + "description": "Load Balancer for www.example.com", + "name": "www.example.com", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "abd90f38ced07c2e2f4df50b1f61d4194" + ] + }, + "pop_pools": { + "LAX": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.2, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + } + }, + "adaptive_routing": { + "failover_across_pools": true + }, + "location_strategy": { + "prefer_ecs": "always", + "mode": "resolver_ip" + }, + "proxied": true + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) + createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2014-02-01T05:20:00.12345Z") + want := LoadBalancer{ + ID: "699d98642c564d2e855e9661899b7252", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + Description: "Load Balancer for www.example.com", + Name: "www.example.com", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + CountryPools: map[string][]string{ + "US": { + "de90f38ced07c2e2f4df50b1f61d4194", + }, + "GB": { + "abd90f38ced07c2e2f4df50b1f61d4194", + }, + }, + PopPools: map[string][]string{ + "LAX": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "LHR": { + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", + }, + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.2, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4, + }, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(true), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "always", + Mode: "resolver_ip", + }, + Proxied: true, + } + + actual, err := client.GetLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "699d98642c564d2e855e9661899b7252") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) } + + _, err = client.GetLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "bar") + assert.Error(t, err) } -func TestListLoadBalancers(t *testing.T) { +func TestGetAccountLoadBalancer(t *testing.T) { setup() defer teardown() @@ -1470,164 +2268,250 @@ func TestListLoadBalancers(t *testing.T) { "success": true, "errors": [], "messages": [], - "result": [ - { - "id": "699d98642c564d2e855e9661899b7252", - "created_on": "2014-01-01T05:20:00.12345Z", - "modified_on": "2014-02-01T05:20:00.12345Z", - "description": "Load Balancer for www.example.com", - "name": "www.example.com", - "ttl": 30, - "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", - "default_pools": [ - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196", - "00920f38ce07c2e2f4df50b1f61d4194" - ], - "region_pools": { - "WNAM": [ - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196" - ], - "ENAM": [ - "00920f38ce07c2e2f4df50b1f61d4194" - ] - }, - "country_pools": { - "US": [ - "de90f38ced07c2e2f4df50b1f61d4194" - ], - "GB": [ - "abd90f38ced07c2e2f4df50b1f61d4194" - ] - }, - "pop_pools": { - "LAX": [ - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196" - ], - "LHR": [ - "abd90f38ced07c2e2f4df50b1f61d4194", - "f9138c5d07c2e2f4df57b1f61d4196" - ], - "SJC": [ - "00920f38ce07c2e2f4df50b1f61d4194" - ] - }, - "random_steering": { - "default_weight": 0.2, - "pool_weights": { - "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, - "de90f38ced07c2e2f4df50b1f61d4194": 0.4 - } - }, - "adaptive_routing": { - "failover_across_pools": true - }, - "location_strategy": { - "prefer_ecs": "always", - "mode": "resolver_ip" - }, - "proxied": true - } - ], - "result_info": { - "page": 1, - "per_page": 20, - "count": 1, - "total_count": 1 + "result": { + "id": "699d98642c564d2e855e9661899b7252", + "created_on": "2014-01-01T05:20:00.12345Z", + "modified_on": "2014-02-01T05:20:00.12345Z", + "description": "Account Load Balancer", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "abd90f38ced07c2e2f4df50b1f61d4194" + ] + }, + "pop_pools": { + "LAX": [ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.2, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + } + }, + "adaptive_routing": { + "failover_across_pools": true + }, + "location_strategy": { + "prefer_ecs": "always", + "mode": "resolver_ip" + }, + "proxied": true } }`) } - mux.HandleFunc("/zones/"+testZoneID+"/load_balancers", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") modifiedOn, _ := time.Parse(time.RFC3339, "2014-02-01T05:20:00.12345Z") - want := []LoadBalancer{ - { - ID: "699d98642c564d2e855e9661899b7252", - CreatedOn: &createdOn, - ModifiedOn: &modifiedOn, - Description: "Load Balancer for www.example.com", - Name: "www.example.com", - TTL: 30, - FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", - DefaultPools: []string{ + want := LoadBalancer{ + ID: "699d98642c564d2e855e9661899b7252", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + Description: "Account Load Balancer", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { "de90f38ced07c2e2f4df50b1f61d4194", "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { "00920f38ce07c2e2f4df50b1f61d4194", }, - RegionPools: map[string][]string{ - "WNAM": { - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196", - }, - "ENAM": { - "00920f38ce07c2e2f4df50b1f61d4194", - }, + }, + CountryPools: map[string][]string{ + "US": { + "de90f38ced07c2e2f4df50b1f61d4194", }, - CountryPools: map[string][]string{ - "US": { - "de90f38ced07c2e2f4df50b1f61d4194", - }, - "GB": { - "abd90f38ced07c2e2f4df50b1f61d4194", - }, + "GB": { + "abd90f38ced07c2e2f4df50b1f61d4194", }, - PopPools: map[string][]string{ - "LAX": { - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196", - }, - "LHR": { - "abd90f38ced07c2e2f4df50b1f61d4194", - "f9138c5d07c2e2f4df57b1f61d4196", - }, - "SJC": { - "00920f38ce07c2e2f4df50b1f61d4194", - }, + }, + PopPools: map[string][]string{ + "LAX": { + "de90f38ced07c2e2f4df50b1f61d4194", + "9290f38c5d07c2e2f4df57b1f61d4196", }, - RandomSteering: &RandomSteering{ - DefaultWeight: 0.2, - PoolWeights: map[string]float64{ - "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, - "de90f38ced07c2e2f4df50b1f61d4194": 0.4, - }, + "LHR": { + "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", }, - AdaptiveRouting: &AdaptiveRouting{ - FailoverAcrossPools: BoolPtr(true), + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", }, - LocationStrategy: &LocationStrategy{ - PreferECS: "always", - Mode: "resolver_ip", + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.2, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, + "de90f38ced07c2e2f4df50b1f61d4194": 0.4, }, - Proxied: true, }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(true), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "always", + Mode: "resolver_ip", + }, + Proxied: true, + } + + actual, err := client.GetLoadBalancer(context.Background(), AccountIdentifier(testAccountID), "699d98642c564d2e855e9661899b7252") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } + + _, err = client.GetLoadBalancer(context.Background(), AccountIdentifier(testAccountID), "bar") + assert.Error(t, err) +} + +func TestDeleteLoadBalancer(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "699d98642c564d2e855e9661899b7252" + } + }`) } - actual, err := client.ListLoadBalancers(context.Background(), ZoneIdentifier(testZoneID), ListLoadBalancerParams{}) - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } + mux.HandleFunc("/zones/"+testZoneID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) + assert.NoError(t, client.DeleteLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "699d98642c564d2e855e9661899b7252")) + assert.Error(t, client.DeleteLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "bar")) } -func TestListLoadBalancer_AccountIsNotSupported(t *testing.T) { +func TestDeleteAccountLoadBalancer(t *testing.T) { setup() defer teardown() - _, err := client.ListLoadBalancers(context.Background(), AccountIdentifier(testAccountID), ListLoadBalancerParams{}) - if assert.Error(t, err) { - assert.Equal(t, fmt.Sprintf(errInvalidResourceContainerAccess, AccountRouteLevel), err.Error()) + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "699d98642c564d2e855e9661899b7252" + } + }`) } + + mux.HandleFunc("/accounts/"+testAccountID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) + assert.NoError(t, client.DeleteLoadBalancer(context.Background(), AccountIdentifier(testAccountID), "699d98642c564d2e855e9661899b7252")) + assert.Error(t, client.DeleteLoadBalancer(context.Background(), AccountIdentifier(testAccountID), "bar")) } -func TestGetLoadBalancer(t *testing.T) { +func TestUpdateLoadBalancer(t *testing.T) { setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) w.Header().Set("content-type", "application/json") + b, err := io.ReadAll(r.Body) + defer r.Body.Close() + if assert.NoError(t, err) { + assert.JSONEq(t, `{ + "id": "699d98642c564d2e855e9661899b7252", + "description": "Load Balancer for www.example.com", + "name": "www.example.com", + "ttl": 30, + "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", + "default_pools": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ], + "region_pools": { + "WNAM": [ + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "ENAM": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "country_pools": { + "US": [ + "de90f38ced07c2e2f4df50b1f61d4194" + ], + "GB": [ + "f9138c5d07c2e2f4df57b1f61d4196" + ] + }, + "pop_pools": { + "LAX": [ + "9290f38c5d07c2e2f4df57b1f61d4196" + ], + "LHR": [ + "f9138c5d07c2e2f4df57b1f61d4196" + ], + "SJC": [ + "00920f38ce07c2e2f4df50b1f61d4194" + ] + }, + "random_steering": { + "default_weight": 0.5, + "pool_weights": { + "9290f38c5d07c2e2f4df57b1f61d4196": 0.2 + } + }, + "adaptive_routing": { + "failover_across_pools": false + }, + "location_strategy": { + "prefer_ecs": "never", + "mode": "pop" + }, + "proxied": true, + "session_affinity": "none", + "session_affinity_attributes": { + "samesite": "Strict", + "secure": "Always", + "zero_downtime_failover": "sticky" + } + }`, string(b)) + } fmt.Fprint(w, `{ "success": true, "errors": [], @@ -1635,19 +2519,16 @@ func TestGetLoadBalancer(t *testing.T) { "result": { "id": "699d98642c564d2e855e9661899b7252", "created_on": "2014-01-01T05:20:00.12345Z", - "modified_on": "2014-02-01T05:20:00.12345Z", + "modified_on": "2017-02-01T05:20:00.12345Z", "description": "Load Balancer for www.example.com", "name": "www.example.com", "ttl": 30, "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", "default_pools": [ - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196", "00920f38ce07c2e2f4df50b1f61d4194" ], "region_pools": { "WNAM": [ - "de90f38ced07c2e2f4df50b1f61d4194", "9290f38c5d07c2e2f4df57b1f61d4196" ], "ENAM": [ @@ -1659,16 +2540,14 @@ func TestGetLoadBalancer(t *testing.T) { "de90f38ced07c2e2f4df50b1f61d4194" ], "GB": [ - "abd90f38ced07c2e2f4df50b1f61d4194" + "f9138c5d07c2e2f4df57b1f61d4196" ] }, "pop_pools": { "LAX": [ - "de90f38ced07c2e2f4df50b1f61d4194", "9290f38c5d07c2e2f4df57b1f61d4196" ], "LHR": [ - "abd90f38ced07c2e2f4df50b1f61d4194", "f9138c5d07c2e2f4df57b1f61d4196" ], "SJC": [ @@ -1676,27 +2555,32 @@ func TestGetLoadBalancer(t *testing.T) { ] }, "random_steering": { - "default_weight": 0.2, + "default_weight": 0.5, "pool_weights": { - "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, - "de90f38ced07c2e2f4df50b1f61d4194": 0.4 + "9290f38c5d07c2e2f4df57b1f61d4196": 0.2 } }, "adaptive_routing": { - "failover_across_pools": true + "failover_across_pools": false }, "location_strategy": { - "prefer_ecs": "always", - "mode": "resolver_ip" + "prefer_ecs": "never", + "mode": "pop" }, - "proxied": true + "proxied": true, + "session_affinity": "none", + "session_affinity_attributes": { + "samesite": "Strict", + "secure": "Always", + "zero_downtime_failover": "sticky" + } } }`) } mux.HandleFunc("/zones/"+testZoneID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-02-01T05:20:00.12345Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2017-02-01T05:20:00.12345Z") want := LoadBalancer{ ID: "699d98642c564d2e855e9661899b7252", CreatedOn: &createdOn, @@ -1706,13 +2590,10 @@ func TestGetLoadBalancer(t *testing.T) { TTL: 30, FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", DefaultPools: []string{ - "de90f38ced07c2e2f4df50b1f61d4194", - "9290f38c5d07c2e2f4df57b1f61d4196", "00920f38ce07c2e2f4df50b1f61d4194", }, RegionPools: map[string][]string{ "WNAM": { - "de90f38ced07c2e2f4df50b1f61d4194", "9290f38c5d07c2e2f4df57b1f61d4196", }, "ENAM": { @@ -1724,16 +2605,71 @@ func TestGetLoadBalancer(t *testing.T) { "de90f38ced07c2e2f4df50b1f61d4194", }, "GB": { - "abd90f38ced07c2e2f4df50b1f61d4194", + "f9138c5d07c2e2f4df57b1f61d4196", }, }, PopPools: map[string][]string{ "LAX": { + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "LHR": { + "f9138c5d07c2e2f4df57b1f61d4196", + }, + "SJC": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + RandomSteering: &RandomSteering{ + DefaultWeight: 0.5, + PoolWeights: map[string]float64{ + "9290f38c5d07c2e2f4df57b1f61d4196": 0.2, + }, + }, + AdaptiveRouting: &AdaptiveRouting{ + FailoverAcrossPools: BoolPtr(false), + }, + LocationStrategy: &LocationStrategy{ + PreferECS: "never", + Mode: "pop", + }, + Proxied: true, + Persistence: "none", + SessionAffinityAttributes: &SessionAffinityAttributes{ + SameSite: "Strict", + Secure: "Always", + ZeroDowntimeFailover: "sticky", + }, + } + request := LoadBalancer{ + ID: "699d98642c564d2e855e9661899b7252", + Description: "Load Balancer for www.example.com", + Name: "www.example.com", + TTL: 30, + FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", + DefaultPools: []string{ + "00920f38ce07c2e2f4df50b1f61d4194", + }, + RegionPools: map[string][]string{ + "WNAM": { + "9290f38c5d07c2e2f4df57b1f61d4196", + }, + "ENAM": { + "00920f38ce07c2e2f4df50b1f61d4194", + }, + }, + CountryPools: map[string][]string{ + "US": { "de90f38ced07c2e2f4df50b1f61d4194", + }, + "GB": { + "f9138c5d07c2e2f4df57b1f61d4196", + }, + }, + PopPools: map[string][]string{ + "LAX": { "9290f38c5d07c2e2f4df57b1f61d4196", }, "LHR": { - "abd90f38ced07c2e2f4df50b1f61d4194", "f9138c5d07c2e2f4df57b1f61d4196", }, "SJC": { @@ -1741,74 +2677,34 @@ func TestGetLoadBalancer(t *testing.T) { }, }, RandomSteering: &RandomSteering{ - DefaultWeight: 0.2, + DefaultWeight: 0.5, PoolWeights: map[string]float64{ - "9290f38c5d07c2e2f4df57b1f61d4196": 0.6, - "de90f38ced07c2e2f4df50b1f61d4194": 0.4, + "9290f38c5d07c2e2f4df57b1f61d4196": 0.2, }, }, AdaptiveRouting: &AdaptiveRouting{ - FailoverAcrossPools: BoolPtr(true), + FailoverAcrossPools: BoolPtr(false), }, LocationStrategy: &LocationStrategy{ - PreferECS: "always", - Mode: "resolver_ip", + PreferECS: "never", + Mode: "pop", + }, + Proxied: true, + Persistence: "none", + SessionAffinityAttributes: &SessionAffinityAttributes{ + SameSite: "Strict", + Secure: "Always", + ZeroDowntimeFailover: "sticky", }, - Proxied: true, } - actual, err := client.GetLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "699d98642c564d2e855e9661899b7252") + actual, err := client.UpdateLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), UpdateLoadBalancerParams{LoadBalancer: request}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } - - _, err = client.GetLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "bar") - assert.Error(t, err) -} - -func TestGetLoadBalancer_AccountIsNotSupported(t *testing.T) { - setup() - defer teardown() - - _, err := client.GetLoadBalancer(context.Background(), AccountIdentifier(testAccountID), "foo") - if assert.Error(t, err) { - assert.Equal(t, fmt.Sprintf(errInvalidResourceContainerAccess, AccountRouteLevel), err.Error()) - } -} - -func TestDeleteLoadBalancer(t *testing.T) { - setup() - defer teardown() - - handler := func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "699d98642c564d2e855e9661899b7252" - } - }`) - } - - mux.HandleFunc("/zones/"+testZoneID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) - assert.NoError(t, client.DeleteLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "699d98642c564d2e855e9661899b7252")) - assert.Error(t, client.DeleteLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), "bar")) -} - -func TestDeleteLoadBalancer_AccountIsNotSupported(t *testing.T) { - setup() - defer teardown() - - err := client.DeleteLoadBalancer(context.Background(), AccountIdentifier(testAccountID), "foo") - if assert.Error(t, err) { - assert.Equal(t, fmt.Sprintf(errInvalidResourceContainerAccess, AccountRouteLevel), err.Error()) - } } -func TestUpdateLoadBalancer(t *testing.T) { +func TestUpdateAccountLoadBalancer(t *testing.T) { setup() defer teardown() @@ -1820,8 +2716,7 @@ func TestUpdateLoadBalancer(t *testing.T) { if assert.NoError(t, err) { assert.JSONEq(t, `{ "id": "699d98642c564d2e855e9661899b7252", - "description": "Load Balancer for www.example.com", - "name": "www.example.com", + "description": "Account Load Balancer", "ttl": 30, "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", "default_pools": [ @@ -1884,8 +2779,7 @@ func TestUpdateLoadBalancer(t *testing.T) { "id": "699d98642c564d2e855e9661899b7252", "created_on": "2014-01-01T05:20:00.12345Z", "modified_on": "2017-02-01T05:20:00.12345Z", - "description": "Load Balancer for www.example.com", - "name": "www.example.com", + "description": "Account Load Balancer", "ttl": 30, "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4", "default_pools": [ @@ -1942,15 +2836,14 @@ func TestUpdateLoadBalancer(t *testing.T) { }`) } - mux.HandleFunc("/zones/"+testZoneID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/load_balancers/699d98642c564d2e855e9661899b7252", handler) createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") modifiedOn, _ := time.Parse(time.RFC3339, "2017-02-01T05:20:00.12345Z") want := LoadBalancer{ ID: "699d98642c564d2e855e9661899b7252", CreatedOn: &createdOn, ModifiedOn: &modifiedOn, - Description: "Load Balancer for www.example.com", - Name: "www.example.com", + Description: "Account Load Balancer", TTL: 30, FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", DefaultPools: []string{ @@ -2006,8 +2899,7 @@ func TestUpdateLoadBalancer(t *testing.T) { } request := LoadBalancer{ ID: "699d98642c564d2e855e9661899b7252", - Description: "Load Balancer for www.example.com", - Name: "www.example.com", + Description: "Account Load Balancer", TTL: 30, FallbackPool: "17b5962d775c646f3f9725cbc7a53df4", DefaultPools: []string{ @@ -2062,22 +2954,12 @@ func TestUpdateLoadBalancer(t *testing.T) { }, } - actual, err := client.UpdateLoadBalancer(context.Background(), ZoneIdentifier(testZoneID), UpdateLoadBalancerParams{LoadBalancer: request}) + actual, err := client.UpdateLoadBalancer(context.Background(), AccountIdentifier(testAccountID), UpdateLoadBalancerParams{LoadBalancer: request}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestUpdateLoadBalancer_AccountIsNotSupported(t *testing.T) { - setup() - defer teardown() - - _, err := client.UpdateLoadBalancer(context.Background(), AccountIdentifier(testAccountID), UpdateLoadBalancerParams{LoadBalancer: LoadBalancer{}}) - if assert.Error(t, err) { - assert.Equal(t, fmt.Sprintf(errInvalidResourceContainerAccess, AccountRouteLevel), err.Error()) - } -} - func TestLoadBalancerPoolHealthDetails(t *testing.T) { setup() defer teardown() From 3df27db83f80e0fd61a80ad36d598320afc5e345 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 11 Sep 2024 12:38:06 +1000 Subject: [PATCH 48/84] refactor(load_balancing): collapse check and reuse rc.Level --- load_balancing.go | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/load_balancing.go b/load_balancing.go index 107a49f9d95..6100b5eaf58 100644 --- a/load_balancing.go +++ b/load_balancing.go @@ -689,10 +689,8 @@ func (api *API) CreateLoadBalancer(ctx context.Context, rc *ResourceContainer, p var uri string switch rc.Level { - case ZoneRouteLevel: - uri = fmt.Sprintf("/zones/%s/load_balancers", rc.Identifier) - case AccountRouteLevel: - uri = fmt.Sprintf("/accounts/%s/load_balancers", rc.Identifier) + case AccountRouteLevel, ZoneRouteLevel: + uri = fmt.Sprintf("/%s/%s/load_balancers", rc.Level, rc.Identifier) default: return LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -715,10 +713,8 @@ func (api *API) ListLoadBalancers(ctx context.Context, rc *ResourceContainer, pa var uri string switch rc.Level { - case ZoneRouteLevel: - uri = fmt.Sprintf("/zones/%s/load_balancers", rc.Identifier) - case AccountRouteLevel: - uri = fmt.Sprintf("/accounts/%s/load_balancers", rc.Identifier) + case AccountRouteLevel, ZoneRouteLevel: + uri = fmt.Sprintf("/%s/%s/load_balancers", rc.Level, rc.Identifier) default: return nil, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -744,10 +740,8 @@ func (api *API) GetLoadBalancer(ctx context.Context, rc *ResourceContainer, load var uri string switch rc.Level { - case ZoneRouteLevel: - uri = fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, loadbalancerID) - case AccountRouteLevel: - uri = fmt.Sprintf("/accounts/%s/load_balancers/%s", rc.Identifier, loadbalancerID) + case AccountRouteLevel, ZoneRouteLevel: + uri = fmt.Sprintf("/%s/%s/load_balancers/%s", rc.Level, rc.Identifier, loadbalancerID) default: return LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -774,10 +768,8 @@ func (api *API) DeleteLoadBalancer(ctx context.Context, rc *ResourceContainer, l var uri string switch rc.Level { - case ZoneRouteLevel: - uri = fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, loadbalancerID) - case AccountRouteLevel: - uri = fmt.Sprintf("/accounts/%s/load_balancers/%s", rc.Identifier, loadbalancerID) + case AccountRouteLevel, ZoneRouteLevel: + uri = fmt.Sprintf("/%s/%s/load_balancers/%s", rc.Level, rc.Identifier, loadbalancerID) default: return fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -799,10 +791,8 @@ func (api *API) UpdateLoadBalancer(ctx context.Context, rc *ResourceContainer, p var uri string switch rc.Level { - case ZoneRouteLevel: - uri = fmt.Sprintf("/zones/%s/load_balancers/%s", rc.Identifier, params.LoadBalancer.ID) - case AccountRouteLevel: - uri = fmt.Sprintf("/accounts/%s/load_balancers/%s", rc.Identifier, params.LoadBalancer.ID) + case AccountRouteLevel, ZoneRouteLevel: + uri = fmt.Sprintf("/%s/%s/load_balancers/%s", rc.Level, rc.Identifier, params.LoadBalancer.ID) default: return LoadBalancer{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } From 1f3b024db81118ffcc99ea97b8a85ec11c16a7ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 02:41:34 +0000 Subject: [PATCH 49/84] Bump golang.org/x/time from 0.5.0 to 0.6.0 Bumps [golang.org/x/time](https://github.com/golang/time) from 0.5.0 to 0.6.0. - [Commits](https://github.com/golang/time/compare/v0.5.0...v0.6.0) --- updated-dependencies: - dependency-name: golang.org/x/time dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b64ca565af2..f2158ba6ff7 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.4 golang.org/x/net v0.29.0 - golang.org/x/time v0.5.0 + golang.org/x/time v0.6.0 ) require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index 7a67d956d66..23a7b427553 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 313ac03bae361f347f64ead7baddf3ac6dc08708 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Sep 2024 02:41:47 +0000 Subject: [PATCH 50/84] add CHANGELOG for #2816 --- .changelog/2816.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2816.txt diff --git a/.changelog/2816.txt b/.changelog/2816.txt new file mode 100644 index 00000000000..9d9a5676be9 --- /dev/null +++ b/.changelog/2816.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/time from 0.5.0 to 0.6.0 +``` From da8f52c0e036e47b6f578da53d2557bfdec5026f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 11 Sep 2024 12:45:00 +1000 Subject: [PATCH 51/84] generate changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c208e1b2d20..51d544c3713 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ ## 0.104.0 (Unreleased) +BREAKING CHANGES: + +* dns: removed deprecated `ZoneID` and `ZoneName` fields ([#2986](https://github.com/cloudflare/cloudflare-go/issues/2986)) + +ENHANCEMENTS: + +* bot_management: add ai_bots_protection to public API ([#2974](https://github.com/cloudflare/cloudflare-go/issues/2974)) + +DEPENDENCIES: + +* deps: bumps golang.org/x/net from 0.28.0 to 0.29.0 ([#3030](https://github.com/cloudflare/cloudflare-go/issues/3030)) +* deps: bumps golang.org/x/time from 0.5.0 to 0.6.0 ([#2816](https://github.com/cloudflare/cloudflare-go/issues/2816)) + ## 0.103.0 (August 28th, 2024) ENHANCEMENTS: From 8743749c8ce71e82a506005135ac90f1120fc061 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 11 Sep 2024 12:45:51 +1000 Subject: [PATCH 52/84] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51d544c3713..ee95151596b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.104.0 (Unreleased) +## 0.105.0 (Unreleased) + +## 0.104.0 (September 11th, 2024) BREAKING CHANGES: From bb420fe58a5d095e20cbf2383c84ff514a7b738e Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Thu, 19 Sep 2024 09:02:12 -0700 Subject: [PATCH 53/84] Add CRUD endpoints for infrastructure access endpoints --- .changelog/3183.txt | 3 + infrastructure_targets.go | 236 +++++++++++++++++++++++++++ infrastructure_targets_test.go | 287 +++++++++++++++++++++++++++++++++ 3 files changed, 526 insertions(+) create mode 100644 .changelog/3183.txt create mode 100644 infrastructure_targets.go create mode 100644 infrastructure_targets_test.go diff --git a/.changelog/3183.txt b/.changelog/3183.txt new file mode 100644 index 00000000000..69e4ec2d5eb --- /dev/null +++ b/.changelog/3183.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +infrastructure_targets: initialize CRUD endpoints for infrastructure access endpoints +``` \ No newline at end of file diff --git a/infrastructure_targets.go b/infrastructure_targets.go new file mode 100644 index 00000000000..7c6e5cb658a --- /dev/null +++ b/infrastructure_targets.go @@ -0,0 +1,236 @@ +package cloudflare + +import ( + "context" + "errors" + "fmt" + "net/http" + "time" + + "github.com/goccy/go-json" +) + +var ErrMissingTargetId = errors.New("required target id missing") + +// AccessApplication represents an Access application. +type Target struct { + Hostname string `json:"hostname"` + ID string `json:"id"` + IP IPInfo `json:"ip"` + CreatedAt time.Time `json:"created_at"` + ModifiedAt time.Time `json:"modified_at"` +} + +type IPDetails struct { + IpAddr string `json:"ip_addr"` + VirtualNetworkId string `json:"virtual_network_id"` +} + +type IPInfo struct { + IPV4 *IPDetails `json:"ipv4,omitempty"` + IPV6 *IPDetails `json:"ipv6,omitempty"` +} + +type InfrastructureTargetParams struct { + Hostname string `json:"hostname"` + IP IPInfo `json:"ip"` +} + +type CreateInfrastructureTargetParams struct { + InfrastructureTargetParams +} + +type UpdateInfrastructureTargetParams struct { + ID string `json:"hostname"` + ModifyParams InfrastructureTargetParams `json:"modify_params"` +} + +// TargetDetailResponse is the API response, containing a single access target. +type TargetDetailResponse struct { + Result Target `json:"result"` + Response +} + +type TargetListDetailResponse struct { + Result []Target `json:"result"` + Response + ResultInfo `json:"result_info"` +} + +type TargetListParams struct { + CreatedAfter string `url:"created_after,omitempty"` + Hostname string `url:"hostname,omitempty"` + HostnameContains string `url:"hostname_contains,omitempty"` + IPV4 string `url:"ip_v4,omitempty"` + IPV6 string `url:"ip_v6,omitempty"` + ModifedAfter string `url:"modified_after,omitempty"` + VirtualNetworkId string `url:"virtual_network_id,omitempty"` + + ResultInfo +} + +// ListInfrastructureTargets returns all applications within an account or zone. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-list +func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceContainer, params TargetListParams) ([]Target, *ResultInfo, error) { + if rc.Identifier == "" { + return []Target{}, &ResultInfo{}, ErrMissingAccountID + } + + baseURL := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) + + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } + + if params.PerPage < 1 { + params.PerPage = 25 + } + + if params.Page < 1 { + params.Page = 1 + } + + var applications []Target + var r TargetListDetailResponse + + for { + uri := buildURI(baseURL, params) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []Target{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []Target{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + applications = append(applications, r.Result...) + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { + break + } + } + + return applications, &r.ResultInfo, nil +} + +// CreateInfrastructureTarget creates a new infrastructure target. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-post +func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureTargetParams) (Target, error) { + if rc.Identifier == "" { + return Target{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return Target{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var targetDetailResponse TargetDetailResponse + err = json.Unmarshal(res, &targetDetailResponse) + if err != nil { + return Target{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return targetDetailResponse.Result, nil +} + +// UpdateInfrastructureTarget updates an existing infrastructure target. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-put +func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureTargetParams) (Target, error) { + if rc.Identifier == "" { + return Target{}, ErrMissingAccountID + } + + if params.ID == "" { + return Target{}, ErrMissingTargetId + } + + uri := fmt.Sprintf( + "/%s/%s/infrastructure/targets/%s", + rc.Level, + rc.Identifier, + params.ID, + ) + + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.ModifyParams) + if err != nil { + return Target{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var targetDetailResponse TargetDetailResponse + err = json.Unmarshal(res, &targetDetailResponse) + if err != nil { + return Target{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return targetDetailResponse.Result, nil +} + +// GetInfrastructureTarget returns a single infrastructure target based on target ID +// ID for either account or zone. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-get +func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) (Target, error) { + if rc.Identifier == "" { + return Target{}, ErrMissingAccountID + } + + if targetID == "" { + return Target{}, ErrMissingTargetId + } + + uri := fmt.Sprintf( + "/%s/%s/infrastructure/targets/%s", + rc.Level, + rc.Identifier, + targetID, + ) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return Target{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var targetDetailResponse TargetDetailResponse + err = json.Unmarshal(res, &targetDetailResponse) + if err != nil { + return Target{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return targetDetailResponse.Result, nil +} + +// DeleteInfrastructureTarget deletes an infrastructure target. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-delete +func (api *API) DeleteInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) error { + if rc.Identifier == "" { + return ErrMissingAccountID + } + + if targetID == "" { + return ErrMissingTargetId + } + + uri := fmt.Sprintf( + "/%s/%s/infrastructure/targets/%s", + rc.Level, + rc.Identifier, + targetID, + ) + + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + return nil +} diff --git a/infrastructure_targets_test.go b/infrastructure_targets_test.go new file mode 100644 index 00000000000..5b587d9ec1f --- /dev/null +++ b/infrastructure_targets_test.go @@ -0,0 +1,287 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +// randomly generated uuid +const testInfrastructureTargetId = "019205b5-97d7-7272-b00e-0ea05e61a124" + +var ( + infrastrctureTargetCreatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") + infrastrctureTargetModifiedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") + expectedInfrastructureTarget = Target{ + Hostname: "infra-access-target", + ID: testInfrastructureTargetId, + IP: IPInfo{ + IPV4: &IPDetails{ + IpAddr: "187.26.29.249", + VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", + }, + IPV6: &IPDetails{ + IpAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", + }, + }, + CreatedAt: infrastrctureTargetCreatedOn, + ModifiedAt: infrastrctureTargetModifiedOn, + } + expectedInfrastructureModified = Target{ + Hostname: "infra-access-target-modified", + ID: testInfrastructureTargetId, + IP: IPInfo{ + IPV4: &IPDetails{ + IpAddr: "250.26.29.250", + VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", + }, + }, + CreatedAt: infrastrctureTargetCreatedOn, + ModifiedAt: infrastrctureTargetModifiedOn, + } +) + +func TestInfrastructureTarget_Create(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` + { + "success": true, + "errors": [], + "messages": [], + "result": { + "created_at": "2024-08-25T05:00:22Z", + "hostname": "infra-access-target", + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "ip": { + "ipv4": { + "ip_addr": "187.26.29.249", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + }, + "ipv6": { + "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + } + }, + "modified_at": "2024-08-25T05:00:22Z" + } + }`) + }) + + // Make sure missing account ID is thrown + _, err := client.CreateInfrastructureTarget(context.Background(), AccountIdentifier(""), CreateInfrastructureTargetParams{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + out, err := client.CreateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), CreateInfrastructureTargetParams{ + InfrastructureTargetParams: InfrastructureTargetParams{ + Hostname: "infra-access-target", + IP: IPInfo{ + IPV4: &IPDetails{ + IpAddr: "187.26.29.249", + VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", + }, + IPV6: &IPDetails{ + IpAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", + }, + }, + }, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureTarget, out, "create infrastructure_target structs not equal") + } +} + +func TestInfrastructureTarget_List(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "created_at": "2024-08-25T05:00:22Z", + "hostname": "infra-access-target", + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "ip": { + "ipv4": { + "ip_addr": "187.26.29.249", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + }, + "ipv6": { + "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + } + }, + "modified_at": "2024-08-25T05:00:22Z" + } + ], + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 1 + } +}`) + }) + + _, _, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(""), TargetListParams{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + out, results, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(testAccountID), TargetListParams{}) + if assert.NoError(t, err) { + assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") + assert.Equal(t, 20, results.PerPage, "expected 20 per page") + assert.Equal(t, expectedInfrastructureTarget, out[0], "list challenge_widgets structs not equal") + } +} + +func TestInfrastructureTarget_Get(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureTargetId, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "created_at": "2024-08-25T05:00:22Z", + "hostname": "infra-access-target", + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "ip": { + "ipv4": { + "ip_addr": "187.26.29.249", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + }, + "ipv6": { + "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + } + }, + "modified_at": "2024-08-25T05:00:22Z" + } +}`) + }) + + _, err := client.GetInfrastructureTarget(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.GetInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingTargetId, err) + } + + out, err := client.GetInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), testInfrastructureTargetId) + + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureTarget, out, "get infrastructure_target not equal to expected") + } +} + +func TestInfrastructureTarget_Update(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureTargetId, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "created_at": "2024-08-25T05:00:22Z", + "hostname": "infra-access-target-modified", + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "ip": { + "ipv4": { + "ip_addr": "250.26.29.250", + "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" + } + }, + "modified_at": "2024-08-25T05:00:22Z" + } +}`) + }) + + _, err := client.UpdateInfrastructureTarget(context.Background(), AccountIdentifier(""), UpdateInfrastructureTargetParams{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.UpdateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureTargetParams{ + ID: "", + ModifyParams: InfrastructureTargetParams{}, + }) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingTargetId, err) + } + + out, err := client.UpdateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureTargetParams{ + ID: testInfrastructureTargetId, + ModifyParams: InfrastructureTargetParams{ + // Updates hostname and IPv4 address. Deletes IPv6 address. + Hostname: "infra-access-target-modified", + IP: IPInfo{ + IPV4: &IPDetails{ + IpAddr: "250.26.29.250", + VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", + }, + }, + }, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureModified, out, "update challenge_widgets structs not equal") + } +} + +func TestInfrastructureTarget_Delete(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureTargetId, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ``) + }) + + // Make sure missing account ID is thrown + err := client.DeleteInfrastructureTarget(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + err = client.DeleteInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingTargetId, err) + } + + err = client.DeleteInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), testInfrastructureTargetId) + assert.NoError(t, err) +} From e35d0b357f1e43e7ad0bdd5f7fe8ba4eb8e3458d Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Thu, 19 Sep 2024 09:13:57 -0700 Subject: [PATCH 54/84] Update comments --- infrastructure_targets.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure_targets.go b/infrastructure_targets.go index 7c6e5cb658a..3f4840e7385 100644 --- a/infrastructure_targets.go +++ b/infrastructure_targets.go @@ -12,7 +12,7 @@ import ( var ErrMissingTargetId = errors.New("required target id missing") -// AccessApplication represents an Access application. +// Target represents an Infrastructure Target. type Target struct { Hostname string `json:"hostname"` ID string `json:"id"` @@ -45,7 +45,7 @@ type UpdateInfrastructureTargetParams struct { ModifyParams InfrastructureTargetParams `json:"modify_params"` } -// TargetDetailResponse is the API response, containing a single access target. +// TargetDetailResponse is the API response, containing a single target. type TargetDetailResponse struct { Result Target `json:"result"` Response From 287166f31592c1e5e2c1bbbb3a6025e69826b1b4 Mon Sep 17 00:00:00 2001 From: hrushikeshdeshpande <161167942+hrushikeshdeshpande@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:01:41 -0400 Subject: [PATCH 55/84] Adding semgrep.yml for Secrets scanning and more --- .github/workflows/semgrep.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/semgrep.yml diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml new file mode 100644 index 00000000000..b40314b3677 --- /dev/null +++ b/.github/workflows/semgrep.yml @@ -0,0 +1,24 @@ +on: + pull_request: {} + workflow_dispatch: {} + push: + branches: + - main + - master + schedule: + - cron: '0 0 * * *' +name: Semgrep config +jobs: + semgrep: + name: semgrep/ci + runs-on: ubuntu-latest + env: + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + SEMGREP_URL: https://cloudflare.semgrep.dev + SEMGREP_APP_URL: https://cloudflare.semgrep.dev + SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version + container: + image: returntocorp/semgrep + steps: + - uses: actions/checkout@v4 + - run: semgrep ci From 4b8e58d9847cef3892d80fdf720e844aa672ab6b Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 23 Sep 2024 12:32:05 +1000 Subject: [PATCH 56/84] s/IpAddr/IPAddr Signed-off-by: Jacob Bednarz --- infrastructure_targets.go | 12 ++++++------ infrastructure_targets_test.go | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/infrastructure_targets.go b/infrastructure_targets.go index 3f4840e7385..2560879e316 100644 --- a/infrastructure_targets.go +++ b/infrastructure_targets.go @@ -22,7 +22,7 @@ type Target struct { } type IPDetails struct { - IpAddr string `json:"ip_addr"` + IPAddr string `json:"ip_addr"` VirtualNetworkId string `json:"virtual_network_id"` } @@ -71,7 +71,7 @@ type TargetListParams struct { // ListInfrastructureTargets returns all applications within an account or zone. // -// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-list +// API reference: https://developers.cloudflare.com/api/operations/infra-targets-list func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceContainer, params TargetListParams) ([]Target, *ResultInfo, error) { if rc.Identifier == "" { return []Target{}, &ResultInfo{}, ErrMissingAccountID @@ -119,7 +119,7 @@ func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceConta // CreateInfrastructureTarget creates a new infrastructure target. // -// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-post +// API reference: https://developers.cloudflare.com/api/operations/infra-targets-post func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureTargetParams) (Target, error) { if rc.Identifier == "" { return Target{}, ErrMissingAccountID @@ -143,7 +143,7 @@ func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceCont // UpdateInfrastructureTarget updates an existing infrastructure target. // -// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-put +// API reference: https://developers.cloudflare.com/api/operations/infra-targets-put func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureTargetParams) (Target, error) { if rc.Identifier == "" { return Target{}, ErrMissingAccountID @@ -177,7 +177,7 @@ func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceCont // GetInfrastructureTarget returns a single infrastructure target based on target ID // ID for either account or zone. // -// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-get +// API reference: https://developers.cloudflare.com/api/operations/infra-targets-get func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) (Target, error) { if rc.Identifier == "" { return Target{}, ErrMissingAccountID @@ -210,7 +210,7 @@ func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContain // DeleteInfrastructureTarget deletes an infrastructure target. // -// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-delete +// API reference: https://developers.cloudflare.com/api/operations/infra-targets-delete func (api *API) DeleteInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) error { if rc.Identifier == "" { return ErrMissingAccountID diff --git a/infrastructure_targets_test.go b/infrastructure_targets_test.go index 5b587d9ec1f..7fd2bedfd28 100644 --- a/infrastructure_targets_test.go +++ b/infrastructure_targets_test.go @@ -21,11 +21,11 @@ var ( ID: testInfrastructureTargetId, IP: IPInfo{ IPV4: &IPDetails{ - IpAddr: "187.26.29.249", + IPAddr: "187.26.29.249", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, IPV6: &IPDetails{ - IpAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + IPAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, @@ -37,7 +37,7 @@ var ( ID: testInfrastructureTargetId, IP: IPInfo{ IPV4: &IPDetails{ - IpAddr: "250.26.29.250", + IPAddr: "250.26.29.250", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, @@ -88,11 +88,11 @@ func TestInfrastructureTarget_Create(t *testing.T) { Hostname: "infra-access-target", IP: IPInfo{ IPV4: &IPDetails{ - IpAddr: "187.26.29.249", + IPAddr: "187.26.29.249", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, IPV6: &IPDetails{ - IpAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + IPAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, @@ -250,7 +250,7 @@ func TestInfrastructureTarget_Update(t *testing.T) { Hostname: "infra-access-target-modified", IP: IPInfo{ IPV4: &IPDetails{ - IpAddr: "250.26.29.250", + IPAddr: "250.26.29.250", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, From 4d8d0bb43a3dcc4f48bfa236a91611425cd73fbb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 23 Sep 2024 12:38:13 +1000 Subject: [PATCH 57/84] namespace all structs Signed-off-by: Jacob Bednarz --- infrastructure_targets.go | 84 +++++++++++++++++----------------- infrastructure_targets_test.go | 54 +++++++++++----------- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/infrastructure_targets.go b/infrastructure_targets.go index 2560879e316..fbb4f319aaf 100644 --- a/infrastructure_targets.go +++ b/infrastructure_targets.go @@ -12,28 +12,28 @@ import ( var ErrMissingTargetId = errors.New("required target id missing") -// Target represents an Infrastructure Target. -type Target struct { - Hostname string `json:"hostname"` - ID string `json:"id"` - IP IPInfo `json:"ip"` - CreatedAt time.Time `json:"created_at"` - ModifiedAt time.Time `json:"modified_at"` +// InfrastructureTarget represents an Infrastructure InfrastructureTarget. +type InfrastructureTarget struct { + Hostname string `json:"hostname"` + ID string `json:"id"` + IP InfrastructureTargetIPInfo `json:"ip"` + CreatedAt time.Time `json:"created_at"` + ModifiedAt time.Time `json:"modified_at"` } -type IPDetails struct { +type InfrastructureTargetIPDetails struct { IPAddr string `json:"ip_addr"` VirtualNetworkId string `json:"virtual_network_id"` } -type IPInfo struct { - IPV4 *IPDetails `json:"ipv4,omitempty"` - IPV6 *IPDetails `json:"ipv6,omitempty"` +type InfrastructureTargetIPInfo struct { + IPV4 *InfrastructureTargetIPDetails `json:"ipv4,omitempty"` + IPV6 *InfrastructureTargetIPDetails `json:"ipv6,omitempty"` } type InfrastructureTargetParams struct { - Hostname string `json:"hostname"` - IP IPInfo `json:"ip"` + Hostname string `json:"hostname"` + IP InfrastructureTargetIPInfo `json:"ip"` } type CreateInfrastructureTargetParams struct { @@ -45,19 +45,19 @@ type UpdateInfrastructureTargetParams struct { ModifyParams InfrastructureTargetParams `json:"modify_params"` } -// TargetDetailResponse is the API response, containing a single target. -type TargetDetailResponse struct { - Result Target `json:"result"` +// InfrastructureTargetDetailResponse is the API response, containing a single target. +type InfrastructureTargetDetailResponse struct { + Result InfrastructureTarget `json:"result"` Response } -type TargetListDetailResponse struct { - Result []Target `json:"result"` +type InfrastructureTargetListDetailResponse struct { + Result []InfrastructureTarget `json:"result"` Response ResultInfo `json:"result_info"` } -type TargetListParams struct { +type InfrastructureTargetListParams struct { CreatedAfter string `url:"created_after,omitempty"` Hostname string `url:"hostname,omitempty"` HostnameContains string `url:"hostname_contains,omitempty"` @@ -72,9 +72,9 @@ type TargetListParams struct { // ListInfrastructureTargets returns all applications within an account or zone. // // API reference: https://developers.cloudflare.com/api/operations/infra-targets-list -func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceContainer, params TargetListParams) ([]Target, *ResultInfo, error) { +func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceContainer, params InfrastructureTargetListParams) ([]InfrastructureTarget, *ResultInfo, error) { if rc.Identifier == "" { - return []Target{}, &ResultInfo{}, ErrMissingAccountID + return []InfrastructureTarget{}, &ResultInfo{}, ErrMissingAccountID } baseURL := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) @@ -92,20 +92,20 @@ func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceConta params.Page = 1 } - var applications []Target - var r TargetListDetailResponse + var applications []InfrastructureTarget + var r InfrastructureTargetListDetailResponse for { uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []Target{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return []InfrastructureTarget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } err = json.Unmarshal(res, &r) if err != nil { - return []Target{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []InfrastructureTarget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } applications = append(applications, r.Result...) params.ResultInfo = r.ResultInfo.Next() @@ -120,22 +120,22 @@ func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceConta // CreateInfrastructureTarget creates a new infrastructure target. // // API reference: https://developers.cloudflare.com/api/operations/infra-targets-post -func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureTargetParams) (Target, error) { +func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureTargetParams) (InfrastructureTarget, error) { if rc.Identifier == "" { - return Target{}, ErrMissingAccountID + return InfrastructureTarget{}, ErrMissingAccountID } uri := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { - return Target{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return InfrastructureTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var targetDetailResponse TargetDetailResponse + var targetDetailResponse InfrastructureTargetDetailResponse err = json.Unmarshal(res, &targetDetailResponse) if err != nil { - return Target{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return InfrastructureTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return targetDetailResponse.Result, nil @@ -144,13 +144,13 @@ func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceCont // UpdateInfrastructureTarget updates an existing infrastructure target. // // API reference: https://developers.cloudflare.com/api/operations/infra-targets-put -func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureTargetParams) (Target, error) { +func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureTargetParams) (InfrastructureTarget, error) { if rc.Identifier == "" { - return Target{}, ErrMissingAccountID + return InfrastructureTarget{}, ErrMissingAccountID } if params.ID == "" { - return Target{}, ErrMissingTargetId + return InfrastructureTarget{}, ErrMissingTargetId } uri := fmt.Sprintf( @@ -162,13 +162,13 @@ func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceCont res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.ModifyParams) if err != nil { - return Target{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return InfrastructureTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var targetDetailResponse TargetDetailResponse + var targetDetailResponse InfrastructureTargetDetailResponse err = json.Unmarshal(res, &targetDetailResponse) if err != nil { - return Target{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return InfrastructureTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return targetDetailResponse.Result, nil @@ -178,13 +178,13 @@ func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceCont // ID for either account or zone. // // API reference: https://developers.cloudflare.com/api/operations/infra-targets-get -func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) (Target, error) { +func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) (InfrastructureTarget, error) { if rc.Identifier == "" { - return Target{}, ErrMissingAccountID + return InfrastructureTarget{}, ErrMissingAccountID } if targetID == "" { - return Target{}, ErrMissingTargetId + return InfrastructureTarget{}, ErrMissingTargetId } uri := fmt.Sprintf( @@ -196,13 +196,13 @@ func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContain res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return Target{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return InfrastructureTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var targetDetailResponse TargetDetailResponse + var targetDetailResponse InfrastructureTargetDetailResponse err = json.Unmarshal(res, &targetDetailResponse) if err != nil { - return Target{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return InfrastructureTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return targetDetailResponse.Result, nil diff --git a/infrastructure_targets_test.go b/infrastructure_targets_test.go index 7fd2bedfd28..016d59ffb4a 100644 --- a/infrastructure_targets_test.go +++ b/infrastructure_targets_test.go @@ -16,28 +16,28 @@ const testInfrastructureTargetId = "019205b5-97d7-7272-b00e-0ea05e61a124" var ( infrastrctureTargetCreatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") infrastrctureTargetModifiedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") - expectedInfrastructureTarget = Target{ + expectedInfrastructureTarget = InfrastructureTarget{ Hostname: "infra-access-target", ID: testInfrastructureTargetId, - IP: IPInfo{ - IPV4: &IPDetails{ - IPAddr: "187.26.29.249", + IP: InfrastructureTargetIPInfo{ + IPV4: &InfrastructureTargetIPDetails{ + IPAddr: "198.51.100.1", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, - IPV6: &IPDetails{ - IPAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + IPV6: &InfrastructureTargetIPDetails{ + IPAddr: "2001:0db8:0000:0000:0000:0000:0000:1000", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, CreatedAt: infrastrctureTargetCreatedOn, ModifiedAt: infrastrctureTargetModifiedOn, } - expectedInfrastructureModified = Target{ + expectedInfrastructureModified = InfrastructureTarget{ Hostname: "infra-access-target-modified", ID: testInfrastructureTargetId, - IP: IPInfo{ - IPV4: &IPDetails{ - IPAddr: "250.26.29.250", + IP: InfrastructureTargetIPInfo{ + IPV4: &InfrastructureTargetIPDetails{ + IPAddr: "198.51.100.2", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, @@ -64,11 +64,11 @@ func TestInfrastructureTarget_Create(t *testing.T) { "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "187.26.29.249", + "ip_addr": "198.51.100.1", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" }, "ipv6": { - "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + "ip_addr": "2001:0db8:0000:0000:0000:0000:0000:1000", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, @@ -86,13 +86,13 @@ func TestInfrastructureTarget_Create(t *testing.T) { out, err := client.CreateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), CreateInfrastructureTargetParams{ InfrastructureTargetParams: InfrastructureTargetParams{ Hostname: "infra-access-target", - IP: IPInfo{ - IPV4: &IPDetails{ - IPAddr: "187.26.29.249", + IP: InfrastructureTargetIPInfo{ + IPV4: &InfrastructureTargetIPDetails{ + IPAddr: "198.51.100.1", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, - IPV6: &IPDetails{ - IPAddr: "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + IPV6: &InfrastructureTargetIPDetails{ + IPAddr: "2001:0db8:0000:0000:0000:0000:0000:1000", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, @@ -122,11 +122,11 @@ func TestInfrastructureTarget_List(t *testing.T) { "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "187.26.29.249", + "ip_addr": "198.51.100.1", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" }, "ipv6": { - "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + "ip_addr": "2001:0db8:0000:0000:0000:0000:0000:1000", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, @@ -142,12 +142,12 @@ func TestInfrastructureTarget_List(t *testing.T) { }`) }) - _, _, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(""), TargetListParams{}) + _, _, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(""), InfrastructureTargetListParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, results, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(testAccountID), TargetListParams{}) + out, results, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(testAccountID), InfrastructureTargetListParams{}) if assert.NoError(t, err) { assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") assert.Equal(t, 20, results.PerPage, "expected 20 per page") @@ -173,11 +173,11 @@ func TestInfrastructureTarget_Get(t *testing.T) { "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "187.26.29.249", + "ip_addr": "198.51.100.1", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" }, "ipv6": { - "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0", + "ip_addr": "2001:0db8:0000:0000:0000:0000:0000:1000", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, @@ -221,7 +221,7 @@ func TestInfrastructureTarget_Update(t *testing.T) { "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "250.26.29.250", + "ip_addr": "198.51.100.2", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, @@ -248,9 +248,9 @@ func TestInfrastructureTarget_Update(t *testing.T) { ModifyParams: InfrastructureTargetParams{ // Updates hostname and IPv4 address. Deletes IPv6 address. Hostname: "infra-access-target-modified", - IP: IPInfo{ - IPV4: &IPDetails{ - IPAddr: "250.26.29.250", + IP: InfrastructureTargetIPInfo{ + IPV4: &InfrastructureTargetIPDetails{ + IPAddr: "198.51.100.2", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, From 124d2f681ff7907092d474aa149a7b274bdec11c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 23 Sep 2024 12:38:57 +1000 Subject: [PATCH 58/84] don't marshal `id` into the payload --- infrastructure_targets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure_targets.go b/infrastructure_targets.go index fbb4f319aaf..1200da117f7 100644 --- a/infrastructure_targets.go +++ b/infrastructure_targets.go @@ -41,7 +41,7 @@ type CreateInfrastructureTargetParams struct { } type UpdateInfrastructureTargetParams struct { - ID string `json:"hostname"` + ID string `json:"-"` ModifyParams InfrastructureTargetParams `json:"modify_params"` } From 0f00db2a6af06aebdb3e6d4321e65496ee403937 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 23 Sep 2024 12:43:02 +1000 Subject: [PATCH 59/84] fix lint --- infrastructure_targets.go | 1 - infrastructure_targets_test.go | 1 - 2 files changed, 2 deletions(-) diff --git a/infrastructure_targets.go b/infrastructure_targets.go index 1200da117f7..5dba32d0273 100644 --- a/infrastructure_targets.go +++ b/infrastructure_targets.go @@ -12,7 +12,6 @@ import ( var ErrMissingTargetId = errors.New("required target id missing") -// InfrastructureTarget represents an Infrastructure InfrastructureTarget. type InfrastructureTarget struct { Hostname string `json:"hostname"` ID string `json:"id"` diff --git a/infrastructure_targets_test.go b/infrastructure_targets_test.go index 016d59ffb4a..01f067cc085 100644 --- a/infrastructure_targets_test.go +++ b/infrastructure_targets_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -// randomly generated uuid const testInfrastructureTargetId = "019205b5-97d7-7272-b00e-0ea05e61a124" var ( From de28b77d2f33a94a36e2c009ec3c186b394bcddc Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 23 Sep 2024 12:44:52 +1000 Subject: [PATCH 60/84] Rename 3183.txt to 3184.txt --- .changelog/{3183.txt => 3184.txt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .changelog/{3183.txt => 3184.txt} (96%) diff --git a/.changelog/3183.txt b/.changelog/3184.txt similarity index 96% rename from .changelog/3183.txt rename to .changelog/3184.txt index 69e4ec2d5eb..e0c858c3517 100644 --- a/.changelog/3183.txt +++ b/.changelog/3184.txt @@ -1,3 +1,3 @@ ```release-note:enhancement infrastructure_targets: initialize CRUD endpoints for infrastructure access endpoints -``` \ No newline at end of file +``` From 52ef9acb8e9d403a5f0b734dd14cb1847cbc5573 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 23 Sep 2024 12:52:13 +1000 Subject: [PATCH 61/84] swap time.Time to pointers --- infrastructure_targets.go | 4 ++-- infrastructure_targets_test.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/infrastructure_targets.go b/infrastructure_targets.go index 5dba32d0273..c6026798ef6 100644 --- a/infrastructure_targets.go +++ b/infrastructure_targets.go @@ -16,8 +16,8 @@ type InfrastructureTarget struct { Hostname string `json:"hostname"` ID string `json:"id"` IP InfrastructureTargetIPInfo `json:"ip"` - CreatedAt time.Time `json:"created_at"` - ModifiedAt time.Time `json:"modified_at"` + CreatedAt *time.Time `json:"created_at"` + ModifiedAt *time.Time `json:"modified_at"` } type InfrastructureTargetIPDetails struct { diff --git a/infrastructure_targets_test.go b/infrastructure_targets_test.go index 01f067cc085..fd60ee2cbc3 100644 --- a/infrastructure_targets_test.go +++ b/infrastructure_targets_test.go @@ -28,8 +28,8 @@ var ( VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, - CreatedAt: infrastrctureTargetCreatedOn, - ModifiedAt: infrastrctureTargetModifiedOn, + CreatedAt: &infrastrctureTargetCreatedOn, + ModifiedAt: &infrastrctureTargetModifiedOn, } expectedInfrastructureModified = InfrastructureTarget{ Hostname: "infra-access-target-modified", @@ -40,8 +40,8 @@ var ( VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, - CreatedAt: infrastrctureTargetCreatedOn, - ModifiedAt: infrastrctureTargetModifiedOn, + CreatedAt: &infrastrctureTargetCreatedOn, + ModifiedAt: &infrastrctureTargetModifiedOn, } ) From 91b43278b1fd0c58648f04944161e36d5bee57e4 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Sun, 22 Sep 2024 20:32:31 -0700 Subject: [PATCH 62/84] Rename Infrastructure Target to Infrastructure Access Target --- infrastructure_access_targets.go | 234 +++++++++++++++++ ...o => infrastructure_access_targets_test.go | 93 +++---- infrastructure_targets.go | 235 ------------------ 3 files changed, 281 insertions(+), 281 deletions(-) create mode 100644 infrastructure_access_targets.go rename infrastructure_targets_test.go => infrastructure_access_targets_test.go (61%) delete mode 100644 infrastructure_targets.go diff --git a/infrastructure_access_targets.go b/infrastructure_access_targets.go new file mode 100644 index 00000000000..0c6a72a8666 --- /dev/null +++ b/infrastructure_access_targets.go @@ -0,0 +1,234 @@ +package cloudflare + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/goccy/go-json" +) + +var ErrMissingTargetId = errors.New("required target id missing") + +type InfrastructureAccessTarget struct { + Hostname string `json:"hostname"` + ID string `json:"id"` + IP InfrastructureAccessTargetIPInfo `json:"ip"` + CreatedAt string `json:"created_at"` + ModifiedAt string `json:"modified_at"` +} + +type InfrastructureAccessTargetIPInfo struct { + IPV4 *InfrastructureAccessTargetIPDetails `json:"ipv4,omitempty"` + IPV6 *InfrastructureAccessTargetIPDetails `json:"ipv6,omitempty"` +} + +type InfrastructureAccessTargetIPDetails struct { + IPAddr string `json:"ip_addr"` + VirtualNetworkId string `json:"virtual_network_id"` +} + +type InfrastructureAccessTargetParams struct { + Hostname string `json:"hostname"` + IP InfrastructureAccessTargetIPInfo `json:"ip"` +} + +type CreateInfrastructureAccessTargetParams struct { + InfrastructureAccessTargetParams +} + +type UpdateInfrastructureAccessTargetParams struct { + ID string `json:"-"` + ModifyParams InfrastructureAccessTargetParams `json:"modify_params"` +} + +// InfrastructureAccessTargetDetailResponse is the API response, containing a single target. +type InfrastructureAccessTargetDetailResponse struct { + Result InfrastructureAccessTarget `json:"result"` + Response +} + +type InfrastructureAccessTargetListDetailResponse struct { + Result []InfrastructureAccessTarget `json:"result"` + Response + ResultInfo `json:"result_info"` +} + +type InfrastructureAccessTargetListParams struct { + Hostname string `url:"hostname,omitempty"` + HostnameContains string `url:"hostname_contains,omitempty"` + IPV4 string `url:"ip_v4,omitempty"` + IPV6 string `url:"ip_v6,omitempty"` + CreatedAfter string `url:"created_after,omitempty"` + ModifedAfter string `url:"modified_after,omitempty"` + VirtualNetworkId string `url:"virtual_network_id,omitempty"` + + ResultInfo +} + +// ListInfrastructureAccessTargets returns all infrastructure access targets within an account. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-list +func (api *API) ListInfrastructureAccessTargets(ctx context.Context, rc *ResourceContainer, params InfrastructureAccessTargetListParams) ([]InfrastructureAccessTarget, *ResultInfo, error) { + if rc.Identifier == "" { + return []InfrastructureAccessTarget{}, &ResultInfo{}, ErrMissingAccountID + } + + baseURL := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) + + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } + + if params.PerPage < 1 { + params.PerPage = 25 + } + + if params.Page < 1 { + params.Page = 1 + } + + var targets []InfrastructureAccessTarget + var r InfrastructureAccessTargetListDetailResponse + + for { + uri := buildURI(baseURL, params) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []InfrastructureAccessTarget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []InfrastructureAccessTarget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + targets = append(targets, r.Result...) + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { + break + } + } + + return targets, &r.ResultInfo, nil +} + +// CreateInfrastructureAccessTarget creates a new infrastructure access target. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-post +func (api *API) CreateInfrastructureAccessTarget(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureAccessTargetParams) (InfrastructureAccessTarget, error) { + if rc.Identifier == "" { + return InfrastructureAccessTarget{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return InfrastructureAccessTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var targetDetailResponse InfrastructureAccessTargetDetailResponse + err = json.Unmarshal(res, &targetDetailResponse) + if err != nil { + return InfrastructureAccessTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return targetDetailResponse.Result, nil +} + +// UpdateInfrastructureAccessTarget updates an existing infrastructure access target. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-put +func (api *API) UpdateInfrastructureAccessTarget(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureAccessTargetParams) (InfrastructureAccessTarget, error) { + if rc.Identifier == "" { + return InfrastructureAccessTarget{}, ErrMissingAccountID + } + + if params.ID == "" { + return InfrastructureAccessTarget{}, ErrMissingTargetId + } + + uri := fmt.Sprintf( + "/%s/%s/infrastructure/targets/%s", + rc.Level, + rc.Identifier, + params.ID, + ) + + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.ModifyParams) + if err != nil { + return InfrastructureAccessTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var targetDetailResponse InfrastructureAccessTargetDetailResponse + err = json.Unmarshal(res, &targetDetailResponse) + if err != nil { + return InfrastructureAccessTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return targetDetailResponse.Result, nil +} + +// GetInfrastructureAccessTarget returns a single infrastructure access target based on target ID +// ID for either account or zone. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-get +func (api *API) GetInfrastructureAccessTarget(ctx context.Context, rc *ResourceContainer, targetID string) (InfrastructureAccessTarget, error) { + if rc.Identifier == "" { + return InfrastructureAccessTarget{}, ErrMissingAccountID + } + + if targetID == "" { + return InfrastructureAccessTarget{}, ErrMissingTargetId + } + + uri := fmt.Sprintf( + "/%s/%s/infrastructure/targets/%s", + rc.Level, + rc.Identifier, + targetID, + ) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return InfrastructureAccessTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var targetDetailResponse InfrastructureAccessTargetDetailResponse + err = json.Unmarshal(res, &targetDetailResponse) + if err != nil { + return InfrastructureAccessTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return targetDetailResponse.Result, nil +} + +// DeleteInfrastructureAccessTarget deletes an infrastructure access target. +// +// Account API reference: https://developers.cloudflare.com/api/operations/infra-targets-delete +func (api *API) DeleteInfrastructureAccessTarget(ctx context.Context, rc *ResourceContainer, targetID string) error { + if rc.Identifier == "" { + return ErrMissingAccountID + } + + if targetID == "" { + return ErrMissingTargetId + } + + uri := fmt.Sprintf( + "/%s/%s/infrastructure/targets/%s", + rc.Level, + rc.Identifier, + targetID, + ) + + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + return nil +} diff --git a/infrastructure_targets_test.go b/infrastructure_access_targets_test.go similarity index 61% rename from infrastructure_targets_test.go rename to infrastructure_access_targets_test.go index fd60ee2cbc3..f00c334c7f0 100644 --- a/infrastructure_targets_test.go +++ b/infrastructure_access_targets_test.go @@ -10,38 +10,39 @@ import ( "github.com/stretchr/testify/assert" ) -const testInfrastructureTargetId = "019205b5-97d7-7272-b00e-0ea05e61a124" +// randomly generated uuid +const testInfrastructureAccessTargetId = "019205b5-97d7-7272-b00e-0ea05e61a124" var ( - infrastrctureTargetCreatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") - infrastrctureTargetModifiedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") - expectedInfrastructureTarget = InfrastructureTarget{ + infrastructureAccessTargetCreatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") + infrastructureAccessTargetModifiedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") + expectedInfrastructureAccessTarget = InfrastructureAccessTarget{ Hostname: "infra-access-target", - ID: testInfrastructureTargetId, - IP: InfrastructureTargetIPInfo{ - IPV4: &InfrastructureTargetIPDetails{ - IPAddr: "198.51.100.1", + ID: testInfrastructureAccessTargetId, + IP: InfrastructureAccessTargetIPInfo{ + IPV4: &InfrastructureAccessTargetIPDetails{ + IPAddr: "187.26.29.249", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, - IPV6: &InfrastructureTargetIPDetails{ + IPV6: &InfrastructureAccessTargetIPDetails{ IPAddr: "2001:0db8:0000:0000:0000:0000:0000:1000", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, - CreatedAt: &infrastrctureTargetCreatedOn, - ModifiedAt: &infrastrctureTargetModifiedOn, + CreatedAt: infrastructureAccessTargetCreatedOn.String(), + ModifiedAt: infrastructureAccessTargetModifiedOn.String(), } - expectedInfrastructureModified = InfrastructureTarget{ + expectedInfrastructureModified = InfrastructureAccessTarget{ Hostname: "infra-access-target-modified", - ID: testInfrastructureTargetId, - IP: InfrastructureTargetIPInfo{ - IPV4: &InfrastructureTargetIPDetails{ - IPAddr: "198.51.100.2", + ID: testInfrastructureAccessTargetId, + IP: InfrastructureAccessTargetIPInfo{ + IPV4: &InfrastructureAccessTargetIPDetails{ + IPAddr: "250.26.29.250", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, - CreatedAt: &infrastrctureTargetCreatedOn, - ModifiedAt: &infrastrctureTargetModifiedOn, + CreatedAt: infrastructureAccessTargetCreatedOn.String(), + ModifiedAt: infrastructureAccessTargetModifiedOn.String(), } ) @@ -77,20 +78,20 @@ func TestInfrastructureTarget_Create(t *testing.T) { }) // Make sure missing account ID is thrown - _, err := client.CreateInfrastructureTarget(context.Background(), AccountIdentifier(""), CreateInfrastructureTargetParams{}) + _, err := client.CreateInfrastructureAccessTarget(context.Background(), AccountIdentifier(""), CreateInfrastructureAccessTargetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, err := client.CreateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), CreateInfrastructureTargetParams{ - InfrastructureTargetParams: InfrastructureTargetParams{ + out, err := client.CreateInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), CreateInfrastructureAccessTargetParams{ + InfrastructureAccessTargetParams: InfrastructureAccessTargetParams{ Hostname: "infra-access-target", - IP: InfrastructureTargetIPInfo{ - IPV4: &InfrastructureTargetIPDetails{ + IP: InfrastructureAccessTargetIPInfo{ + IPV4: &InfrastructureAccessTargetIPDetails{ IPAddr: "198.51.100.1", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, - IPV6: &InfrastructureTargetIPDetails{ + IPV6: &InfrastructureAccessTargetIPDetails{ IPAddr: "2001:0db8:0000:0000:0000:0000:0000:1000", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, @@ -98,7 +99,7 @@ func TestInfrastructureTarget_Create(t *testing.T) { }, }) if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureTarget, out, "create infrastructure_target structs not equal") + assert.Equal(t, expectedInfrastructureAccessTarget, out, "create infrastructure_target structs not equal") } } @@ -141,16 +142,16 @@ func TestInfrastructureTarget_List(t *testing.T) { }`) }) - _, _, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(""), InfrastructureTargetListParams{}) + _, _, err := client.ListInfrastructureAccessTargets(context.Background(), AccountIdentifier(""), InfrastructureAccessTargetListParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, results, err := client.ListInfrastructureTargets(context.Background(), AccountIdentifier(testAccountID), InfrastructureTargetListParams{}) + out, results, err := client.ListInfrastructureAccessTargets(context.Background(), AccountIdentifier(testAccountID), InfrastructureAccessTargetListParams{}) if assert.NoError(t, err) { assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") assert.Equal(t, 20, results.PerPage, "expected 20 per page") - assert.Equal(t, expectedInfrastructureTarget, out[0], "list challenge_widgets structs not equal") + assert.Equal(t, expectedInfrastructureAccessTarget, out[0], "list challenge_widgets structs not equal") } } @@ -158,7 +159,7 @@ func TestInfrastructureTarget_Get(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureTargetId, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureAccessTargetId, func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ` @@ -185,20 +186,20 @@ func TestInfrastructureTarget_Get(t *testing.T) { }`) }) - _, err := client.GetInfrastructureTarget(context.Background(), AccountIdentifier(""), "") + _, err := client.GetInfrastructureAccessTarget(context.Background(), AccountIdentifier(""), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.GetInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), "") + _, err = client.GetInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingTargetId, err) } - out, err := client.GetInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), testInfrastructureTargetId) + out, err := client.GetInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), testInfrastructureAccessTargetId) if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureTarget, out, "get infrastructure_target not equal to expected") + assert.Equal(t, expectedInfrastructureAccessTarget, out, "get infrastructure_target not equal to expected") } } @@ -206,7 +207,7 @@ func TestInfrastructureTarget_Update(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureTargetId, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureAccessTargetId, func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ` @@ -229,26 +230,26 @@ func TestInfrastructureTarget_Update(t *testing.T) { }`) }) - _, err := client.UpdateInfrastructureTarget(context.Background(), AccountIdentifier(""), UpdateInfrastructureTargetParams{}) + _, err := client.UpdateInfrastructureAccessTarget(context.Background(), AccountIdentifier(""), UpdateInfrastructureAccessTargetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.UpdateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureTargetParams{ + _, err = client.UpdateInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureAccessTargetParams{ ID: "", - ModifyParams: InfrastructureTargetParams{}, + ModifyParams: InfrastructureAccessTargetParams{}, }) if assert.Error(t, err) { assert.Equal(t, ErrMissingTargetId, err) } - out, err := client.UpdateInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureTargetParams{ - ID: testInfrastructureTargetId, - ModifyParams: InfrastructureTargetParams{ + out, err := client.UpdateInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureAccessTargetParams{ + ID: testInfrastructureAccessTargetId, + ModifyParams: InfrastructureAccessTargetParams{ // Updates hostname and IPv4 address. Deletes IPv6 address. Hostname: "infra-access-target-modified", - IP: InfrastructureTargetIPInfo{ - IPV4: &InfrastructureTargetIPDetails{ + IP: InfrastructureAccessTargetIPInfo{ + IPV4: &InfrastructureAccessTargetIPDetails{ IPAddr: "198.51.100.2", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, @@ -264,23 +265,23 @@ func TestInfrastructureTarget_Delete(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureTargetId, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/infrastructure/targets/"+testInfrastructureAccessTargetId, func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ``) }) // Make sure missing account ID is thrown - err := client.DeleteInfrastructureTarget(context.Background(), AccountIdentifier(""), "") + err := client.DeleteInfrastructureAccessTarget(context.Background(), AccountIdentifier(""), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - err = client.DeleteInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), "") + err = client.DeleteInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingTargetId, err) } - err = client.DeleteInfrastructureTarget(context.Background(), AccountIdentifier(testAccountID), testInfrastructureTargetId) + err = client.DeleteInfrastructureAccessTarget(context.Background(), AccountIdentifier(testAccountID), testInfrastructureAccessTargetId) assert.NoError(t, err) } diff --git a/infrastructure_targets.go b/infrastructure_targets.go deleted file mode 100644 index c6026798ef6..00000000000 --- a/infrastructure_targets.go +++ /dev/null @@ -1,235 +0,0 @@ -package cloudflare - -import ( - "context" - "errors" - "fmt" - "net/http" - "time" - - "github.com/goccy/go-json" -) - -var ErrMissingTargetId = errors.New("required target id missing") - -type InfrastructureTarget struct { - Hostname string `json:"hostname"` - ID string `json:"id"` - IP InfrastructureTargetIPInfo `json:"ip"` - CreatedAt *time.Time `json:"created_at"` - ModifiedAt *time.Time `json:"modified_at"` -} - -type InfrastructureTargetIPDetails struct { - IPAddr string `json:"ip_addr"` - VirtualNetworkId string `json:"virtual_network_id"` -} - -type InfrastructureTargetIPInfo struct { - IPV4 *InfrastructureTargetIPDetails `json:"ipv4,omitempty"` - IPV6 *InfrastructureTargetIPDetails `json:"ipv6,omitempty"` -} - -type InfrastructureTargetParams struct { - Hostname string `json:"hostname"` - IP InfrastructureTargetIPInfo `json:"ip"` -} - -type CreateInfrastructureTargetParams struct { - InfrastructureTargetParams -} - -type UpdateInfrastructureTargetParams struct { - ID string `json:"-"` - ModifyParams InfrastructureTargetParams `json:"modify_params"` -} - -// InfrastructureTargetDetailResponse is the API response, containing a single target. -type InfrastructureTargetDetailResponse struct { - Result InfrastructureTarget `json:"result"` - Response -} - -type InfrastructureTargetListDetailResponse struct { - Result []InfrastructureTarget `json:"result"` - Response - ResultInfo `json:"result_info"` -} - -type InfrastructureTargetListParams struct { - CreatedAfter string `url:"created_after,omitempty"` - Hostname string `url:"hostname,omitempty"` - HostnameContains string `url:"hostname_contains,omitempty"` - IPV4 string `url:"ip_v4,omitempty"` - IPV6 string `url:"ip_v6,omitempty"` - ModifedAfter string `url:"modified_after,omitempty"` - VirtualNetworkId string `url:"virtual_network_id,omitempty"` - - ResultInfo -} - -// ListInfrastructureTargets returns all applications within an account or zone. -// -// API reference: https://developers.cloudflare.com/api/operations/infra-targets-list -func (api *API) ListInfrastructureTargets(ctx context.Context, rc *ResourceContainer, params InfrastructureTargetListParams) ([]InfrastructureTarget, *ResultInfo, error) { - if rc.Identifier == "" { - return []InfrastructureTarget{}, &ResultInfo{}, ErrMissingAccountID - } - - baseURL := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) - - autoPaginate := true - if params.PerPage >= 1 || params.Page >= 1 { - autoPaginate = false - } - - if params.PerPage < 1 { - params.PerPage = 25 - } - - if params.Page < 1 { - params.Page = 1 - } - - var applications []InfrastructureTarget - var r InfrastructureTargetListDetailResponse - - for { - uri := buildURI(baseURL, params) - - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []InfrastructureTarget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) - } - - err = json.Unmarshal(res, &r) - if err != nil { - return []InfrastructureTarget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - applications = append(applications, r.Result...) - params.ResultInfo = r.ResultInfo.Next() - if params.ResultInfo.Done() || !autoPaginate { - break - } - } - - return applications, &r.ResultInfo, nil -} - -// CreateInfrastructureTarget creates a new infrastructure target. -// -// API reference: https://developers.cloudflare.com/api/operations/infra-targets-post -func (api *API) CreateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureTargetParams) (InfrastructureTarget, error) { - if rc.Identifier == "" { - return InfrastructureTarget{}, ErrMissingAccountID - } - - uri := fmt.Sprintf("/%s/%s/infrastructure/targets", rc.Level, rc.Identifier) - - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) - if err != nil { - return InfrastructureTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) - } - - var targetDetailResponse InfrastructureTargetDetailResponse - err = json.Unmarshal(res, &targetDetailResponse) - if err != nil { - return InfrastructureTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return targetDetailResponse.Result, nil -} - -// UpdateInfrastructureTarget updates an existing infrastructure target. -// -// API reference: https://developers.cloudflare.com/api/operations/infra-targets-put -func (api *API) UpdateInfrastructureTarget(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureTargetParams) (InfrastructureTarget, error) { - if rc.Identifier == "" { - return InfrastructureTarget{}, ErrMissingAccountID - } - - if params.ID == "" { - return InfrastructureTarget{}, ErrMissingTargetId - } - - uri := fmt.Sprintf( - "/%s/%s/infrastructure/targets/%s", - rc.Level, - rc.Identifier, - params.ID, - ) - - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.ModifyParams) - if err != nil { - return InfrastructureTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) - } - - var targetDetailResponse InfrastructureTargetDetailResponse - err = json.Unmarshal(res, &targetDetailResponse) - if err != nil { - return InfrastructureTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return targetDetailResponse.Result, nil -} - -// GetInfrastructureTarget returns a single infrastructure target based on target ID -// ID for either account or zone. -// -// API reference: https://developers.cloudflare.com/api/operations/infra-targets-get -func (api *API) GetInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) (InfrastructureTarget, error) { - if rc.Identifier == "" { - return InfrastructureTarget{}, ErrMissingAccountID - } - - if targetID == "" { - return InfrastructureTarget{}, ErrMissingTargetId - } - - uri := fmt.Sprintf( - "/%s/%s/infrastructure/targets/%s", - rc.Level, - rc.Identifier, - targetID, - ) - - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return InfrastructureTarget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) - } - - var targetDetailResponse InfrastructureTargetDetailResponse - err = json.Unmarshal(res, &targetDetailResponse) - if err != nil { - return InfrastructureTarget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return targetDetailResponse.Result, nil -} - -// DeleteInfrastructureTarget deletes an infrastructure target. -// -// API reference: https://developers.cloudflare.com/api/operations/infra-targets-delete -func (api *API) DeleteInfrastructureTarget(ctx context.Context, rc *ResourceContainer, targetID string) error { - if rc.Identifier == "" { - return ErrMissingAccountID - } - - if targetID == "" { - return ErrMissingTargetId - } - - uri := fmt.Sprintf( - "/%s/%s/infrastructure/targets/%s", - rc.Level, - rc.Identifier, - targetID, - ) - - _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) - if err != nil { - return fmt.Errorf("%s: %w", errMakeRequestError, err) - } - - return nil -} From bab187b471ffad471474640696e3b90d1fa48cd2 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Sun, 22 Sep 2024 20:38:54 -0700 Subject: [PATCH 63/84] nit: Rename file singular verbiage --- ...structure_access_targets.go => infrastructure_access_target.go | 0 ...access_targets_test.go => infrastructure_access_target_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename infrastructure_access_targets.go => infrastructure_access_target.go (100%) rename infrastructure_access_targets_test.go => infrastructure_access_target_test.go (100%) diff --git a/infrastructure_access_targets.go b/infrastructure_access_target.go similarity index 100% rename from infrastructure_access_targets.go rename to infrastructure_access_target.go diff --git a/infrastructure_access_targets_test.go b/infrastructure_access_target_test.go similarity index 100% rename from infrastructure_access_targets_test.go rename to infrastructure_access_target_test.go From cbfd80fd83e33b4fe6a187868f018a5b8b57b273 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Tue, 24 Sep 2024 13:00:01 -0700 Subject: [PATCH 64/84] lint fixes --- infrastructure_access_target_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/infrastructure_access_target_test.go b/infrastructure_access_target_test.go index f00c334c7f0..87c45b79dff 100644 --- a/infrastructure_access_target_test.go +++ b/infrastructure_access_target_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -// randomly generated uuid const testInfrastructureAccessTargetId = "019205b5-97d7-7272-b00e-0ea05e61a124" var ( From c5020a5496d531336c5e59c496cd823844e7bbbb Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Tue, 24 Sep 2024 13:22:31 -0700 Subject: [PATCH 65/84] fix unit tests --- infrastructure_access_target_test.go | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/infrastructure_access_target_test.go b/infrastructure_access_target_test.go index 87c45b79dff..b80bcda76b0 100644 --- a/infrastructure_access_target_test.go +++ b/infrastructure_access_target_test.go @@ -36,7 +36,7 @@ var ( ID: testInfrastructureAccessTargetId, IP: InfrastructureAccessTargetIPInfo{ IPV4: &InfrastructureAccessTargetIPDetails{ - IPAddr: "250.26.29.250", + IPAddr: "198.51.100.2", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, }, @@ -45,7 +45,7 @@ var ( } ) -func TestInfrastructureTarget_Create(t *testing.T) { +func TestInfrastructureAccessTarget_Create(t *testing.T) { setup() defer teardown() @@ -58,12 +58,12 @@ func TestInfrastructureTarget_Create(t *testing.T) { "errors": [], "messages": [], "result": { - "created_at": "2024-08-25T05:00:22Z", + "created_at": "2024-08-25 05:00:22 +0000 UTC", "hostname": "infra-access-target", "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "198.51.100.1", + "ip_addr": "187.26.29.249", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" }, "ipv6": { @@ -71,7 +71,7 @@ func TestInfrastructureTarget_Create(t *testing.T) { "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, - "modified_at": "2024-08-25T05:00:22Z" + "modified_at": "2024-08-25 05:00:22 +0000 UTC" } }`) }) @@ -87,7 +87,7 @@ func TestInfrastructureTarget_Create(t *testing.T) { Hostname: "infra-access-target", IP: InfrastructureAccessTargetIPInfo{ IPV4: &InfrastructureAccessTargetIPDetails{ - IPAddr: "198.51.100.1", + IPAddr: "187.26.29.249", VirtualNetworkId: "c77b744e-acc8-428f-9257-6878c046ed55", }, IPV6: &InfrastructureAccessTargetIPDetails{ @@ -98,7 +98,7 @@ func TestInfrastructureTarget_Create(t *testing.T) { }, }) if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureAccessTarget, out, "create infrastructure_target structs not equal") + assert.Equal(t, expectedInfrastructureAccessTarget, out, "create infrastructure_access_target structs not equal") } } @@ -116,12 +116,12 @@ func TestInfrastructureTarget_List(t *testing.T) { "messages": [], "result": [ { - "created_at": "2024-08-25T05:00:22Z", + "created_at": "2024-08-25 05:00:22 +0000 UTC", "hostname": "infra-access-target", "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "198.51.100.1", + "ip_addr": "187.26.29.249", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" }, "ipv6": { @@ -129,7 +129,7 @@ func TestInfrastructureTarget_List(t *testing.T) { "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, - "modified_at": "2024-08-25T05:00:22Z" + "modified_at": "2024-08-25 05:00:22 +0000 UTC" } ], "result_info": { @@ -167,12 +167,12 @@ func TestInfrastructureTarget_Get(t *testing.T) { "errors": [], "messages": [], "result": { - "created_at": "2024-08-25T05:00:22Z", + "created_at": "2024-08-25 05:00:22 +0000 UTC", "hostname": "infra-access-target", "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { "ipv4": { - "ip_addr": "198.51.100.1", + "ip_addr": "187.26.29.249", "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" }, "ipv6": { @@ -180,7 +180,7 @@ func TestInfrastructureTarget_Get(t *testing.T) { "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, - "modified_at": "2024-08-25T05:00:22Z" + "modified_at": "2024-08-25 05:00:22 +0000 UTC" } }`) }) @@ -215,7 +215,7 @@ func TestInfrastructureTarget_Update(t *testing.T) { "errors": [], "messages": [], "result": { - "created_at": "2024-08-25T05:00:22Z", + "created_at": "2024-08-25 05:00:22 +0000 UTC", "hostname": "infra-access-target-modified", "id": "019205b5-97d7-7272-b00e-0ea05e61a124", "ip": { @@ -224,7 +224,7 @@ func TestInfrastructureTarget_Update(t *testing.T) { "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55" } }, - "modified_at": "2024-08-25T05:00:22Z" + "modified_at": "2024-08-25 05:00:22 +0000 UTC" } }`) }) From 53ac6a505d55b93c9cdc897d3c0536bdf232f835 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 25 Sep 2024 10:57:05 +1000 Subject: [PATCH 66/84] generate changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee95151596b..ba6fe371e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## 0.105.0 (Unreleased) +ENHANCEMENTS: + +* device_posture_rule: add score field for custom_s2s posture rule ([#3031](https://github.com/cloudflare/cloudflare-go/issues/3031)) +* infrastructure_targets: initialize CRUD endpoints for infrastructure access endpoints ([#3184](https://github.com/cloudflare/cloudflare-go/issues/3184)) +* load_balancing: add account load balancer support ([#3027](https://github.com/cloudflare/cloudflare-go/issues/3027)) + ## 0.104.0 (September 11th, 2024) BREAKING CHANGES: From a30cc482d6b8f0ef63d952b3ec60694bb9c8e2d4 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 25 Sep 2024 10:57:56 +1000 Subject: [PATCH 67/84] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6fe371e2d..e95a5cdb0df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.105.0 (Unreleased) +## 0.106.0 (Unreleased) + +## 0.105.0 (September 25th, 2024) ENHANCEMENTS: From e4f81381ce3e0173599811322fa0a1f8df7d1d31 Mon Sep 17 00:00:00 2001 From: Hrushikesh Deshpande <161167942+hrushikeshdeshpande@users.noreply.github.com> Date: Tue, 24 Sep 2024 21:56:32 -0400 Subject: [PATCH 68/84] Update semgrep.yml --- .github/workflows/semgrep.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index b40314b3677..4090692fe0b 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -18,7 +18,7 @@ jobs: SEMGREP_APP_URL: https://cloudflare.semgrep.dev SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version container: - image: returntocorp/semgrep + image: semgrep/semgrep steps: - uses: actions/checkout@v4 - run: semgrep ci From 861b107110314b42bfcc2c87ff94d353cd725a0f Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 13:32:31 -0700 Subject: [PATCH 69/84] Add CRUD endpoints for Infrastructure Applications --- access_application.go | 18 +- access_infrastructure_application.go | 208 +++++++++ access_infrastructure_application_test.go | 501 ++++++++++++++++++++++ access_policy.go | 9 + infrastructure_access_target_test.go | 4 +- 5 files changed, 730 insertions(+), 10 deletions(-) create mode 100644 access_infrastructure_application.go create mode 100644 access_infrastructure_application_test.go diff --git a/access_application.go b/access_application.go index def62c0b870..045bfb3ca19 100644 --- a/access_application.go +++ b/access_application.go @@ -15,14 +15,15 @@ type AccessApplicationType string // These constants represent all valid application types. const ( - SelfHosted AccessApplicationType = "self_hosted" - SSH AccessApplicationType = "ssh" - VNC AccessApplicationType = "vnc" - Biso AccessApplicationType = "biso" - AppLauncher AccessApplicationType = "app_launcher" - Warp AccessApplicationType = "warp" - Bookmark AccessApplicationType = "bookmark" - Saas AccessApplicationType = "saas" + SelfHosted AccessApplicationType = "self_hosted" + SSH AccessApplicationType = "ssh" + VNC AccessApplicationType = "vnc" + Biso AccessApplicationType = "biso" + AppLauncher AccessApplicationType = "app_launcher" + Warp AccessApplicationType = "warp" + Bookmark AccessApplicationType = "bookmark" + Saas AccessApplicationType = "saas" + Infrastructure AccessApplicationType = "infrastructure" ) // AccessApplication represents an Access application. @@ -59,6 +60,7 @@ type AccessApplication struct { Tags []string `json:"tags,omitempty"` SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` Policies []AccessPolicy `json:"policies,omitempty"` + TargetContexts []InfraTargetContext `json:"target_criteria,omitempty"` AccessAppLauncherCustomization } diff --git a/access_infrastructure_application.go b/access_infrastructure_application.go new file mode 100644 index 00000000000..d655d912959 --- /dev/null +++ b/access_infrastructure_application.go @@ -0,0 +1,208 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + + "github.com/goccy/go-json" +) + +type InfraProtocol string + +const ( + InfraSSH InfraProtocol = "SSH" + RDP InfraProtocol = "RDP" +) + +// WARNING : The following table has a constraint. Each organization can specify at maximum one protocol for each of their ports. +// There can be at maximum a single (OrgID, Port, Protocol) combination, which can be shared across multiple records. +type InfraTargetContext struct { + TargetAttributes map[string][]string `json:"target_attributes"` + Port int `json:"port"` + Protocol InfraProtocol `json:"protocol"` +} + +type InfrastructureApplication struct { + // Items common to both SAML and OIDC + ID string `json:"id,omitempty"` + Type AccessApplicationType `json:"type"` + Name string `json:"name"` + Aud string `json:"aud,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + ScimConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` + TargetContexts []InfraTargetContext `json:"target_criteria"` + Policies []AccessPolicy `json:"policies"` +} + +type InfrastructureApplicationParams struct { + Name string `json:"name"` + Type AccessApplicationType `json:"type"` + TargetContexts []InfraTargetContext `json:"target_criteria"` + Policies []AccessPolicy `json:"policies"` +} + +type CreateInfrastructureApplicationParams struct { + InfrastructureApplicationParams +} + +type UpdateInfrastructureApplicationParams struct { + ID string `json:"-"` + InfrastructureApplicationParams +} + +// ListAccessInfrastructureApplications returns all applications within an account or zone. +// +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-list-access-applications +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-list-access-applications +func (api *API) ListAccessInfrastructureApplications(ctx context.Context, rc *ResourceContainer, params ListAccessApplicationsParams) ([]InfrastructureApplication, *ResultInfo, error) { + if rc.Identifier == "" { + return []InfrastructureApplication{}, &ResultInfo{}, ErrMissingAccountID + } + baseURL := fmt.Sprintf("/%s/%s/access/apps?app_type=infrastructure", rc.Level, rc.Identifier) + + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } + + if params.PerPage < 1 { + params.PerPage = 25 + } + + if params.Page < 1 { + params.Page = 1 + } + + var infraApps []InfrastructureApplication + var r AccessApplicationListResponse + + for { + uri := buildURI(baseURL, params) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []InfrastructureApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + err = json.Unmarshal(res, &r) + if err != nil { + return []InfrastructureApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + applications := r.Result + for _, app := range applications { + infraApps = append(infraApps, InfrastructureApplication{ + ID: app.ID, + Type: app.Type, + Name: app.Name, + Aud: app.AUD, + CreatedAt: app.CreatedAt.String(), + UpdatedAt: app.UpdatedAt.String(), + ScimConfig: app.SCIMConfig, + TargetContexts: app.TargetContexts, + Policies: app.Policies, + }) + } + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { + break + } + } + + return infraApps, &r.ResultInfo, nil +} + +// CreateAccessInfrastructureApplication creates a new access application. +// +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application +func (api *API) CreateAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureApplicationParams) (InfrastructureApplication, error) { + if rc.Identifier == "" { + return InfrastructureApplication{}, ErrMissingAccountID + } + uri := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier) + return api.sendInfrastructureApplicationRequest(ctx, http.MethodPost, uri, params.InfrastructureApplicationParams) +} + +// UpdateAccessInfrastructureApplication creates a new access application. +// +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application +func (api *API) UpdateAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureApplicationParams) (InfrastructureApplication, error) { + if rc.Identifier == "" { + return InfrastructureApplication{}, ErrMissingAccountID + } + if params.ID == "" { + return InfrastructureApplication{}, ErrMissingTargetId + } + uri := fmt.Sprintf("/%s/%s/access/apps/%s", rc.Level, rc.Identifier, params.ID) + return api.sendInfrastructureApplicationRequest(ctx, http.MethodPut, uri, params.InfrastructureApplicationParams) +} + +func (api *API) sendInfrastructureApplicationRequest(ctx context.Context, httpMethod string, uri string, params InfrastructureApplicationParams) (InfrastructureApplication, error) { + res, err := api.makeRequestContext(ctx, httpMethod, uri, params) + if err != nil { + return InfrastructureApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var accessApplicationDetailResponse AccessApplicationDetailResponse + err = json.Unmarshal(res, &accessApplicationDetailResponse) + if err != nil { + return InfrastructureApplication{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + accessApp := accessApplicationDetailResponse.Result + return InfrastructureApplication{ + ID: accessApp.ID, + Type: accessApp.Type, + Name: accessApp.Name, + Aud: accessApp.AUD, + CreatedAt: accessApp.CreatedAt.String(), + UpdatedAt: accessApp.UpdatedAt.String(), + ScimConfig: accessApp.SCIMConfig, + TargetContexts: accessApp.TargetContexts, + Policies: accessApp.Policies, + }, nil +} + +// GetAccessInfrastructureApplication returns a single infrastructure application based on the application ID for either account or zone. +// +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-get-an-access-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-get-an-access-application +func (api *API) GetAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, applicationID string) (InfrastructureApplication, error) { + if rc.Identifier == "" { + return InfrastructureApplication{}, ErrMissingAccountID + } + if applicationID == "" { + return InfrastructureApplication{}, ErrMissingTargetId + } + infraAccessApp, err := api.GetAccessApplication(ctx, rc, applicationID) + if err != nil { + return InfrastructureApplication{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return InfrastructureApplication{ + ID: infraAccessApp.ID, + Type: infraAccessApp.Type, + Name: infraAccessApp.Name, + Aud: infraAccessApp.AUD, + CreatedAt: infraAccessApp.CreatedAt.String(), + UpdatedAt: infraAccessApp.UpdatedAt.String(), + ScimConfig: infraAccessApp.SCIMConfig, + TargetContexts: infraAccessApp.TargetContexts, + Policies: infraAccessApp.Policies, + }, nil +} + +// DeleteAccessInfrastructureApplication deletes a single infrastructure application. +// +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-delete-an-access-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-delete-an-access-application +func (api *API) DeleteAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, applicationID string) error { + if rc.Identifier == "" { + return ErrMissingAccountID + } + if applicationID == "" { + return ErrMissingTargetId + } + return api.DeleteAccessApplication(ctx, rc, applicationID) +} diff --git a/access_infrastructure_application_test.go b/access_infrastructure_application_test.go new file mode 100644 index 00000000000..4e16b29c74d --- /dev/null +++ b/access_infrastructure_application_test.go @@ -0,0 +1,501 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +const testInfrastructureApplicationId = "019205b5-97d7-7272-b00e-0ea05e61a124" + +var ( + accessPolicyCreatedOn, _ = time.Parse(time.RFC3339, "2020-08-25T05:00:22Z") + accessPolicyUpdatedOn, _ = time.Parse(time.RFC3339, "2020-08-25T05:00:22Z") + infrastructureApplicationCreatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") + infrastructureApplicationUpdatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T14:30:22Z") + expectedInfraAppPolicy = AccessPolicy{ + ID: "699d98642c564d2e855e9661899b7252", + Precedence: 1, + Reusable: BoolPtr(true), + Decision: "allow", + CreatedAt: &accessPolicyCreatedOn, + UpdatedAt: &accessPolicyUpdatedOn, + Name: "my infra SSH policy", + Include: []any{ + map[string]interface{}{"email": map[string]interface{}{"email": "devuser@example.com"}}, + }, + InfraConnectionRules: &InfraConnectionRules{ + SSH: &InfraConnectionRulesSSH{ + Usernames: []string{"devuser"}, + }, + }, + } + expectedInfrastructureApplication = InfrastructureApplication{ + ID: testInfrastructureApplicationId, + Name: "infrastructure_application_test", + Type: "infrastructure", + Aud: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + CreatedAt: infrastructureAccessTargetCreatedOn.String(), + UpdatedAt: infrastructureApplicationCreatedOn.String(), + TargetContexts: []InfraTargetContext{ + { + TargetAttributes: map[string][]string{ + "name": {"vault 420", "vault 421"}, + "env": {"dev", "staging"}, + }, + Port: 24, + Protocol: "SSH", + }, + }, + Policies: []AccessPolicy{ + expectedInfraAppPolicy, + }, + } + + expectedInfrastructureApplicationModified = InfrastructureApplication{ + ID: testInfrastructureApplicationId, + Name: "infrastructure_application_test_updated", + Type: "infrastructure", + Aud: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + CreatedAt: infrastructureAccessTargetCreatedOn.String(), + UpdatedAt: infrastructureApplicationUpdatedOn.String(), + TargetContexts: []InfraTargetContext{ + { + TargetAttributes: map[string][]string{ + "name": {"vault 425", "vault 430"}, + "env": {"staging"}, + }, + Port: 24, + Protocol: "SSH", + }, + }, + Policies: []AccessPolicy{ + expectedInfraAppPolicy, + }, + } +) + +func TestInfrastructureApplication_List(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps?app_type=infrastructure", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "created_at": "2024-08-25T05:00:22Z", + "updated_at": "2024-08-25T05:00:22Z", + "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + "name": "infrastructure_application_test", + "domain": "test.example.com/admin", + "type": "infrastructure", + "session_duration": "24h", + "auto_redirect_to_identity": false, + "enable_binding_cookie": false, + "custom_deny_url": "https://www.example.com", + "custom_non_identity_deny_url": "https://blocked.com", + "custom_deny_message": "denied!", + "http_only_cookie_attribute": true, + "same_site_cookie_attribute": "strict", + "logo_url": "https://www.example.com/example.png", + "skip_interstitial": true, + "app_launcher_visible": true, + "service_auth_401_redirect": true, + "path_cookie_attribute": true, + "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], + "allow_authenticate_via_warp": true, + "options_preflight_bypass": false, + "target_criteria": [ + { + "target_attributes": { + "name": [ "vault 420", "vault 421" ], + "env": [ "dev", "staging" ] + }, + "port": 24, + "protocol": "SSH" + } + ], + "policies": [ + { + "id": "699d98642c564d2e855e9661899b7252", + "precedence": 1, + "reusable": true, + "decision": "allow", + "created_at": "2020-08-25T05:00:22Z", + "updated_at": "2020-08-25T05:00:22Z", + "name": "my infra SSH policy", + "include": [ + { + "email": { + "email": "devuser@example.com" + } + } + ], + "connection_rules": { + "ssh": { + "usernames": ["devuser"] + } + } + } + ] + } + ], + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 1 + } + }`) + }) + + _, _, err := client.ListAccessInfrastructureApplications(context.Background(), AccountIdentifier(""), ListAccessApplicationsParams{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + out, results, err := client.ListAccessInfrastructureApplications(context.Background(), AccountIdentifier(testAccountID), ListAccessApplicationsParams{}) + if assert.NoError(t, err) { + assert.Equal(t, 1, len(out), "expected 1 infrastructure_application") + assert.Equal(t, 20, results.PerPage, "expected 20 per page") + assert.Equal(t, expectedInfrastructureApplication, out[0], "list infrastructure_application structs not equal") + } +} + +func TestInfrastructureApplication_Create(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "created_at": "2024-08-25T05:00:22Z", + "updated_at": "2024-08-25T05:00:22Z", + "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + "name": "infrastructure_application_test", + "domain": "test.example.com/admin", + "type": "infrastructure", + "session_duration": "24h", + "auto_redirect_to_identity": false, + "enable_binding_cookie": false, + "custom_deny_url": "https://www.example.com", + "custom_non_identity_deny_url": "https://blocked.com", + "custom_deny_message": "denied!", + "http_only_cookie_attribute": true, + "same_site_cookie_attribute": "strict", + "logo_url": "https://www.example.com/example.png", + "skip_interstitial": true, + "app_launcher_visible": true, + "service_auth_401_redirect": true, + "path_cookie_attribute": true, + "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], + "allow_authenticate_via_warp": true, + "options_preflight_bypass": false, + "target_criteria": [ + { + "target_attributes": { + "name": [ "vault 420", "vault 421" ], + "env": [ "dev", "staging" ] + }, + "port": 24, + "protocol": "SSH" + } + ], + "policies": [ + { + "id": "699d98642c564d2e855e9661899b7252", + "precedence": 1, + "reusable": true, + "decision": "allow", + "created_at": "2020-08-25T05:00:22Z", + "updated_at": "2020-08-25T05:00:22Z", + "name": "my infra SSH policy", + "include": [ + { + "email": { + "email": "devuser@example.com" + } + } + ], + "connection_rules": { + "ssh": { + "usernames": ["devuser"] + } + } + } + ] + } + }`) + }) + + // Make sure missing account ID is thrown + _, err := client.CreateAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), CreateInfrastructureApplicationParams{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + // We expect this to parse through the Access Application response and only return + // Infrastructure Application built from that response + out, err := client.CreateAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), CreateInfrastructureApplicationParams{ + InfrastructureApplicationParams: InfrastructureApplicationParams{ + Name: "infrastructure_application_test", + Type: "infrastructure", + TargetContexts: []InfraTargetContext{ + { + TargetAttributes: map[string][]string{ + "name": {"vault 420", "vault 421"}, + "env": {"dev", "staging"}, + }, + Port: 24, + Protocol: "SSH", + }, + }, + Policies: []AccessPolicy{ + expectedInfraAppPolicy, + }, + }, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureApplication, out, "create infrastructure_application structs not equal") + } +} + +func TestInfrastructureApplication_Update(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testInfrastructureApplicationId, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "created_at": "2024-08-25T05:00:22Z", + "updated_at": "2024-08-25T14:30:22Z", + "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + "name": "infrastructure_application_test_updated", + "domain": "test.example.com/admin", + "type": "infrastructure", + "session_duration": "24h", + "auto_redirect_to_identity": false, + "enable_binding_cookie": false, + "custom_deny_url": "https://www.example.com", + "custom_non_identity_deny_url": "https://blocked.com", + "custom_deny_message": "denied!", + "http_only_cookie_attribute": true, + "same_site_cookie_attribute": "strict", + "logo_url": "https://www.example.com/example.png", + "skip_interstitial": true, + "app_launcher_visible": true, + "service_auth_401_redirect": true, + "path_cookie_attribute": true, + "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], + "allow_authenticate_via_warp": true, + "options_preflight_bypass": false, + "target_criteria": [ + { + "target_attributes": { + "name": [ "vault 425", "vault 430" ], + "env": [ "staging" ] + }, + "port": 24, + "protocol": "SSH" + } + ], + "policies": [ + { + "id": "699d98642c564d2e855e9661899b7252", + "precedence": 1, + "reusable": true, + "decision": "allow", + "created_at": "2020-08-25T05:00:22Z", + "updated_at": "2020-08-25T05:00:22Z", + "name": "my infra SSH policy", + "include": [ + { + "email": { + "email": "devuser@example.com" + } + } + ], + "connection_rules": { + "ssh": { + "usernames": ["devuser"] + } + } + } + ] + } + }`) + }) + + _, err := client.UpdateAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), UpdateInfrastructureApplicationParams{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.UpdateAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureApplicationParams{ + ID: "", + InfrastructureApplicationParams: InfrastructureApplicationParams{}, + }) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingTargetId, err) + } + + out, err := client.UpdateAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureApplicationParams{ + ID: testInfrastructureApplicationId, + InfrastructureApplicationParams: InfrastructureApplicationParams{ + Name: "infrastructure_application_test_updated", + Type: "infrastructure", + TargetContexts: []InfraTargetContext{ + { + TargetAttributes: map[string][]string{ + "name": {"vault 420", "vault 430"}, + "env": {"staging"}, + }, + Port: 24, + Protocol: "SSH", + }, + }, + Policies: []AccessPolicy{ + expectedInfraAppPolicy, + }, + }, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureApplicationModified, out, "update infrastructure_application structs not equal") + } +} + +func TestInfrastructureApplication_Get(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testInfrastructureApplicationId, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "019205b5-97d7-7272-b00e-0ea05e61a124", + "created_at": "2024-08-25T05:00:22Z", + "updated_at": "2024-08-25T05:00:22Z", + "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + "name": "infrastructure_application_test", + "domain": "test.example.com/admin", + "type": "infrastructure", + "session_duration": "24h", + "auto_redirect_to_identity": false, + "enable_binding_cookie": false, + "custom_deny_url": "https://www.example.com", + "custom_non_identity_deny_url": "https://blocked.com", + "custom_deny_message": "denied!", + "http_only_cookie_attribute": true, + "same_site_cookie_attribute": "strict", + "logo_url": "https://www.example.com/example.png", + "skip_interstitial": true, + "app_launcher_visible": true, + "service_auth_401_redirect": true, + "path_cookie_attribute": true, + "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], + "allow_authenticate_via_warp": true, + "options_preflight_bypass": false, + "target_criteria": [ + { + "target_attributes": { + "name": [ "vault 420", "vault 421" ], + "env": [ "dev", "staging" ] + }, + "port": 24, + "protocol": "SSH" + } + ], + "policies": [ + { + "id": "699d98642c564d2e855e9661899b7252", + "precedence": 1, + "reusable": true, + "decision": "allow", + "created_at": "2020-08-25T05:00:22Z", + "updated_at": "2020-08-25T05:00:22Z", + "name": "my infra SSH policy", + "include": [ + { + "email": { + "email": "devuser@example.com" + } + } + ], + "connection_rules": { + "ssh": { + "usernames": ["devuser"] + } + } + } + ] + } + }`) + }) + + _, err := client.GetAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.GetAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingTargetId, err) + } + + out, err := client.GetAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), testInfrastructureApplicationId) + + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureApplication, out, "get infrastructure_target not equal to expected") + } +} + +func TestInfrastructureApplication_Delete(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testInfrastructureApplicationId, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ``) + }) + + // Make sure missing account ID is thrown + err := client.DeleteAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + err = client.DeleteAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingTargetId, err) + } + + err = client.DeleteAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), testInfrastructureApplicationId) + assert.NoError(t, err) +} diff --git a/access_policy.go b/access_policy.go index a70ceede50c..53717ab9055 100644 --- a/access_policy.go +++ b/access_policy.go @@ -15,6 +15,14 @@ type AccessApprovalGroup struct { ApprovalsNeeded int `json:"approvals_needed,omitempty"` } +type InfraConnectionRulesSSH struct { + Usernames []string `json:"usernames"` +} + +type InfraConnectionRules struct { + SSH *InfraConnectionRulesSSH `json:"ssh,omitempty"` +} + // AccessPolicy defines a policy for allowing or disallowing access to // one or more Access applications. type AccessPolicy struct { @@ -36,6 +44,7 @@ type AccessPolicy struct { PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` ApprovalRequired *bool `json:"approval_required,omitempty"` ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + InfraConnectionRules *InfraConnectionRules `json:"connection_rules,omitempty"` // The include policy works like an OR logical operator. The user must // satisfy one of the rules. diff --git a/infrastructure_access_target_test.go b/infrastructure_access_target_test.go index b80bcda76b0..dc1423ff035 100644 --- a/infrastructure_access_target_test.go +++ b/infrastructure_access_target_test.go @@ -150,7 +150,7 @@ func TestInfrastructureTarget_List(t *testing.T) { if assert.NoError(t, err) { assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") assert.Equal(t, 20, results.PerPage, "expected 20 per page") - assert.Equal(t, expectedInfrastructureAccessTarget, out[0], "list challenge_widgets structs not equal") + assert.Equal(t, expectedInfrastructureAccessTarget, out[0], "list infrastructure_access_target structs not equal") } } @@ -256,7 +256,7 @@ func TestInfrastructureTarget_Update(t *testing.T) { }, }) if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureModified, out, "update challenge_widgets structs not equal") + assert.Equal(t, expectedInfrastructureModified, out, "update infrastructure_access_target structs not equal") } } From 03cb4b481f5dee223031444a2fb2dbb79d3ee851 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 14:18:10 -0700 Subject: [PATCH 70/84] Use existing endpoints --- access_application.go | 2 + access_infrastructure_application.go | 179 +-------- access_infrastructure_application_test.go | 432 +++------------------- 3 files changed, 48 insertions(+), 565 deletions(-) diff --git a/access_application.go b/access_application.go index 045bfb3ca19..8ae914f4e31 100644 --- a/access_application.go +++ b/access_application.go @@ -306,6 +306,7 @@ type CreateAccessApplicationParams struct { CustomPages []string `json:"custom_pages,omitempty"` Tags []string `json:"tags,omitempty"` SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` + TargetContexts []InfraTargetContext `json:"target_criteria,omitempty"` // List of policy ids to link to this application in ascending order of precedence. Policies []string `json:"policies,omitempty"` AccessAppLauncherCustomization @@ -341,6 +342,7 @@ type UpdateAccessApplicationParams struct { CustomPages []string `json:"custom_pages,omitempty"` Tags []string `json:"tags,omitempty"` SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` + TargetContexts []InfraTargetContext `json:"target_criteria,omitempty"` // List of policy ids to link to this application in ascending order of precedence. // Can reference reusable policies and policies specific to this application. // If this field is not provided, the existing policies will not be modified. diff --git a/access_infrastructure_application.go b/access_infrastructure_application.go index d655d912959..3ed1ce9eff8 100644 --- a/access_infrastructure_application.go +++ b/access_infrastructure_application.go @@ -1,13 +1,5 @@ package cloudflare -import ( - "context" - "fmt" - "net/http" - - "github.com/goccy/go-json" -) - type InfraProtocol string const ( @@ -36,173 +28,4 @@ type InfrastructureApplication struct { Policies []AccessPolicy `json:"policies"` } -type InfrastructureApplicationParams struct { - Name string `json:"name"` - Type AccessApplicationType `json:"type"` - TargetContexts []InfraTargetContext `json:"target_criteria"` - Policies []AccessPolicy `json:"policies"` -} - -type CreateInfrastructureApplicationParams struct { - InfrastructureApplicationParams -} - -type UpdateInfrastructureApplicationParams struct { - ID string `json:"-"` - InfrastructureApplicationParams -} - -// ListAccessInfrastructureApplications returns all applications within an account or zone. -// -// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-list-access-applications -// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-list-access-applications -func (api *API) ListAccessInfrastructureApplications(ctx context.Context, rc *ResourceContainer, params ListAccessApplicationsParams) ([]InfrastructureApplication, *ResultInfo, error) { - if rc.Identifier == "" { - return []InfrastructureApplication{}, &ResultInfo{}, ErrMissingAccountID - } - baseURL := fmt.Sprintf("/%s/%s/access/apps?app_type=infrastructure", rc.Level, rc.Identifier) - - autoPaginate := true - if params.PerPage >= 1 || params.Page >= 1 { - autoPaginate = false - } - - if params.PerPage < 1 { - params.PerPage = 25 - } - - if params.Page < 1 { - params.Page = 1 - } - - var infraApps []InfrastructureApplication - var r AccessApplicationListResponse - - for { - uri := buildURI(baseURL, params) - - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []InfrastructureApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) - } - err = json.Unmarshal(res, &r) - if err != nil { - return []InfrastructureApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - applications := r.Result - for _, app := range applications { - infraApps = append(infraApps, InfrastructureApplication{ - ID: app.ID, - Type: app.Type, - Name: app.Name, - Aud: app.AUD, - CreatedAt: app.CreatedAt.String(), - UpdatedAt: app.UpdatedAt.String(), - ScimConfig: app.SCIMConfig, - TargetContexts: app.TargetContexts, - Policies: app.Policies, - }) - } - params.ResultInfo = r.ResultInfo.Next() - if params.ResultInfo.Done() || !autoPaginate { - break - } - } - - return infraApps, &r.ResultInfo, nil -} - -// CreateAccessInfrastructureApplication creates a new access application. -// -// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application -// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application -func (api *API) CreateAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, params CreateInfrastructureApplicationParams) (InfrastructureApplication, error) { - if rc.Identifier == "" { - return InfrastructureApplication{}, ErrMissingAccountID - } - uri := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier) - return api.sendInfrastructureApplicationRequest(ctx, http.MethodPost, uri, params.InfrastructureApplicationParams) -} - -// UpdateAccessInfrastructureApplication creates a new access application. -// -// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application -// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application -func (api *API) UpdateAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, params UpdateInfrastructureApplicationParams) (InfrastructureApplication, error) { - if rc.Identifier == "" { - return InfrastructureApplication{}, ErrMissingAccountID - } - if params.ID == "" { - return InfrastructureApplication{}, ErrMissingTargetId - } - uri := fmt.Sprintf("/%s/%s/access/apps/%s", rc.Level, rc.Identifier, params.ID) - return api.sendInfrastructureApplicationRequest(ctx, http.MethodPut, uri, params.InfrastructureApplicationParams) -} - -func (api *API) sendInfrastructureApplicationRequest(ctx context.Context, httpMethod string, uri string, params InfrastructureApplicationParams) (InfrastructureApplication, error) { - res, err := api.makeRequestContext(ctx, httpMethod, uri, params) - if err != nil { - return InfrastructureApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) - } - - var accessApplicationDetailResponse AccessApplicationDetailResponse - err = json.Unmarshal(res, &accessApplicationDetailResponse) - if err != nil { - return InfrastructureApplication{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - accessApp := accessApplicationDetailResponse.Result - return InfrastructureApplication{ - ID: accessApp.ID, - Type: accessApp.Type, - Name: accessApp.Name, - Aud: accessApp.AUD, - CreatedAt: accessApp.CreatedAt.String(), - UpdatedAt: accessApp.UpdatedAt.String(), - ScimConfig: accessApp.SCIMConfig, - TargetContexts: accessApp.TargetContexts, - Policies: accessApp.Policies, - }, nil -} - -// GetAccessInfrastructureApplication returns a single infrastructure application based on the application ID for either account or zone. -// -// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-get-an-access-application -// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-get-an-access-application -func (api *API) GetAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, applicationID string) (InfrastructureApplication, error) { - if rc.Identifier == "" { - return InfrastructureApplication{}, ErrMissingAccountID - } - if applicationID == "" { - return InfrastructureApplication{}, ErrMissingTargetId - } - infraAccessApp, err := api.GetAccessApplication(ctx, rc, applicationID) - if err != nil { - return InfrastructureApplication{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return InfrastructureApplication{ - ID: infraAccessApp.ID, - Type: infraAccessApp.Type, - Name: infraAccessApp.Name, - Aud: infraAccessApp.AUD, - CreatedAt: infraAccessApp.CreatedAt.String(), - UpdatedAt: infraAccessApp.UpdatedAt.String(), - ScimConfig: infraAccessApp.SCIMConfig, - TargetContexts: infraAccessApp.TargetContexts, - Policies: infraAccessApp.Policies, - }, nil -} - -// DeleteAccessInfrastructureApplication deletes a single infrastructure application. -// -// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-delete-an-access-application -// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-delete-an-access-application -func (api *API) DeleteAccessInfrastructureApplication(ctx context.Context, rc *ResourceContainer, applicationID string) error { - if rc.Identifier == "" { - return ErrMissingAccountID - } - if applicationID == "" { - return ErrMissingTargetId - } - return api.DeleteAccessApplication(ctx, rc, applicationID) -} +// Reuse methods from access_application diff --git a/access_infrastructure_application_test.go b/access_infrastructure_application_test.go index 4e16b29c74d..0e4d621ef41 100644 --- a/access_infrastructure_application_test.go +++ b/access_infrastructure_application_test.go @@ -13,20 +13,20 @@ import ( const testInfrastructureApplicationId = "019205b5-97d7-7272-b00e-0ea05e61a124" var ( - accessPolicyCreatedOn, _ = time.Parse(time.RFC3339, "2020-08-25T05:00:22Z") - accessPolicyUpdatedOn, _ = time.Parse(time.RFC3339, "2020-08-25T05:00:22Z") - infrastructureApplicationCreatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T05:00:22Z") - infrastructureApplicationUpdatedOn, _ = time.Parse(time.RFC3339, "2024-08-25T14:30:22Z") + accessPolicyCreatedOn, _ = time.Parse(time.RFC3339, "2024-09-24T17:58:44Z") + accessPolicyUpdatedOn, _ = time.Parse(time.RFC3339, "2024-09-24T17:58:44Z") + infrastructureApplicationCreatedOn, _ = time.Parse(time.RFC3339, "2024-09-14T05:13:43Z") + infrastructureApplicationUpdatedOn, _ = time.Parse(time.RFC3339, "2024-09-24T17:58:44Z") expectedInfraAppPolicy = AccessPolicy{ - ID: "699d98642c564d2e855e9661899b7252", + ID: "8dd6af47-a80b-48cb-89c1-f39299ebf096", Precedence: 1, - Reusable: BoolPtr(true), + Reusable: BoolPtr(false), Decision: "allow", CreatedAt: &accessPolicyCreatedOn, UpdatedAt: &accessPolicyUpdatedOn, Name: "my infra SSH policy", Include: []any{ - map[string]interface{}{"email": map[string]interface{}{"email": "devuser@example.com"}}, + map[string]interface{}{"email": map[string]interface{}{"email": "devuser@cloudflare.com"}}, }, InfraConnectionRules: &InfraConnectionRules{ SSH: &InfraConnectionRulesSSH{ @@ -38,14 +38,13 @@ var ( ID: testInfrastructureApplicationId, Name: "infrastructure_application_test", Type: "infrastructure", - Aud: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + Aud: "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", CreatedAt: infrastructureAccessTargetCreatedOn.String(), UpdatedAt: infrastructureApplicationCreatedOn.String(), TargetContexts: []InfraTargetContext{ { TargetAttributes: map[string][]string{ - "name": {"vault 420", "vault 421"}, - "env": {"dev", "staging"}, + "hostname": {"cfgo-acc-tests"}, }, Port: 24, Protocol: "SSH", @@ -60,14 +59,13 @@ var ( ID: testInfrastructureApplicationId, Name: "infrastructure_application_test_updated", Type: "infrastructure", - Aud: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + Aud: "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", CreatedAt: infrastructureAccessTargetCreatedOn.String(), UpdatedAt: infrastructureApplicationUpdatedOn.String(), TargetContexts: []InfraTargetContext{ { TargetAttributes: map[string][]string{ - "name": {"vault 425", "vault 430"}, - "env": {"staging"}, + "hostname": {"cfgo-acc-tests"}, }, Port: 24, Protocol: "SSH", @@ -79,99 +77,6 @@ var ( } ) -func TestInfrastructureApplication_List(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/accounts/"+testAccountID+"/access/apps?app_type=infrastructure", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": [ - { - "id": "019205b5-97d7-7272-b00e-0ea05e61a124", - "created_at": "2024-08-25T05:00:22Z", - "updated_at": "2024-08-25T05:00:22Z", - "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", - "name": "infrastructure_application_test", - "domain": "test.example.com/admin", - "type": "infrastructure", - "session_duration": "24h", - "auto_redirect_to_identity": false, - "enable_binding_cookie": false, - "custom_deny_url": "https://www.example.com", - "custom_non_identity_deny_url": "https://blocked.com", - "custom_deny_message": "denied!", - "http_only_cookie_attribute": true, - "same_site_cookie_attribute": "strict", - "logo_url": "https://www.example.com/example.png", - "skip_interstitial": true, - "app_launcher_visible": true, - "service_auth_401_redirect": true, - "path_cookie_attribute": true, - "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], - "allow_authenticate_via_warp": true, - "options_preflight_bypass": false, - "target_criteria": [ - { - "target_attributes": { - "name": [ "vault 420", "vault 421" ], - "env": [ "dev", "staging" ] - }, - "port": 24, - "protocol": "SSH" - } - ], - "policies": [ - { - "id": "699d98642c564d2e855e9661899b7252", - "precedence": 1, - "reusable": true, - "decision": "allow", - "created_at": "2020-08-25T05:00:22Z", - "updated_at": "2020-08-25T05:00:22Z", - "name": "my infra SSH policy", - "include": [ - { - "email": { - "email": "devuser@example.com" - } - } - ], - "connection_rules": { - "ssh": { - "usernames": ["devuser"] - } - } - } - ] - } - ], - "result_info": { - "page": 1, - "per_page": 20, - "count": 1, - "total_count": 1 - } - }`) - }) - - _, _, err := client.ListAccessInfrastructureApplications(context.Background(), AccountIdentifier(""), ListAccessApplicationsParams{}) - if assert.Error(t, err) { - assert.Equal(t, ErrMissingAccountID, err) - } - - out, results, err := client.ListAccessInfrastructureApplications(context.Background(), AccountIdentifier(testAccountID), ListAccessApplicationsParams{}) - if assert.NoError(t, err) { - assert.Equal(t, 1, len(out), "expected 1 infrastructure_application") - assert.Equal(t, 20, results.PerPage, "expected 20 per page") - assert.Equal(t, expectedInfrastructureApplication, out[0], "list infrastructure_application structs not equal") - } -} - func TestInfrastructureApplication_Create(t *testing.T) { setup() defer teardown() @@ -184,318 +89,71 @@ func TestInfrastructureApplication_Create(t *testing.T) { "errors": [], "messages": [], "result": { - "id": "019205b5-97d7-7272-b00e-0ea05e61a124", - "created_at": "2024-08-25T05:00:22Z", - "updated_at": "2024-08-25T05:00:22Z", - "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", - "name": "infrastructure_application_test", - "domain": "test.example.com/admin", + "id": "0a20bd6b-26bb-4e9f-a835-f81f4e5f4427", + "uid": "0a20bd6b-26bb-4e9f-a835-f81f4e5f4427", "type": "infrastructure", - "session_duration": "24h", - "auto_redirect_to_identity": false, - "enable_binding_cookie": false, - "custom_deny_url": "https://www.example.com", - "custom_non_identity_deny_url": "https://blocked.com", - "custom_deny_message": "denied!", - "http_only_cookie_attribute": true, - "same_site_cookie_attribute": "strict", - "logo_url": "https://www.example.com/example.png", - "skip_interstitial": true, - "app_launcher_visible": true, - "service_auth_401_redirect": true, - "path_cookie_attribute": true, - "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], - "allow_authenticate_via_warp": true, - "options_preflight_bypass": false, + "name": "infrastructure_application_test", + "aud": "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", + "created_at": "2024-09-14T05:13:43Z", + "updated_at": "2024-09-24T17:58:44Z", "target_criteria": [ { "target_attributes": { - "name": [ "vault 420", "vault 421" ], - "env": [ "dev", "staging" ] + "hostname": [ "cfgo-acc-tests" ] }, - "port": 24, + "port": 22, "protocol": "SSH" } - ], + ], "policies": [ { - "id": "699d98642c564d2e855e9661899b7252", - "precedence": 1, - "reusable": true, + "created_at": "2024-09-24T17:58:44Z", "decision": "allow", - "created_at": "2020-08-25T05:00:22Z", - "updated_at": "2020-08-25T05:00:22Z", - "name": "my infra SSH policy", + "exclude": [], + "id": "8dd6af47-a80b-48cb-89c1-f39299ebf096", "include": [ { "email": { - "email": "devuser@example.com" + "email": "devuser@cloudflare.com" } } ], + "name": "my infra SSH policy", + "require": [], "connection_rules": { "ssh": { - "usernames": ["devuser"] + "usernames": [ "devuser" ] } - } + }, + "uid": "8dd6af47-a80b-48cb-89c1-f39299ebf096", + "updated_at": "2024-09-24T17:58:44Z", + "reusable": false, + "precedence": 1 } ] - } + }, }`) }) - // Make sure missing account ID is thrown - _, err := client.CreateAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), CreateInfrastructureApplicationParams{}) - if assert.Error(t, err) { - assert.Equal(t, ErrMissingAccountID, err) - } - // We expect this to parse through the Access Application response and only return // Infrastructure Application built from that response - out, err := client.CreateAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), CreateInfrastructureApplicationParams{ - InfrastructureApplicationParams: InfrastructureApplicationParams{ - Name: "infrastructure_application_test", - Type: "infrastructure", - TargetContexts: []InfraTargetContext{ - { - TargetAttributes: map[string][]string{ - "name": {"vault 420", "vault 421"}, - "env": {"dev", "staging"}, - }, - Port: 24, - Protocol: "SSH", + out, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ + Name: "infrastructure_application_test", + Type: "infrastructure", + TargetContexts: []InfraTargetContext{ + { + TargetAttributes: map[string][]string{ + "hostname": {"cfgo-acc-tests"}, }, - }, - Policies: []AccessPolicy{ - expectedInfraAppPolicy, + Port: 24, + Protocol: "SSH", }, }, - }) - if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureApplication, out, "create infrastructure_application structs not equal") - } -} - -func TestInfrastructureApplication_Update(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testInfrastructureApplicationId, func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "019205b5-97d7-7272-b00e-0ea05e61a124", - "created_at": "2024-08-25T05:00:22Z", - "updated_at": "2024-08-25T14:30:22Z", - "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", - "name": "infrastructure_application_test_updated", - "domain": "test.example.com/admin", - "type": "infrastructure", - "session_duration": "24h", - "auto_redirect_to_identity": false, - "enable_binding_cookie": false, - "custom_deny_url": "https://www.example.com", - "custom_non_identity_deny_url": "https://blocked.com", - "custom_deny_message": "denied!", - "http_only_cookie_attribute": true, - "same_site_cookie_attribute": "strict", - "logo_url": "https://www.example.com/example.png", - "skip_interstitial": true, - "app_launcher_visible": true, - "service_auth_401_redirect": true, - "path_cookie_attribute": true, - "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], - "allow_authenticate_via_warp": true, - "options_preflight_bypass": false, - "target_criteria": [ - { - "target_attributes": { - "name": [ "vault 425", "vault 430" ], - "env": [ "staging" ] - }, - "port": 24, - "protocol": "SSH" - } - ], - "policies": [ - { - "id": "699d98642c564d2e855e9661899b7252", - "precedence": 1, - "reusable": true, - "decision": "allow", - "created_at": "2020-08-25T05:00:22Z", - "updated_at": "2020-08-25T05:00:22Z", - "name": "my infra SSH policy", - "include": [ - { - "email": { - "email": "devuser@example.com" - } - } - ], - "connection_rules": { - "ssh": { - "usernames": ["devuser"] - } - } - } - ] - } - }`) - }) - - _, err := client.UpdateAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), UpdateInfrastructureApplicationParams{}) - if assert.Error(t, err) { - assert.Equal(t, ErrMissingAccountID, err) - } - - _, err = client.UpdateAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureApplicationParams{ - ID: "", - InfrastructureApplicationParams: InfrastructureApplicationParams{}, - }) - if assert.Error(t, err) { - assert.Equal(t, ErrMissingTargetId, err) - } - - out, err := client.UpdateAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), UpdateInfrastructureApplicationParams{ - ID: testInfrastructureApplicationId, - InfrastructureApplicationParams: InfrastructureApplicationParams{ - Name: "infrastructure_application_test_updated", - Type: "infrastructure", - TargetContexts: []InfraTargetContext{ - { - TargetAttributes: map[string][]string{ - "name": {"vault 420", "vault 430"}, - "env": {"staging"}, - }, - Port: 24, - Protocol: "SSH", - }, - }, - Policies: []AccessPolicy{ - expectedInfraAppPolicy, - }, + Policies: []string{ + "8dd6af47-a80b-48cb-89c1-f39299ebf096", }, }) if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureApplicationModified, out, "update infrastructure_application structs not equal") - } -} - -func TestInfrastructureApplication_Get(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testInfrastructureApplicationId, func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "019205b5-97d7-7272-b00e-0ea05e61a124", - "created_at": "2024-08-25T05:00:22Z", - "updated_at": "2024-08-25T05:00:22Z", - "aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", - "name": "infrastructure_application_test", - "domain": "test.example.com/admin", - "type": "infrastructure", - "session_duration": "24h", - "auto_redirect_to_identity": false, - "enable_binding_cookie": false, - "custom_deny_url": "https://www.example.com", - "custom_non_identity_deny_url": "https://blocked.com", - "custom_deny_message": "denied!", - "http_only_cookie_attribute": true, - "same_site_cookie_attribute": "strict", - "logo_url": "https://www.example.com/example.png", - "skip_interstitial": true, - "app_launcher_visible": true, - "service_auth_401_redirect": true, - "path_cookie_attribute": true, - "custom_pages": ["480f4f69-1a28-4fdd-9240-1ed29f0ac1dc"], - "allow_authenticate_via_warp": true, - "options_preflight_bypass": false, - "target_criteria": [ - { - "target_attributes": { - "name": [ "vault 420", "vault 421" ], - "env": [ "dev", "staging" ] - }, - "port": 24, - "protocol": "SSH" - } - ], - "policies": [ - { - "id": "699d98642c564d2e855e9661899b7252", - "precedence": 1, - "reusable": true, - "decision": "allow", - "created_at": "2020-08-25T05:00:22Z", - "updated_at": "2020-08-25T05:00:22Z", - "name": "my infra SSH policy", - "include": [ - { - "email": { - "email": "devuser@example.com" - } - } - ], - "connection_rules": { - "ssh": { - "usernames": ["devuser"] - } - } - } - ] - } - }`) - }) - - _, err := client.GetAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), "") - if assert.Error(t, err) { - assert.Equal(t, ErrMissingAccountID, err) - } - - _, err = client.GetAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), "") - if assert.Error(t, err) { - assert.Equal(t, ErrMissingTargetId, err) - } - - out, err := client.GetAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), testInfrastructureApplicationId) - - if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureApplication, out, "get infrastructure_target not equal to expected") - } -} - -func TestInfrastructureApplication_Delete(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testInfrastructureApplicationId, func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, ``) - }) - - // Make sure missing account ID is thrown - err := client.DeleteAccessInfrastructureApplication(context.Background(), AccountIdentifier(""), "") - if assert.Error(t, err) { - assert.Equal(t, ErrMissingAccountID, err) - } - - err = client.DeleteAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), "") - if assert.Error(t, err) { - assert.Equal(t, ErrMissingTargetId, err) + assert.Equal(t, expectedInfrastructureApplication, out, "create infrastructure_application structs not equal") } - - err = client.DeleteAccessInfrastructureApplication(context.Background(), AccountIdentifier(testAccountID), testInfrastructureApplicationId) - assert.NoError(t, err) } From d9eed0fe49f9e1ded793298f8290c367d4e12f8e Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 15:11:49 -0700 Subject: [PATCH 71/84] Use existing access application crud endpoints and rewrite test cases --- access_infrastructure_application.go | 15 -- access_infrastructure_application_test.go | 251 +++++++++++++++++++--- 2 files changed, 225 insertions(+), 41 deletions(-) diff --git a/access_infrastructure_application.go b/access_infrastructure_application.go index 3ed1ce9eff8..8e968b08ba3 100644 --- a/access_infrastructure_application.go +++ b/access_infrastructure_application.go @@ -14,18 +14,3 @@ type InfraTargetContext struct { Port int `json:"port"` Protocol InfraProtocol `json:"protocol"` } - -type InfrastructureApplication struct { - // Items common to both SAML and OIDC - ID string `json:"id,omitempty"` - Type AccessApplicationType `json:"type"` - Name string `json:"name"` - Aud string `json:"aud,omitempty"` - CreatedAt string `json:"created_at,omitempty"` - UpdatedAt string `json:"updated_at,omitempty"` - ScimConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` - TargetContexts []InfraTargetContext `json:"target_criteria"` - Policies []AccessPolicy `json:"policies"` -} - -// Reuse methods from access_application diff --git a/access_infrastructure_application_test.go b/access_infrastructure_application_test.go index 0e4d621ef41..5490e9a67a6 100644 --- a/access_infrastructure_application_test.go +++ b/access_infrastructure_application_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" ) -const testInfrastructureApplicationId = "019205b5-97d7-7272-b00e-0ea05e61a124" +const testInfrastructureApplicationId = "f52d1f8f-f194-4ac1-845f-e47203bf4dbb" var ( accessPolicyCreatedOn, _ = time.Parse(time.RFC3339, "2024-09-24T17:58:44Z") @@ -28,25 +28,46 @@ var ( Include: []any{ map[string]interface{}{"email": map[string]interface{}{"email": "devuser@cloudflare.com"}}, }, + Exclude: []any{}, + Require: []any{}, InfraConnectionRules: &InfraConnectionRules{ SSH: &InfraConnectionRulesSSH{ Usernames: []string{"devuser"}, }, }, } - expectedInfrastructureApplication = InfrastructureApplication{ - ID: testInfrastructureApplicationId, - Name: "infrastructure_application_test", - Type: "infrastructure", - Aud: "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", - CreatedAt: infrastructureAccessTargetCreatedOn.String(), - UpdatedAt: infrastructureApplicationCreatedOn.String(), + expectedInfrastructureApplication = AccessApplication{ + ID: testInfrastructureApplicationId, + CreatedAt: &infrastructureApplicationCreatedOn, + UpdatedAt: &infrastructureApplicationUpdatedOn, + AUD: "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", + Name: "infrastructure_application_test", + Domain: "", + Type: "infrastructure", + SessionDuration: "", + AllowedIdps: nil, + AutoRedirectToIdentity: nil, + EnableBindingCookie: nil, + AppLauncherVisible: nil, + ServiceAuth401Redirect: nil, + CustomDenyMessage: "", + CustomDenyURL: "", + SameSiteCookieAttribute: "", + HttpOnlyCookieAttribute: nil, + LogoURL: "", + SkipInterstitial: nil, + PathCookieAttribute: nil, + CustomPages: nil, + Tags: nil, + CustomNonIdentityDenyURL: "", + AllowAuthenticateViaWarp: nil, + OptionsPreflightBypass: nil, TargetContexts: []InfraTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests"}, }, - Port: 24, + Port: 22, Protocol: "SSH", }, }, @@ -55,19 +76,38 @@ var ( }, } - expectedInfrastructureApplicationModified = InfrastructureApplication{ - ID: testInfrastructureApplicationId, - Name: "infrastructure_application_test_updated", - Type: "infrastructure", - Aud: "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", - CreatedAt: infrastructureAccessTargetCreatedOn.String(), - UpdatedAt: infrastructureApplicationUpdatedOn.String(), + expectedInfrastructureApplicationUpdated = AccessApplication{ + ID: testInfrastructureApplicationId, + CreatedAt: &infrastructureApplicationCreatedOn, + UpdatedAt: &infrastructureApplicationUpdatedOn, + AUD: "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", + Name: "infrastructure_application_test_updated", + Domain: "", + Type: "infrastructure", + SessionDuration: "", + AllowedIdps: nil, + AutoRedirectToIdentity: nil, + EnableBindingCookie: nil, + AppLauncherVisible: nil, + ServiceAuth401Redirect: nil, + CustomDenyMessage: "", + CustomDenyURL: "", + SameSiteCookieAttribute: "", + HttpOnlyCookieAttribute: nil, + LogoURL: "", + SkipInterstitial: nil, + PathCookieAttribute: nil, + CustomPages: nil, + Tags: nil, + CustomNonIdentityDenyURL: "", + AllowAuthenticateViaWarp: nil, + OptionsPreflightBypass: nil, TargetContexts: []InfraTargetContext{ { TargetAttributes: map[string][]string{ - "hostname": {"cfgo-acc-tests"}, + "hostname": {"cfgo-acc-tests", "cfgo-acc-tests-duplicate"}, }, - Port: 24, + Port: 22, Protocol: "SSH", }, }, @@ -89,8 +129,7 @@ func TestInfrastructureApplication_Create(t *testing.T) { "errors": [], "messages": [], "result": { - "id": "0a20bd6b-26bb-4e9f-a835-f81f4e5f4427", - "uid": "0a20bd6b-26bb-4e9f-a835-f81f4e5f4427", + "id": "f52d1f8f-f194-4ac1-845f-e47203bf4dbb", "type": "infrastructure", "name": "infrastructure_application_test", "aud": "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", @@ -131,13 +170,11 @@ func TestInfrastructureApplication_Create(t *testing.T) { "precedence": 1 } ] - }, + } }`) }) - // We expect this to parse through the Access Application response and only return - // Infrastructure Application built from that response - out, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "infrastructure_application_test", Type: "infrastructure", TargetContexts: []InfraTargetContext{ @@ -145,7 +182,7 @@ func TestInfrastructureApplication_Create(t *testing.T) { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests"}, }, - Port: 24, + Port: 22, Protocol: "SSH", }, }, @@ -154,6 +191,168 @@ func TestInfrastructureApplication_Create(t *testing.T) { }, }) if assert.NoError(t, err) { - assert.Equal(t, expectedInfrastructureApplication, out, "create infrastructure_application structs not equal") + assert.Equal(t, expectedInfrastructureApplication, actual, "create infrastructure_application structs not equal") } } + +func TestInfrastructureApplication_Update(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "f52d1f8f-f194-4ac1-845f-e47203bf4dbb", + "type": "infrastructure", + "name": "infrastructure_application_test_updated", + "aud": "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", + "created_at": "2024-09-14T05:13:43Z", + "updated_at": "2024-09-24T17:58:44Z", + "target_criteria": [ + { + "target_attributes": { + "hostname": [ "cfgo-acc-tests", "cfgo-acc-tests-duplicate" ] + }, + "port": 22, + "protocol": "SSH" + } + ], + "policies": [ + { + "created_at": "2024-09-24T17:58:44Z", + "decision": "allow", + "exclude": [], + "id": "8dd6af47-a80b-48cb-89c1-f39299ebf096", + "include": [ + { + "email": { + "email": "devuser@cloudflare.com" + } + } + ], + "name": "my infra SSH policy", + "require": [], + "connection_rules": { + "ssh": { + "usernames": [ "devuser" ] + } + }, + "uid": "8dd6af47-a80b-48cb-89c1-f39299ebf096", + "updated_at": "2024-09-24T17:58:44Z", + "reusable": false, + "precedence": 1 + } + ] + } + }`) + }) + + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ + Name: "infrastructure_application_test_updated", + Type: "infrastructure", + TargetContexts: []InfraTargetContext{ + { + TargetAttributes: map[string][]string{ + "hostname": {"cfgo-acc-tests", "cfgo-acc-tests-duplicate"}, + }, + Port: 22, + Protocol: "SSH", + }, + }, + Policies: []string{ + "8dd6af47-a80b-48cb-89c1-f39299ebf096", + }, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureApplicationUpdated, actual, "create infrastructure_application structs not equal") + } +} + +func TestInfrastructureApplication_Get(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f52d1f8f-f194-4ac1-845f-e47203bf4dbb", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "f52d1f8f-f194-4ac1-845f-e47203bf4dbb", + "type": "infrastructure", + "name": "infrastructure_application_test", + "aud": "6570722c13470d8c3e7aed619fc66cdf948002efbb06601166b8f2dad85fae34", + "created_at": "2024-09-14T05:13:43Z", + "updated_at": "2024-09-24T17:58:44Z", + "target_criteria": [ + { + "target_attributes": { + "hostname": [ "cfgo-acc-tests" ] + }, + "port": 22, + "protocol": "SSH" + } + ], + "policies": [ + { + "created_at": "2024-09-24T17:58:44Z", + "decision": "allow", + "exclude": [], + "id": "8dd6af47-a80b-48cb-89c1-f39299ebf096", + "include": [ + { + "email": { + "email": "devuser@cloudflare.com" + } + } + ], + "name": "my infra SSH policy", + "require": [], + "connection_rules": { + "ssh": { + "usernames": [ "devuser" ] + } + }, + "uid": "8dd6af47-a80b-48cb-89c1-f39299ebf096", + "updated_at": "2024-09-24T17:58:44Z", + "reusable": false, + "precedence": 1 + } + ] + } + }`) + }) + + actual, err := client.GetAccessApplication(context.Background(), AccountIdentifier(testAccountID), "f52d1f8f-f194-4ac1-845f-e47203bf4dbb") + if assert.NoError(t, err) { + assert.Equal(t, expectedInfrastructureApplication, actual, "get infrastructure_application structs not equal") + } +} + +func TestInfrastructureApplication_Delete(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f52d1f8f-f194-4ac1-845f-e47203bf4dbb", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "f52d1f8f-f194-4ac1-845f-e47203bf4dbb" + } + }`) + }) + + err := client.DeleteAccessApplication(context.Background(), AccountIdentifier(testAccountID), "f52d1f8f-f194-4ac1-845f-e47203bf4dbb") + assert.NoError(t, err) +} From 76fa2f79d1f3d13d8ad69145485237656febcd82 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 15:12:40 -0700 Subject: [PATCH 72/84] Cleanup comments --- access_infrastructure_application.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/access_infrastructure_application.go b/access_infrastructure_application.go index 8e968b08ba3..f471d6935af 100644 --- a/access_infrastructure_application.go +++ b/access_infrastructure_application.go @@ -7,8 +7,6 @@ const ( RDP InfraProtocol = "RDP" ) -// WARNING : The following table has a constraint. Each organization can specify at maximum one protocol for each of their ports. -// There can be at maximum a single (OrgID, Port, Protocol) combination, which can be shared across multiple records. type InfraTargetContext struct { TargetAttributes map[string][]string `json:"target_attributes"` Port int `json:"port"` From 24fb45ce9500e69da295c18ef80d64952dd95b2b Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 15:14:22 -0700 Subject: [PATCH 73/84] Move infra related types to appropriate file --- access_infrastructure_application.go | 8 ++++++++ access_policy.go | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/access_infrastructure_application.go b/access_infrastructure_application.go index f471d6935af..6d6e3e0e68f 100644 --- a/access_infrastructure_application.go +++ b/access_infrastructure_application.go @@ -12,3 +12,11 @@ type InfraTargetContext struct { Port int `json:"port"` Protocol InfraProtocol `json:"protocol"` } + +type InfraConnectionRulesSSH struct { + Usernames []string `json:"usernames"` +} + +type InfraConnectionRules struct { + SSH *InfraConnectionRulesSSH `json:"ssh,omitempty"` +} diff --git a/access_policy.go b/access_policy.go index 53717ab9055..cd1fe68f5ac 100644 --- a/access_policy.go +++ b/access_policy.go @@ -15,14 +15,6 @@ type AccessApprovalGroup struct { ApprovalsNeeded int `json:"approvals_needed,omitempty"` } -type InfraConnectionRulesSSH struct { - Usernames []string `json:"usernames"` -} - -type InfraConnectionRules struct { - SSH *InfraConnectionRulesSSH `json:"ssh,omitempty"` -} - // AccessPolicy defines a policy for allowing or disallowing access to // one or more Access applications. type AccessPolicy struct { From e27fa5924182fc8e392f96134095f74bf7ba2546 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 18:29:32 -0700 Subject: [PATCH 74/84] Struct types should use pointers as they are optional --- access_application.go | 6 +++--- access_infrastructure_application_test.go | 8 ++++---- access_policy.go | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/access_application.go b/access_application.go index 8ae914f4e31..644a0f60235 100644 --- a/access_application.go +++ b/access_application.go @@ -60,7 +60,7 @@ type AccessApplication struct { Tags []string `json:"tags,omitempty"` SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` Policies []AccessPolicy `json:"policies,omitempty"` - TargetContexts []InfraTargetContext `json:"target_criteria,omitempty"` + TargetContexts *[]InfraTargetContext `json:"target_criteria,omitempty"` AccessAppLauncherCustomization } @@ -306,7 +306,7 @@ type CreateAccessApplicationParams struct { CustomPages []string `json:"custom_pages,omitempty"` Tags []string `json:"tags,omitempty"` SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` - TargetContexts []InfraTargetContext `json:"target_criteria,omitempty"` + TargetContexts *[]InfraTargetContext `json:"target_criteria,omitempty"` // List of policy ids to link to this application in ascending order of precedence. Policies []string `json:"policies,omitempty"` AccessAppLauncherCustomization @@ -342,7 +342,7 @@ type UpdateAccessApplicationParams struct { CustomPages []string `json:"custom_pages,omitempty"` Tags []string `json:"tags,omitempty"` SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` - TargetContexts []InfraTargetContext `json:"target_criteria,omitempty"` + TargetContexts *[]InfraTargetContext `json:"target_criteria,omitempty"` // List of policy ids to link to this application in ascending order of precedence. // Can reference reusable policies and policies specific to this application. // If this field is not provided, the existing policies will not be modified. diff --git a/access_infrastructure_application_test.go b/access_infrastructure_application_test.go index 5490e9a67a6..c53fd1e3be6 100644 --- a/access_infrastructure_application_test.go +++ b/access_infrastructure_application_test.go @@ -62,7 +62,7 @@ var ( CustomNonIdentityDenyURL: "", AllowAuthenticateViaWarp: nil, OptionsPreflightBypass: nil, - TargetContexts: []InfraTargetContext{ + TargetContexts: &[]InfraTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests"}, @@ -102,7 +102,7 @@ var ( CustomNonIdentityDenyURL: "", AllowAuthenticateViaWarp: nil, OptionsPreflightBypass: nil, - TargetContexts: []InfraTargetContext{ + TargetContexts: &[]InfraTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests", "cfgo-acc-tests-duplicate"}, @@ -177,7 +177,7 @@ func TestInfrastructureApplication_Create(t *testing.T) { actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "infrastructure_application_test", Type: "infrastructure", - TargetContexts: []InfraTargetContext{ + TargetContexts: &[]InfraTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests"}, @@ -255,7 +255,7 @@ func TestInfrastructureApplication_Update(t *testing.T) { actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "infrastructure_application_test_updated", Type: "infrastructure", - TargetContexts: []InfraTargetContext{ + TargetContexts: &[]InfraTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests", "cfgo-acc-tests-duplicate"}, diff --git a/access_policy.go b/access_policy.go index cd1fe68f5ac..b59dc8bda3c 100644 --- a/access_policy.go +++ b/access_policy.go @@ -101,6 +101,7 @@ type CreateAccessPolicyParams struct { PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` ApprovalRequired *bool `json:"approval_required,omitempty"` ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + InfraConnectionRules *InfraConnectionRules `json:"connection_rules,omitempty"` // The include policy works like an OR logical operator. The user must // satisfy one of the rules. @@ -134,6 +135,7 @@ type UpdateAccessPolicyParams struct { PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` ApprovalRequired *bool `json:"approval_required,omitempty"` ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + InfraConnectionRules *InfraConnectionRules `json:"connection_rules,omitempty"` // The include policy works like an OR logical operator. The user must // satisfy one of the rules. From 12ad68e078921f6c8fd4f520dc112c21eecf31c3 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 23:01:45 -0700 Subject: [PATCH 75/84] Add connection rules to access policy tests --- access_policy_test.go | 50 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/access_policy_test.go b/access_policy_test.go index 75642138205..d7a8669445a 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -55,6 +55,11 @@ var ( ApprovalsNeeded: 1, }, }, + InfraConnectionRules: &InfraConnectionRules{ + SSH: &InfraConnectionRulesSSH{ + Usernames: []string{"root", "ec2-user"}, + }, + }, } ) @@ -115,7 +120,12 @@ func TestAccessPolicies(t *testing.T) { ], "approvals_needed": 1 } - ] + ], + "connection_rules": { + "ssh": { + "usernames": ["root", "ec2-user"] + } + } } ], "result_info": { @@ -214,7 +224,12 @@ func TestAccessPolicy(t *testing.T) { "email_addresses": ["email1@example.com", "email2@example.com"], "approvals_needed": 1 } - ] + ], + "connection_rules": { + "ssh": { + "usernames": ["root", "ec2-user"] + } + } } } `) @@ -307,7 +322,12 @@ func TestCreateAccessPolicy(t *testing.T) { "email_addresses": ["email1@example.com", "email2@example.com"], "approvals_needed": 1 } - ] + ], + "connection_rules": { + "ssh": { + "usernames": ["root", "ec2-user"] + } + } } } `) @@ -345,6 +365,11 @@ func TestCreateAccessPolicy(t *testing.T) { ApprovalsNeeded: 1, }, }, + InfraConnectionRules: &InfraConnectionRules{ + SSH: &InfraConnectionRulesSSH{ + Usernames: []string{"root", "ec2-user"}, + }, + }, } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler) @@ -415,6 +440,11 @@ func TestCreateAccessPolicyAuthContextRule(t *testing.T) { ApprovalsNeeded: 1, }, }, + InfraConnectionRules: &InfraConnectionRules{ + SSH: &InfraConnectionRulesSSH{ + Usernames: []string{"root", "ec2-user"}, + }, + }, } handler := func(w http.ResponseWriter, r *http.Request) { @@ -462,7 +492,12 @@ func TestCreateAccessPolicyAuthContextRule(t *testing.T) { "email_addresses": ["email1@example.com", "email2@example.com"], "approvals_needed": 1 } - ] + ], + "connection_rules": { + "ssh": { + "usernames": ["root", "ec2-user"] + } + } } } `) @@ -604,7 +639,12 @@ func TestUpdateAccessPolicy(t *testing.T) { "email_addresses": ["email1@example.com", "email2@example.com"], "approvals_needed": 1 } - ] + ], + "connection_rules": { + "ssh": { + "usernames": ["root", "ec2-user"] + } + } } } `) From 47211888381b8c968be9fe08c2b92e7939020340 Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Wed, 25 Sep 2024 23:03:07 -0700 Subject: [PATCH 76/84] small fix --- access_policy_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/access_policy_test.go b/access_policy_test.go index d7a8669445a..28dd6a448c1 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -589,6 +589,11 @@ func TestUpdateAccessPolicy(t *testing.T) { ApprovalsNeeded: 1, }, }, + InfraConnectionRules: &InfraConnectionRules{ + SSH: &InfraConnectionRulesSSH{ + Usernames: []string{"root", "ec2-user"}, + }, + }, } handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) From 8c36601119df35b9080d3f343f52b9530ebb952f Mon Sep 17 00:00:00 2001 From: Sai Dadireddy Date: Thu, 26 Sep 2024 18:13:26 -0700 Subject: [PATCH 77/84] add changelog --- .changelog/3186.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/3186.txt diff --git a/.changelog/3186.txt b/.changelog/3186.txt new file mode 100644 index 00000000000..c0d9da1db8b --- /dev/null +++ b/.changelog/3186.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +access_application: added target contexts support for access application type infrastructure +``` + +```release-note:enhancement +access_policy: added infrastructure connection rule support for access policy +``` From f7dbab24d74ea9ecd6deb9e099b64acca3a6e2eb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 27 Sep 2024 13:36:28 +1000 Subject: [PATCH 78/84] expand Infra => Infrastructure with correct namespace --- access_application.go | 184 +++++++++++----------- access_infrastructure_application.go | 20 +-- access_infrastructure_application_test.go | 12 +- access_policy.go | 42 ++--- access_policy_test.go | 16 +- 5 files changed, 137 insertions(+), 137 deletions(-) diff --git a/access_application.go b/access_application.go index 644a0f60235..2944cf114da 100644 --- a/access_application.go +++ b/access_application.go @@ -28,39 +28,39 @@ const ( // AccessApplication represents an Access application. type AccessApplication struct { - GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` - AllowedIdps []string `json:"allowed_idps,omitempty"` - CustomDenyMessage string `json:"custom_deny_message,omitempty"` - LogoURL string `json:"logo_url,omitempty"` - AUD string `json:"aud,omitempty"` - Domain string `json:"domain"` - SelfHostedDomains []string `json:"self_hosted_domains"` - Type AccessApplicationType `json:"type,omitempty"` - SessionDuration string `json:"session_duration,omitempty"` - SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` - CustomDenyURL string `json:"custom_deny_url,omitempty"` - CustomNonIdentityDenyURL string `json:"custom_non_identity_deny_url,omitempty"` - Name string `json:"name"` - ID string `json:"id,omitempty"` - PrivateAddress string `json:"private_address"` - CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - SaasApplication *SaasApplication `json:"saas_app,omitempty"` - AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` - SkipInterstitial *bool `json:"skip_interstitial,omitempty"` - AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` - EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` - HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` - ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` - PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` - AllowAuthenticateViaWarp *bool `json:"allow_authenticate_via_warp,omitempty"` - OptionsPreflightBypass *bool `json:"options_preflight_bypass,omitempty"` - CustomPages []string `json:"custom_pages,omitempty"` - Tags []string `json:"tags,omitempty"` - SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` - Policies []AccessPolicy `json:"policies,omitempty"` - TargetContexts *[]InfraTargetContext `json:"target_criteria,omitempty"` + GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` + AllowedIdps []string `json:"allowed_idps,omitempty"` + CustomDenyMessage string `json:"custom_deny_message,omitempty"` + LogoURL string `json:"logo_url,omitempty"` + AUD string `json:"aud,omitempty"` + Domain string `json:"domain"` + SelfHostedDomains []string `json:"self_hosted_domains"` + Type AccessApplicationType `json:"type,omitempty"` + SessionDuration string `json:"session_duration,omitempty"` + SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` + CustomDenyURL string `json:"custom_deny_url,omitempty"` + CustomNonIdentityDenyURL string `json:"custom_non_identity_deny_url,omitempty"` + Name string `json:"name"` + ID string `json:"id,omitempty"` + PrivateAddress string `json:"private_address"` + CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + SaasApplication *SaasApplication `json:"saas_app,omitempty"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` + SkipInterstitial *bool `json:"skip_interstitial,omitempty"` + AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` + EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` + HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` + ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` + PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` + AllowAuthenticateViaWarp *bool `json:"allow_authenticate_via_warp,omitempty"` + OptionsPreflightBypass *bool `json:"options_preflight_bypass,omitempty"` + CustomPages []string `json:"custom_pages,omitempty"` + Tags []string `json:"tags,omitempty"` + SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` + Policies []AccessPolicy `json:"policies,omitempty"` + TargetContexts *[]AccessInfrastructureTargetContext `json:"target_criteria,omitempty"` AccessAppLauncherCustomization } @@ -278,71 +278,71 @@ type ListAccessApplicationsParams struct { } type CreateAccessApplicationParams struct { - AllowedIdps []string `json:"allowed_idps,omitempty"` - AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` - AUD string `json:"aud,omitempty"` - AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` - CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` - CustomDenyMessage string `json:"custom_deny_message,omitempty"` - CustomDenyURL string `json:"custom_deny_url,omitempty"` - CustomNonIdentityDenyURL string `json:"custom_non_identity_deny_url,omitempty"` - Domain string `json:"domain"` - EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` - GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` - HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` - LogoURL string `json:"logo_url,omitempty"` - Name string `json:"name"` - PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` - PrivateAddress string `json:"private_address"` - SaasApplication *SaasApplication `json:"saas_app,omitempty"` - SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` - SelfHostedDomains []string `json:"self_hosted_domains"` - ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` - SessionDuration string `json:"session_duration,omitempty"` - SkipInterstitial *bool `json:"skip_interstitial,omitempty"` - OptionsPreflightBypass *bool `json:"options_preflight_bypass,omitempty"` - Type AccessApplicationType `json:"type,omitempty"` - AllowAuthenticateViaWarp *bool `json:"allow_authenticate_via_warp,omitempty"` - CustomPages []string `json:"custom_pages,omitempty"` - Tags []string `json:"tags,omitempty"` - SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` - TargetContexts *[]InfraTargetContext `json:"target_criteria,omitempty"` + AllowedIdps []string `json:"allowed_idps,omitempty"` + AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` + AUD string `json:"aud,omitempty"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` + CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` + CustomDenyMessage string `json:"custom_deny_message,omitempty"` + CustomDenyURL string `json:"custom_deny_url,omitempty"` + CustomNonIdentityDenyURL string `json:"custom_non_identity_deny_url,omitempty"` + Domain string `json:"domain"` + EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` + GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` + HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` + LogoURL string `json:"logo_url,omitempty"` + Name string `json:"name"` + PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` + PrivateAddress string `json:"private_address"` + SaasApplication *SaasApplication `json:"saas_app,omitempty"` + SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` + SelfHostedDomains []string `json:"self_hosted_domains"` + ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` + SessionDuration string `json:"session_duration,omitempty"` + SkipInterstitial *bool `json:"skip_interstitial,omitempty"` + OptionsPreflightBypass *bool `json:"options_preflight_bypass,omitempty"` + Type AccessApplicationType `json:"type,omitempty"` + AllowAuthenticateViaWarp *bool `json:"allow_authenticate_via_warp,omitempty"` + CustomPages []string `json:"custom_pages,omitempty"` + Tags []string `json:"tags,omitempty"` + SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` + TargetContexts *[]AccessInfrastructureTargetContext `json:"target_criteria,omitempty"` // List of policy ids to link to this application in ascending order of precedence. Policies []string `json:"policies,omitempty"` AccessAppLauncherCustomization } type UpdateAccessApplicationParams struct { - ID string `json:"id,omitempty"` - AllowedIdps []string `json:"allowed_idps,omitempty"` - AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` - AUD string `json:"aud,omitempty"` - AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` - CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` - CustomDenyMessage string `json:"custom_deny_message,omitempty"` - CustomDenyURL string `json:"custom_deny_url,omitempty"` - CustomNonIdentityDenyURL string `json:"custom_non_identity_deny_url,omitempty"` - Domain string `json:"domain"` - EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` - GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` - HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` - LogoURL string `json:"logo_url,omitempty"` - Name string `json:"name"` - PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` - PrivateAddress string `json:"private_address"` - SaasApplication *SaasApplication `json:"saas_app,omitempty"` - SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` - SelfHostedDomains []string `json:"self_hosted_domains"` - ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` - SessionDuration string `json:"session_duration,omitempty"` - SkipInterstitial *bool `json:"skip_interstitial,omitempty"` - Type AccessApplicationType `json:"type,omitempty"` - AllowAuthenticateViaWarp *bool `json:"allow_authenticate_via_warp,omitempty"` - OptionsPreflightBypass *bool `json:"options_preflight_bypass,omitempty"` - CustomPages []string `json:"custom_pages,omitempty"` - Tags []string `json:"tags,omitempty"` - SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` - TargetContexts *[]InfraTargetContext `json:"target_criteria,omitempty"` + ID string `json:"id,omitempty"` + AllowedIdps []string `json:"allowed_idps,omitempty"` + AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` + AUD string `json:"aud,omitempty"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` + CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` + CustomDenyMessage string `json:"custom_deny_message,omitempty"` + CustomDenyURL string `json:"custom_deny_url,omitempty"` + CustomNonIdentityDenyURL string `json:"custom_non_identity_deny_url,omitempty"` + Domain string `json:"domain"` + EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` + GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` + HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` + LogoURL string `json:"logo_url,omitempty"` + Name string `json:"name"` + PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` + PrivateAddress string `json:"private_address"` + SaasApplication *SaasApplication `json:"saas_app,omitempty"` + SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` + SelfHostedDomains []string `json:"self_hosted_domains"` + ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` + SessionDuration string `json:"session_duration,omitempty"` + SkipInterstitial *bool `json:"skip_interstitial,omitempty"` + Type AccessApplicationType `json:"type,omitempty"` + AllowAuthenticateViaWarp *bool `json:"allow_authenticate_via_warp,omitempty"` + OptionsPreflightBypass *bool `json:"options_preflight_bypass,omitempty"` + CustomPages []string `json:"custom_pages,omitempty"` + Tags []string `json:"tags,omitempty"` + SCIMConfig *AccessApplicationSCIMConfig `json:"scim_config,omitempty"` + TargetContexts *[]AccessInfrastructureTargetContext `json:"target_criteria,omitempty"` // List of policy ids to link to this application in ascending order of precedence. // Can reference reusable policies and policies specific to this application. // If this field is not provided, the existing policies will not be modified. diff --git a/access_infrastructure_application.go b/access_infrastructure_application.go index 6d6e3e0e68f..3824400f2fc 100644 --- a/access_infrastructure_application.go +++ b/access_infrastructure_application.go @@ -1,22 +1,22 @@ package cloudflare -type InfraProtocol string +type AccessInfrastructureProtocol string const ( - InfraSSH InfraProtocol = "SSH" - RDP InfraProtocol = "RDP" + AccessInfrastructureSSH AccessInfrastructureProtocol = "SSH" + AccessInfrastructureRDP AccessInfrastructureProtocol = "RDP" ) -type InfraTargetContext struct { - TargetAttributes map[string][]string `json:"target_attributes"` - Port int `json:"port"` - Protocol InfraProtocol `json:"protocol"` +type AccessInfrastructureTargetContext struct { + TargetAttributes map[string][]string `json:"target_attributes"` + Port int `json:"port"` + Protocol AccessInfrastructureProtocol `json:"protocol"` } -type InfraConnectionRulesSSH struct { +type AccessInfrastructureConnectionRulesSSH struct { Usernames []string `json:"usernames"` } -type InfraConnectionRules struct { - SSH *InfraConnectionRulesSSH `json:"ssh,omitempty"` +type AccessInfrastructureConnectionRules struct { + SSH *AccessInfrastructureConnectionRulesSSH `json:"ssh,omitempty"` } diff --git a/access_infrastructure_application_test.go b/access_infrastructure_application_test.go index c53fd1e3be6..9b992b59677 100644 --- a/access_infrastructure_application_test.go +++ b/access_infrastructure_application_test.go @@ -30,8 +30,8 @@ var ( }, Exclude: []any{}, Require: []any{}, - InfraConnectionRules: &InfraConnectionRules{ - SSH: &InfraConnectionRulesSSH{ + InfrastructureConnectionRules: &AccessInfrastructureConnectionRules{ + SSH: &AccessInfrastructureConnectionRulesSSH{ Usernames: []string{"devuser"}, }, }, @@ -62,7 +62,7 @@ var ( CustomNonIdentityDenyURL: "", AllowAuthenticateViaWarp: nil, OptionsPreflightBypass: nil, - TargetContexts: &[]InfraTargetContext{ + TargetContexts: &[]AccessInfrastructureTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests"}, @@ -102,7 +102,7 @@ var ( CustomNonIdentityDenyURL: "", AllowAuthenticateViaWarp: nil, OptionsPreflightBypass: nil, - TargetContexts: &[]InfraTargetContext{ + TargetContexts: &[]AccessInfrastructureTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests", "cfgo-acc-tests-duplicate"}, @@ -177,7 +177,7 @@ func TestInfrastructureApplication_Create(t *testing.T) { actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "infrastructure_application_test", Type: "infrastructure", - TargetContexts: &[]InfraTargetContext{ + TargetContexts: &[]AccessInfrastructureTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests"}, @@ -255,7 +255,7 @@ func TestInfrastructureApplication_Update(t *testing.T) { actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "infrastructure_application_test_updated", Type: "infrastructure", - TargetContexts: &[]InfraTargetContext{ + TargetContexts: &[]AccessInfrastructureTargetContext{ { TargetAttributes: map[string][]string{ "hostname": {"cfgo-acc-tests", "cfgo-acc-tests-duplicate"}, diff --git a/access_policy.go b/access_policy.go index b59dc8bda3c..2b2ec812d6d 100644 --- a/access_policy.go +++ b/access_policy.go @@ -30,13 +30,13 @@ type AccessPolicy struct { Reusable *bool `json:"reusable,omitempty"` Name string `json:"name"` - IsolationRequired *bool `json:"isolation_required,omitempty"` - SessionDuration *string `json:"session_duration,omitempty"` - PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` - PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` - ApprovalRequired *bool `json:"approval_required,omitempty"` - ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` - InfraConnectionRules *InfraConnectionRules `json:"connection_rules,omitempty"` + IsolationRequired *bool `json:"isolation_required,omitempty"` + SessionDuration *string `json:"session_duration,omitempty"` + PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` + PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` + ApprovalRequired *bool `json:"approval_required,omitempty"` + ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + InfrastructureConnectionRules *AccessInfrastructureConnectionRules `json:"connection_rules,omitempty"` // The include policy works like an OR logical operator. The user must // satisfy one of the rules. @@ -95,13 +95,13 @@ type CreateAccessPolicyParams struct { Decision string `json:"decision"` Name string `json:"name"` - IsolationRequired *bool `json:"isolation_required,omitempty"` - SessionDuration *string `json:"session_duration,omitempty"` - PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` - PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` - ApprovalRequired *bool `json:"approval_required,omitempty"` - ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` - InfraConnectionRules *InfraConnectionRules `json:"connection_rules,omitempty"` + IsolationRequired *bool `json:"isolation_required,omitempty"` + SessionDuration *string `json:"session_duration,omitempty"` + PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` + PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` + ApprovalRequired *bool `json:"approval_required,omitempty"` + ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + InfrastructureConnectionRules *AccessInfrastructureConnectionRules `json:"connection_rules,omitempty"` // The include policy works like an OR logical operator. The user must // satisfy one of the rules. @@ -129,13 +129,13 @@ type UpdateAccessPolicyParams struct { Decision string `json:"decision"` Name string `json:"name"` - IsolationRequired *bool `json:"isolation_required,omitempty"` - SessionDuration *string `json:"session_duration,omitempty"` - PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` - PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` - ApprovalRequired *bool `json:"approval_required,omitempty"` - ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` - InfraConnectionRules *InfraConnectionRules `json:"connection_rules,omitempty"` + IsolationRequired *bool `json:"isolation_required,omitempty"` + SessionDuration *string `json:"session_duration,omitempty"` + PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` + PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` + ApprovalRequired *bool `json:"approval_required,omitempty"` + ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + InfrastructureConnectionRules *AccessInfrastructureConnectionRules `json:"connection_rules,omitempty"` // The include policy works like an OR logical operator. The user must // satisfy one of the rules. diff --git a/access_policy_test.go b/access_policy_test.go index 28dd6a448c1..6ed033fda01 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -55,8 +55,8 @@ var ( ApprovalsNeeded: 1, }, }, - InfraConnectionRules: &InfraConnectionRules{ - SSH: &InfraConnectionRulesSSH{ + InfrastructureConnectionRules: &AccessInfrastructureConnectionRules{ + SSH: &AccessInfrastructureConnectionRulesSSH{ Usernames: []string{"root", "ec2-user"}, }, }, @@ -365,8 +365,8 @@ func TestCreateAccessPolicy(t *testing.T) { ApprovalsNeeded: 1, }, }, - InfraConnectionRules: &InfraConnectionRules{ - SSH: &InfraConnectionRulesSSH{ + InfrastructureConnectionRules: &AccessInfrastructureConnectionRules{ + SSH: &AccessInfrastructureConnectionRulesSSH{ Usernames: []string{"root", "ec2-user"}, }, }, @@ -440,8 +440,8 @@ func TestCreateAccessPolicyAuthContextRule(t *testing.T) { ApprovalsNeeded: 1, }, }, - InfraConnectionRules: &InfraConnectionRules{ - SSH: &InfraConnectionRulesSSH{ + InfrastructureConnectionRules: &AccessInfrastructureConnectionRules{ + SSH: &AccessInfrastructureConnectionRulesSSH{ Usernames: []string{"root", "ec2-user"}, }, }, @@ -589,8 +589,8 @@ func TestUpdateAccessPolicy(t *testing.T) { ApprovalsNeeded: 1, }, }, - InfraConnectionRules: &InfraConnectionRules{ - SSH: &InfraConnectionRulesSSH{ + InfrastructureConnectionRules: &AccessInfrastructureConnectionRules{ + SSH: &AccessInfrastructureConnectionRulesSSH{ Usernames: []string{"root", "ec2-user"}, }, }, From d6ec26a78e67dcdf85f9eead230be2d59d850207 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 27 Sep 2024 13:46:47 +1000 Subject: [PATCH 79/84] generate changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e95a5cdb0df..8b9f8a2d299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## 0.106.0 (Unreleased) +ENHANCEMENTS: + +* access_application: added target contexts support for access application type infrastructure ([#3186](https://github.com/cloudflare/cloudflare-go/issues/3186)) +* access_policy: added infrastructure connection rule support for access policy ([#3186](https://github.com/cloudflare/cloudflare-go/issues/3186)) + ## 0.105.0 (September 25th, 2024) ENHANCEMENTS: From e9034aa4e57e47ea135e383e97d94a832d113ab5 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 27 Sep 2024 13:47:38 +1000 Subject: [PATCH 80/84] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b9f8a2d299..b7b23bd0a74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.106.0 (Unreleased) +## 0.107.0 (Unreleased) + +## 0.106.0 (September 27th, 2024) ENHANCEMENTS: From 608d4b82b9fa9d6e808096c549462843b5a342a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:28:49 +0000 Subject: [PATCH 81/84] Bump golang.org/x/time from 0.6.0 to 0.7.0 Bumps [golang.org/x/time](https://github.com/golang/time) from 0.6.0 to 0.7.0. - [Commits](https://github.com/golang/time/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/time dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f2158ba6ff7..4cc688f2adb 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.4 golang.org/x/net v0.29.0 - golang.org/x/time v0.6.0 + golang.org/x/time v0.7.0 ) require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index 23a7b427553..8387ca594e0 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From d5da0f54f9eb2332825ddc11dc011d9591ca46d8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 4 Oct 2024 16:29:02 +0000 Subject: [PATCH 82/84] add CHANGELOG for #3321 --- .changelog/3321.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/3321.txt diff --git a/.changelog/3321.txt b/.changelog/3321.txt new file mode 100644 index 00000000000..a5aa56db05a --- /dev/null +++ b/.changelog/3321.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/time from 0.6.0 to 0.7.0 +``` From 33936a43260de1cfb2114cebe3fa9fd613f9ea8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:56:18 +0000 Subject: [PATCH 83/84] Bump golang.org/x/net from 0.29.0 to 0.30.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.29.0 to 0.30.0. - [Commits](https://github.com/golang/net/compare/v0.29.0...v0.30.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4cc688f2adb..ddc60219b3e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.4 - golang.org/x/net v0.29.0 + golang.org/x/net v0.30.0 golang.org/x/time v0.7.0 ) @@ -25,6 +25,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/text v0.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8387ca594e0..8f04a34b265 100644 --- a/go.sum +++ b/go.sum @@ -39,10 +39,10 @@ github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From a38bb06c53914b46d0f5ab4424ce0bc22a9ff073 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 7 Oct 2024 22:56:43 +0000 Subject: [PATCH 84/84] add CHANGELOG for #3336 --- .changelog/3336.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/3336.txt diff --git a/.changelog/3336.txt b/.changelog/3336.txt new file mode 100644 index 00000000000..c5e48f1f166 --- /dev/null +++ b/.changelog/3336.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.29.0 to 0.30.0 +```