Skip to content

Commit be5dca6

Browse files
committed
Support clear API key cache (#5147)
* Support clear API key cache * Patched to support optional ids
1 parent 32be62b commit be5dca6

File tree

11 files changed

+222
-1
lines changed

11 files changed

+222
-1
lines changed

src/ApiGenerator/Domain/Specification/UrlPart.cs

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public string HighLevelTypeName
6969

7070
case "forecast_id":
7171
case "action_id":
72+
case "ids" when Type == "list":
7273
return "Ids";
7374

7475
case "index":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"security.clear_api_key_cache": {
3+
"url": {
4+
"paths": ["/_security/api_key/{ids}/_clear_cache", "/_security/api_key/*/_clear_cache"]
5+
}
6+
}
7+
}

src/Elasticsearch.Net/ElasticLowLevelClient.Security.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,16 @@ public TResponse ClearApiKeyCache<TResponse>(string ids, ClearApiKeyCacheRequest
8787
///<param name = "requestParameters">Request specific configuration such as querystring parameters &amp; request specific connection settings.</param>
8888
[MapsApi("security.clear_api_key_cache", "ids")]
8989
public Task<TResponse> ClearApiKeyCacheAsync<TResponse>(string ids, ClearApiKeyCacheRequestParameters requestParameters = null, CancellationToken ctx = default)
90-
where TResponse : class, ITransportResponse, new() => DoRequestAsync<TResponse>(POST, Url($"_security/api_key/{ids:ids}/_clear_cache"), ctx, null, RequestParams(requestParameters));
90+
where TResponse : class, IElasticsearchResponse, new() => DoRequestAsync<TResponse>(POST, Url($"_security/api_key/{ids:ids}/_clear_cache"), ctx, null, RequestParams(requestParameters));
91+
///<summary>POST on /_security/api_key/*/_clear_cache <para>https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</para></summary>
92+
///<param name = "requestParameters">Request specific configuration such as querystring parameters &amp; request specific connection settings.</param>
93+
public TResponse ClearApiKeyCache<TResponse>(ClearApiKeyCacheRequestParameters requestParameters = null)
94+
where TResponse : class, IElasticsearchResponse, new() => DoRequest<TResponse>(POST, "_security/api_key/*/_clear_cache", null, RequestParams(requestParameters));
95+
///<summary>POST on /_security/api_key/*/_clear_cache <para>https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</para></summary>
96+
///<param name = "requestParameters">Request specific configuration such as querystring parameters &amp; request specific connection settings.</param>
97+
[MapsApi("security.clear_api_key_cache", "")]
98+
public Task<TResponse> ClearApiKeyCacheAsync<TResponse>(ClearApiKeyCacheRequestParameters requestParameters = null, CancellationToken ctx = default)
99+
where TResponse : class, IElasticsearchResponse, new() => DoRequestAsync<TResponse>(POST, "_security/api_key/*/_clear_cache", ctx, null, RequestParams(requestParameters));
91100
///<summary>POST on /_security/privilege/{application}/_clear_cache <para>https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-privilege-cache.html</para></summary>
92101
///<param name = "application">A comma-separated list of application names</param>
93102
///<param name = "requestParameters">Request specific configuration such as querystring parameters &amp; request specific connection settings.</param>

src/Nest/Descriptors.Security.cs

+22
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,28 @@ public ChangePasswordDescriptor(): base()
6262
public ChangePasswordDescriptor Refresh(Refresh? refresh) => Qs("refresh", refresh);
6363
}
6464

