Skip to content

Commit 7db3347

Browse files
author
Christian
committed
# Fix hostname validation in SCMU
# Fix hostname validation in SCMU ## Summary This PR completes the fix for issue #5190 by adding proper hostname validation to ServiceControl.Config. While PR #5238 partially addressed the issue by allowing dashes in hostnames, it didn't implement comprehensive hostname validation, leaving users able to enter invalid hostnames that would cause configuration issues. ## Background **Original Issue**: #5190 reported that ServiceControl.Config was not properly validating hostname fields, allowing users to enter invalid values that would cause runtime failures. **Previous Fix**: PR #5238 addressed part of the problem by allowing dashes in hostnames, but the validation was still incomplete and didn't prevent other invalid hostname formats. **This Fix**: Implements comprehensive RFC-compliant hostname validation using .NET's built-in `Uri.CheckHostName()` method. ## Validation Behavior The new validation accepts: - ✅ Valid DNS hostnames (server01, myhost.domain.com) - ✅ localhost - ✅ Hostnames with dashes (server-01, my-host.domain.com) - *previously fixed by PR #5238*
1 parent 6231690 commit 7db3347

File tree

6 files changed

+20
-0
lines changed

6 files changed

+20
-0
lines changed

src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddViewModelValidator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public ServiceControlAddViewModelValidator()
5252

5353
RuleFor(viewModel => viewModel.ErrorHostName)
5454
.NotEmpty()
55+
.ValidHostname()
5556
.When(viewModel => viewModel.InstallErrorInstance);
5657

5758
RuleFor(x => x.ErrorPortNumber)
@@ -155,6 +156,7 @@ public ServiceControlAddViewModelValidator()
155156

156157
RuleFor(viewModel => viewModel.AuditHostName)
157158
.NotEmpty()
159+
.ValidHostname()
158160
.When(viewModel => viewModel.InstallAuditInstance);
159161

160162
RuleFor(x => x.AuditPortNumber)

src/ServiceControl.Config/UI/InstanceEdit/ServiceControlAuditEditViewModelValidator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public ServiceControlAuditEditViewModelValidator()
1414

1515
RuleFor(x => x.HostName)
1616
.NotEmpty()
17+
.ValidHostname()
1718
.When(x => x.SubmitAttempted);
1819

1920
RuleFor(x => x.PortNumber)

src/ServiceControl.Config/UI/InstanceEdit/ServiceControlEditViewModelValidator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public ServiceControlEditViewModelValidator()
1414

1515
RuleFor(x => x.HostName)
1616
.NotEmpty()
17+
.ValidHostname()
1718
.When(x => x.SubmitAttempted);
1819

1920
RuleFor(x => x.PortNumber)

src/ServiceControl.Config/UI/SharedInstanceEditor/SharedMonitoringEditorViewModelValidator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ protected SharedMonitoringEditorViewModelValidator()
99
{
1010
RuleFor(x => x.HostName)
1111
.NotEmpty()
12+
.ValidHostname()
1213
.When(x => x.SubmitAttempted);
1314

1415
RuleFor(x => x.LogPath)

src/ServiceControl.Config/UI/Upgrades/AddNewAuditInstanceViewModelValidator.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ public AddNewAuditInstanceViewModelValidator()
6060
.NotEmpty()
6161
.NotEqual(x => x.ServiceControlAudit.AuditQueueName).WithMessage(string.Format(Validation.Validations.MSG_UNIQUEQUEUENAME, "Audit"))
6262
.When(x => x.SubmitAttempted && (x.ServiceControlAudit.AuditForwarding?.Value ?? false));
63+
64+
RuleFor(x => x.ServiceControlAudit.HostName)
65+
.NotEmpty()
66+
.ValidHostname()
67+
.When(x => x.SubmitAttempted);
6368
}
6469
}
6570
}

src/ServiceControl.Config/Validation/Validations.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ public static IRuleBuilderOptions<T, string> MustBeUniqueWindowsServiceName<T>(t
202202
});
203203
}
204204

205+
public static IRuleBuilderOptions<T, string> ValidHostname<T>(this IRuleBuilder<T, string> ruleBuilder)
206+
{
207+
return ruleBuilder.Must((t, hostname) =>
208+
!string.IsNullOrWhiteSpace(hostname) &&
209+
Uri.CheckHostName(hostname) == UriHostNameType.Dns)
210+
.WithMessage(MSG_INVALID_HOSTNAME);
211+
}
212+
205213
public const string MSG_EMAIL_NOT_VALID = "Not Valid.";
206214

207215
public const string MSG_THIS_TRANSPORT_REQUIRES_A_CONNECTION_STRING = "This transport requires a connection string.";
@@ -234,6 +242,8 @@ public static IRuleBuilderOptions<T, string> MustBeUniqueWindowsServiceName<T>(t
234242

235243
public const string MSG_ILLEGAL_PATH_CHAR = "Paths cannot contain characters {0}";
236244

245+
public const string MSG_INVALID_HOSTNAME = "Hostname is not valid.";
246+
237247
static char[] ILLEGAL_PATH_CHARS =
238248
{
239249
'*',

0 commit comments

Comments
 (0)