diff --git a/docs/resources/acl.md b/docs/resources/acl.md index 21750aa7..eac7cdde 100644 --- a/docs/resources/acl.md +++ b/docs/resources/acl.md @@ -10,6 +10,8 @@ description: |- The acl resource allows you to configure a Tailscale ACL. See https://tailscale.com/kb/1018/acls for more information. Note that this resource will completely overwrite existing ACL contents for a given tailnet. +If tests are defined in the ACL (the top-level `tests` section), ACL validation will occur before creation and update operations are applied. + ## Example Usage ```terraform diff --git a/tailscale/resource_acl.go b/tailscale/resource_acl.go index 5009b52f..d923545e 100644 --- a/tailscale/resource_acl.go +++ b/tailscale/resource_acl.go @@ -93,6 +93,10 @@ func resourceACLCreate(ctx context.Context, d *schema.ResourceData, m interface{ return diagnosticsError(err, "Failed to unmarshal ACL") } + if err := runACLTests(ctx, client, d, acl); err != nil { + return err + } + // Setting the `ts-default` ETag will make this operation succeed only if // ACL contents has never been changed from its default value. if err := client.SetACL(ctx, acl, tailscale.WithETag("ts-default")); err != nil { @@ -123,6 +127,10 @@ func resourceACLUpdate(ctx context.Context, d *schema.ResourceData, m interface{ return diagnosticsError(err, "Failed to unmarshal ACL") } + if err := runACLTests(ctx, client, d, acl); err != nil { + return err + } + if err := client.SetACL(ctx, acl); err != nil { return diagnosticsError(err, "Failed to set ACL") } @@ -148,3 +156,16 @@ func unmarshalACL(s string) (tailscale.ACL, error) { return acl, nil } + +func runACLTests(ctx context.Context, client *tailscale.Client, d *schema.ResourceData, acl tailscale.ACL) diag.Diagnostics { + if len(acl.Tests) == 0 { + return nil + } + + // TODO: It might be useful to have an attribute on the resource to be able to bypass this. + if err := client.ValidateACL(ctx, acl); err != nil { + return diagnosticsError(err, "Failed to validate ACL") + } + + return nil +}