65+
///<summary>Descriptor for ClearApiKeyCache <para>https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</para></summary>
66+
public partial class ClearApiKeyCacheDescriptor : RequestDescriptorBase<ClearApiKeyCacheDescriptor, ClearApiKeyCacheRequestParameters, IClearApiKeyCacheRequest>, IClearApiKeyCacheRequest
67+
{
68+
internal override ApiUrls ApiUrls => ApiUrlsLookups.SecurityClearApiKeyCache;
69+
///<summary>/_security/api_key/{ids}/_clear_cache</summary>
70+
///<param name = "ids">Optional, accepts null</param>
71+
public ClearApiKeyCacheDescriptor(Ids ids): base(r => r.Optional("ids", ids))
72+
{
73+
}
74+
75+
///<summary>/_security/api_key/*/_clear_cache</summary>
76+
public ClearApiKeyCacheDescriptor(): base()
77+
{
78+
}
79+
80+
// values part of the url path
81+
Ids IClearApiKeyCacheRequest.Ids => Self.RouteValues.Get<Ids>("ids");
82+
///<summary>A comma-separated list of IDs of API keys to clear from the cache</summary>
83+
public ClearApiKeyCacheDescriptor Ids(Ids ids) => Assign(ids, (a, v) => a.RouteValues.Optional("ids", v));
84+
// Request parameters
85+
}
86+
6587
///<summary>Descriptor for ClearCachedPrivileges <para>https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-privilege-cache.html</para></summary>
6688
public partial class ClearCachedPrivilegesDescriptor : RequestDescriptorBase<ClearCachedPrivilegesDescriptor, ClearCachedPrivilegesRequestParameters, IClearCachedPrivilegesRequest>, IClearCachedPrivilegesRequest
6789
{

src/Nest/ElasticClient.Security.cs

+24
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,30 @@ internal SecurityNamespace(ElasticClient client): base(client)
8585
/// </summary>
8686
public Task<ChangePasswordResponse> ChangePasswordAsync(IChangePasswordRequest request, CancellationToken ct = default) => DoRequestAsync<IChangePasswordRequest, ChangePasswordResponse>(request, request.RequestParameters, ct);
8787
/// <summary>
88+
/// <c>POST</c> request to the <c>security.clear_api_key_cache</c> API, read more about this API online:
89+
/// <para></para>
90+
/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</a>
91+
/// </summary>
92+
public ClearApiKeyCacheResponse ClearApiKeyCache(Func<ClearApiKeyCacheDescriptor, IClearApiKeyCacheRequest> selector = null) => ClearApiKeyCache(selector.InvokeOrDefault(new ClearApiKeyCacheDescriptor()));
93+
/// <summary>
94+
/// <c>POST</c> request to the <c>security.clear_api_key_cache</c> API, read more about this API online:
95+
/// <para></para>
96+
/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</a>
97+
/// </summary>
98+
public Task<ClearApiKeyCacheResponse> ClearApiKeyCacheAsync(Func<ClearApiKeyCacheDescriptor, IClearApiKeyCacheRequest> selector = null, CancellationToken ct = default) => ClearApiKeyCacheAsync(selector.InvokeOrDefault(new ClearApiKeyCacheDescriptor()), ct);
99+
/// <summary>
100+
/// <c>POST</c> request to the <c>security.clear_api_key_cache</c> API, read more about this API online:
101+
/// <para></para>
102+
/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</a>
103+
/// </summary>
104+
public ClearApiKeyCacheResponse ClearApiKeyCache(IClearApiKeyCacheRequest request) => DoRequest<IClearApiKeyCacheRequest, ClearApiKeyCacheResponse>(request, request.RequestParameters);
105+
/// <summary>
106+
/// <c>POST</c> request to the <c>security.clear_api_key_cache</c> API, read more about this API online:
107+
/// <para></para>
108+
/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</a>
109+
/// </summary>
110+
public Task<ClearApiKeyCacheResponse> ClearApiKeyCacheAsync(IClearApiKeyCacheRequest request, CancellationToken ct = default) => DoRequestAsync<IClearApiKeyCacheRequest, ClearApiKeyCacheResponse>(request, request.RequestParameters, ct);
111+
/// <summary>
88112
/// <c>POST</c> request to the <c>security.clear_cached_privileges</c> API, read more about this API online:
89113
/// <para></para>
90114
/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-privilege-cache.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-privilege-cache.html</a>

src/Nest/Requests.Security.cs

+32
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,38 @@ public Refresh? Refresh
8686
}
8787
}
8888

