Skip to content

Commit 7d0fffc

Browse files
committed
Fix GetRoleMappings when multiple distinguished names returned (#5271)
* Fix deserialisation of multiple dns * Support serialisation
1 parent bd964b9 commit 7d0fffc

File tree

6 files changed

+155
-0
lines changed

6 files changed

+155
-0
lines changed

src/Nest/XPack/Security/RoleMapping/Rules/Field/DistinguishedNameRule.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System.Collections.Generic;
6+
57
namespace Nest
68
{
79
public class DistinguishedNameRule : FieldRuleBase
810
{
911
public DistinguishedNameRule(string name) => DistinguishedName = name;
12+
13+
public DistinguishedNameRule(IEnumerable<string> names) => DistinguishedNames = names;
1014
}
1115
}

src/Nest/XPack/Security/RoleMapping/Rules/Field/FieldRuleBase.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ protected string DistinguishedName
2020
set => BackingDictionary.Add("dn", value);
2121
}
2222

23+
[IgnoreDataMember]
24+
protected IEnumerable<string> DistinguishedNames
25+
{
26+
get => BackingDictionary.TryGetValue("dn", out var o) ? (IEnumerable<string>)o : null;
27+
set => BackingDictionary.Add("dn", value);
28+
}
29+
2330
[IgnoreDataMember]
2431
protected IEnumerable<string> Groups
2532
{

src/Nest/XPack/Security/RoleMapping/Rules/Field/FieldRuleBaseFormatter.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System;
56
using System.Collections.Generic;
67
using Nest.Utf8Json;
78
namespace Nest
@@ -38,6 +39,13 @@ public FieldRuleBase Deserialize(ref JsonReader reader, IJsonFormatterResolver f
3839
fieldRule = new UsernameRule(username);
3940
break;
4041
case 1:
42+
if (reader.GetCurrentJsonToken() == JsonToken.BeginArray)
43+
{
44+
var fm = formatterResolver.GetFormatter<IEnumerable<string>>();
45+
var dns = fm.Deserialize(ref reader, formatterResolver);
46+
fieldRule = new DistinguishedNameRule(dns);
47+
break;
48+
}
4149
var dn = reader.ReadString();
4250
fieldRule = new DistinguishedNameRule(dn);
4351
break;

src/Nest/XPack/Security/RoleMapping/Rules/Role/RoleMappingRulesDescriptor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ private RoleMappingRulesDescriptor Add(RoleMappingRuleBase m)
2020
return this;
2121
}
2222

23+
public RoleMappingRulesDescriptor DistinguishedName(IEnumerable<string> names) => Add(new DistinguishedNameRule(names));
24+
2325
public RoleMappingRulesDescriptor DistinguishedName(string name) => Add(new DistinguishedNameRule(name));
2426

2527
public RoleMappingRulesDescriptor Username(string username) => Add(new UsernameRule(username));
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Elastic.Elasticsearch.Xunit.XunitPlumbing;
7+
using Elasticsearch.Net;
8+
using FluentAssertions;
9+
using Nest;
10+
11+
namespace Tests.Reproduce
12+
{
13+
public class GitHubIssue5270
14+
{
15+
private static readonly byte[] ResponseBytes = Encoding.UTF8.GetBytes(@"{
16+
""test admin role mapping"" : {
17+
""enabled"" : true,
18+
""roles"" : [
19+
""apm_user""
20+
],
21+
""rules"" : {
22+
""any"" : [
23+
{
24+
""field"" : {
25+
""dn"" : [
26+
""CN=Bloggs Joe abcdef01,OU=Users,OU=_Central,OU=S1000,OU=SG001,DC=ad001,DC=example,DC=net"",
27+
""cn=bloggs joe abcdef02,ou=usersfunctional,ou=_central,ou=accadm,OU=SG001,DC=ad001,DC=example,DC=net""
28+
]
29+
}
30+
}
31+
]
32+
},
33+
""metadata"" : { }
34+
}
35+
}");
36+
37+
[U]
38+
public async Task GetRoleMappings()
39+
{
40+
var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
41+
var settings = new ConnectionSettings(pool, new InMemoryConnection(ResponseBytes));
42+
var client = new ElasticClient(settings);
43+
44+
// ReSharper disable once MethodHasAsyncOverload
45+
var roleResponse = client.Security.GetRoleMapping();
46+
roleResponse.RoleMappings.Count.Should().Be(1);
47+
Assert(roleResponse);
48+
49+
roleResponse = await client.Security.GetRoleMappingAsync();
50+
roleResponse.RoleMappings.Count.Should().Be(1);
51+
Assert(roleResponse);
52+
}
53+
54+
private static void Assert(GetRoleMappingResponse roleResponse) =>
55+
roleResponse.RoleMappings["test admin role mapping"]
56+
.Rules.Should()
57+
.BeAssignableTo<AnyRoleMappingRule>()
58+
.Subject.Any.First()
59+
.Should()
60+
.BeAssignableTo<FieldRoleMappingRule>()
61+
.Subject.Field.Should()
62+
.BeAssignableTo<DistinguishedNameRule>()
63+
.Subject["dn"].Should().BeAssignableTo<IEnumerable<string>>()
64+
.Subject.Count().Should().Be(2);
65+
}
66+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using Elastic.Elasticsearch.Xunit.XunitPlumbing;
8+
using Elasticsearch.Net;
9+
using Nest;
10+
using Tests.Core.ManagedElasticsearch.Clusters;
11+
using Tests.Framework.EndpointTests;
12+
using Tests.Framework.EndpointTests.TestState;
13+
14+
namespace Tests.XPack.Security.RoleMapping
15+
{
16+
[SkipVersion("<5.5.0", "Does not exist in earlier versions")]
17+
public class DistinguishedNamesRoleMappingsTests
18+
: ApiTestBase<XPackCluster, PutRoleMappingResponse, IPutRoleMappingRequest, PutRoleMappingDescriptor, PutRoleMappingRequest>
19+
{
20+
public DistinguishedNamesRoleMappingsTests(XPackCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
21+
22+
protected override HttpMethod HttpMethod => HttpMethod.PUT;
23+
protected override string UrlPath => "/_security/role_mapping/name";
24+
protected override bool SupportsDeserialization => false;
25+
26+
protected override object ExpectJson => new
27+
{
28+
enabled = true,
29+
roles = new[] { "user_role" },
30+
rules = new
31+
{
32+
any = new object[]
33+
{
34+
new
35+
{
36+
field = new {
37+
dn = new [] {
38+
"a",
39+
"b"
40+
}
41+
}
42+
}
43+
}
44+
}
45+
};
46+
47+
protected override PutRoleMappingRequest Initializer { get; } = new("name")
48+
{
49+
Enabled = true,
50+
Roles = new List<string> { "user_role" },
51+
Rules = new AnyRoleMappingRule(new DistinguishedNameRule(new List<string>
52+
{
53+
"a", "b"
54+
}))
55+
};
56+
57+
protected override PutRoleMappingDescriptor NewDescriptor() => new("name");
58+
59+
protected override Func<PutRoleMappingDescriptor, IPutRoleMappingRequest> Fluent =>
60+
d => d.Enabled().Roles("user_role").Rules(r => r.Any(a => a.DistinguishedName(new List<string> { "a", "b" })));
61+
62+
protected override LazyResponses ClientUsage() => Calls(
63+
(client, f) => client.Security.PutRoleMapping("name", f),
64+
(client, f) => client.Security.PutRoleMappingAsync("name", f),
65+
(client, r) => client.Security.PutRoleMapping(r),
66+
(client, r) => client.Security.PutRoleMappingAsync(r));
67+
}
68+
}

0 commit comments

Comments
 (0)