Repository: cloudflare/cloudflare-go
Pull request #1419 (2023-10-09 18:27:07)

Add support for setting ssh encryption key in Zero Trust
## Description

We currently allow users to set a public key that can used to encrypt their SSH logs in the UI. We are adding support for that key in cloudflare-go and terraform. 

## Has your change been tested?

Unit tests

## Screenshots (if appropriate):

This is the setting we are adding support for. 

<img width="1051" alt="image" src="https://github.com/cloudflare/cloudflare-go/assets/2245471/ff523fec-b327-4b31-8972-ae65c8ca33e4">


## Types of changes

What sort of change does your code introduce/modify?

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.
- [ ] 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/1419.txt b/.changelog/1419.txt
new file mode 100644
index 000000000..a17415283
--- /dev/null
+++ b/.changelog/1419.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+teams: Add `audit_ssh_settings` endpoints
+```
diff --git a/teams_audit_ssh_settings.go b/teams_audit_ssh_settings.go
new file mode 100644
index 000000000..a4ec1e320
--- /dev/null
+++ b/teams_audit_ssh_settings.go
@@ -0,0 +1,86 @@
+package cloudflare
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/goccy/go-json"
+)
+
+// TeamsList represents a Teams List.
+type AuditSSHSettings struct {
+	PublicKey string     `json:"public_key"`
+	SeedUUID  string     `json:"seed_id"`
+	CreatedAt *time.Time `json:"created_at"`
+	UpdatedAt *time.Time `json:"updated_at"`
+}
+
+type AuditSSHSettingsResponse struct {
+	Result AuditSSHSettings `json:"result"`
+	Response
+	ResultInfo `json:"result_info"`
+}
+
+type GetAuditSSHSettingsParams struct{}
+
+type UpdateAuditSSHSettingsParams struct {
+	PublicKey string `json:"public_key"`
+}
+
+// GetAuditSSHSettings returns the accounts zt audit ssh settings.
+//
+// API reference: https://api.cloudflare.com/#zero-trust-get-audit-ssh-settings
+func (api *API) GetAuditSSHSettings(ctx context.Context, rc *ResourceContainer, params GetAuditSSHSettingsParams) (AuditSSHSettings, ResultInfo, error) {
+	if rc.Level != AccountRouteLevel {
+		return AuditSSHSettings{}, ResultInfo{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level)
+	}
+
+	uri := fmt.Sprintf("/%s/%s/gateway/audit_ssh_settings", rc.Level, rc.Identifier)
+
+	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+	if err != nil {
+		return AuditSSHSettings{}, ResultInfo{}, err
+	}
+
+	var auditSSHSettingsResponse AuditSSHSettingsResponse
+	err = json.Unmarshal(res, &auditSSHSettingsResponse)
+	if err != nil {
+		return AuditSSHSettings{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return auditSSHSettingsResponse.Result, auditSSHSettingsResponse.ResultInfo, nil
+}
+
+// UpdateAuditSSHSettings updates an existing zt audit ssh setting.
+//
+// API reference: https://api.cloudflare.com/#zero-trust-update-audit-ssh-settings
+func (api *API) UpdateAuditSSHSettings(ctx context.Context, rc *ResourceContainer, params UpdateAuditSSHSettingsParams) (AuditSSHSettings, error) {
+	if rc.Level != AccountRouteLevel {
+		return AuditSSHSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level)
+	}
+
+	if rc.Identifier == "" {
+		return AuditSSHSettings{}, ErrMissingAccountID
+	}
+
+	uri := fmt.Sprintf(
+		"/%s/%s/gateway/audit_ssh_settings",
+		rc.Level,
+		rc.Identifier,
+	)
+
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
+	if err != nil {
+		return AuditSSHSettings{}, err
+	}
+
+	var auditSSHSettingsResponse AuditSSHSettingsResponse
+	err = json.Unmarshal(res, &auditSSHSettingsResponse)
+	if err != nil {
+		return AuditSSHSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return auditSSHSettingsResponse.Result, nil
+}


Test patch:
diff --git a/teams_audit_ssh_settings_test.go b/teams_audit_ssh_settings_test.go
new file mode 100644
index 000000000..934f98099
--- /dev/null
+++ b/teams_audit_ssh_settings_test.go
@@ -0,0 +1,91 @@
+package cloudflare
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetAuditSSHSettings(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": {
+				"public_key": "1pyl6I1tL7xfJuFYVzXlUW8uXXlpxegHXBzGCBKaSFA=",
+				"seed_id": "f1f968a9-83e7-401a-8abc-e0efe128425c",
+				"created_at": "2014-01-01T05:20:00.12345Z",
+				"updated_at": "2014-01-01T05:20:00.12345Z"
+			}
+		}
+		`)
+	}
+
+	createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
+	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
+
+	want := AuditSSHSettings{
+		PublicKey: "1pyl6I1tL7xfJuFYVzXlUW8uXXlpxegHXBzGCBKaSFA=",
+		SeedUUID:  "f1f968a9-83e7-401a-8abc-e0efe128425c",
+		CreatedAt: &createdAt,
+		UpdatedAt: &updatedAt,
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/gateway/audit_ssh_settings", handler)
+
+	actual, _, err := client.GetAuditSSHSettings(context.Background(), AccountIdentifier(testAccountID), GetAuditSSHSettingsParams{})
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+}
+
+func TestUpdateAuditSSHSettings(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": {
+				"public_key": "updated1tL7xfJuFYVzXlUW8uXXlpxegHXBzGCBKaSFA=",
+				"seed_id": "f1f968a9-83e7-401a-8abc-e0efe128425c",
+				"created_at": "2014-01-01T05:20:00.12345Z",
+				"updated_at": "2014-01-01T05:20:00.12345Z"
+			}
+		}
+		`)
+	}
+
+	createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
+	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
+
+	want := AuditSSHSettings{
+		PublicKey: "updated1tL7xfJuFYVzXlUW8uXXlpxegHXBzGCBKaSFA=",
+		SeedUUID:  "f1f968a9-83e7-401a-8abc-e0efe128425c",
+		CreatedAt: &createdAt,
+		UpdatedAt: &updatedAt,
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/gateway/audit_ssh_settings", handler)
+
+	actual, err := client.UpdateAuditSSHSettings(context.Background(), AccountIdentifier(testAccountID), UpdateAuditSSHSettingsParams{PublicKey: "updated1tL7xfJuFYVzXlUW8uXXlpxegHXBzGCBKaSFA="})
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+}