89+
[InterfaceDataContract]
90+
public partial interface IClearApiKeyCacheRequest : IRequest<ClearApiKeyCacheRequestParameters>
91+
{
92+
[IgnoreDataMember]
93+
Ids Ids
94+
{
95+
get;
96+
}
97+
}
98+
99+
///<summary>Request for ClearApiKeyCache <para>https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-api-key-cache.html</para></summary>
100+
public partial class ClearApiKeyCacheRequest : PlainRequestBase<ClearApiKeyCacheRequestParameters>, IClearApiKeyCacheRequest
101+
{
102+
protected IClearApiKeyCacheRequest Self => this;
103+
internal override ApiUrls ApiUrls => ApiUrlsLookups.SecurityClearApiKeyCache;
104+
///<summary>/_security/api_key/{ids}/_clear_cache</summary>
105+
///<param name = "ids">Optional, accepts null</param>
106+
public ClearApiKeyCacheRequest(Ids ids): base(r => r.Optional("ids", ids))
107+
{
108+
}
109+
110+
///<summary>/_security/api_key/*/_clear_cache</summary>
111+
public ClearApiKeyCacheRequest(): base()
112+
{
113+
}
114+
115+
// values part of the url path
116+
[IgnoreDataMember]
117+
Ids IClearApiKeyCacheRequest.Ids => Self.RouteValues.Get<Ids>("ids");
118+
// Request parameters
119+
}
120+
89121
[InterfaceDataContract]
90122
public partial interface IClearCachedPrivilegesRequest : IRequest<ClearCachedPrivilegesRequestParameters>
91123
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
namespace Nest
6+
{
7+
[MapsApi("security.clear_api_key_cache")]
8+
[ReadAs(typeof(ClearApiKeyCacheRequest))]
9+
public partial interface IClearApiKeyCacheRequest { }
10+
11+
public partial class ClearApiKeyCacheRequest { }
12+
13+
public partial class ClearApiKeyCacheDescriptor { }
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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.Collections.Generic;
6+
using System.Runtime.Serialization;
7+
using Elasticsearch.Net;
8+
using Elasticsearch.Net.Utf8Json;
9+
10+
namespace Nest
11+
{
12+
public class ClearApiKeyCacheResponse : NodesResponseBase
13+
{
14+
/// <summary>
15+
/// The cluster name.
16+
/// </summary>
17+
[DataMember(Name = "cluster_name")]
18+
public string ClusterName { get; internal set; }
19+
20+
/// <summary>
21+
/// A dictionary of <see cref="CompactNodeInfo"/> container details of the nodes that cleared the cache.
22+
/// </summary>
23+
[DataMember(Name = "nodes")]
24+
[JsonFormatter(typeof(VerbatimInterfaceReadOnlyDictionaryKeysFormatter<string, CompactNodeInfo>))]
25+
public IReadOnlyDictionary<string, CompactNodeInfo> Nodes { get; internal set; } = EmptyReadOnly<string, CompactNodeInfo>.Dictionary;
26+
}
27+
}

src/Nest/_Generated/ApiUrlsLookup.generated.cs

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ internal static class ApiUrlsLookups
239239
internal static ApiUrls NoNamespaceSearchTemplate = new ApiUrls(new[]{"_search/template", "{index}/_search/template"});
240240
internal static ApiUrls SecurityAuthenticate = new ApiUrls(new[]{"_security/_authenticate"});
241241
internal static ApiUrls SecurityChangePassword = new ApiUrls(new[]{"_security/user/{username}/_password", "_security/user/_password"});
242+
internal static ApiUrls SecurityClearApiKeyCache = new ApiUrls(new[]{"_security/api_key/{ids}/_clear_cache", "_security/api_key/*/_clear_cache"});
242243
internal static ApiUrls SecurityClearCachedPrivileges = new ApiUrls(new[]{"_security/privilege/{application}/_clear_cache"});
243244
internal static ApiUrls SecurityClearCachedRealms = new ApiUrls(new[]{"_security/realm/{realms}/_clear_cache"});
244245
internal static ApiUrls SecurityClearCachedRoles = new ApiUrls(new[]{"_security/role/{name}/_clear_cache"});

tests/Tests/XPack/Security/ApiKey/SecurityApiKeyTests.cs

+66
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information
44

55
using System;
6+
using System.Linq;
67
using System.Threading.Tasks;
78
using Elastic.Elasticsearch.Xunit.XunitPlumbing;
89
using Elastic.Transport;
@@ -23,6 +24,9 @@ public class SecurityApiKeyTests : CoordinatedIntegrationTestBase<XPackCluster>
2324
private const string GetApiKeyStep = nameof(GetApiKeyStep);
2425
private const string GetAllApiKeysStep = nameof(GetAllApiKeysStep);
2526
private const string InvalidateApiKeyStep = nameof(InvalidateApiKeyStep);
27+
private const string GetAnotherApiKeyStep = nameof(GetAnotherApiKeyStep);
28+
private const string ClearApiKeyCacheStep = nameof(ClearApiKeyCacheStep);
29+
private const string ClearAllApiKeyCacheStep = nameof(ClearAllApiKeyCacheStep);
2630

2731
public SecurityApiKeyTests(XPackCluster cluster, EndpointUsage usage) : base(new CoordinatedUsage(cluster, usage)
2832
{
@@ -186,6 +190,52 @@ public SecurityApiKeyTests(XPackCluster cluster, EndpointUsage usage) : base(new
186190
(v, c, r) => c.Security.InvalidateApiKey(r),
187191
(v, c, r) => c.Security.InvalidateApiKeyAsync(r)
188192
)
193+
},
194+
{
195+
GetAnotherApiKeyStep, u =>
196+
u.Calls<GetApiKeyDescriptor, GetApiKeyRequest, IGetApiKeyRequest, GetApiKeyResponse>(
197+
v => new GetApiKeyRequest
198+
{
199+
Name = v,
200+
RequestConfiguration = new RequestConfiguration
201+
{
202+
BasicAuthenticationCredentials = new BasicAuthenticationCredentials($"user-{v}", "password")
203+
}
204+
},
205+
(v, d) => d
206+
.Name(v)
207+
.RequestConfiguration(r => r.BasicAuthentication($"user-{v}", "password"))
208+
,
209+
(v, c, f) => c.Security.GetApiKey(f),
210+
(v, c, f) => c.Security.GetApiKeyAsync(f),
211+
(v, c, r) => c.Security.GetApiKey(r),
212+
(v, c, r) => c.Security.GetApiKeyAsync(r),
213+
(r, values) => values.ExtendedValue("apiKey", r.ApiKeys.FirstOrDefault()?.Id ?? string.Empty)
214+
)
215+
},
216+
{
217+
// API introduced in 7.10.0
218+
ClearApiKeyCacheStep, ">=7.10.0", u =>
219+
u.Calls<ClearApiKeyCacheDescriptor, ClearApiKeyCacheRequest, IClearApiKeyCacheRequest, ClearApiKeyCacheResponse>(
220+
v => new ClearApiKeyCacheRequest(u.Usage.CallUniqueValues.ExtendedValue<string>("apiKey") ?? string.Empty),
221+
(v, d) => d,
222+
(v, c, f) => c.Security.ClearApiKeyCache(f => f.Ids(u.Usage.CallUniqueValues.ExtendedValue<string>("apiKey"))),
223+
(v, c, f) => c.Security.ClearApiKeyCacheAsync(f => f.Ids(u.Usage.CallUniqueValues.ExtendedValue<string>("apiKey"))),
224+
(v, c, r) => c.Security.ClearApiKeyCache(r),
225+
(v, c, r) => c.Security.ClearApiKeyCacheAsync(r)
226+
)
227+
},
228+
{
229+
// API introduced in 7.10.0
230+
ClearAllApiKeyCacheStep, ">=7.10.0", u =>
231+
u.Calls<ClearApiKeyCacheDescriptor, ClearApiKeyCacheRequest, IClearApiKeyCacheRequest, ClearApiKeyCacheResponse>(
232+
v => new ClearApiKeyCacheRequest(),
233+
(v, d) => d,
234+
(v, c, f) => c.Security.ClearApiKeyCache(),
235+
(v, c, f) => c.Security.ClearApiKeyCacheAsync(),
236+
(v, c, r) => c.Security.ClearApiKeyCache(r),
237+
(v, c, r) => c.Security.ClearApiKeyCacheAsync(r)
238+
)
189239
}
190240
}) { }
191241

