Skip to content

Commit

Permalink
tailscale: use V2 client for device authorization
Browse files Browse the repository at this point in the history
Updates tailscale/corp#21867

Signed-off-by: Percy Wegmann <percy@tailscale.com>
  • Loading branch information
oxtoacart committed Aug 2, 2024
1 parent 5d7e328 commit 07728ef
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 79 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/stretchr/testify v1.9.0
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
github.com/tailscale/tailscale-client-go v1.17.1-0.20240729175651-90a1e935cc19
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20240801195603-6096900af9df
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20240802162120-6b9dd0c993f7
golang.org/x/tools v0.23.0
tailscale.com v1.70.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29X
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8=
github.com/tailscale/tailscale-client-go v1.17.1-0.20240729175651-90a1e935cc19 h1:fRLv1yZH1ueL1cnpLhOnOymoBfMCIviCn0e0VkAjkK4=
github.com/tailscale/tailscale-client-go v1.17.1-0.20240729175651-90a1e935cc19/go.mod h1:jbwJyHniK3nyLttwcDTXnfdDQEnADvc4VMOP8hZWnR0=
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20240801195603-6096900af9df h1:XjHI0pFxhttM1nEn/WNGOO3wrJYEJSZarJm0i5WFXgY=
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20240801195603-6096900af9df/go.mod h1:i/MSgQ71kdyh1Wdp50XxrIgtsyO4uZ2SZSPd83lGKHM=
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20240802162120-6b9dd0c993f7 h1:+TDfp+C1iJfFA835NnP2yzrlwK1NneYFVoEG07bocmM=
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20240802162120-6b9dd0c993f7/go.mod h1:i/MSgQ71kdyh1Wdp50XxrIgtsyO4uZ2SZSPd83lGKHM=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
Expand Down
56 changes: 13 additions & 43 deletions tailscale/resource_device_authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/tailscale/tailscale-client-go/tailscale"
)

func resourceDeviceAuthorization() *schema.Resource {
Expand Down Expand Up @@ -35,41 +33,27 @@ func resourceDeviceAuthorization() *schema.Resource {
}

func resourceDeviceAuthorizationRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*Clients).V1
client := m.(*Clients).V2
deviceID := d.Id()

devices, err := client.Devices(ctx)
device, err := client.Devices().Get(ctx, deviceID)
if err != nil {
return diagnosticsError(err, "Failed to fetch devices")
}

var selected *tailscale.Device
for _, device := range devices {
if device.ID != deviceID {
continue
}

selected = &device
break
}

if selected == nil {
return diag.Errorf("Could not find device with id %s", deviceID)
return diagnosticsError(err, "Failed to fetch device")
}

d.SetId(selected.ID)
d.Set("device_id", selected.ID)
d.Set("authorized", selected.Authorized)
d.SetId(device.ID)
d.Set("device_id", device.ID)
d.Set("authorized", device.Authorized)
return nil
}

func resourceDeviceAuthorizationCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*Clients).V1
client := m.(*Clients).V2
deviceID := d.Get("device_id").(string)
authorized := d.Get("authorized").(bool)

if authorized {
if err := client.AuthorizeDevice(ctx, deviceID); err != nil {
if err := client.Devices().SetAuthorized(ctx, deviceID, true); err != nil {
return diagnosticsError(err, "Failed to authorize device")
}
}
Expand All @@ -79,36 +63,22 @@ func resourceDeviceAuthorizationCreate(ctx context.Context, d *schema.ResourceDa
}

func resourceDeviceAuthorizationUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*Clients).V1
client := m.(*Clients).V2
deviceID := d.Get("device_id").(string)

devices, err := client.Devices(ctx)
device, err := client.Devices().Get(ctx, deviceID)
if err != nil {
return diagnosticsError(err, "Failed to fetch devices")
}

var selected *tailscale.Device
for _, device := range devices {
if device.ID != deviceID {
continue
}

selected = &device
break
}

if selected == nil {
return diag.Errorf("Could not find device with id %s", deviceID)
return diagnosticsError(err, "Failed to fetch device")
}

// Currently, the Tailscale API only supports authorizing a device, but not un-authorizing one. So if the device
// data from the API states it is authorized then we can't do anything else here.
if selected.Authorized {
if device.Authorized {
d.Set("authorized", true)
return nil
}

if err = client.AuthorizeDevice(ctx, deviceID); err != nil {
if err = client.Devices().SetAuthorized(ctx, deviceID, true); err != nil {
return diagnosticsError(err, "Failed to authorize device")
}

Expand Down
47 changes: 14 additions & 33 deletions tailscale/resource_device_authorization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"

"github.com/tailscale/tailscale-client-go/tailscale"
tsclient "github.com/tailscale/tailscale-client-go/v2"
"github.com/tailscale/terraform-provider-tailscale/tailscale"
)

const testDeviceAuthorization = `
var testDeviceAuthorization = fmt.Sprintf(`
data "tailscale_device" "test_device" {
name = "%s"
}
resource "tailscale_device_authorization" "test_authorization" {
device_id = data.tailscale_device.test_device.id
authorized = true
}`
}`, os.Getenv("TAILSCALE_TEST_DEVICE_NAME"))

var expectedDeviceAuthorizationBasic = &tsclient.Device{
Authorized: true,
}

func TestAccTailscaleDeviceAuthorization_Basic(t *testing.T) {
resource.Test(t, resource.TestCase{
Expand Down Expand Up @@ -59,27 +64,15 @@ func testAccCheckDeviceAuthorized(resourceName string) resource.TestCheckFunc {
return fmt.Errorf("resource has no ID set")
}

client := testAccProvider.Meta().(*tailscale.Client)
client := testAccProvider.Meta().(*tailscale.Clients).V2
// Devices are not currently deauthorized when this resource is deleted,
// expect that the device both exists and is still authorized.
devices, err := client.Devices(context.Background())
device, err := client.Devices().Get(context.Background(), rs.Primary.ID)
if err != nil {
return err
}

var selected *tailscale.Device
for _, device := range devices {
if device.ID == rs.Primary.ID {
selected = &device
break
}
}

if selected == nil {
return fmt.Errorf("expected device with id %q to exist", rs.Primary.ID)
}

if selected.Authorized != true {
if device.Authorized != true {
return fmt.Errorf("device with id %q is not authorized", rs.Primary.ID)
}

Expand All @@ -88,7 +81,7 @@ func testAccCheckDeviceAuthorized(resourceName string) resource.TestCheckFunc {
}

func testAccCheckDeviceAuthorizationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*tailscale.Client)
client := testAccProvider.Meta().(*tailscale.Clients).V2

for _, rs := range s.RootModule().Resources {
if rs.Type != "tailscale_device_authorization" {
Expand All @@ -101,24 +94,12 @@ func testAccCheckDeviceAuthorizationDestroy(s *terraform.State) error {

// Devices are not currently deauthorized when this resource is deleted,
// expect that the device both exists and is still authorized.
devices, err := client.Devices(context.Background())
device, err := client.Devices().Get(context.Background(), rs.Primary.ID)
if err != nil {
return err
}

var selected *tailscale.Device
for _, device := range devices {
if device.ID == rs.Primary.ID {
selected = &device
break
}
}

if selected == nil {
return fmt.Errorf("expected device with id %q to exist", rs.Primary.ID)
}

if selected.Authorized != true {
if device.Authorized != true {
return fmt.Errorf("device with id %q is not authorized", rs.Primary.ID)
}
}
Expand Down

0 comments on commit 07728ef

Please sign in to comment.