fix(security): id-form credential references match by id only; id-shaped driver names refused (#849 review)
A driver named 'drv' (env form DRV) matched every sibling's id-form variable env:<PREFIX>DRV_<12HEX>_... as 'another instance', breaking the recommended id convention fleet-wide - including for a name that pre-dates the rule. ReferenceNames is split into ReferenceNamesId / ReferenceNamesName; a reference whose instance part is id-shaped (secret: DRV-<12 hex>, env: DRV_<12 HEX>[_...]) is matched by id only. DescribeNameChangeProblemsAsync also refuses new names whose env form is DRV or starts with an id form (IsReservedInstanceName) at create, /raw rename and config-modal update. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+8
@@ -71,6 +71,14 @@ public sealed class DraftValidatorCredentialInstanceAndPathTests
|
||||
Drv("DRV-c", "C", "GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"env:GALAXY_MXGW_API_KEY"}}"""))
|
||||
.ShouldBeEmpty();
|
||||
|
||||
/// <summary>#849 review: a pre-existing driver named 'drv' must not fail the id-form variables of its siblings.</summary>
|
||||
[Fact]
|
||||
public void A_driver_named_drv_does_not_break_id_form_env_variables() =>
|
||||
Validate(
|
||||
Drv("DRV-0123456789ab", "A", "GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"env:OTOPCUA_GALAXY_DRV_0123456789AB_KEY"}}"""),
|
||||
Drv("DRV-fedcba987654", "drv", "GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"env:OTOPCUA_GALAXY_DRV_FEDCBA987654_KEY"}}"""))
|
||||
.ShouldBeEmpty();
|
||||
|
||||
[Fact]
|
||||
public void Shared_and_own_keys_pass() =>
|
||||
Validate(
|
||||
|
||||
+62
-3
@@ -181,8 +181,67 @@ public sealed class CredentialInstanceScopeTests
|
||||
refs.Count.ShouldBe(2);
|
||||
refs[0].ShouldBe(new InstanceReference("Gateway.ApiKeySecretRef", CredentialReferenceKind.Secret, "gw"));
|
||||
refs[1].ShouldBe(new InstanceReference("AlarmAck.FallbackPasswordSecretRef", CredentialReferenceKind.Environment, "ACK_PW"));
|
||||
DriverCredentialPolicy.ReferenceNames(refs[1], "ack").ShouldBeTrue();
|
||||
DriverCredentialPolicy.ReferenceNames(refs[1], "ac").ShouldBeFalse();
|
||||
DriverCredentialPolicy.ReferenceNames(refs[0], "GW").ShouldBeTrue();
|
||||
DriverCredentialPolicy.ReferenceNamesName(refs[1], "ack").ShouldBeTrue();
|
||||
DriverCredentialPolicy.ReferenceNamesName(refs[1], "ac").ShouldBeFalse();
|
||||
DriverCredentialPolicy.ReferenceNamesName(refs[0], "GW").ShouldBeTrue();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// #849 review — a driver NAMED 'drv' (or id-shaped) must not shadow the id convention
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
private const string RealId = "DRV-0123456789ab"; // the RawTreeService.NewId shape
|
||||
|
||||
private static readonly DriverInstanceIdentity[] WithDrvNamed =
|
||||
[
|
||||
new(RealId, "PlantA", DriverTypeNames.Galaxy),
|
||||
new("DRV-fedcba987654", "drv", DriverTypeNames.Galaxy), // a pre-existing driver named 'drv'
|
||||
new("DRV-111111111111", "DRV-0123456789AB", DriverTypeNames.Galaxy), // …or named like another's id
|
||||
];
|
||||
|
||||
[Theory]
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_0123456789AB_KEY")]
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_0123456789AB")]
|
||||
[InlineData("env:GALAXY_MXGW_DRV_0123456789AB_API_KEY")]
|
||||
[InlineData("secret:galaxy/DRV-0123456789ab/apikey")]
|
||||
public void An_id_form_reference_is_matched_by_id_only_so_a_pre_existing_drv_name_does_not_break_it(string reference) =>
|
||||
DriverCredentialPolicy.DescribeOtherInstanceProblems(DriverTypeNames.Galaxy, Galaxy(reference), RealId, WithDrvNamed)
|
||||
.ShouldBeEmpty();
|
||||
|
||||
[Fact]
|
||||
public void An_id_form_reference_still_names_the_other_instance_by_its_id() =>
|
||||
DriverCredentialPolicy.DescribeOtherInstanceProblems(
|
||||
DriverTypeNames.Galaxy, Galaxy("env:OTOPCUA_GALAXY_DRV_0123456789AB_KEY"), "DRV-fedcba987654", WithDrvNamed)
|
||||
.ShouldHaveSingleItem().ShouldContain(RealId);
|
||||
|
||||
[Fact]
|
||||
public void A_drv_name_still_matches_a_reference_that_is_not_id_shaped() =>
|
||||
// 'DRV_FOO' is not an id form, so the name 'drv' does claim it (the create/rename check refuses that name anyway).
|
||||
DriverCredentialPolicy.DescribeOtherInstanceProblems(DriverTypeNames.Galaxy, Galaxy("env:OTOPCUA_GALAXY_DRV_FOO_KEY"), RealId, WithDrvNamed)
|
||||
.ShouldHaveSingleItem();
|
||||
|
||||
[Theory]
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_0123456789AB_KEY", true)]
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_0123456789AB", true)]
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_0123456789ABC_KEY", false)] // 13 hex: not an id form
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_0123456789AG_KEY", false)] // not hex
|
||||
[InlineData("env:OTOPCUA_GALAXY_DRV_KEY", false)]
|
||||
[InlineData("secret:galaxy/DRV-0123456789ab/k", true)]
|
||||
[InlineData("secret:galaxy/drv-0123456789AB/k", true)]
|
||||
[InlineData("secret:galaxy/DRV-0123456789ab-x/k", false)]
|
||||
public void Id_shape_detection(string reference, bool expected) =>
|
||||
DriverCredentialPolicy.IsIdShaped(DriverCredentialPolicy.CollectInstanceReferences(DriverTypeNames.Galaxy, Galaxy(reference)).Single())
|
||||
.ShouldBe(expected);
|
||||
|
||||
[Theory]
|
||||
[InlineData("drv", true)]
|
||||
[InlineData("DRV", true)]
|
||||
[InlineData("drv-", false)] // env form 'DRV_' — neither 'DRV' nor an id form
|
||||
[InlineData("DRV-0123456789ab", true)]
|
||||
[InlineData("drv 0123456789AB extra", true)]
|
||||
[InlineData("DRV-0123456789", false)]
|
||||
[InlineData("Driver", false)]
|
||||
[InlineData("PlantA", false)]
|
||||
public void Reserved_instance_names(string name, bool expected) =>
|
||||
DriverCredentialPolicy.IsReservedInstanceName(name).ShouldBe(expected);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user