@@ -227,5 +277,21 @@ [I] public async Task SecurityInvalidateApiKeyResponse() => await Assert<Invalid
227277
r.PreviouslyInvalidatedApiKeys.Should().BeEmpty();
228278
r.InvalidatedApiKeys.Should().HaveCount(2);
229279
});
280+
281+
[I] public async Task SecurityClearApiKeyCacheResponse() => await Assert<ClearApiKeyCacheResponse>(ClearApiKeyCacheStep, r =>
282+
{
283+
r.IsValid.Should().BeTrue();
284+
r.NodeStatistics.Successful.Should().BeGreaterOrEqualTo(1);
285+
r.ClusterName.Should().NotBeNullOrEmpty();
286+
r.Nodes.Count.Should().BeGreaterOrEqualTo(1);
287+
});
288+
289+
[I] public async Task SecurityClearAllApiKeyCacheResponse() => await Assert<ClearApiKeyCacheResponse>(ClearAllApiKeyCacheStep, r =>
290+
{
291+
r.IsValid.Should().BeTrue();
292+
r.NodeStatistics.Successful.Should().BeGreaterOrEqualTo(1);
293+
r.ClusterName.Should().NotBeNullOrEmpty();
294+
r.Nodes.Count.Should().BeGreaterOrEqualTo(1);
295+
});
230296
}
231297
}

