diff --git a/.golangci.yml b/.golangci.yml
index 223cf95..679a35a 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,5 +1,5 @@
-# Visit https://golangci-lint.run/ for usage documentation
-# and information on other useful linters
+# Visit https://golangci-lint.run/ for usage documentation and information on
+# other useful linters
 issues:
   max-per-linter: 0
   max-same-issues: 0
@@ -24,4 +24,4 @@ linters:
     - unconvert
     - unparam
     - unused
-    - vet
\ No newline at end of file
+    - vet
diff --git a/internal/codersdkvalidator/display_name.go b/internal/codersdkvalidator/display_name.go
new file mode 100644
index 0000000..1000c32
--- /dev/null
+++ b/internal/codersdkvalidator/display_name.go
@@ -0,0 +1,10 @@
+package codersdkvalidator
+
+import (
+	"github.com/coder/coder/v2/codersdk"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+func DisplayName() validator.String {
+	return validatorFromFunc(codersdk.DisplayNameValid, "value must be a valid display name")
+}
diff --git a/internal/codersdkvalidator/group_name.go b/internal/codersdkvalidator/group_name.go
new file mode 100644
index 0000000..20313db
--- /dev/null
+++ b/internal/codersdkvalidator/group_name.go
@@ -0,0 +1,10 @@
+package codersdkvalidator
+
+import (
+	"github.com/coder/coder/v2/codersdk"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+func GroupName() validator.String {
+	return validatorFromFunc(codersdk.GroupNameValid, "value must be a valid group name")
+}
diff --git a/internal/codersdkvalidator/name.go b/internal/codersdkvalidator/name.go
new file mode 100644
index 0000000..14adb25
--- /dev/null
+++ b/internal/codersdkvalidator/name.go
@@ -0,0 +1,10 @@
+package codersdkvalidator
+
+import (
+	"github.com/coder/coder/v2/codersdk"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+func Name() validator.String {
+	return validatorFromFunc(codersdk.NameValid, "value must be a valid name")
+}
diff --git a/internal/codersdkvalidator/template_version_name.go b/internal/codersdkvalidator/template_version_name.go
new file mode 100644
index 0000000..32c69d6
--- /dev/null
+++ b/internal/codersdkvalidator/template_version_name.go
@@ -0,0 +1,10 @@
+package codersdkvalidator
+
+import (
+	"github.com/coder/coder/v2/codersdk"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+func TemplateVersionName() validator.String {
+	return validatorFromFunc(codersdk.TemplateVersionNameValid, "value must be a valid template version name")
+}
diff --git a/internal/codersdkvalidator/user_real_name.go b/internal/codersdkvalidator/user_real_name.go
new file mode 100644
index 0000000..5bf9686
--- /dev/null
+++ b/internal/codersdkvalidator/user_real_name.go
@@ -0,0 +1,10 @@
+package codersdkvalidator
+
+import (
+	"github.com/coder/coder/v2/codersdk"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+func UserRealName() validator.String {
+	return validatorFromFunc(codersdk.UserRealNameValid, "value must be a valid name for a user")
+}
diff --git a/internal/codersdkvalidator/validator_from_func.go b/internal/codersdkvalidator/validator_from_func.go
new file mode 100644
index 0000000..9d5e631
--- /dev/null
+++ b/internal/codersdkvalidator/validator_from_func.go
@@ -0,0 +1,51 @@
+package codersdkvalidator
+
+import (
+	"context"
+
+	"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+type functionValidator struct {
+	check          func(string) error
+	defaultMessage string
+	err            error
+}
+
+func validatorFromFunc(check func(string) error, defaultMessage string) functionValidator {
+	return functionValidator{
+		check:          check,
+		defaultMessage: defaultMessage,
+	}
+}
+
+var _ validator.String = functionValidator{}
+
+func (v functionValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
+	if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
+		return
+	}
+
+	name := req.ConfigValue.ValueString()
+	if v.err = v.check(name); v.err != nil {
+		resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
+			req.Path,
+			v.Description(ctx),
+			name,
+		))
+	}
+}
+
+var _ validator.Describer = functionValidator{}
+
+func (v functionValidator) Description(_ context.Context) string {
+	if v.err != nil {
+		return v.err.Error()
+	}
+	return v.defaultMessage
+}
+
+func (v functionValidator) MarkdownDescription(ctx context.Context) string {
+	return v.Description(ctx)
+}
diff --git a/internal/provider/group_resource.go b/internal/provider/group_resource.go
index a7dcd6a..fa370a0 100644
--- a/internal/provider/group_resource.go
+++ b/internal/provider/group_resource.go
@@ -6,8 +6,8 @@ import (
 	"strings"
 
 	"github.com/coder/coder/v2/codersdk"
+	"github.com/coder/terraform-provider-coderd/internal/codersdkvalidator"
 	"github.com/google/uuid"
-	"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
 	"github.com/hashicorp/terraform-plugin-framework/attr"
 	"github.com/hashicorp/terraform-plugin-framework/diag"
 	"github.com/hashicorp/terraform-plugin-framework/path"
@@ -77,8 +77,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest,
 				MarkdownDescription: "The unique name of the group.",
 				Required:            true,
 				Validators: []validator.String{
-					stringvalidator.LengthBetween(1, 36),
-					stringvalidator.RegexMatches(nameValidRegex, "Group names must be alpahnumeric with hyphens."),
+					codersdkvalidator.GroupName(),
 				},
 			},
 			"display_name": schema.StringAttribute{
@@ -86,8 +85,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest,
 				Computed:            true,
 				Optional:            true,
 				Validators: []validator.String{
-					stringvalidator.LengthBetween(1, 64),
-					stringvalidator.RegexMatches(displayNameRegex, "Group display names must be alphanumeric with spaces"),
+					codersdkvalidator.DisplayName(),
 				},
 				Default: stringdefault.StaticString(""),
 			},
diff --git a/internal/provider/template_resource.go b/internal/provider/template_resource.go
index 1d1edf2..a5834db 100644
--- a/internal/provider/template_resource.go
+++ b/internal/provider/template_resource.go
@@ -13,6 +13,7 @@ import (
 	"github.com/coder/coder/v2/coderd/util/ptr"
 	"github.com/coder/coder/v2/codersdk"
 	"github.com/coder/coder/v2/provisionersdk"
+	"github.com/coder/terraform-provider-coderd/internal/codersdkvalidator"
 	"github.com/google/uuid"
 	"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
 	"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
@@ -258,8 +259,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques
 				MarkdownDescription: "The name of the template.",
 				Required:            true,
 				Validators: []validator.String{
-					stringvalidator.LengthBetween(1, 32),
-					stringvalidator.RegexMatches(nameValidRegex, "Template names must be alphanumeric with hyphens."),
+					codersdkvalidator.Name(),
 				},
 			},
 			"display_name": schema.StringAttribute{
@@ -267,8 +267,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques
 				Optional:            true,
 				Computed:            true,
 				Validators: []validator.String{
-					stringvalidator.LengthBetween(1, 64),
-					stringvalidator.RegexMatches(displayNameRegex, "Template display names must be alphanumeric with spaces."),
+					codersdkvalidator.DisplayName(),
 				},
 			},
 			"description": schema.StringAttribute{
@@ -418,8 +417,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques
 							Optional:            true,
 							Computed:            true,
 							Validators: []validator.String{
-								stringvalidator.LengthBetween(1, 64),
-								stringvalidator.RegexMatches(templateVersionNameRegex, "Template version names must be alphanumeric with underscores and dots."),
+								codersdkvalidator.TemplateVersionName(),
 							},
 						},
 						"message": schema.StringAttribute{
diff --git a/internal/provider/user_resource.go b/internal/provider/user_resource.go
index a560df5..3fa570e 100644
--- a/internal/provider/user_resource.go
+++ b/internal/provider/user_resource.go
@@ -22,6 +22,7 @@ import (
 	"github.com/hashicorp/terraform-plugin-log/tflog"
 
 	"github.com/coder/coder/v2/codersdk"
+	"github.com/coder/terraform-provider-coderd/internal/codersdkvalidator"
 )
 
 // Ensure provider defined types fully satisfy framework interfaces.
@@ -71,8 +72,7 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
 				MarkdownDescription: "Username of the user.",
 				Required:            true,
 				Validators: []validator.String{
-					stringvalidator.LengthBetween(1, 32),
-					stringvalidator.RegexMatches(nameValidRegex, "Username must be alphanumeric with hyphens."),
+					codersdkvalidator.Name(),
 				},
 			},
 			"name": schema.StringAttribute{
@@ -80,7 +80,7 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
 				Computed:            true,
 				Optional:            true,
 				Validators: []validator.String{
-					stringvalidator.LengthBetween(1, 128),
+					codersdkvalidator.UserRealName(),
 				},
 			},
 			"email": schema.StringAttribute{
diff --git a/internal/provider/util.go b/internal/provider/util.go
index 2d998cc..720259c 100644
--- a/internal/provider/util.go
+++ b/internal/provider/util.go
@@ -8,18 +8,11 @@ import (
 	"net/http"
 	"os"
 	"path/filepath"
-	"regexp"
 
 	"github.com/coder/coder/v2/codersdk"
 	"github.com/google/uuid"
 )
 
-var (
-	nameValidRegex           = regexp.MustCompile("^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$")
-	templateVersionNameRegex = regexp.MustCompile(`^[a-zA-Z0-9]+(?:[_.-]{1}[a-zA-Z0-9]+)*$`)
-	displayNameRegex         = regexp.MustCompile(`^[^\s](.*[^\s])?$`)
-)
-
 func PrintOrNull(v any) string {
 	if v == nil {
 		return "null"