Repository: cloudflare/cloudflare-go
Pull request #3680 (2024-11-27 09:49:07)

Fix for deleting per hostname authenticated origin pulls
## Description

Fixes an issue with the authenticated origin pulls per hostname where the API docs state that in order to delete an instance the enabled flag must be set to null.

API docs can be found here:

https://developers.cloudflare.com/api/operations/per-hostname-authenticated-origin-pull-enable-or-disable-a-hostname-for-client-authentication

This fix is required to correct an issue with the cloudflare terraform provider which is currently failing to destroy these resources correctly.

This can lead to a hard lock of mtls certificates and origin pulls configured on them as the cloudflare API contains validation bugs on the endpoint documented on the URL above.

Issue raised on the terraform provider:

https://github.com/cloudflare/terraform-provider-cloudflare/issues/4648

PR raised to fix this on the terraform provider:

https://github.com/cloudflare/terraform-provider-cloudflare/pull/4649

## Has your change been tested?

Unit tests have been extended to ensure that `nil` is allowed as a value when making this `PUT` request.

## Types of changes

What sort of change does your code introduce/modify?

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

- [x] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.
- [x] This change is using publicly documented in [cloudflare/api-schemas](https://github.com/cloudflare/api-schemas) 
      and relies on stable APIs.

[1]: https://help.github.com/articles/closing-issues-using-keywords/


github-actions[bot]: Oops! It looks like no changelog entry is attached to this PR. Please include a release note as described in https://github.com/cloudflare/cloudflare-go/blob/master/docs/changelog-process.md.

Example: 

~~~
```release-note:TYPE
Release note
```
~~~

If you do not require a release note to be included, please add the `workflow/skip-changelog-entry` label.

Patch:
diff --git a/.changelog/3680.txt b/.changelog/3680.txt
new file mode 100644
index 000000000..cc9b33bee
--- /dev/null
+++ b/.changelog/3680.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+authenticated_origin_pulls_per_hostname: fixes the struct to allow null (nil) values on the `Enabled` property
+```
diff --git a/authenticated_origin_pulls_per_hostname.go b/authenticated_origin_pulls_per_hostname.go
index c8ea3eccb..06810b91e 100644
--- a/authenticated_origin_pulls_per_hostname.go
+++ b/authenticated_origin_pulls_per_hostname.go
@@ -67,7 +67,7 @@ type PerHostnameAuthenticatedOriginPullsCertificateParams struct {
 type PerHostnameAuthenticatedOriginPullsConfig struct {
 	Hostname string `json:"hostname"`
 	CertID   string `json:"cert_id"`
-	Enabled  bool   `json:"enabled"`
+	Enabled  *bool  `json:"enabled"`
 }
 
 // PerHostnameAuthenticatedOriginPullsConfigParams represents the expected config param format for Per Hostname AuthenticatedOriginPulls applied on a hostname.


Test patch:
diff --git a/authenticated_origin_pulls_per_hostname_test.go b/authenticated_origin_pulls_per_hostname_test.go
index 635ceb101..20a4ae60d 100644
--- a/authenticated_origin_pulls_per_hostname_test.go
+++ b/authenticated_origin_pulls_per_hostname_test.go
@@ -293,7 +293,76 @@ func TestEditPerHostnameAuthenticatedOriginPullsConfig(t *testing.T) {
 		{
 			Hostname: "app.example.com",
 			CertID:   "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60",
-			Enabled:  true,
+			Enabled:  BoolPtr(true),
+		},
+	}
+	actual, err := client.EditPerHostnameAuthenticatedOriginPullsConfig(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353", config)
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+}
+
+func TestDeletePerHostnameAuthenticatedOriginPullsConfig(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprint(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": [
+			  {
+				"hostname": "app.example.com",
+				"cert_id": "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60",
+				"enabled": true,
+				"status": "active",
+				"created_at": "2100-01-01T05:20:00Z",
+				"updated_at": "2100-01-01T05:20:00Z",
+				"cert_status": "active",
+				"issuer": "GlobalSign",
+				"signature": "SHA256WithRSA",
+				"serial_number": "6743787633689793699141714808227354901",
+				"certificate": "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIJAMHAwfXZ5/PWMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\nBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX\naWRnaXRzIFB0eSBMdGQwHhcNMTYwODI0MTY0MzAxWhcNMTYxMTIyMTY0MzAxWjBF\nMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50\nZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAwQHoetcl9+5ikGzV6cMzWtWPJHqXT3wpbEkRU9Yz7lgvddmGdtcGbg/1\nCGZu0jJGkMoppoUo4c3dts3iwqRYmBikUP77wwY2QGmDZw2FvkJCJlKnabIRuGvB\nKwzESIXgKk2016aTP6/dAjEHyo6SeoK8lkIySUvK0fyOVlsiEsCmOpidtnKX/a+5\n0GjB79CJH4ER2lLVZnhePFR/zUOyPxZQQ4naHf7yu/b5jhO0f8fwt+pyFxIXjbEI\ndZliWRkRMtzrHOJIhrmJ2A1J7iOrirbbwillwjjNVUWPf3IJ3M12S9pEewooaeO2\nizNTERcG9HzAacbVRn2Y2SWIyT/18QIDAQABo4GnMIGkMB0GA1UdDgQWBBT/LbE4\n9rWf288N6sJA5BRb6FJIGDB1BgNVHSMEbjBsgBT/LbE49rWf288N6sJA5BRb6FJI\nGKFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV\nBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAMHAwfXZ5/PWMAwGA1UdEwQF\nMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHHFwl0tH0quUYZYO0dZYt4R7SJ0pCm2\n2satiyzHl4OnXcHDpekAo7/a09c6Lz6AU83cKy/+x3/djYHXWba7HpEu0dR3ugQP\nMlr4zrhd9xKZ0KZKiYmtJH+ak4OM4L3FbT0owUZPyjLSlhMtJVcoRp5CJsjAMBUG\nSvD8RX+T01wzox/Qb+lnnNnOlaWpqu8eoOenybxKp1a9ULzIVvN/LAcc+14vioFq\n2swRWtmocBAs8QR9n4uvbpiYvS8eYueDCWMM4fvFfBhaDZ3N9IbtySh3SpFdQDhw\nYbjM2rxXiyLGxB4Bol7QTv4zHif7Zt89FReT/NBy4rzaskDJY5L6xmY=\n-----END CERTIFICATE-----\n",
+				"cert_uploaded_on": "2019-10-28T18:11:23.37411Z",
+				"cert_updated_at": "2100-01-01T05:20:00Z",
+				"expires_on": "2100-01-01T05:20:00Z"
+			  }
+			]
+		  }`)
+	}
+	mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/origin_tls_client_auth/hostnames", handler)
+	createdAt, _ := time.Parse(time.RFC3339, "2100-01-01T05:20:00Z")
+	updatedAt, _ := time.Parse(time.RFC3339, "2100-01-01T05:20:00Z")
+	certUploadedOn, _ := time.Parse(time.RFC3339, "2019-10-28T18:11:23.37411Z")
+	certUpdatedAt, _ := time.Parse(time.RFC3339, "2100-01-01T05:20:00Z")
+	expiresOn, _ := time.Parse(time.RFC3339, "2100-01-01T05:20:00Z")
+
+	want := []PerHostnameAuthenticatedOriginPullsDetails{
+		{
+			Hostname:       "app.example.com",
+			CertID:         "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60",
+			Enabled:        true,
+			Status:         "active",
+			CreatedAt:      createdAt,
+			UpdatedAt:      updatedAt,
+			CertStatus:     "active",
+			Issuer:         "GlobalSign",
+			Signature:      "SHA256WithRSA",
+			SerialNumber:   "6743787633689793699141714808227354901",
+			Certificate:    "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIJAMHAwfXZ5/PWMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\nBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX\naWRnaXRzIFB0eSBMdGQwHhcNMTYwODI0MTY0MzAxWhcNMTYxMTIyMTY0MzAxWjBF\nMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50\nZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAwQHoetcl9+5ikGzV6cMzWtWPJHqXT3wpbEkRU9Yz7lgvddmGdtcGbg/1\nCGZu0jJGkMoppoUo4c3dts3iwqRYmBikUP77wwY2QGmDZw2FvkJCJlKnabIRuGvB\nKwzESIXgKk2016aTP6/dAjEHyo6SeoK8lkIySUvK0fyOVlsiEsCmOpidtnKX/a+5\n0GjB79CJH4ER2lLVZnhePFR/zUOyPxZQQ4naHf7yu/b5jhO0f8fwt+pyFxIXjbEI\ndZliWRkRMtzrHOJIhrmJ2A1J7iOrirbbwillwjjNVUWPf3IJ3M12S9pEewooaeO2\nizNTERcG9HzAacbVRn2Y2SWIyT/18QIDAQABo4GnMIGkMB0GA1UdDgQWBBT/LbE4\n9rWf288N6sJA5BRb6FJIGDB1BgNVHSMEbjBsgBT/LbE49rWf288N6sJA5BRb6FJI\nGKFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV\nBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAMHAwfXZ5/PWMAwGA1UdEwQF\nMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHHFwl0tH0quUYZYO0dZYt4R7SJ0pCm2\n2satiyzHl4OnXcHDpekAo7/a09c6Lz6AU83cKy/+x3/djYHXWba7HpEu0dR3ugQP\nMlr4zrhd9xKZ0KZKiYmtJH+ak4OM4L3FbT0owUZPyjLSlhMtJVcoRp5CJsjAMBUG\nSvD8RX+T01wzox/Qb+lnnNnOlaWpqu8eoOenybxKp1a9ULzIVvN/LAcc+14vioFq\n2swRWtmocBAs8QR9n4uvbpiYvS8eYueDCWMM4fvFfBhaDZ3N9IbtySh3SpFdQDhw\nYbjM2rxXiyLGxB4Bol7QTv4zHif7Zt89FReT/NBy4rzaskDJY5L6xmY=\n-----END CERTIFICATE-----\n",
+			CertUploadedOn: certUploadedOn,
+			CertUpdatedAt:  certUpdatedAt,
+			ExpiresOn:      expiresOn,
+		},
+	}
+
+	config := []PerHostnameAuthenticatedOriginPullsConfig{
+		{
+			Hostname: "app.example.com",
+			CertID:   "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60",
+			Enabled:  nil,
 		},
 	}
 	actual, err := client.EditPerHostnameAuthenticatedOriginPullsConfig(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353", config)