tests/Tests/XPack/Security/ApiKey/SecurityApiKeyUrlTests.cs

+18
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,22 @@ [U] public override async Task Urls() => await UrlTester.PUT("/_security/api_key
3535
.FluentAsync(c => c.Security.CreateApiKeyAsync(p => p))
3636
.RequestAsync(c => c.Security.CreateApiKeyAsync(new CreateApiKeyRequest()));
3737
}
38+
39+
public class SecurityClearApiKeyCacheUrlTests : UrlTestsBase
40+
{
41+
[U] public override async Task Urls()
42+
{
43+
await UrlTester.POST("/_security/api_key/id1%2Cid2/_clear_cache")
44+
.Fluent(c => c.Security.ClearApiKeyCache(f => f.Ids("id1,id2")))
45+
.Request(c => c.Security.ClearApiKeyCache(new ClearApiKeyCacheRequest("id1,id2")))
46+
.FluentAsync(c => c.Security.ClearApiKeyCacheAsync(f => f.Ids("id1,id2")))
47+
.RequestAsync(c => c.Security.ClearApiKeyCacheAsync(new ClearApiKeyCacheRequest("id1,id2")));
48+
49+
await UrlTester.POST("/_security/api_key/*/_clear_cache")
50+
.Fluent(c => c.Security.ClearApiKeyCache())
51+
.Request(c => c.Security.ClearApiKeyCache(new ClearApiKeyCacheRequest()))
52+
.FluentAsync(c => c.Security.ClearApiKeyCacheAsync())
53+
.RequestAsync(c => c.Security.ClearApiKeyCacheAsync(new ClearApiKeyCacheRequest()));
54+
}
55+
}
3856
}

0 commit comments

Comments
 (0)