From 1ea644bca9ccbeaec648b925934e544feaf2aac2 Mon Sep 17 00:00:00 2001 From: vasil Date: Thu, 3 Aug 2023 17:44:08 -0500 Subject: [PATCH 1/4] add per-hostname tls settings api and tests --- per_hostname_tls_settings.go | 117 +++++++++++++++++ per_hostname_tls_settings_test.go | 202 ++++++++++++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 per_hostname_tls_settings.go create mode 100644 per_hostname_tls_settings_test.go diff --git a/per_hostname_tls_settings.go b/per_hostname_tls_settings.go new file mode 100644 index 00000000000..1cf884b459d --- /dev/null +++ b/per_hostname_tls_settings.go @@ -0,0 +1,117 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "time" +) + +// HostnameTLSSetting represents the metadata for a user-created tls setting. +type HostnameTLSSetting struct { + Hostname string `json:"hostname"` + Value interface{} `json:"value"` + Status string `json:"status"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// HostnameTLSSettingResponse represents the response from the PUT and DELETE endpoints for per-hostname tls settings. +type HostnameTLSSettingResponse struct { + Response + Result HostnameTLSSetting `json:"result"` +} + +// HostnameTLSSettingsResponse represents the response from the retrieval endpoint for per-hostname tls settings. +type HostnameTLSSettingsResponse struct { + Response + Result []HostnameTLSSetting `json:"result"` + ResultInfo `json:"result_info"` +} + +// EditHostnameTLSSettingParams represents the data related to the per-hostname tls setting being edited. +type EditHostnameTLSSettingParams struct { + Value interface{} `json:"value"` +} + +type ListHostnameTLSSettingsParams struct { + PaginationOptions + Limit int `url:"limit,omitempty"` + Offset int `url:"offset,omitempty"` + Hostname []string `url:"hostname,omitempty"` +} + +var ( + ErrMissingHostnameTLSSettingName = errors.New("tls setting name required but missing") +) + +// ListHostnameTLSSettings returns a list of all user-created tls setting values for the specified setting and hostnames. +// +// API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-list +func (api *API) ListHostnameTLSSettings(ctx context.Context, rc *ResourceContainer, setting string, params ListHostnameTLSSettingsParams) ([]HostnameTLSSetting, ResultInfo, error) { + if rc.Identifier == "" { + return []HostnameTLSSetting{}, ResultInfo{}, ErrMissingZoneID + } + if setting == "" { + return []HostnameTLSSetting{}, ResultInfo{}, ErrMissingHostnameTLSSettingName + } + + uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s", rc.Identifier, setting) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) + if err != nil { + return []HostnameTLSSetting{}, ResultInfo{}, err + } + var r HostnameTLSSettingsResponse + if err := json.Unmarshal(res, &r); err != nil { + return []HostnameTLSSetting{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, r.ResultInfo, err +} + +// EditHostnameTLSSetting will update the per-hostname tls setting for the specified hostname. +// +// API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-put +func (api *API) EditHostnameTLSSetting(ctx context.Context, rc *ResourceContainer, setting, hostname string, params EditHostnameTLSSettingParams) (HostnameTLSSetting, error) { + if rc.Identifier == "" { + return HostnameTLSSetting{}, ErrMissingZoneID + } + if setting == "" { + return HostnameTLSSetting{}, ErrMissingHostnameTLSSettingName + } + + uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s/%s", rc.Identifier, setting, hostname) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return HostnameTLSSetting{}, err + } + var r HostnameTLSSettingResponse + if err := json.Unmarshal(res, &r); err != nil { + return HostnameTLSSetting{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// DeleteHostnameTLSSetting will delete the specified per-hostname tls setting. +// +// API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-delete +func (api *API) DeleteHostnameTLSSetting(ctx context.Context, rc *ResourceContainer, setting, hostname string) (HostnameTLSSetting, error) { + if rc.Identifier == "" { + return HostnameTLSSetting{}, ErrMissingZoneID + } + if setting == "" { + return HostnameTLSSetting{}, ErrMissingHostnameTLSSettingName + } + + uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s/%s", rc.Identifier, setting, hostname) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return HostnameTLSSetting{}, err + } + var r HostnameTLSSettingResponse + if err := json.Unmarshal(res, &r); err != nil { + return HostnameTLSSetting{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} diff --git a/per_hostname_tls_settings_test.go b/per_hostname_tls_settings_test.go new file mode 100644 index 00000000000..cccbaaf47c9 --- /dev/null +++ b/per_hostname_tls_settings_test.go @@ -0,0 +1,202 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestListHostnameTLSSettingsMinTLSVersion(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", + "value": "1.2", + "status": "active", + "created_at": "2023-07-26T21:12:55.56942Z", + "updated_at": "2023-07-31T22:06:44.739794Z" + } + ], + "result_info": { + "page": 1, + "per_page": 50, + "count": 1, + "total_count": 1, + "total_pages": 1 + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/min_tls_version", handler) + createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") + updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") + want := []HostnameTLSSetting{ + { + Hostname: "app.example.com", + Value: "1.2", + Status: "active", + CreatedAt: createdAt, + UpdatedAt: updatedAt, + }, + } + + actual, _, err := client.ListHostnameTLSSettings(context.Background(), ZoneIdentifier(testZoneID), "min_tls_version", ListHostnameTLSSettingsParams{}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListHostnameTLSSettingsCiphers(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", + "value": [ + "AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256" + ], + "status": "active", + "created_at": "2023-07-26T21:12:55.56942Z", + "updated_at": "2023-07-31T22:06:44.739794Z" + } + ], + "result_info": { + "page": 1, + "per_page": 50, + "count": 1, + "total_count": 1, + "total_pages": 1 + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/ciphers", handler) + createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") + updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") + + strs := []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"} + cipherssuites := make([]interface{}, len(strs)) + for i, s := range strs { + cipherssuites[i] = s + } + want := []HostnameTLSSetting{ + { + Hostname: "app.example.com", + Value: cipherssuites, + Status: "active", + CreatedAt: createdAt, + UpdatedAt: updatedAt, + }, + } + + actual, _, err := client.ListHostnameTLSSettings(context.Background(), ZoneIdentifier(testZoneID), "ciphers", ListHostnameTLSSettingsParams{}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestEditHostnameTLSSetting(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", + "value": [ + "AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256" + ], + "status": "active", + "created_at": "2023-07-26T21:12:55.56942Z", + "updated_at": "2023-07-31T22:06:44.739794Z" + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/ciphers/app.example.com", handler) + createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") + updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") + + strs := []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"} + cipherssuites := make([]interface{}, len(strs)) + for i, s := range strs { + cipherssuites[i] = s + } + want := HostnameTLSSetting{ + Hostname: "app.example.com", + Value: cipherssuites, + Status: "active", + CreatedAt: createdAt, + UpdatedAt: updatedAt, + } + + params := EditHostnameTLSSettingParams{ + Value: []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"}, + } + actual, err := client.EditHostnameTLSSetting(context.Background(), ZoneIdentifier(testZoneID), "ciphers", "app.example.com", params) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteHostnameTLSSetting(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", + "value": "", + "status": "active", + "created_at": "2023-07-26T21:12:55.56942Z", + "updated_at": "2023-07-31T22:06:44.739794Z" + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/ciphers/app.example.com", handler) + createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") + updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") + want := HostnameTLSSetting{ + Hostname: "app.example.com", + Value: "", + Status: "active", + CreatedAt: createdAt, + UpdatedAt: updatedAt, + } + + actual, err := client.DeleteHostnameTLSSetting(context.Background(), ZoneIdentifier(testZoneID), "ciphers", "app.example.com") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} From b5942540c62dbb3de36ab3a42f4c235debf9988f Mon Sep 17 00:00:00 2001 From: vasil Date: Wed, 9 Aug 2023 14:40:21 -0500 Subject: [PATCH 2/4] updated per-hostname tls settings implementation - split ciphers from the rest of the tls settings due to unique response structure --- per_hostname_tls_settings.go | 173 ++++++++++++++++++++++++++---- per_hostname_tls_settings_test.go | 135 +++++++++++++++++------ 2 files changed, 256 insertions(+), 52 deletions(-) diff --git a/per_hostname_tls_settings.go b/per_hostname_tls_settings.go index 1cf884b459d..0138be12f1b 100644 --- a/per_hostname_tls_settings.go +++ b/per_hostname_tls_settings.go @@ -11,11 +11,11 @@ import ( // HostnameTLSSetting represents the metadata for a user-created tls setting. type HostnameTLSSetting struct { - Hostname string `json:"hostname"` - Value interface{} `json:"value"` - Status string `json:"status"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + Hostname string `json:"hostname"` + Value string `json:"value"` + Status string `json:"status"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` } // HostnameTLSSettingResponse represents the response from the PUT and DELETE endpoints for per-hostname tls settings. @@ -31,18 +31,28 @@ type HostnameTLSSettingsResponse struct { ResultInfo `json:"result_info"` } -// EditHostnameTLSSettingParams represents the data related to the per-hostname tls setting being edited. -type EditHostnameTLSSettingParams struct { - Value interface{} `json:"value"` -} - +// ListHostnameTLSSettingsParams represents the data related to per-hostname tls settings being retrieved. type ListHostnameTLSSettingsParams struct { + Setting string PaginationOptions Limit int `url:"limit,omitempty"` Offset int `url:"offset,omitempty"` Hostname []string `url:"hostname,omitempty"` } +// UpdateHostnameTLSSettingParams represents the data related to the per-hostname tls setting being updated. +type UpdateHostnameTLSSettingParams struct { + Setting string + Hostname string + Value string `json:"value"` +} + +// DeleteHostnameTLSSettingParams represents the data related to the per-hostname tls setting being deleted. +type DeleteHostnameTLSSettingParams struct { + Setting string + Hostname string +} + var ( ErrMissingHostnameTLSSettingName = errors.New("tls setting name required but missing") ) @@ -50,15 +60,15 @@ var ( // ListHostnameTLSSettings returns a list of all user-created tls setting values for the specified setting and hostnames. // // API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-list -func (api *API) ListHostnameTLSSettings(ctx context.Context, rc *ResourceContainer, setting string, params ListHostnameTLSSettingsParams) ([]HostnameTLSSetting, ResultInfo, error) { +func (api *API) ListHostnameTLSSettings(ctx context.Context, rc *ResourceContainer, params ListHostnameTLSSettingsParams) ([]HostnameTLSSetting, ResultInfo, error) { if rc.Identifier == "" { return []HostnameTLSSetting{}, ResultInfo{}, ErrMissingZoneID } - if setting == "" { + if params.Setting == "" { return []HostnameTLSSetting{}, ResultInfo{}, ErrMissingHostnameTLSSettingName } - uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s", rc.Identifier, setting) + uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s", rc.Identifier, params.Setting) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) if err != nil { return []HostnameTLSSetting{}, ResultInfo{}, err @@ -70,18 +80,21 @@ func (api *API) ListHostnameTLSSettings(ctx context.Context, rc *ResourceContain return r.Result, r.ResultInfo, err } -// EditHostnameTLSSetting will update the per-hostname tls setting for the specified hostname. +// UpdateHostnameTLSSetting will update the per-hostname tls setting for the specified hostname. // // API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-put -func (api *API) EditHostnameTLSSetting(ctx context.Context, rc *ResourceContainer, setting, hostname string, params EditHostnameTLSSettingParams) (HostnameTLSSetting, error) { +func (api *API) UpdateHostnameTLSSetting(ctx context.Context, rc *ResourceContainer, params UpdateHostnameTLSSettingParams) (HostnameTLSSetting, error) { if rc.Identifier == "" { return HostnameTLSSetting{}, ErrMissingZoneID } - if setting == "" { + if params.Setting == "" { return HostnameTLSSetting{}, ErrMissingHostnameTLSSettingName } + if params.Hostname == "" { + return HostnameTLSSetting{}, ErrMissingHostname + } - uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s/%s", rc.Identifier, setting, hostname) + uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s/%s", rc.Identifier, params.Setting, params.Hostname) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return HostnameTLSSetting{}, err @@ -96,15 +109,18 @@ func (api *API) EditHostnameTLSSetting(ctx context.Context, rc *ResourceContaine // DeleteHostnameTLSSetting will delete the specified per-hostname tls setting. // // API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-delete -func (api *API) DeleteHostnameTLSSetting(ctx context.Context, rc *ResourceContainer, setting, hostname string) (HostnameTLSSetting, error) { +func (api *API) DeleteHostnameTLSSetting(ctx context.Context, rc *ResourceContainer, params DeleteHostnameTLSSettingParams) (HostnameTLSSetting, error) { if rc.Identifier == "" { return HostnameTLSSetting{}, ErrMissingZoneID } - if setting == "" { + if params.Setting == "" { return HostnameTLSSetting{}, ErrMissingHostnameTLSSettingName } + if params.Hostname == "" { + return HostnameTLSSetting{}, ErrMissingHostname + } - uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s/%s", rc.Identifier, setting, hostname) + uri := fmt.Sprintf("/zones/%s/hostnames/settings/%s/%s", rc.Identifier, params.Setting, params.Hostname) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return HostnameTLSSetting{}, err @@ -115,3 +131,120 @@ func (api *API) DeleteHostnameTLSSetting(ctx context.Context, rc *ResourceContai } return r.Result, nil } + +// HostnameTLSSettingCiphers represents the metadata for a user-created ciphers tls setting. +type HostnameTLSSettingCiphers struct { + Hostname string `json:"hostname"` + Value []string `json:"value"` + Status string `json:"status"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// HostnameTLSSettingCiphersResponse represents the response from the PUT and DELETE endpoints for per-hostname ciphers tls settings. +type HostnameTLSSettingCiphersResponse struct { + Response + Result HostnameTLSSettingCiphers `json:"result"` +} + +// HostnameTLSSettingsCiphersResponse represents the response from the retrieval endpoint for per-hostname ciphers tls settings. +type HostnameTLSSettingsCiphersResponse struct { + Response + Result []HostnameTLSSettingCiphers `json:"result"` + ResultInfo `json:"result_info"` +} + +// ListHostnameTLSSettingsCiphersParams represents the data related to per-hostname ciphers tls settings being retrieved +type ListHostnameTLSSettingsCiphersParams struct { + PaginationOptions + Limit int `url:"limit,omitempty"` + Offset int `url:"offset,omitempty"` + Hostname []string `url:"hostname,omitempty"` +} + +// UpdateHostnameTLSSettingCiphersParams represents the data related to the per-hostname ciphers tls setting being updated. +type UpdateHostnameTLSSettingCiphersParams struct { + Hostname string + Value []string `json:"value"` +} + +// DeleteHostnameTLSSettingCiphersParams represents the data related to the per-hostname ciphers tls setting being deleted. +type DeleteHostnameTLSSettingCiphersParams struct { + Hostname string +} + +// ListHostnameTLSSettingsCiphers returns a list of all user-created tls setting ciphers values for the specified setting and hostnames. +// Ciphers functions are separate due to the API returning a list of strings as the value, rather than a string (as is the case for the other tls settings). +// +// API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-list +func (api *API) ListHostnameTLSSettingsCiphers(ctx context.Context, rc *ResourceContainer, params ListHostnameTLSSettingsCiphersParams) ([]HostnameTLSSettingCiphers, ResultInfo, error) { + if rc.Identifier == "" { + return []HostnameTLSSettingCiphers{}, ResultInfo{}, ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/hostnames/settings/ciphers", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) + if err != nil { + return []HostnameTLSSettingCiphers{}, ResultInfo{}, err + } + var r HostnameTLSSettingsCiphersResponse + if err := json.Unmarshal(res, &r); err != nil { + return []HostnameTLSSettingCiphers{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, r.ResultInfo, err +} + +// UpdateHostnameTLSSettingCiphers will update the per-hostname ciphers tls setting for the specified hostname. +// Ciphers functions are separate due to the API returning a list of strings as the value, rather than a string (as is the case for the other tls settings). +// +// API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-put +func (api *API) UpdateHostnameTLSSettingCiphers(ctx context.Context, rc *ResourceContainer, params UpdateHostnameTLSSettingCiphersParams) (HostnameTLSSettingCiphers, error) { + if rc.Identifier == "" { + return HostnameTLSSettingCiphers{}, ErrMissingZoneID + } + if params.Hostname == "" { + return HostnameTLSSettingCiphers{}, ErrMissingHostname + } + + uri := fmt.Sprintf("/zones/%s/hostnames/settings/ciphers/%s", rc.Identifier, params.Hostname) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return HostnameTLSSettingCiphers{}, err + } + var r HostnameTLSSettingCiphersResponse + if err := json.Unmarshal(res, &r); err != nil { + return HostnameTLSSettingCiphers{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// DeleteHostnameTLSSettingCiphers will delete the specified per-hostname ciphers tls setting value. +// Ciphers functions are separate due to the API returning a list of strings as the value, rather than a string (as is the case for the other tls settings). +// +// API reference: https://developers.cloudflare.com/api/operations/per-hostname-tls-settings-delete +func (api *API) DeleteHostnameTLSSettingCiphers(ctx context.Context, rc *ResourceContainer, params DeleteHostnameTLSSettingCiphersParams) (HostnameTLSSettingCiphers, error) { + if rc.Identifier == "" { + return HostnameTLSSettingCiphers{}, ErrMissingZoneID + } + if params.Hostname == "" { + return HostnameTLSSettingCiphers{}, ErrMissingHostname + } + + uri := fmt.Sprintf("/zones/%s/hostnames/settings/ciphers/%s", rc.Identifier, params.Hostname) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return HostnameTLSSettingCiphers{}, err + } + // Unmarshal into HostnameTLSSettingResponse first because the API returns an empty string + var r HostnameTLSSettingResponse + if err := json.Unmarshal(res, &r); err != nil { + return HostnameTLSSettingCiphers{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return HostnameTLSSettingCiphers{ + Hostname: r.Result.Hostname, + Value: []string{}, + Status: r.Result.Status, + CreatedAt: r.Result.CreatedAt, + UpdatedAt: r.Result.UpdatedAt, + }, nil +} diff --git a/per_hostname_tls_settings_test.go b/per_hostname_tls_settings_test.go index cccbaaf47c9..b857d2eb6f1 100644 --- a/per_hostname_tls_settings_test.go +++ b/per_hostname_tls_settings_test.go @@ -47,12 +47,92 @@ func TestListHostnameTLSSettingsMinTLSVersion(t *testing.T) { Hostname: "app.example.com", Value: "1.2", Status: "active", - CreatedAt: createdAt, - UpdatedAt: updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, }, } - actual, _, err := client.ListHostnameTLSSettings(context.Background(), ZoneIdentifier(testZoneID), "min_tls_version", ListHostnameTLSSettingsParams{}) + actual, _, err := client.ListHostnameTLSSettings(context.Background(), ZoneIdentifier(testZoneID), ListHostnameTLSSettingsParams{Setting: "min_tls_version"}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateHostnameTLSSettingMinTLSVersion(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", + "value": "1.2", + "status": "active", + "created_at": "2023-07-26T21:12:55.56942Z", + "updated_at": "2023-07-31T22:06:44.739794Z" + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/min_tls_version/app.example.com", handler) + createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") + updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") + + want := HostnameTLSSetting{ + Hostname: "app.example.com", + Value: "1.2", + Status: "active", + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + } + + params := UpdateHostnameTLSSettingParams{ + Setting: "min_tls_version", + Hostname: "app.example.com", + Value: "1.2", + } + actual, err := client.UpdateHostnameTLSSetting(context.Background(), ZoneIdentifier(testZoneID), params) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteHostnameTLSSettingMinTLSVersion(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", + "value": "", + "status": "active", + "created_at": "2023-07-26T21:12:55.56942Z", + "updated_at": "2023-07-31T22:06:44.739794Z" + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/min_tls_version/app.example.com", handler) + createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") + updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") + want := HostnameTLSSetting{ + Hostname: "app.example.com", + Value: "", + Status: "active", + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + } + + actual, err := client.DeleteHostnameTLSSetting(context.Background(), ZoneIdentifier(testZoneID), DeleteHostnameTLSSettingParams{Setting: "min_tls_version", Hostname: "app.example.com"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -94,28 +174,23 @@ func TestListHostnameTLSSettingsCiphers(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") - strs := []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"} - cipherssuites := make([]interface{}, len(strs)) - for i, s := range strs { - cipherssuites[i] = s - } - want := []HostnameTLSSetting{ + want := []HostnameTLSSettingCiphers{ { Hostname: "app.example.com", - Value: cipherssuites, + Value: []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"}, Status: "active", - CreatedAt: createdAt, - UpdatedAt: updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, }, } - actual, _, err := client.ListHostnameTLSSettings(context.Background(), ZoneIdentifier(testZoneID), "ciphers", ListHostnameTLSSettingsParams{}) + actual, _, err := client.ListHostnameTLSSettingsCiphers(context.Background(), ZoneIdentifier(testZoneID), ListHostnameTLSSettingsCiphersParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestEditHostnameTLSSetting(t *testing.T) { +func TestUpdateHostnameTLSSettingCiphers(t *testing.T) { setup() defer teardown() @@ -142,29 +217,25 @@ func TestEditHostnameTLSSetting(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") - strs := []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"} - cipherssuites := make([]interface{}, len(strs)) - for i, s := range strs { - cipherssuites[i] = s - } - want := HostnameTLSSetting{ + want := HostnameTLSSettingCiphers{ Hostname: "app.example.com", - Value: cipherssuites, + Value: []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"}, Status: "active", - CreatedAt: createdAt, - UpdatedAt: updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, } - params := EditHostnameTLSSettingParams{ - Value: []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"}, + params := UpdateHostnameTLSSettingCiphersParams{ + Hostname: "app.example.com", + Value: []string{"AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"}, } - actual, err := client.EditHostnameTLSSetting(context.Background(), ZoneIdentifier(testZoneID), "ciphers", "app.example.com", params) + actual, err := client.UpdateHostnameTLSSettingCiphers(context.Background(), ZoneIdentifier(testZoneID), params) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestDeleteHostnameTLSSetting(t *testing.T) { +func TestDeleteHostnameTLSSettingCiphers(t *testing.T) { setup() defer teardown() @@ -187,15 +258,15 @@ func TestDeleteHostnameTLSSetting(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/hostnames/settings/ciphers/app.example.com", handler) createdAt, _ := time.Parse(time.RFC3339, "2023-07-26T21:12:55.56942Z") updatedAt, _ := time.Parse(time.RFC3339, "2023-07-31T22:06:44.739794Z") - want := HostnameTLSSetting{ + want := HostnameTLSSettingCiphers{ Hostname: "app.example.com", - Value: "", + Value: []string{}, Status: "active", - CreatedAt: createdAt, - UpdatedAt: updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, } - actual, err := client.DeleteHostnameTLSSetting(context.Background(), ZoneIdentifier(testZoneID), "ciphers", "app.example.com") + actual, err := client.DeleteHostnameTLSSettingCiphers(context.Background(), ZoneIdentifier(testZoneID), DeleteHostnameTLSSettingCiphersParams{Hostname: "app.example.com"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } From 61b5ed13d49ce441632f9eebd0224c0eca7fd11c Mon Sep 17 00:00:00 2001 From: vasil Date: Wed, 9 Aug 2023 15:27:26 -0500 Subject: [PATCH 3/4] added period to the end of HostnameTLSSettingCiphersResponse top level comment --- per_hostname_tls_settings.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/per_hostname_tls_settings.go b/per_hostname_tls_settings.go index 0138be12f1b..26beec88423 100644 --- a/per_hostname_tls_settings.go +++ b/per_hostname_tls_settings.go @@ -154,7 +154,7 @@ type HostnameTLSSettingsCiphersResponse struct { ResultInfo `json:"result_info"` } -// ListHostnameTLSSettingsCiphersParams represents the data related to per-hostname ciphers tls settings being retrieved +// ListHostnameTLSSettingsCiphersParams represents the data related to per-hostname ciphers tls settings being retrieved. type ListHostnameTLSSettingsCiphersParams struct { PaginationOptions Limit int `url:"limit,omitempty"` From fb3ee8990ba5c0ed4299d1953560a81534e7a7d3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 10 Aug 2023 14:27:02 +1000 Subject: [PATCH 4/4] add changelog --- .changelog/1356.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1356.txt diff --git a/.changelog/1356.txt b/.changelog/1356.txt new file mode 100644 index 00000000000..dd94e72a35c --- /dev/null +++ b/.changelog/1356.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +per_hostname_tls_settings: add support for managing hostname level TLS settings +```