From 2a6a3beee74164b5302ad62bb502a8d175cd9f39 Mon Sep 17 00:00:00 2001 From: Tylor Stewart Date: Wed, 16 Mar 2022 20:40:15 +1000 Subject: [PATCH 01/38] fix type for AccessOrganizationLoginDesign --- access_organization.go | 4 +++- access_organization_test.go | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/access_organization.go b/access_organization.go index 774c3febaf..a0ec7ff15f 100644 --- a/access_organization.go +++ b/access_organization.go @@ -22,8 +22,10 @@ type AccessOrganization struct { // AccessOrganizationLoginDesign represents the login design options. type AccessOrganizationLoginDesign struct { BackgroundColor string `json:"background_color"` - TextColor string `json:"text_color"` LogoPath string `json:"logo_path"` + TextColor string `json:"text_color"` + HeaderText string `json:"header_text"` + FooterText string `json:"footer_text"` } // AccessOrganizationListResponse represents the response from the list diff --git a/access_organization_test.go b/access_organization_test.go index 7f25a0feba..81d8264e42 100644 --- a/access_organization_test.go +++ b/access_organization_test.go @@ -28,8 +28,10 @@ func TestAccessOrganization(t *testing.T) { "auth_domain": "test.cloudflareaccess.com", "login_design": { "background_color": "#c5ed1b", + "logo_path": "https://example.com/logo.png", "text_color": "#c5ed1b", - "logo_path": "https://example.com/logo.png" + "header_text": "Widget Corp", + "footer_text": "© Widget Corp" } } } @@ -46,8 +48,10 @@ func TestAccessOrganization(t *testing.T) { AuthDomain: "test.cloudflareaccess.com", LoginDesign: AccessOrganizationLoginDesign{ BackgroundColor: "#c5ed1b", - TextColor: "#c5ed1b", LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", }, } @@ -86,8 +90,10 @@ func TestCreateAccessOrganization(t *testing.T) { "auth_domain": "test.cloudflareaccess.com", "login_design": { "background_color": "#c5ed1b", + "logo_path": "https://example.com/logo.png", "text_color": "#c5ed1b", - "logo_path": "https://example.com/logo.png" + "header_text": "Widget Corp", + "footer_text": "© Widget Corp" } } } @@ -104,8 +110,10 @@ func TestCreateAccessOrganization(t *testing.T) { AuthDomain: "test.cloudflareaccess.com", LoginDesign: AccessOrganizationLoginDesign{ BackgroundColor: "#c5ed1b", - TextColor: "#c5ed1b", LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", }, } @@ -144,8 +152,10 @@ func TestUpdateAccessOrganization(t *testing.T) { "auth_domain": "test.cloudflareaccess.com", "login_design": { "background_color": "#c5ed1b", + "logo_path": "https://example.com/logo.png", "text_color": "#c5ed1b", - "logo_path": "https://example.com/logo.png" + "header_text": "Widget Corp", + "footer_text": "© Widget Corp" } } } @@ -162,8 +172,10 @@ func TestUpdateAccessOrganization(t *testing.T) { AuthDomain: "test.cloudflareaccess.com", LoginDesign: AccessOrganizationLoginDesign{ BackgroundColor: "#c5ed1b", - TextColor: "#c5ed1b", LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", }, } From 14d4e6d1979eb28f98bde5c37b9a5b4468a8cb6b Mon Sep 17 00:00:00 2001 From: Matti Paksula Date: Fri, 8 Apr 2022 16:04:51 +0300 Subject: [PATCH 02/38] fix --content filter for record list --- cmd/flarectl/zone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/flarectl/zone.go b/cmd/flarectl/zone.go index 29b2fd5c89..ad771b11c2 100644 --- a/cmd/flarectl/zone.go +++ b/cmd/flarectl/zone.go @@ -293,7 +293,7 @@ func zoneRecords(c *cli.Context) error { rr.Name = c.String("name") } if c.String("content") != "" { - rr.Name = c.String("content") + rr.Content = c.String("content") } var err error records, err = api.DNSRecords(context.Background(), zoneID, rr) From 5798d3ca318eca48adc7cc5140785c6c3dd33eb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 16:05:48 +0000 Subject: [PATCH 03/38] build(deps): bump actions/setup-go from 2 to 3 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1185fbe97b..889982f6b5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: go-version: ^1.17 - name: structslop diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 503d96100f..4f72be1c1d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: go-version: ^1.17 - name: Run GoReleaser diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fafc82674f..ae34e90297 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - name: Checkout code From 81c2d67c0735528328ea0006f3df6920c3a712ba Mon Sep 17 00:00:00 2001 From: Max Nystrom Date: Mon, 11 Apr 2022 16:12:57 -0700 Subject: [PATCH 04/38] Include the Blocked Custom Hostname status for Custom Hostnames. --- custom_hostname.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/custom_hostname.go b/custom_hostname.go index e7727e8a81..7d152868e5 100644 --- a/custom_hostname.go +++ b/custom_hostname.go @@ -22,8 +22,10 @@ const ( ACTIVE CustomHostnameStatus = "active" // MOVED status represents state of CustomHostname is moved. MOVED CustomHostnameStatus = "moved" - // DELETED status represents state of CustomHostname is removed. + // DELETED status represents state of CustomHostname is deleted. DELETED CustomHostnameStatus = "deleted" + // BLOCKED status represents state of CustomHostname is blocked from going active. + BLOCKED CustomHostnameStatus = "blocked" ) // CustomHostnameSSLSettings represents the SSL settings for a custom hostname. From c2134c36e296994828ba66ed9e77155d5b1c3da1 Mon Sep 17 00:00:00 2001 From: Ting-Wai To Date: Wed, 13 Apr 2022 16:48:31 -0700 Subject: [PATCH 05/38] Add ZeroDowntimeFailover field to SessionAffinityAttributes --- load_balancing.go | 12 +++++++----- load_balancing_test.go | 36 ++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/load_balancing.go b/load_balancing.go index 43f155f4af..472e3e4a5a 100644 --- a/load_balancing.go +++ b/load_balancing.go @@ -166,15 +166,17 @@ type LoadBalancerRuleOverrides struct { // LoadBalancerRuleOverridesSessionAffinityAttrs mimics SessionAffinityAttributes without the // DrainDuration field as that field can not be overwritten via rules. type LoadBalancerRuleOverridesSessionAffinityAttrs struct { - SameSite string `json:"samesite,omitempty"` - Secure string `json:"secure,omitempty"` + SameSite string `json:"samesite,omitempty"` + Secure string `json:"secure,omitempty"` + ZeroDowntimeFailover string `json:"zero_downtime_failover,omitempty"` } // SessionAffinityAttributes represents the fields used to set attributes in a load balancer session affinity cookie. type SessionAffinityAttributes struct { - SameSite string `json:"samesite,omitempty"` - Secure string `json:"secure,omitempty"` - DrainDuration int `json:"drain_duration,omitempty"` + SameSite string `json:"samesite,omitempty"` + Secure string `json:"secure,omitempty"` + DrainDuration int `json:"drain_duration,omitempty"` + ZeroDowntimeFailover string `json:"zero_downtime_failover,omitempty"` } // LoadBalancerOriginHealth represents the health of the origin. diff --git a/load_balancing_test.go b/load_balancing_test.go index 677f261e6e..5c4280a54c 100644 --- a/load_balancing_test.go +++ b/load_balancing_test.go @@ -950,7 +950,8 @@ func TestCreateLoadBalancer(t *testing.T) { "session_affinity_attributes": { "samesite": "Strict", "secure": "Always", - "drain_duration": 60 + "drain_duration": 60, + "zero_downtime_failover": "sticky" } }`, string(b)) } @@ -1018,7 +1019,8 @@ func TestCreateLoadBalancer(t *testing.T) { "session_affinity_attributes": { "samesite": "Strict", "secure": "Always", - "drain_duration": 60 + "drain_duration": 60, + "zero_downtime_failover": "sticky" } } }`) @@ -1085,9 +1087,10 @@ func TestCreateLoadBalancer(t *testing.T) { Persistence: "cookie", PersistenceTTL: 5000, SessionAffinityAttributes: &SessionAffinityAttributes{ - SameSite: "Strict", - Secure: "Always", - DrainDuration: 60, + SameSite: "Strict", + Secure: "Always", + DrainDuration: 60, + ZeroDowntimeFailover: "sticky", }, } request := LoadBalancer{ @@ -1145,9 +1148,10 @@ func TestCreateLoadBalancer(t *testing.T) { Persistence: "cookie", PersistenceTTL: 5000, SessionAffinityAttributes: &SessionAffinityAttributes{ - SameSite: "Strict", - Secure: "Always", - DrainDuration: 60, + SameSite: "Strict", + Secure: "Always", + DrainDuration: 60, + ZeroDowntimeFailover: "sticky", }, } @@ -1470,7 +1474,8 @@ func TestModifyLoadBalancer(t *testing.T) { "session_affinity": "none", "session_affinity_attributes": { "samesite": "Strict", - "secure": "Always" + "secure": "Always", + "zero_downtime_failover": "sticky" } }`, string(b)) } @@ -1520,7 +1525,8 @@ func TestModifyLoadBalancer(t *testing.T) { "session_affinity": "none", "session_affinity_attributes": { "samesite": "Strict", - "secure": "Always" + "secure": "Always", + "zero_downtime_failover": "sticky" } } }`) @@ -1570,8 +1576,9 @@ func TestModifyLoadBalancer(t *testing.T) { Proxied: true, Persistence: "none", SessionAffinityAttributes: &SessionAffinityAttributes{ - SameSite: "Strict", - Secure: "Always", + SameSite: "Strict", + Secure: "Always", + ZeroDowntimeFailover: "sticky", }, } request := LoadBalancer{ @@ -1613,8 +1620,9 @@ func TestModifyLoadBalancer(t *testing.T) { Proxied: true, Persistence: "none", SessionAffinityAttributes: &SessionAffinityAttributes{ - SameSite: "Strict", - Secure: "Always", + SameSite: "Strict", + Secure: "Always", + ZeroDowntimeFailover: "sticky", }, } From 41d106ba456f7c9e51357447e75dd88ae6ae347f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 14 Apr 2022 14:00:00 +1000 Subject: [PATCH 06/38] disable structslop for now --- .github/workflows/lint.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 889982f6b5..ef94dfdb3e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,15 +12,15 @@ jobs: version: latest args: "--config .golintci.yaml" only-new-issues: true # only show new issues in the PR, not all. - structslop: - name: structslop - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 - with: - go-version: ^1.17 - - name: structslop - run: | - go generate -tags tools tools/tools.go - $(go env GOPATH)/bin/structslop . + #structslop: + # name: structslop + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - uses: actions/setup-go@v3 + # with: + # go-version: ^1.17 + # - name: structslop + # run: | + # go generate -tags tools tools/tools.go + # $(go env GOPATH)/bin/structslop . From 8d040019443d92bedee6c5aa689fb77dedc278fb Mon Sep 17 00:00:00 2001 From: Sachin Fernandes Date: Thu, 14 Apr 2022 18:19:09 -0700 Subject: [PATCH 07/38] Add log custom fields phase and action --- rulesets.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rulesets.go b/rulesets.go index b7ceae9f0f..e3a1b72c26 100644 --- a/rulesets.go +++ b/rulesets.go @@ -19,14 +19,15 @@ const ( RulesetPhaseDDoSL4 RulesetPhase = "ddos_l4" RulesetPhaseDDoSL7 RulesetPhase = "ddos_l7" + RulesetPhaseHTTPLogCustomFields RulesetPhase = "http_log_custom_fields" RulesetPhaseHTTPRequestFirewallCustom RulesetPhase = "http_request_firewall_custom" RulesetPhaseHTTPRequestFirewallManaged RulesetPhase = "http_request_firewall_managed" RulesetPhaseHTTPRequestLateTransform RulesetPhase = "http_request_late_transform" RulesetPhaseHTTPRequestMain RulesetPhase = "http_request_main" RulesetPhaseHTTPRequestSanitize RulesetPhase = "http_request_sanitize" RulesetPhaseHTTPRequestTransform RulesetPhase = "http_request_transform" - RulesetPhaseHTTPResponseHeadersTransform RulesetPhase = "http_response_headers_transform" RulesetPhaseHTTPResponseFirewallManaged RulesetPhase = "http_response_firewall_managed" + RulesetPhaseHTTPResponseHeadersTransform RulesetPhase = "http_response_headers_transform" RulesetPhaseMagicTransit RulesetPhase = "magic_transit" RulesetPhaseRateLimit RulesetPhase = "http_ratelimit" @@ -37,6 +38,7 @@ const ( RulesetRuleActionForceConnectionClose RulesetRuleAction = "force_connection_close" RulesetRuleActionJSChallenge RulesetRuleAction = "js_challenge" RulesetRuleActionLog RulesetRuleAction = "log" + RulesetRuleActionLogCustomField RulesetRuleAction = "log_custom_field" RulesetRuleActionRewrite RulesetRuleAction = "rewrite" RulesetRuleActionScore RulesetRuleAction = "score" RulesetRuleActionSkip RulesetRuleAction = "skip" @@ -71,14 +73,15 @@ func RulesetPhaseValues() []string { return []string{ string(RulesetPhaseDDoSL4), string(RulesetPhaseDDoSL7), + string(RulesetPhaseHTTPLogCustomFields), string(RulesetPhaseHTTPRequestFirewallCustom), string(RulesetPhaseHTTPRequestFirewallManaged), string(RulesetPhaseHTTPRequestLateTransform), string(RulesetPhaseHTTPRequestMain), string(RulesetPhaseHTTPRequestSanitize), string(RulesetPhaseHTTPRequestTransform), - string(RulesetPhaseHTTPResponseHeadersTransform), string(RulesetPhaseHTTPResponseFirewallManaged), + string(RulesetPhaseHTTPResponseHeadersTransform), string(RulesetPhaseMagicTransit), string(RulesetPhaseRateLimit), } @@ -95,6 +98,7 @@ func RulesetRuleActionValues() []string { string(RulesetRuleActionForceConnectionClose), string(RulesetRuleActionJSChallenge), string(RulesetRuleActionLog), + string(RulesetRuleActionLogCustomField), string(RulesetRuleActionRewrite), string(RulesetRuleActionScore), string(RulesetRuleActionSkip), From 5d64cb069bbae4e1800e9c53b80448ed65adb01d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Apr 2022 16:04:15 +0000 Subject: [PATCH 08/38] build(deps): bump github.com/urfave/cli/v2 from 2.4.0 to 2.4.4 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.4.0 to 2.4.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.4.0...v2.4.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 | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 86c765465d..b9ec5c8317 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/orijtech/structslop v0.0.6 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.1 - github.com/urfave/cli/v2 v2.4.0 + github.com/urfave/cli/v2 v2.4.4 golang.org/x/net v0.0.0-20220225172249-27dd8689420f golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index cf79808cb5..89cd9fa845 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,4 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/dave/dst v0.26.2 h1:lnxLAKI3tx7MgLNVDirFCsDTlTG9nKTk7GcptKcWSwY= @@ -39,8 +39,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.4.0 h1:m2pxjjDFgDxSPtO8WSdbndj17Wu2y8vOT86wE/tjr+I= -github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg= +github.com/urfave/cli/v2 v2.4.4 h1:IvwT3XfI6RytTmIzC35UAu9oyK+bHgUPXDDZNqribkI= +github.com/urfave/cli/v2 v2.4.4/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= @@ -85,6 +85,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From d9e995c554cc8b7f362c1b3e71dffa3e54885d0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 16:05:07 +0000 Subject: [PATCH 09/38] build(deps): bump github.com/urfave/cli/v2 from 2.4.4 to 2.4.8 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.4.4 to 2.4.8. - [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.4.4...v2.4.8) --- 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 b9ec5c8317..bc083e4c4c 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/orijtech/structslop v0.0.6 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.1 - github.com/urfave/cli/v2 v2.4.4 + github.com/urfave/cli/v2 v2.4.8 golang.org/x/net v0.0.0-20220225172249-27dd8689420f golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index 89cd9fa845..fd9f3b3bd3 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.4.4 h1:IvwT3XfI6RytTmIzC35UAu9oyK+bHgUPXDDZNqribkI= -github.com/urfave/cli/v2 v2.4.4/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= +github.com/urfave/cli/v2 v2.4.8 h1:9HuvvddU3oEJr1tJlwUVVsk3snVWMuKSpyAO+SzTNuI= +github.com/urfave/cli/v2 v2.4.8/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= From 9f89c0ca37f50959a5f0fd9e8b7fae1528b6b123 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 16:13:12 +0000 Subject: [PATCH 10/38] build(deps): bump github/codeql-action from 1 to 2 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v1...v2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 317f71ea48..59925db3a0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,7 +42,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -53,7 +53,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -67,4 +67,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 From 9db435fc25401a763390399dab379fd92430e778 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 16:03:13 +0000 Subject: [PATCH 11/38] build(deps): bump github.com/urfave/cli/v2 from 2.4.8 to 2.5.0 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.4.8 to 2.5.0. - [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.4.8...v2.5.0) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 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 bc083e4c4c..b22dac50dc 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/orijtech/structslop v0.0.6 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.1 - github.com/urfave/cli/v2 v2.4.8 + github.com/urfave/cli/v2 v2.5.0 golang.org/x/net v0.0.0-20220225172249-27dd8689420f golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index fd9f3b3bd3..dc8544b198 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.4.8 h1:9HuvvddU3oEJr1tJlwUVVsk3snVWMuKSpyAO+SzTNuI= -github.com/urfave/cli/v2 v2.4.8/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= +github.com/urfave/cli/v2 v2.5.0 h1:2sqblaW62ebcTIEvwb8eRvDfNHeBAeKxfhdynaanhug= +github.com/urfave/cli/v2 v2.5.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= From 7d1ccc695c9552038e409bb5177cf692fd9f6fb1 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Tue, 26 Apr 2022 19:02:59 -0400 Subject: [PATCH 12/38] Add new expiration field --- device_posture_rule.go | 1 + device_posture_rule_test.go | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/device_posture_rule.go b/device_posture_rule.go index 5dbd1a4cdc..555de47521 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -152,6 +152,7 @@ type DevicePostureRule struct { Schedule string `json:"schedule,omitempty"` Match []DevicePostureRuleMatch `json:"match,omitempty"` Input DevicePostureRuleInput `json:"input,omitempty"` + Expiration string `json:"expiration,omitempty"` } // DevicePostureRuleMatch represents the conditions that the client must match to run the rule. diff --git a/device_posture_rule_test.go b/device_posture_rule_test.go index c8843a8966..308827cdb4 100644 --- a/device_posture_rule_test.go +++ b/device_posture_rule_test.go @@ -252,6 +252,7 @@ func TestDevicePostureRules(t *testing.T) { "type": "file", "name": "My rule name", "description": "My description", + "expiration": "1h", "match": [ { "platform": "ios" @@ -283,6 +284,7 @@ func TestDevicePostureRules(t *testing.T) { Description: "My description", Type: "file", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ ID: "9e597887-345e-4a32-a09c-68811b129768", @@ -317,6 +319,7 @@ func TestDevicePostureFileRule(t *testing.T) { "result": { "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", "schedule": "1h", + "expiration": "1h", "type": "file", "name": "My rule name", "description": "My description", @@ -341,6 +344,7 @@ func TestDevicePostureFileRule(t *testing.T) { Description: "My description", Type: "file", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ Path: "/tmp/test", @@ -372,6 +376,7 @@ func TestDevicePostureDiskEncryptionRule(t *testing.T) { "result": { "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", "schedule": "1h", + "expiration": "1h", "type": "disk_encryption", "name": "My rule name", "description": "My description", @@ -394,6 +399,7 @@ func TestDevicePostureDiskEncryptionRule(t *testing.T) { Description: "My description", Type: "disk_encryption", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ RequireAll: true, @@ -423,6 +429,7 @@ func TestDevicePostureOsVersionRule(t *testing.T) { "result": { "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", "schedule": "1h", + "expiration": "1h", "type": "os_version", "name": "My rule name", "description": "My description", @@ -446,6 +453,7 @@ func TestDevicePostureOsVersionRule(t *testing.T) { Description: "My description", Type: "os_version", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ Version: "10.0.1", @@ -476,6 +484,7 @@ func TestDevicePostureDomainJoinedRule(t *testing.T) { "result": { "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", "schedule": "1h", + "expiration": "1h", "type": "domain_joined", "name": "My rule name", "description": "My description", @@ -498,6 +507,7 @@ func TestDevicePostureDomainJoinedRule(t *testing.T) { Description: "My description", Type: "domain_joined", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ Domain: "example.com", @@ -527,6 +537,7 @@ func TestCreateDevicePostureRule(t *testing.T) { "result": { "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", "schedule": "1h", + "expiration": "1h", "type": "file", "name": "My rule name", "description": "My description", @@ -549,6 +560,7 @@ func TestCreateDevicePostureRule(t *testing.T) { Description: "My description", Type: "file", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ID: "9e597887-345e-4a32-a09c-68811b129768"}, } @@ -560,6 +572,7 @@ func TestCreateDevicePostureRule(t *testing.T) { Description: "My description", Type: "file", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ID: "9e597887-345e-4a32-a09c-68811b129768"}, }) @@ -583,6 +596,7 @@ func TestUpdateDevicePostureRule(t *testing.T) { "result": { "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", "schedule": "1h", + "expiration": "1h", "type": "file", "name": "My rule name", "description": "My description", @@ -605,6 +619,7 @@ func TestUpdateDevicePostureRule(t *testing.T) { Description: "My description", Type: "file", Schedule: "1h", + Expiration: "1h", Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ID: "9e597887-345e-4a32-a09c-68811b129768"}, } From 528ae9166b84db7195b12c3fb50176b09b3bebda Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 27 Apr 2022 09:25:36 +1000 Subject: [PATCH 13/38] argo_tunnel: Deprecate `ArgoTunnel` methods in favour of `Tunnel` methods The Argo Tunnel product has been rebadged to be Tunnels and is due to be sunset in Feb 2024[1]. This brings the library in line with that expectation and deprecates the older methods. The API is 1:1 compatible so just the method names are changing. In addition, I've moved the newer methods to follow the upcoming experimental changes[2] for parameters which makes the methods more consistent for use. As a fallback measure I also updated the ArgoTunnel methods to use the `cfd_tunnel` URL to ensure we don't have anyone left behind but the plan is to remove these methods with the API endpoints so best poke people to move now. Closes #832 [1]: https://api.cloudflare.com/#argo-tunnel-properties [2]: https://github.com/cloudflare/cloudflare-go/blob/master/docs/experimental.md --- argo_tunnel.go | 20 ++- argo_tunnel_test.go | 10 +- tunnels.go | 294 ++++++++++++++++++++++++++++++++++++++++++++ tunnels_test.go | 221 +++++++++++++++++++++++++++++++++ 4 files changed, 535 insertions(+), 10 deletions(-) create mode 100644 tunnels.go create mode 100644 tunnels_test.go diff --git a/argo_tunnel.go b/argo_tunnel.go index 4ad69ca60a..91d9586220 100644 --- a/argo_tunnel.go +++ b/argo_tunnel.go @@ -44,8 +44,10 @@ type ArgoTunnelDetailResponse struct { // ArgoTunnels lists all tunnels. // // API reference: https://api.cloudflare.com/#argo-tunnel-list-argo-tunnels +// +// Deprecated: Use `Tunnels` instead. func (api *API) ArgoTunnels(ctx context.Context, accountID string) ([]ArgoTunnel, error) { - uri := fmt.Sprintf("/accounts/%s/tunnels", accountID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", accountID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, argoV1Header()) if err != nil { @@ -63,8 +65,10 @@ func (api *API) ArgoTunnels(ctx context.Context, accountID string) ([]ArgoTunnel // ArgoTunnel returns a single Argo tunnel. // // API reference: https://api.cloudflare.com/#argo-tunnel-get-argo-tunnel +// +// Deprecated: Use `Tunnel` instead. func (api *API) ArgoTunnel(ctx context.Context, accountID, tunnelUUID string) (ArgoTunnel, error) { - uri := fmt.Sprintf("/accounts/%s/tunnels/%s", accountID, tunnelUUID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", accountID, tunnelUUID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, argoV1Header()) if err != nil { @@ -82,8 +86,10 @@ func (api *API) ArgoTunnel(ctx context.Context, accountID, tunnelUUID string) (A // CreateArgoTunnel creates a new tunnel for the account. // // API reference: https://api.cloudflare.com/#argo-tunnel-create-argo-tunnel +// +// Deprecated: Use `CreateTunnel` instead. func (api *API) CreateArgoTunnel(ctx context.Context, accountID, name, secret string) (ArgoTunnel, error) { - uri := fmt.Sprintf("/accounts/%s/tunnels", accountID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", accountID) tunnel := ArgoTunnel{Name: name, Secret: secret} @@ -104,8 +110,10 @@ func (api *API) CreateArgoTunnel(ctx context.Context, accountID, name, secret st // DeleteArgoTunnel removes a single Argo tunnel. // // API reference: https://api.cloudflare.com/#argo-tunnel-delete-argo-tunnel +// +// Deprecated: Use `DeleteTunnel` instead. func (api *API) DeleteArgoTunnel(ctx context.Context, accountID, tunnelUUID string) error { - uri := fmt.Sprintf("/accounts/%s/tunnels/%s", accountID, tunnelUUID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", accountID, tunnelUUID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, argoV1Header()) if err != nil { @@ -124,8 +132,10 @@ func (api *API) DeleteArgoTunnel(ctx context.Context, accountID, tunnelUUID stri // CleanupArgoTunnelConnections deletes any inactive connections on a tunnel. // // API reference: https://api.cloudflare.com/#argo-tunnel-clean-up-argo-tunnel-connections +// +// Deprecated: Use `CleanupTunnelConnections` instead. func (api *API) CleanupArgoTunnelConnections(ctx context.Context, accountID, tunnelUUID string) error { - uri := fmt.Sprintf("/accounts/%s/tunnels/%s/connections", accountID, tunnelUUID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", accountID, tunnelUUID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, argoV1Header()) if err != nil { diff --git a/argo_tunnel_test.go b/argo_tunnel_test.go index 82dbb77b10..29f29e1002 100644 --- a/argo_tunnel_test.go +++ b/argo_tunnel_test.go @@ -40,7 +40,7 @@ func TestArgoTunnels(t *testing.T) { `) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/tunnels", handler) + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/cfd_tunnel", handler) createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") @@ -91,7 +91,7 @@ func TestArgoTunnel(t *testing.T) { `) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/tunnels/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") @@ -142,7 +142,7 @@ func TestCreateArgoTunnel(t *testing.T) { `) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/tunnels", handler) + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/cfd_tunnel", handler) createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") @@ -193,7 +193,7 @@ func TestDeleteArgoTunnel(t *testing.T) { `) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/tunnels/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) err := client.DeleteArgoTunnel(context.Background(), "01a7362d577a6c3019a474fd6f485823", "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) @@ -214,7 +214,7 @@ func TestCleanupArgoTunnelConnections(t *testing.T) { `) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/tunnels/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/connections", handler) + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/connections", handler) err := client.CleanupArgoTunnelConnections(context.Background(), "01a7362d577a6c3019a474fd6f485823", "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) diff --git a/tunnels.go b/tunnels.go new file mode 100644 index 0000000000..083cdf0c60 --- /dev/null +++ b/tunnels.go @@ -0,0 +1,294 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/google/go-querystring/query" + "github.com/pkg/errors" +) + +// Tunnel is the struct definition of a tunnel. +type Tunnel struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Secret string `json:"tunnel_secret,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + DeletedAt *time.Time `json:"deleted_at,omitempty"` + Connections []TunnelConnection `json:"connections,omitempty"` +} + +// TunnelConnection represents the connections associated with a tunnel. +type TunnelConnection struct { + ColoName string `json:"colo_name"` + UUID string `json:"uuid"` + IsPendingReconnect bool `json:"is_pending_reconnect"` +} + +// TunnelsDetailResponse is used for representing the API response payload for +// multiple tunnels. +type TunnelsDetailResponse struct { + Result []Tunnel `json:"result"` + Response +} + +// TunnelDetailResponse is used for representing the API response payload for +// a single tunnel. +type TunnelDetailResponse struct { + Result Tunnel `json:"result"` + Response +} + +type TunnelParams struct { + AccountID string + UUID string +} + +type TunnelCreateParams struct { + AccountID string `json:"-"` + Name string `json:"name,omitempty"` + Secret string `json:"tunnel_secret,omitempty"` +} + +type TunnelUpdateParams struct { + AccountID string `json:"-"` + Name string `json:"name,omitempty"` + Secret string `json:"tunnel_secret,omitempty"` +} + +type TunnelDeleteParams struct { + AccountID string + UUID string +} + +type TunnelCleanupParams struct { + AccountID string + UUID string +} + +type TunnelTokenParams struct { + AccountID string + UUID string +} + +type TunnelListParams struct { + AccountID string + Name string `url:"name,omitempty"` + UUID string `url:"uuid,omitempty"` + IsDeleted bool `url:"is_deleted,omitempty"` + ExistedAt *time.Time `url:"existed_at,omitempty"` +} + +// Tunnels lists all tunnels. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-list-cloudflare-tunnels +func (api *API) Tunnels(ctx context.Context, params TunnelListParams) ([]Tunnel, error) { + if params.AccountID == "" { + return []Tunnel{}, ErrMissingAccountID + } + + v, _ := query.Values(params) + queryParams := v.Encode() + if queryParams != "" { + queryParams = "?" + queryParams + } + + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", params.AccountID) + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri+queryParams, nil, tunnelV1Header()) + if err != nil { + return []Tunnel{}, err + } + + var argoDetailsResponse TunnelsDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return []Tunnel{}, errors.Wrap(err, errUnmarshalError) + } + return argoDetailsResponse.Result, nil +} + +// Tunnel returns a single Argo tunnel. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-get-cloudflare-tunnel +func (api *API) Tunnel(ctx context.Context, params TunnelParams) (Tunnel, error) { + if params.AccountID == "" { + return Tunnel{}, ErrMissingAccountID + } + + if params.UUID == "" { + return Tunnel{}, errors.New("missing tunnel UUID") + } + + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.UUID) + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, tunnelV1Header()) + if err != nil { + return Tunnel{}, err + } + + var argoDetailsResponse TunnelDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return Tunnel{}, errors.Wrap(err, errUnmarshalError) + } + return argoDetailsResponse.Result, nil +} + +// CreateTunnel creates a new tunnel for the account. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-create-cloudflare-tunnel +func (api *API) CreateTunnel(ctx context.Context, params TunnelCreateParams) (Tunnel, error) { + if params.AccountID == "" { + return Tunnel{}, ErrMissingAccountID + } + + if params.Name == "" { + return Tunnel{}, errors.New("missing tunnel name") + } + + if params.Secret == "" { + return Tunnel{}, errors.New("missing tunnel secret") + } + + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", params.AccountID) + + tunnel := Tunnel{Name: params.Name, Secret: params.Secret} + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPost, uri, tunnel, tunnelV1Header()) + if err != nil { + return Tunnel{}, err + } + + var argoDetailsResponse TunnelDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return Tunnel{}, errors.Wrap(err, errUnmarshalError) + } + + return argoDetailsResponse.Result, nil +} + +// UpdateTunnel updates an existing tunnel for the account. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-update-cloudflare-tunnel +func (api *API) UpdateTunnel(ctx context.Context, params TunnelUpdateParams) (Tunnel, error) { + if params.AccountID == "" { + return Tunnel{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", params.AccountID) + + var tunnel Tunnel + + if params.Name != "" { + tunnel.Name = params.Name + } + + if params.Secret != "" { + tunnel.Secret = params.Secret + } + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPatch, uri, tunnel, tunnelV1Header()) + if err != nil { + return Tunnel{}, err + } + + var argoDetailsResponse TunnelDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return Tunnel{}, errors.Wrap(err, errUnmarshalError) + } + + return argoDetailsResponse.Result, nil +} + +// DeleteTunnel removes a single Argo tunnel. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-delete-cloudflare-tunnel +func (api *API) DeleteTunnel(ctx context.Context, params TunnelDeleteParams) error { + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.UUID) + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, tunnelV1Header()) + if err != nil { + return err + } + + var argoDetailsResponse TunnelDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return errors.Wrap(err, errUnmarshalError) + } + + return nil +} + +// CleanupTunnelConnections deletes any inactive connections on a tunnel. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-clean-up-cloudflare-tunnel-connections +func (api *API) CleanupTunnelConnections(ctx context.Context, params TunnelCleanupParams) error { + if params.AccountID == "" { + return ErrMissingAccountID + } + + if params.UUID == "" { + return errors.New("missing tunnel UUID") + } + + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", params.AccountID, params.UUID) + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, tunnelV1Header()) + if err != nil { + return err + } + + var argoDetailsResponse TunnelDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return errors.Wrap(err, errUnmarshalError) + } + + return nil +} + +// TunnelToken gets the cloudflared token for a tunnel. +// +// API reference: https://api.cloudflare.com/#cloudflare-tunnel-get-cloudflare-tunnel-token +func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error { + if params.AccountID == "" { + return ErrMissingAccountID + } + + if params.UUID == "" { + return errors.New("missing tunnel UUID") + } + + uri := fmt.Sprintf("accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.UUID) + + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, tunnelV1Header()) + if err != nil { + return err + } + + var argoDetailsResponse TunnelDetailResponse + err = json.Unmarshal(res, &argoDetailsResponse) + if err != nil { + return errors.Wrap(err, errUnmarshalError) + } + + return nil +} + +// The early implementation of Tunnel endpoints didn't conform to the V4 +// API standard response structure. This has been remedied going forward however +// to support older clients this isn't yet the default. An explicit `Accept` +// header is used to get the V4 compatible version. +func tunnelV1Header() http.Header { + header := make(http.Header) + header.Set("Accept", "application/json;version=1") + + return header +} diff --git a/tunnels_test.go b/tunnels_test.go new file mode 100644 index 0000000000..e08609542a --- /dev/null +++ b/tunnels_test.go @@ -0,0 +1,221 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestTunnels(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, `{ + "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", + "uuid": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "is_pending_reconnect": false + } + ] + } + ] + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + want := []Tunnel{{ + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + Name: "blog", + CreatedAt: &createdAt, + DeletedAt: &deletedAt, + Connections: []TunnelConnection{{ + ColoName: "DFW", + UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + IsPendingReconnect: false, + }}, + }} + + actual, err := client.Tunnels(context.Background(), TunnelListParams{AccountID: testAccountID}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestTunnel(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, `{ + "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", + "uuid":"f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "is_pending_reconnect":false + } + ] + } + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + want := Tunnel{ + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + Name: "blog", + CreatedAt: &createdAt, + DeletedAt: &deletedAt, + Connections: []TunnelConnection{{ + ColoName: "DFW", + UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + IsPendingReconnect: false, + }}, + } + + actual, err := client.Tunnel(context.Background(), TunnelParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestCreateTunnel(t *testing.T) { + setup() + defer teardown() + + 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") + fmt.Fprintf(w, `{ + "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", + "uuid":"f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "is_pending_reconnect":false + } + ] + } + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + want := Tunnel{ + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + Name: "blog", + CreatedAt: &createdAt, + DeletedAt: &deletedAt, + Connections: []TunnelConnection{{ + ColoName: "DFW", + UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + IsPendingReconnect: false, + }}, + } + + actual, err := client.CreateTunnel(context.Background(), TunnelCreateParams{AccountID: testAccountID, Name: "blog", Secret: "notarealsecret"}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteTunnel(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.Fprintf(w, `{ + "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", + "uuid":"f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "is_pending_reconnect":false + } + ] + } + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) + + err := client.DeleteTunnel(context.Background(), TunnelDeleteParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + assert.NoError(t, err) +} + +func TestCleanupTunnelConnections(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.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [] + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/connections", handler) + + err := client.CleanupTunnelConnections(context.Background(), TunnelCleanupParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + assert.NoError(t, err) +} From 8d40d80264a7bdea67bc8f4620c99875be47c517 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 05:44:20 +1000 Subject: [PATCH 14/38] rename files to be singluar --- tunnels.go => tunnel.go | 0 tunnels_test.go => tunnel_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tunnels.go => tunnel.go (100%) rename tunnels_test.go => tunnel_test.go (100%) diff --git a/tunnels.go b/tunnel.go similarity index 100% rename from tunnels.go rename to tunnel.go diff --git a/tunnels_test.go b/tunnel_test.go similarity index 100% rename from tunnels_test.go rename to tunnel_test.go From 8a1e24db09478fb6d0032862dc72e0512eac679f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 05:49:03 +1000 Subject: [PATCH 15/38] remove accept header for v1 payload --- tunnel.go | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/tunnel.go b/tunnel.go index 083cdf0c60..38b845a162 100644 --- a/tunnel.go +++ b/tunnel.go @@ -98,7 +98,7 @@ func (api *API) Tunnels(ctx context.Context, params TunnelListParams) ([]Tunnel, uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", params.AccountID) - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri+queryParams, nil, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri+queryParams, nil, nil) if err != nil { return []Tunnel{}, err } @@ -125,7 +125,7 @@ func (api *API) Tunnel(ctx context.Context, params TunnelParams) (Tunnel, error) uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.UUID) - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, nil) if err != nil { return Tunnel{}, err } @@ -158,7 +158,7 @@ func (api *API) CreateTunnel(ctx context.Context, params TunnelCreateParams) (Tu tunnel := Tunnel{Name: params.Name, Secret: params.Secret} - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPost, uri, tunnel, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPost, uri, tunnel, nil) if err != nil { return Tunnel{}, err } @@ -192,7 +192,7 @@ func (api *API) UpdateTunnel(ctx context.Context, params TunnelUpdateParams) (Tu tunnel.Secret = params.Secret } - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPatch, uri, tunnel, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPatch, uri, tunnel, nil) if err != nil { return Tunnel{}, err } @@ -212,7 +212,7 @@ func (api *API) UpdateTunnel(ctx context.Context, params TunnelUpdateParams) (Tu func (api *API) DeleteTunnel(ctx context.Context, params TunnelDeleteParams) error { uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.UUID) - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, nil) if err != nil { return err } @@ -240,7 +240,7 @@ func (api *API) CleanupTunnelConnections(ctx context.Context, params TunnelClean uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", params.AccountID, params.UUID) - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, nil) if err != nil { return err } @@ -268,7 +268,7 @@ func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error uri := fmt.Sprintf("accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.UUID) - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, tunnelV1Header()) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, nil) if err != nil { return err } @@ -281,14 +281,3 @@ func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error return nil } - -// The early implementation of Tunnel endpoints didn't conform to the V4 -// API standard response structure. This has been remedied going forward however -// to support older clients this isn't yet the default. An explicit `Accept` -// header is used to get the V4 compatible version. -func tunnelV1Header() http.Header { - header := make(http.Header) - header.Set("Accept", "application/json;version=1") - - return header -} From 0d572c9be64334b159cb117303468bbc37d0c9eb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 05:55:01 +1000 Subject: [PATCH 16/38] add more fields to structs --- tunnel.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tunnel.go b/tunnel.go index 38b845a162..37e5e4ac7f 100644 --- a/tunnel.go +++ b/tunnel.go @@ -13,19 +13,25 @@ import ( // Tunnel is the struct definition of a tunnel. type Tunnel struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Secret string `json:"tunnel_secret,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - DeletedAt *time.Time `json:"deleted_at,omitempty"` - Connections []TunnelConnection `json:"connections,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Secret string `json:"tunnel_secret,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + DeletedAt *time.Time `json:"deleted_at,omitempty"` + Connections []TunnelConnection `json:"connections,omitempty"` + ConnsActiveAt *time.Time `json:"conns_active_at,omitempty"` + ConnInactiveAt *time.Time `json:"conns_inactive_at,omitempty"` } // TunnelConnection represents the connections associated with a tunnel. type TunnelConnection struct { ColoName string `json:"colo_name"` - UUID string `json:"uuid"` + ID string `json:"id"` IsPendingReconnect bool `json:"is_pending_reconnect"` + ClientID string `json:"client_id"` + ClientVersion string `json:"client_version"` + OpenedAt string `json:"opened_at"` + OriginIP string `json:"origin_ip"` } // TunnelsDetailResponse is used for representing the API response payload for From 8119715eac16cab59b30bb8bae33df965b9c6679 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 05:55:19 +1000 Subject: [PATCH 17/38] swap get token to use GET --- tunnel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tunnel.go b/tunnel.go index 37e5e4ac7f..c972a4cf92 100644 --- a/tunnel.go +++ b/tunnel.go @@ -274,7 +274,7 @@ func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error uri := fmt.Sprintf("accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.UUID) - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, nil) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, nil) if err != nil { return err } From 258d85302dca121e71c062e18e28eeb35b474519 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 05:56:31 +1000 Subject: [PATCH 18/38] update description of TunnelToken --- tunnel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tunnel.go b/tunnel.go index c972a4cf92..34292b6c5d 100644 --- a/tunnel.go +++ b/tunnel.go @@ -260,7 +260,7 @@ func (api *API) CleanupTunnelConnections(ctx context.Context, params TunnelClean return nil } -// TunnelToken gets the cloudflared token for a tunnel. +// TunnelToken that allows to run a tunnel. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-get-cloudflare-tunnel-token func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error { From 8cfbaa8cc575cce529f2ce083e55cb68be73c881 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 06:09:46 +1000 Subject: [PATCH 19/38] fix tests for more fields --- tunnel_test.go | 60 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/tunnel_test.go b/tunnel_test.go index e08609542a..3074392e23 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -31,7 +31,11 @@ func TestTunnels(t *testing.T) { { "colo_name": "DFW", "uuid": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "is_pending_reconnect": false + "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": "85.12.78.6" } ] } @@ -51,8 +55,12 @@ func TestTunnels(t *testing.T) { DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", IsPendingReconnect: false, + ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", + ClientVersion: "2022.2.0", + OpenedAt: "2021-01-25T18:22:34.317854Z", + OriginIP: "85.12.78.6", }}, }} @@ -79,11 +87,15 @@ func TestTunnel(t *testing.T) { "name":"blog", "created_at":"2009-11-10T23:00:00Z", "deleted_at":"2009-11-10T23:00:00Z", - "connections":[ + "connections": [ { - "colo_name":"DFW", - "uuid":"f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "is_pending_reconnect":false + "colo_name": "DFW", + "uuid": "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": "85.12.78.6" } ] } @@ -102,8 +114,12 @@ func TestTunnel(t *testing.T) { DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", IsPendingReconnect: false, + ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", + ClientVersion: "2022.2.0", + OpenedAt: "2021-01-25T18:22:34.317854Z", + OriginIP: "85.12.78.6", }}, } @@ -130,11 +146,15 @@ func TestCreateTunnel(t *testing.T) { "name":"blog", "created_at":"2009-11-10T23:00:00Z", "deleted_at":"2009-11-10T23:00:00Z", - "connections":[ + "connections": [ { - "colo_name":"DFW", - "uuid":"f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "is_pending_reconnect":false + "colo_name": "DFW", + "uuid": "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": "85.12.78.6" } ] } @@ -153,8 +173,12 @@ func TestCreateTunnel(t *testing.T) { DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", IsPendingReconnect: false, + ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", + ClientVersion: "2022.2.0", + OpenedAt: "2021-01-25T18:22:34.317854Z", + OriginIP: "85.12.78.6", }}, } @@ -181,11 +205,15 @@ func TestDeleteTunnel(t *testing.T) { "name":"blog", "created_at":"2009-11-10T23:00:00Z", "deleted_at":"2009-11-10T23:00:00Z", - "connections":[ + "connections": [ { - "colo_name":"DFW", - "uuid":"f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "is_pending_reconnect":false + "colo_name": "DFW", + "uuid": "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": "85.12.78.6" } ] } From 2ed1608f51710b8d8573bbdad47056ae6024d2b7 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 28 Apr 2022 08:33:34 +1000 Subject: [PATCH 20/38] swap tunnel UUID for ID --- tunnel.go | 30 +++++++++++++++--------------- tunnel_test.go | 16 ++++++++-------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tunnel.go b/tunnel.go index 34292b6c5d..6f0cad3393 100644 --- a/tunnel.go +++ b/tunnel.go @@ -50,7 +50,7 @@ type TunnelDetailResponse struct { type TunnelParams struct { AccountID string - UUID string + ID string } type TunnelCreateParams struct { @@ -67,23 +67,23 @@ type TunnelUpdateParams struct { type TunnelDeleteParams struct { AccountID string - UUID string + ID string } type TunnelCleanupParams struct { AccountID string - UUID string + ID string } type TunnelTokenParams struct { AccountID string - UUID string + ID string } type TunnelListParams struct { AccountID string Name string `url:"name,omitempty"` - UUID string `url:"uuid,omitempty"` + UUID string `url:"uuid,omitempty"` // the tunnel ID IsDeleted bool `url:"is_deleted,omitempty"` ExistedAt *time.Time `url:"existed_at,omitempty"` } @@ -125,11 +125,11 @@ func (api *API) Tunnel(ctx context.Context, params TunnelParams) (Tunnel, error) return Tunnel{}, ErrMissingAccountID } - if params.UUID == "" { - return Tunnel{}, errors.New("missing tunnel UUID") + if params.ID == "" { + return Tunnel{}, errors.New("missing tunnel ID") } - uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.UUID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.ID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, nil) if err != nil { @@ -216,7 +216,7 @@ func (api *API) UpdateTunnel(ctx context.Context, params TunnelUpdateParams) (Tu // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-delete-cloudflare-tunnel func (api *API) DeleteTunnel(ctx context.Context, params TunnelDeleteParams) error { - uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.UUID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", params.AccountID, params.ID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, nil) if err != nil { @@ -240,11 +240,11 @@ func (api *API) CleanupTunnelConnections(ctx context.Context, params TunnelClean return ErrMissingAccountID } - if params.UUID == "" { - return errors.New("missing tunnel UUID") + if params.ID == "" { + return errors.New("missing tunnel ID") } - uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", params.AccountID, params.UUID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", params.AccountID, params.ID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodDelete, uri, nil, nil) if err != nil { @@ -268,11 +268,11 @@ func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error return ErrMissingAccountID } - if params.UUID == "" { - return errors.New("missing tunnel UUID") + if params.ID == "" { + return errors.New("missing tunnel ID") } - uri := fmt.Sprintf("accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.UUID) + uri := fmt.Sprintf("accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.ID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, nil) if err != nil { diff --git a/tunnel_test.go b/tunnel_test.go index 3074392e23..d6287544bb 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -30,7 +30,7 @@ func TestTunnels(t *testing.T) { "connections": [ { "colo_name": "DFW", - "uuid": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "is_pending_reconnect": false, "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", "client_version": "2022.2.0", @@ -64,7 +64,7 @@ func TestTunnels(t *testing.T) { }}, }} - actual, err := client.Tunnels(context.Background(), TunnelListParams{AccountID: testAccountID}) + actual, err := client.Tunnels(context.Background(), TunnelListParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -90,7 +90,7 @@ func TestTunnel(t *testing.T) { "connections": [ { "colo_name": "DFW", - "uuid": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "is_pending_reconnect": false, "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", "client_version": "2022.2.0", @@ -123,7 +123,7 @@ func TestTunnel(t *testing.T) { }}, } - actual, err := client.Tunnel(context.Background(), TunnelParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + actual, err := client.Tunnel(context.Background(), TunnelParams{AccountID: testAccountID, ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -149,7 +149,7 @@ func TestCreateTunnel(t *testing.T) { "connections": [ { "colo_name": "DFW", - "uuid": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "is_pending_reconnect": false, "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", "client_version": "2022.2.0", @@ -208,7 +208,7 @@ func TestDeleteTunnel(t *testing.T) { "connections": [ { "colo_name": "DFW", - "uuid": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "is_pending_reconnect": false, "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", "client_version": "2022.2.0", @@ -223,7 +223,7 @@ func TestDeleteTunnel(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - err := client.DeleteTunnel(context.Background(), TunnelDeleteParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + err := client.DeleteTunnel(context.Background(), TunnelDeleteParams{AccountID: testAccountID, ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) assert.NoError(t, err) } @@ -244,6 +244,6 @@ func TestCleanupTunnelConnections(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/connections", handler) - err := client.CleanupTunnelConnections(context.Background(), TunnelCleanupParams{AccountID: testAccountID, UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + err := client.CleanupTunnelConnections(context.Background(), TunnelCleanupParams{AccountID: testAccountID, ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) assert.NoError(t, err) } From 881d68cfb2321f9ec54457ecd4e835fd8704ea27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Apr 2022 16:03:10 +0000 Subject: [PATCH 21/38] build(deps): bump github.com/urfave/cli/v2 from 2.5.0 to 2.5.1 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.5.0 to 2.5.1. - [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.5.0...v2.5.1) --- 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 b22dac50dc..bdb7ed8fac 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/orijtech/structslop v0.0.6 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.1 - github.com/urfave/cli/v2 v2.5.0 + github.com/urfave/cli/v2 v2.5.1 golang.org/x/net v0.0.0-20220225172249-27dd8689420f golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index dc8544b198..9a5fe0bc36 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.5.0 h1:2sqblaW62ebcTIEvwb8eRvDfNHeBAeKxfhdynaanhug= -github.com/urfave/cli/v2 v2.5.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= +github.com/urfave/cli/v2 v2.5.1 h1:YKwdkyA0xTBzOaP2G0DVxBnCheHGP+Y9VbKAs4K1Ess= +github.com/urfave/cli/v2 v2.5.1/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= From af23c9e9acb62c5cd04fbb7aaccedf16dde6ac35 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Thu, 28 Apr 2022 12:52:43 +0100 Subject: [PATCH 22/38] Add Origin Override rulesets support --- rulesets.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/rulesets.go b/rulesets.go index 371ba8b421..34c2cc5290 100644 --- a/rulesets.go +++ b/rulesets.go @@ -26,6 +26,7 @@ const ( RulesetPhaseHTTPRequestMain RulesetPhase = "http_request_main" RulesetPhaseHTTPRequestSanitize RulesetPhase = "http_request_sanitize" RulesetPhaseHTTPRequestTransform RulesetPhase = "http_request_transform" + RulesetPhaseHTTPRequestOrigin RulesetPhase = "http_request_origin" RulesetPhaseHTTPResponseFirewallManaged RulesetPhase = "http_response_firewall_managed" RulesetPhaseHTTPResponseHeadersTransform RulesetPhase = "http_response_headers_transform" RulesetPhaseMagicTransit RulesetPhase = "magic_transit" @@ -43,6 +44,7 @@ const ( RulesetRuleActionRewrite RulesetRuleAction = "rewrite" RulesetRuleActionScore RulesetRuleAction = "score" RulesetRuleActionSkip RulesetRuleAction = "skip" + RulesetRuleActionRoute RulesetRuleAction = "route" RulesetActionParameterProductBIC RulesetActionParameterProduct = "bic" RulesetActionParameterProductHOT RulesetActionParameterProduct = "hot" @@ -81,6 +83,7 @@ func RulesetPhaseValues() []string { string(RulesetPhaseHTTPRequestMain), string(RulesetPhaseHTTPRequestSanitize), string(RulesetPhaseHTTPRequestTransform), + string(RulesetPhaseHTTPRequestOrigin), string(RulesetPhaseHTTPResponseFirewallManaged), string(RulesetPhaseHTTPResponseHeadersTransform), string(RulesetPhaseMagicTransit), @@ -104,6 +107,7 @@ func RulesetRuleActionValues() []string { string(RulesetRuleActionRewrite), string(RulesetRuleActionScore), string(RulesetRuleActionSkip), + string(RulesetRuleActionRoute), } } @@ -180,6 +184,8 @@ type RulesetRuleActionParameters struct { MatchedData *RulesetRuleActionParametersMatchedData `json:"matched_data,omitempty"` Version string `json:"version,omitempty"` Response *RulesetRuleActionParametersBlockResponse `json:"response,omitempty"` + HostHeader string `json:"host_header,omitempty"` + Origin *RulesetRuleActionParametersOrigin `json:"origin,omitempty"` } // RulesetRuleActionParametersBlockResponse holds the BlockResponse struct @@ -246,6 +252,13 @@ type RulesetRuleActionParametersMatchedData struct { PublicKey string `json:"public_key,omitempty"` } +// RulesetRuleActionParametersOrigin is the definition for define action +// parameters that involve Origin override. +type RulesetRuleActionParametersOrigin struct { + Host string `json:"host,omitempty"` + Port uint16 `json:"port,omitempty"` +} + // RulesetRule contains information about a single Ruleset Rule. type RulesetRule struct { ID string `json:"id,omitempty"` From a52384af81008a9b3989d57368fc74d814abdd07 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 29 Apr 2022 18:54:41 +1000 Subject: [PATCH 23/38] magic_firewall_ruleset: deprecate in favour of generic ruleset methods Magic Firewall Rulesets were the original edge rules engine implementations however, now, we have a more robust and deeper integration with the generic ruleset methods where `magic_transit` lives along side the ever growing configuration options available in ERE. --- magic_firewall_rulesets.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/magic_firewall_rulesets.go b/magic_firewall_rulesets.go index 4ba3aa10e9..d17f4f8933 100644 --- a/magic_firewall_rulesets.go +++ b/magic_firewall_rulesets.go @@ -99,6 +99,8 @@ type UpdateMagicFirewallRulesetResponse struct { // ListMagicFirewallRulesets lists all Rulesets for a given account // // API reference: https://api.cloudflare.com/#rulesets-list-rulesets +// +// Deprecated: Use `ListZoneRuleset` or `ListAccountRuleset` instead. func (api *API) ListMagicFirewallRulesets(ctx context.Context, accountID string) ([]MagicFirewallRuleset, error) { uri := fmt.Sprintf("/accounts/%s/rulesets", accountID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) @@ -117,6 +119,8 @@ func (api *API) ListMagicFirewallRulesets(ctx context.Context, accountID string) // GetMagicFirewallRuleset returns a specific Magic Firewall Ruleset // // API reference: https://api.cloudflare.com/#rulesets-get-a-ruleset +// +// Deprecated: Use `GetZoneRuleset` or `GetAccountRuleset` instead. func (api *API) GetMagicFirewallRuleset(ctx context.Context, accountID, ID string) (MagicFirewallRuleset, error) { uri := fmt.Sprintf("/accounts/%s/rulesets/%s", accountID, ID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) @@ -135,6 +139,8 @@ func (api *API) GetMagicFirewallRuleset(ctx context.Context, accountID, ID strin // CreateMagicFirewallRuleset creates a Magic Firewall ruleset // // API reference: https://api.cloudflare.com/#rulesets-list-rulesets +// +// Deprecated: Use `CreateZoneRuleset` or `CreateAccountRuleset` instead. func (api *API) CreateMagicFirewallRuleset(ctx context.Context, accountID, name, description string, rules []MagicFirewallRulesetRule) (MagicFirewallRuleset, error) { uri := fmt.Sprintf("/accounts/%s/rulesets", accountID) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, @@ -159,6 +165,8 @@ func (api *API) CreateMagicFirewallRuleset(ctx context.Context, accountID, name, // DeleteMagicFirewallRuleset deletes a Magic Firewall ruleset // // API reference: https://api.cloudflare.com/#rulesets-delete-ruleset +// +// Deprecated: Use `DeleteZoneRuleset` or `DeleteAccountRuleset` instead. func (api *API) DeleteMagicFirewallRuleset(ctx context.Context, accountID, ID string) error { uri := fmt.Sprintf("/accounts/%s/rulesets/%s", accountID, ID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) @@ -179,6 +187,8 @@ func (api *API) DeleteMagicFirewallRuleset(ctx context.Context, accountID, ID st // UpdateMagicFirewallRuleset updates a Magic Firewall ruleset // // API reference: https://api.cloudflare.com/#rulesets-update-ruleset +// +// Deprecated: Use `UpdateZoneRuleset` or `UpdateAccountRuleset` instead. func (api *API) UpdateMagicFirewallRuleset(ctx context.Context, accountID, ID string, description string, rules []MagicFirewallRulesetRule) (MagicFirewallRuleset, error) { uri := fmt.Sprintf("/accounts/%s/rulesets/%s", accountID, ID) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, From b39cc40969a13af9f1b6de9b331c069c3f555e51 Mon Sep 17 00:00:00 2001 From: Bradley Glover Date: Fri, 29 Apr 2022 14:39:14 -0700 Subject: [PATCH 24/38] tunnel_routes: change TunnelRoutesListParams to encoded Options --- tunnel_routes.go | 48 ++++++++++++++++++++++++++++++++----------- tunnel_routes_test.go | 2 +- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/tunnel_routes.go b/tunnel_routes.go index f91d2ad8f4..cc0800226a 100644 --- a/tunnel_routes.go +++ b/tunnel_routes.go @@ -21,14 +21,14 @@ type TunnelRoute struct { DeletedAt *time.Time `json:"deleted_at"` } -type TunnelRoutesListParams struct { - AccountID string `json:"-"` - TunnelID string `json:"tunnel_id,omitempty"` - Comment string `json:"comment,omitempty"` - IsDeleted *bool `json:"is_deleted,omitempty"` - NetworkSubset string `json:"network_subset,omitempty"` - NetworkSuperset string `json:"network_superset,omitempty"` - ExistedAt *time.Time `json:"existed_at,omitempty"` +type TunnelRoutesListOptions struct { + AccountID string + TunnelID string + Comment string + IsDeleted *bool + NetworkSubset string + NetworkSuperset string + ExistedAt *time.Time PaginationOptions } @@ -67,16 +67,40 @@ type tunnelRouteResponse struct { Result TunnelRoute `json:"result"` } +// encode encodes non-nil fields into URL encoded form. +func (o TunnelRoutesListOptions) encode() string { + v := url.Values{} + if o.TunnelID != "" { + v.Set("tunnel_id", fmt.Sprintf("%s", o.TunnelID)) + } + if o.Comment != "" { + v.Set("comment", fmt.Sprintf("%s", o.Comment)) + } + if o.IsDeleted != nil { + v.Set("is_deleted", fmt.Sprintf("%t", *o.IsDeleted)) + } + if o.NetworkSubset != "" { + v.Set("network_subset", fmt.Sprintf("%s", o.NetworkSubset)) + } + if o.NetworkSuperset != "" { + v.Set("network_superset", fmt.Sprintf("%s", o.NetworkSuperset)) + } + if o.ExistedAt != nil { + v.Set("existed_at", (*o.ExistedAt).Format(time.RFC3339)) + } + return v.Encode() +} + // ListTunnelRoutes lists all defined routes for tunnels in the account. // // See: https://api.cloudflare.com/#tunnel-route-list-tunnel-routes -func (api *API) ListTunnelRoutes(ctx context.Context, params TunnelRoutesListParams) ([]TunnelRoute, error) { - if params.AccountID == "" { +func (api *API) ListTunnelRoutes(ctx context.Context, options TunnelRoutesListOptions) ([]TunnelRoute, error) { + if options.AccountID == "" { return []TunnelRoute{}, ErrMissingAccountID } - uri := fmt.Sprintf("/%s/%s/teamnet/routes", AccountRouteRoot, params.AccountID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) + uri := fmt.Sprintf("/%s/%s/teamnet/routes?%s", AccountRouteRoot, options.AccountID, options.encode()) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, options) if err != nil { return []TunnelRoute{}, err diff --git a/tunnel_routes_test.go b/tunnel_routes_test.go index 13d7cb5fdc..3d8ca72e37 100644 --- a/tunnel_routes_test.go +++ b/tunnel_routes_test.go @@ -49,7 +49,7 @@ func TestListTunnelRoutes(t *testing.T) { }, } - params := TunnelRoutesListParams{AccountID: testAccountID} + params := TunnelRoutesListOptions{AccountID: testAccountID} got, err := client.ListTunnelRoutes(context.Background(), params) if assert.NoError(t, err) { From afffc2b351e0d7b1bb4ef38aa409a22dbc66c6ee Mon Sep 17 00:00:00 2001 From: Bradley Glover Date: Fri, 29 Apr 2022 15:17:23 -0700 Subject: [PATCH 25/38] tunnel_routes: revert to Params to prevent breaking change --- tunnel_routes.go | 12 ++++++------ tunnel_routes_test.go | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tunnel_routes.go b/tunnel_routes.go index cc0800226a..c3c23c6b20 100644 --- a/tunnel_routes.go +++ b/tunnel_routes.go @@ -21,7 +21,7 @@ type TunnelRoute struct { DeletedAt *time.Time `json:"deleted_at"` } -type TunnelRoutesListOptions struct { +type TunnelRoutesListParams struct { AccountID string TunnelID string Comment string @@ -68,7 +68,7 @@ type tunnelRouteResponse struct { } // encode encodes non-nil fields into URL encoded form. -func (o TunnelRoutesListOptions) encode() string { +func (o TunnelRoutesListParams) encode() string { v := url.Values{} if o.TunnelID != "" { v.Set("tunnel_id", fmt.Sprintf("%s", o.TunnelID)) @@ -94,13 +94,13 @@ func (o TunnelRoutesListOptions) encode() string { // ListTunnelRoutes lists all defined routes for tunnels in the account. // // See: https://api.cloudflare.com/#tunnel-route-list-tunnel-routes -func (api *API) ListTunnelRoutes(ctx context.Context, options TunnelRoutesListOptions) ([]TunnelRoute, error) { - if options.AccountID == "" { +func (api *API) ListTunnelRoutes(ctx context.Context, params TunnelRoutesListParams) ([]TunnelRoute, error) { + if params.AccountID == "" { return []TunnelRoute{}, ErrMissingAccountID } - uri := fmt.Sprintf("/%s/%s/teamnet/routes?%s", AccountRouteRoot, options.AccountID, options.encode()) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, options) + uri := fmt.Sprintf("/%s/%s/teamnet/routes?%s", AccountRouteRoot, params.AccountID, params.encode()) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) if err != nil { return []TunnelRoute{}, err diff --git a/tunnel_routes_test.go b/tunnel_routes_test.go index 3d8ca72e37..13d7cb5fdc 100644 --- a/tunnel_routes_test.go +++ b/tunnel_routes_test.go @@ -49,7 +49,7 @@ func TestListTunnelRoutes(t *testing.T) { }, } - params := TunnelRoutesListOptions{AccountID: testAccountID} + params := TunnelRoutesListParams{AccountID: testAccountID} got, err := client.ListTunnelRoutes(context.Background(), params) if assert.NoError(t, err) { From 562f64a0924ac9e6cf2420cf8b597cbef21a9190 Mon Sep 17 00:00:00 2001 From: Bradley Glover Date: Fri, 29 Apr 2022 15:45:58 -0700 Subject: [PATCH 26/38] tunnel_routes: linting --- tunnel_routes.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tunnel_routes.go b/tunnel_routes.go index c3c23c6b20..3f30c9fded 100644 --- a/tunnel_routes.go +++ b/tunnel_routes.go @@ -71,19 +71,19 @@ type tunnelRouteResponse struct { func (o TunnelRoutesListParams) encode() string { v := url.Values{} if o.TunnelID != "" { - v.Set("tunnel_id", fmt.Sprintf("%s", o.TunnelID)) + v.Set("tunnel_id", o.TunnelID) } if o.Comment != "" { - v.Set("comment", fmt.Sprintf("%s", o.Comment)) + v.Set("comment", o.Comment) } if o.IsDeleted != nil { v.Set("is_deleted", fmt.Sprintf("%t", *o.IsDeleted)) } if o.NetworkSubset != "" { - v.Set("network_subset", fmt.Sprintf("%s", o.NetworkSubset)) + v.Set("network_subset", o.NetworkSubset) } if o.NetworkSuperset != "" { - v.Set("network_superset", fmt.Sprintf("%s", o.NetworkSuperset)) + v.Set("network_superset", o.NetworkSuperset) } if o.ExistedAt != nil { v.Set("existed_at", (*o.ExistedAt).Format(time.RFC3339)) From 28d9a2552c94333befa41206c76830177158e5b3 Mon Sep 17 00:00:00 2001 From: Bradley Glover Date: Fri, 29 Apr 2022 16:58:23 -0700 Subject: [PATCH 27/38] tunnel_routes: remove encode() and use go-querystring --- tunnel_routes.go | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/tunnel_routes.go b/tunnel_routes.go index 3f30c9fded..c77bcc160b 100644 --- a/tunnel_routes.go +++ b/tunnel_routes.go @@ -8,6 +8,7 @@ import ( "net/url" "time" + "github.com/google/go-querystring/query" "github.com/pkg/errors" ) @@ -23,12 +24,12 @@ type TunnelRoute struct { type TunnelRoutesListParams struct { AccountID string - TunnelID string - Comment string - IsDeleted *bool - NetworkSubset string - NetworkSuperset string - ExistedAt *time.Time + TunnelID string `url:"tunnel_id,omitempty"` + Comment string `url:"comment,omitempty"` + IsDeleted *bool `url:"is_deleted,omitempty"` + NetworkSubset string `url:"network_subset,omitempty"` + NetworkSuperset string `url:"network_superset,omitempty"` + ExistedAt *time.Time `url:"existed_at,omitempty"` PaginationOptions } @@ -67,30 +68,6 @@ type tunnelRouteResponse struct { Result TunnelRoute `json:"result"` } -// encode encodes non-nil fields into URL encoded form. -func (o TunnelRoutesListParams) encode() string { - v := url.Values{} - if o.TunnelID != "" { - v.Set("tunnel_id", o.TunnelID) - } - if o.Comment != "" { - v.Set("comment", o.Comment) - } - if o.IsDeleted != nil { - v.Set("is_deleted", fmt.Sprintf("%t", *o.IsDeleted)) - } - if o.NetworkSubset != "" { - v.Set("network_subset", o.NetworkSubset) - } - if o.NetworkSuperset != "" { - v.Set("network_superset", o.NetworkSuperset) - } - if o.ExistedAt != nil { - v.Set("existed_at", (*o.ExistedAt).Format(time.RFC3339)) - } - return v.Encode() -} - // ListTunnelRoutes lists all defined routes for tunnels in the account. // // See: https://api.cloudflare.com/#tunnel-route-list-tunnel-routes @@ -99,8 +76,14 @@ func (api *API) ListTunnelRoutes(ctx context.Context, params TunnelRoutesListPar return []TunnelRoute{}, ErrMissingAccountID } - uri := fmt.Sprintf("/%s/%s/teamnet/routes?%s", AccountRouteRoot, params.AccountID, params.encode()) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) + v, _ := query.Values(params) + queryParams := v.Encode() + if queryParams != "" { + queryParams = "?" + queryParams + } + + uri := fmt.Sprintf("/%s/%s/teamnet/routes", AccountRouteRoot, params.AccountID) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri+queryParams, params) if err != nil { return []TunnelRoute{}, err From 89f8337a5f80f2f9bb7c8f06b47a0be194b12ec5 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 6 May 2022 15:25:19 +1000 Subject: [PATCH 28/38] healthchecks: add Notification.Trigger to HealthcheckNotification struct --- healthchecks.go | 1 + healthchecks_test.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/healthchecks.go b/healthchecks.go index 303e15a177..d40965e873 100644 --- a/healthchecks.go +++ b/healthchecks.go @@ -56,6 +56,7 @@ type HealthcheckTCPConfig struct { type HealthcheckNotification struct { Suspended bool `json:"suspended,omitempty"` EmailAddresses []string `json:"email_addresses,omitempty"` + Trigger string `json:"trigger,omitempty"` } // HealthcheckListResponse is the API response, containing an array of healthchecks. diff --git a/healthchecks_test.go b/healthchecks_test.go index bace050e22..952f0800bd 100644 --- a/healthchecks_test.go +++ b/healthchecks_test.go @@ -47,7 +47,8 @@ const ( "tcp_config": null, "notification": { "suspended": false, - "email_addresses": ["alerts@example.com"] + "email_addresses": ["alerts@example.com"], + "trigger": "ALL" }, "created_on": "2019-01-13T12:20:00.12345Z", "modified_on": "2019-01-13T12:20:00.12345Z", @@ -90,6 +91,7 @@ var ( Notification: HealthcheckNotification{ Suspended: false, EmailAddresses: []string{"alerts@example.com"}, + Trigger: "ALL", }, Status: "unknown", FailureReason: "", From 7e3b1c77ab0547a5ca3d6ff12bf6528ec5038be9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 16:02:43 +0000 Subject: [PATCH 29/38] build(deps): bump github.com/urfave/cli/v2 from 2.5.1 to 2.6.0 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.5.1 to 2.6.0. - [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.5.1...v2.6.0) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 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 bdb7ed8fac..ae6477caed 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/orijtech/structslop v0.0.6 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.1 - github.com/urfave/cli/v2 v2.5.1 + github.com/urfave/cli/v2 v2.6.0 golang.org/x/net v0.0.0-20220225172249-27dd8689420f golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index 9a5fe0bc36..c245447cb6 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.5.1 h1:YKwdkyA0xTBzOaP2G0DVxBnCheHGP+Y9VbKAs4K1Ess= -github.com/urfave/cli/v2 v2.5.1/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= +github.com/urfave/cli/v2 v2.6.0 h1:yj2Drkflh8X/zUrkWlWlUjZYHyWN7WMmpVxyxXIUyv8= +github.com/urfave/cli/v2 v2.6.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= From 94878b63b7f8de20a8b30de071fd801af73e6673 Mon Sep 17 00:00:00 2001 From: Cole MacKenzie Date: Fri, 6 May 2022 12:37:41 -0700 Subject: [PATCH 30/38] Add `frequency` field to logpush job Adds the field `frequency` to `LogpushJob` struct. ``` The frequency at which Cloudflare sends batches of logs to your destination. Setting frequency to high sends your logs in larger quantities of smaller files. Setting frequency to low sends logs in smaller quantities of larger files. ``` https://api.cloudflare.com/#logpush-jobs-create-logpush-job --- logpush.go | 1 + logpush_test.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/logpush.go b/logpush.go index 709e512470..1f20ddd2d3 100644 --- a/logpush.go +++ b/logpush.go @@ -22,6 +22,7 @@ type LogpushJob struct { LastComplete *time.Time `json:"last_complete,omitempty"` LastError *time.Time `json:"last_error,omitempty"` ErrorMessage string `json:"error_message,omitempty"` + Frequency string `json:"frequency,omitempty"` } // LogpushJobsResponse is the API response, containing an array of Logpush Jobs. diff --git a/logpush_test.go b/logpush_test.go index a2f0463aa7..f2df74141e 100644 --- a/logpush_test.go +++ b/logpush_test.go @@ -23,7 +23,8 @@ const ( "destination_conf": "s3://mybucket/logs?region=us-west-2", "last_complete": "%[2]s", "last_error": "%[2]s", - "error_message": "test" + "error_message": "test", + "frequency": "high" } ` serverLogpushGetOwnershipChallengeDescription = `{ @@ -52,6 +53,7 @@ var ( LastComplete: &testLogpushTimestamp, LastError: &testLogpushTimestamp, ErrorMessage: "test", + Frequency: "high", } expectedLogpushGetOwnershipChallengeStruct = LogpushGetOwnershipChallenge{ Filename: "logs/challenge-filename.txt", From 76c67230be9cf81a1b5d9c95e1b518c5976343ed Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 10 May 2022 08:19:57 +1000 Subject: [PATCH 31/38] rulesets: add `http_request_sbfm` phase Closes cloudflare/terraform-provider-cloudflare#1604 --- rulesets.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rulesets.go b/rulesets.go index 34c2cc5290..0bbfad9700 100644 --- a/rulesets.go +++ b/rulesets.go @@ -31,6 +31,7 @@ const ( RulesetPhaseHTTPResponseHeadersTransform RulesetPhase = "http_response_headers_transform" RulesetPhaseMagicTransit RulesetPhase = "magic_transit" RulesetPhaseRateLimit RulesetPhase = "http_ratelimit" + RulesetPhaseSuperBotFightMode RulesetPhase = "http_request_sbfm" RulesetRuleActionBlock RulesetRuleAction = "block" RulesetRuleActionChallenge RulesetRuleAction = "challenge" @@ -88,6 +89,7 @@ func RulesetPhaseValues() []string { string(RulesetPhaseHTTPResponseHeadersTransform), string(RulesetPhaseMagicTransit), string(RulesetPhaseRateLimit), + string(RulesetPhaseSuperBotFightMode), } } From 53bd41f081330b3f1130928d698c4aa2e6d4842f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 10 May 2022 08:53:24 +1000 Subject: [PATCH 32/38] Create CODEOWNERS --- .github/CODEOWNERS | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..a5d8a3a9b9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ + +# Own a service and want to be defined as an owner here? Open a PR or +# hit up @jacobbednarz to add your team. + +* @jacobbednarz From d436ff243cf45739a6aa57d17fbd774c6fe80764 Mon Sep 17 00:00:00 2001 From: Brad Swenson Date: Fri, 6 May 2022 10:01:09 -0500 Subject: [PATCH 33/38] add next_event_prequeue_start_time and next_event_start_time and use time pointer" --- waiting_room.go | 64 +++++++++++++++++++++++--------------------- waiting_room_test.go | 41 +++++++++++++++------------- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/waiting_room.go b/waiting_room.go index f7da89c6a7..9a7dddc320 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -12,21 +12,23 @@ import ( // WaitingRoom describes a WaitingRoom object. type WaitingRoom struct { - CreatedOn time.Time `json:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty"` - Path string `json:"path"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - CustomPageHTML string `json:"custom_page_html,omitempty"` - Host string `json:"host"` - ID string `json:"id,omitempty"` - NewUsersPerMinute int `json:"new_users_per_minute"` - TotalActiveUsers int `json:"total_active_users"` - SessionDuration int `json:"session_duration"` - QueueAll bool `json:"queue_all"` - DisableSessionRenewal bool `json:"disable_session_renewal"` - Suspended bool `json:"suspended"` - JsonResponseEnabled bool `json:"json_response_enabled"` + CreatedOn time.Time `json:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + Path string `json:"path"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + CustomPageHTML string `json:"custom_page_html,omitempty"` + Host string `json:"host"` + ID string `json:"id,omitempty"` + NewUsersPerMinute int `json:"new_users_per_minute"` + TotalActiveUsers int `json:"total_active_users"` + SessionDuration int `json:"session_duration"` + QueueAll bool `json:"queue_all"` + DisableSessionRenewal bool `json:"disable_session_renewal"` + Suspended bool `json:"suspended"` + JsonResponseEnabled bool `json:"json_response_enabled"` + NextEventPrequeueStartTime *time.Time `json:"next_event_prequeue_start_time,omitempty"` + NextEventStartTime *time.Time `json:"next_event_start_time,omitempty"` } // WaitingRoomStatus describes the status of a waiting room. @@ -40,22 +42,22 @@ type WaitingRoomStatus struct { // WaitingRoomEvent describes a WaitingRoomEvent object. type WaitingRoomEvent struct { - EventEndTime time.Time `json:"event_end_time"` - CreatedOn time.Time `json:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty"` - PrequeueStartTime time.Time `json:"prequeue_start_time,omitempty"` - EventStartTime time.Time `json:"event_start_time"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - QueueingMethod string `json:"queueing_method,omitempty"` - ID string `json:"id,omitempty"` - CustomPageHTML string `json:"custom_page_html,omitempty"` - NewUsersPerMinute int `json:"new_users_per_minute,omitempty"` - TotalActiveUsers int `json:"total_active_users,omitempty"` - SessionDuration int `json:"session_duration,omitempty"` - DisableSessionRenewal *bool `json:"disable_session_renewal,omitempty"` - Suspended bool `json:"suspended"` - ShuffleAtEventStart bool `json:"shuffle_at_event_start"` + EventEndTime time.Time `json:"event_end_time"` + CreatedOn time.Time `json:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + PrequeueStartTime *time.Time `json:"prequeue_start_time,omitempty"` + EventStartTime time.Time `json:"event_start_time"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + QueueingMethod string `json:"queueing_method,omitempty"` + ID string `json:"id,omitempty"` + CustomPageHTML string `json:"custom_page_html,omitempty"` + NewUsersPerMinute int `json:"new_users_per_minute,omitempty"` + TotalActiveUsers int `json:"total_active_users,omitempty"` + SessionDuration int `json:"session_duration,omitempty"` + DisableSessionRenewal *bool `json:"disable_session_renewal,omitempty"` + Suspended bool `json:"suspended"` + ShuffleAtEventStart bool `json:"shuffle_at_event_start"` } // WaitingRoomPagePreviewURL describes a WaitingRoomPagePreviewURL object. diff --git a/waiting_room_test.go b/waiting_room_test.go index 24d65bf630..ef0202493c 100644 --- a/waiting_room_test.go +++ b/waiting_room_test.go @@ -34,9 +34,12 @@ var waitingRoomJSON = fmt.Sprintf(` "session_duration": 10, "disable_session_renewal": false, "json_response_enabled": true, - "custom_page_html": "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}" + "custom_page_html": "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}", + "next_event_prequeue_start_time": null, + "next_event_start_time": "%s" } - `, waitingRoomID, testTimestampWaitingRoom.Format(time.RFC3339Nano), testTimestampWaitingRoom.Format(time.RFC3339Nano)) + `, waitingRoomID, testTimestampWaitingRoom.Format(time.RFC3339Nano), testTimestampWaitingRoom.Format(time.RFC3339Nano), + testTimestampWaitingRoomEventStart.Format(time.RFC3339Nano)) var waitingRoomEventJSON = fmt.Sprintf(` { @@ -80,21 +83,23 @@ var waitingRoomPagePreviewJSON = ` ` var waitingRoom = WaitingRoom{ - ID: waitingRoomID, - CreatedOn: testTimestampWaitingRoom, - ModifiedOn: testTimestampWaitingRoom, - Name: "production_webinar", - Description: "Production - DO NOT MODIFY", - Suspended: false, - Host: "shop.example.com", - Path: "/shop/checkout", - QueueAll: true, - NewUsersPerMinute: 600, - TotalActiveUsers: 1000, - SessionDuration: 10, - DisableSessionRenewal: false, - JsonResponseEnabled: true, - CustomPageHTML: "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}", + ID: waitingRoomID, + CreatedOn: testTimestampWaitingRoom, + ModifiedOn: testTimestampWaitingRoom, + Name: "production_webinar", + Description: "Production - DO NOT MODIFY", + Suspended: false, + Host: "shop.example.com", + Path: "/shop/checkout", + QueueAll: true, + NewUsersPerMinute: 600, + TotalActiveUsers: 1000, + SessionDuration: 10, + DisableSessionRenewal: false, + JsonResponseEnabled: true, + CustomPageHTML: "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}", + NextEventStartTime: &testTimestampWaitingRoomEventStart, + NextEventPrequeueStartTime: nil, } var waitingRoomEvent = WaitingRoomEvent{ @@ -104,7 +109,7 @@ var waitingRoomEvent = WaitingRoomEvent{ Name: "production_webinar_event", Description: "Production event - DO NOT MODIFY", Suspended: false, - PrequeueStartTime: testTimestampWaitingRoomEventPrequeue, + PrequeueStartTime: &testTimestampWaitingRoomEventPrequeue, EventStartTime: testTimestampWaitingRoomEventStart, EventEndTime: testTimestampWaitingRoomEventEnd, ShuffleAtEventStart: false, From 06d521f980bd0ff964e2bc0c918ad6fa4b97d627 Mon Sep 17 00:00:00 2001 From: Justin Holmes Date: Tue, 10 May 2022 16:16:09 -0500 Subject: [PATCH 34/38] Fix inability to set http only attr to false --- access_application.go | 2 +- access_application_test.go | 42 +++++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/access_application.go b/access_application.go index 85bc6e3f8e..64f82076f2 100644 --- a/access_application.go +++ b/access_application.go @@ -44,7 +44,7 @@ type AccessApplication struct { 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"` + HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` ServiceAuth401Redirect bool `json:"service_auth_401_redirect,omitempty"` } diff --git a/access_application_test.go b/access_application_test.go index d5570f6e1a..a1d0ef130e 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -57,6 +57,7 @@ func TestAccessApplications(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") + httpOnlyVal := true want := []AccessApplication{{ ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", CreatedAt: &createdAt, @@ -74,7 +75,7 @@ func TestAccessApplications(t *testing.T) { CustomDenyMessage: "denied!", CustomDenyURL: "https://www.example.com", SameSiteCookieAttribute: "strict", - HttpOnlyCookieAttribute: true, + HttpOnlyCookieAttribute: &httpOnlyVal, LogoURL: "https://www.example.com/example.png", SkipInterstitial: true, }} @@ -124,7 +125,8 @@ func TestAccessApplication(t *testing.T) { "logo_url": "https://www.example.com/example.png", "skip_interstitial": true, "app_launcher_visible": true, - "service_auth_401_redirect": true + "service_auth_401_redirect": true, + "http_only_cookie_attribute": false } } `) @@ -133,24 +135,26 @@ func TestAccessApplication(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") + httpOnlyVal := false want := AccessApplication{ - ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", - CreatedAt: &createdAt, - UpdatedAt: &updatedAt, - AUD: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", - Name: "Admin Site", - Domain: "test.example.com/admin", - Type: "self_hosted", - SessionDuration: "24h", - AllowedIdps: []string{"f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}, - AutoRedirectToIdentity: false, - EnableBindingCookie: false, - AppLauncherVisible: true, - ServiceAuth401Redirect: true, - CustomDenyMessage: "denied!", - CustomDenyURL: "https://www.example.com", - LogoURL: "https://www.example.com/example.png", - SkipInterstitial: true, + ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + AUD: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + Name: "Admin Site", + Domain: "test.example.com/admin", + Type: "self_hosted", + SessionDuration: "24h", + AllowedIdps: []string{"f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}, + AutoRedirectToIdentity: false, + EnableBindingCookie: false, + AppLauncherVisible: true, + ServiceAuth401Redirect: true, + CustomDenyMessage: "denied!", + CustomDenyURL: "https://www.example.com", + LogoURL: "https://www.example.com/example.png", + SkipInterstitial: true, + HttpOnlyCookieAttribute: &httpOnlyVal, } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) From 96a299ed9f82481e502ef566ec5a9d8080564536 Mon Sep 17 00:00:00 2001 From: Justin Holmes Date: Thu, 12 May 2022 09:54:53 -0500 Subject: [PATCH 35/38] Use BoolPtr instead --- access_application_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/access_application_test.go b/access_application_test.go index a1d0ef130e..8b19ac7c59 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -57,7 +57,6 @@ func TestAccessApplications(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - httpOnlyVal := true want := []AccessApplication{{ ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", CreatedAt: &createdAt, @@ -75,7 +74,7 @@ func TestAccessApplications(t *testing.T) { CustomDenyMessage: "denied!", CustomDenyURL: "https://www.example.com", SameSiteCookieAttribute: "strict", - HttpOnlyCookieAttribute: &httpOnlyVal, + HttpOnlyCookieAttribute: BoolPtr(true), LogoURL: "https://www.example.com/example.png", SkipInterstitial: true, }} @@ -135,7 +134,6 @@ func TestAccessApplication(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - httpOnlyVal := false want := AccessApplication{ ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", CreatedAt: &createdAt, @@ -154,7 +152,7 @@ func TestAccessApplication(t *testing.T) { CustomDenyURL: "https://www.example.com", LogoURL: "https://www.example.com/example.png", SkipInterstitial: true, - HttpOnlyCookieAttribute: &httpOnlyVal, + HttpOnlyCookieAttribute: BoolPtr(true), } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) From 3edf6987864218463e372b63e2f67c66108d24dd Mon Sep 17 00:00:00 2001 From: Justin Holmes Date: Thu, 12 May 2022 10:30:47 -0500 Subject: [PATCH 36/38] Fix test --- access_application_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/access_application_test.go b/access_application_test.go index 8b19ac7c59..00c07dd063 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -152,7 +152,7 @@ func TestAccessApplication(t *testing.T) { CustomDenyURL: "https://www.example.com", LogoURL: "https://www.example.com/example.png", SkipInterstitial: true, - HttpOnlyCookieAttribute: BoolPtr(true), + HttpOnlyCookieAttribute: BoolPtr(false), } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) From 39e1bae890974d5db7855d57d7a7ab9844950efc Mon Sep 17 00:00:00 2001 From: Bradley Glover Date: Thu, 12 May 2022 11:30:30 -0700 Subject: [PATCH 37/38] tunnel: return tunnel token, fix uri --- tunnel.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tunnel.go b/tunnel.go index 6f0cad3393..623b9a1005 100644 --- a/tunnel.go +++ b/tunnel.go @@ -48,6 +48,12 @@ type TunnelDetailResponse struct { Response } +// TunnelTokenResponse is the API response for a tunnel token. +type TunnelTokenResponse struct { + Result string `json:"result"` + Response +} + type TunnelParams struct { AccountID string ID string @@ -263,27 +269,27 @@ func (api *API) CleanupTunnelConnections(ctx context.Context, params TunnelClean // TunnelToken that allows to run a tunnel. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-get-cloudflare-tunnel-token -func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) error { +func (api *API) TunnelToken(ctx context.Context, params TunnelTokenParams) (string, error) { if params.AccountID == "" { - return ErrMissingAccountID + return "", ErrMissingAccountID } if params.ID == "" { - return errors.New("missing tunnel ID") + return "", errors.New("missing tunnel ID") } - uri := fmt.Sprintf("accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.ID) + uri := fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/token", params.AccountID, params.ID) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, nil) if err != nil { - return err + return "", err } - var argoDetailsResponse TunnelDetailResponse - err = json.Unmarshal(res, &argoDetailsResponse) + var tunnelTokenResponse TunnelTokenResponse + err = json.Unmarshal(res, &tunnelTokenResponse) if err != nil { - return errors.Wrap(err, errUnmarshalError) + return "", errors.Wrap(err, errUnmarshalError) } - return nil + return tunnelTokenResponse.Result, nil } From 1062d818e23bbbe5ccaa581b7f973531aeff6554 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 13 May 2022 09:08:38 +1000 Subject: [PATCH 38/38] add test coverage --- tunnel_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tunnel_test.go b/tunnel_test.go index d6287544bb..50819828fb 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -247,3 +247,26 @@ func TestCleanupTunnelConnections(t *testing.T) { err := client.CleanupTunnelConnections(context.Background(), TunnelCleanupParams{AccountID: testAccountID, ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) assert.NoError(t, err) } + +func TestTunnelToken(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, `{ + "success": true, + "errors": [], + "messages": [], + "result": "ZHNraGdhc2RraGFza2hqZGFza2poZGFza2poYXNrZGpoYWtzamRoa2FzZGpoa2FzamRoa2Rhc2po\na2FzamRoa2FqCg==" + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/token", handler) + + token, err := client.TunnelToken(context.Background(), TunnelTokenParams{AccountID: testAccountID, ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + assert.NoError(t, err) + assert.Equal(t, "ZHNraGdhc2RraGFza2hqZGFza2poZGFza2poYXNrZGpoYWtzamRoa2FzZGpoa2FzamRoa2Rhc2po\na2FzamRoa2FqCg==", token) +}