diff --git a/tailscale/client.go b/tailscale/client.go index fd77eec..85e466a 100644 --- a/tailscale/client.go +++ b/tailscale/client.go @@ -441,7 +441,14 @@ func (c *Client) ValidateACL(ctx context.Context, acl ACL) error { return err } - return c.performRequest(req, nil) + var response APIError + if err := c.performRequest(req, &response); err != nil { + return err + } + if response.Message != "" { + return fmt.Errorf("ACL validation failed: %s; %v", response.Message, response.Data) + } + return nil } type DNSPreferences struct { diff --git a/tailscale/client_test.go b/tailscale/client_test.go index 9b97d1c..1569d45 100644 --- a/tailscale/client_test.go +++ b/tailscale/client_test.go @@ -950,7 +950,36 @@ func TestClient_ValidateACL(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, server.ResponseBody, acl) assert.EqualValues(t, http.MethodPost, server.Method) + assert.EqualValues(t, "application/json", server.Header.Get("Content-Type")) assert.EqualValues(t, "/api/v2/tailnet/example.com/acl/validate", server.Path) + + tests := []struct { + name string + responseCode int + responseBody any + wantErr string + }{ + { + name: "403_response", + responseCode: 403, + responseBody: tailscale.APIError{Message: "access denied"}, + wantErr: "access denied", + }, + { + name: "200_response_with_error", + responseCode: 200, + responseBody: tailscale.APIError{Message: "validation failed"}, + wantErr: "validation failed", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server.ResponseCode = tt.responseCode + server.ResponseBody = tt.responseBody + err := client.ValidateACL(context.Background(), acl) + assert.ErrorContains(t, err, tt.wantErr) + }) + } } func TestClient_UserAgent(t *testing.T) {