Skip to content

Commit 4e641ab

Browse files
committed
Merge branch 'master' into delete-snap-on-searchable-index-deletion
2 parents 982d6ea + 8c09fc8 commit 4e641ab

File tree

178 files changed

+3423
-976
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

178 files changed

+3423
-976
lines changed

.ci/jobs.t/elastic+elasticsearch+pull-request+packaging-tests-unix.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,15 @@
3232
type: label-expression
3333
name: os
3434
values:
35-
- centos-6-packaging
3635
- centos-7-packaging
3736
- centos-8-packaging
38-
- debian-8-packaging
3937
- debian-9-packaging
4038
- debian-10-packaging
4139
- opensuse-15-1-packaging
42-
- oraclelinux-6-packaging
4340
- oraclelinux-7-packaging
4441
- oraclelinux-8-packaging
4542
- sles-12-packaging
4643
- sles-15-packaging
47-
- ubuntu-16.04-packaging
4844
- ubuntu-18.04-packaging
4945
- ubuntu-20.04-packaging
5046
- axis:

build-tools-internal/src/main/groovy/elasticsearch.run.gradle

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ testClusters {
2727
throw new IllegalArgumentException("Unsupported self-generated license type: [" + licenseType + "[basic] or [trial].")
2828
}
2929
setting 'xpack.security.enabled', 'true'
30-
if (VersionProperties.elasticsearch.toString().endsWith('-SNAPSHOT')) {
31-
setting 'es.shutdown_feature_flag_enabled', 'true'
32-
}
3330
keystore 'bootstrap.password', 'password'
3431
user username: 'elastic-admin', password: 'elastic-password', role: 'superuser'
3532
}

client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetServiceAccountCredentialsResponse.java

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,84 +9,83 @@
99
package org.elasticsearch.client.security;
1010

1111
import org.elasticsearch.client.security.support.ServiceTokenInfo;
12-
import org.elasticsearch.common.xcontent.ParseField;
1312
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
13+
import org.elasticsearch.common.xcontent.ParseField;
1414
import org.elasticsearch.common.xcontent.XContentParser;
1515

1616
import java.io.IOException;
17+
import java.util.ArrayList;
1718
import java.util.List;
18-
import java.util.Map;
1919
import java.util.Objects;
20-
import java.util.stream.Collectors;
21-
import java.util.stream.Stream;
2220

2321
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
22+
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
2423

2524
/**
2625
* Response when requesting credentials of a service account.
2726
*/
2827
public final class GetServiceAccountCredentialsResponse {
2928

3029
private final String principal;
31-
private final String nodeName;
32-
private final List<ServiceTokenInfo> serviceTokenInfos;
30+
private final List<ServiceTokenInfo> indexTokenInfos;
31+
private final ServiceAccountCredentialsNodesResponse nodesResponse;
3332

34-
public GetServiceAccountCredentialsResponse(
35-
String principal, String nodeName, List<ServiceTokenInfo> serviceTokenInfos) {
33+
public GetServiceAccountCredentialsResponse(String principal,
34+
List<ServiceTokenInfo> indexTokenInfos,
35+
ServiceAccountCredentialsNodesResponse nodesResponse) {
3636
this.principal = Objects.requireNonNull(principal, "principal is required");
37-
this.nodeName = Objects.requireNonNull(nodeName, "nodeName is required");
38-
this.serviceTokenInfos = List.copyOf(Objects.requireNonNull(serviceTokenInfos, "service token infos are required)"));
37+
this.indexTokenInfos = List.copyOf(Objects.requireNonNull(indexTokenInfos, "service token infos are required"));
38+
this.nodesResponse = Objects.requireNonNull(nodesResponse, "nodes response is required");
3939
}
4040

4141
public String getPrincipal() {
4242
return principal;
4343
}
4444

45-
public String getNodeName() {
46-
return nodeName;
47-
}
48-
49-
public List<ServiceTokenInfo> getServiceTokenInfos() {
50-
return serviceTokenInfos;
45+
public List<ServiceTokenInfo> getIndexTokenInfos() {
46+
return indexTokenInfos;
5147
}
5248

53-
@Override
54-
public boolean equals(Object o) {
55-
if (this == o)
56-
return true;
57-
if (o == null || getClass() != o.getClass())
58-
return false;
59-
GetServiceAccountCredentialsResponse that = (GetServiceAccountCredentialsResponse) o;
60-
return principal.equals(that.principal) && nodeName.equals(that.nodeName) && serviceTokenInfos.equals(that.serviceTokenInfos);
61-
}
62-
63-
@Override
64-
public int hashCode() {
65-
return Objects.hash(principal, nodeName, serviceTokenInfos);
49+
public ServiceAccountCredentialsNodesResponse getNodesResponse() {
50+
return nodesResponse;
6651
}
6752

53+
@SuppressWarnings("unchecked")
6854
static ConstructingObjectParser<GetServiceAccountCredentialsResponse, Void> PARSER =
6955
new ConstructingObjectParser<>("get_service_account_credentials_response",
7056
args -> {
71-
@SuppressWarnings("unchecked")
72-
final List<ServiceTokenInfo> tokenInfos = Stream.concat(
73-
((Map<String, Object>) args[3]).keySet().stream().map(name -> new ServiceTokenInfo(name, "index")),
74-
((Map<String, Object>) args[4]).keySet().stream().map(name -> new ServiceTokenInfo(name, "file")))
75-
.collect(Collectors.toList());
76-
assert tokenInfos.size() == (int) args[2] : "number of tokens do not match";
77-
return new GetServiceAccountCredentialsResponse((String) args[0], (String) args[1], tokenInfos);
57+
final int count = (int) args[1];
58+
final List<ServiceTokenInfo> indexTokenInfos = (List<ServiceTokenInfo>) args[2];
59+
final ServiceAccountCredentialsNodesResponse fileTokensResponse = (ServiceAccountCredentialsNodesResponse) args[3];
60+
if (count != indexTokenInfos.size() + fileTokensResponse.getFileTokenInfos().size()) {
61+
throw new IllegalArgumentException("number of tokens do not match");
62+
}
63+
return new GetServiceAccountCredentialsResponse((String) args[0], indexTokenInfos, fileTokensResponse);
7864
});
7965

8066
static {
8167
PARSER.declareString(constructorArg(), new ParseField("service_account"));
82-
PARSER.declareString(constructorArg(), new ParseField("node_name"));
8368
PARSER.declareInt(constructorArg(), new ParseField("count"));
84-
PARSER.declareObject(constructorArg(), (p, c) -> p.map(), new ParseField("tokens"));
85-
PARSER.declareObject(constructorArg(), (p, c) -> p.map(), new ParseField("file_tokens"));
69+
PARSER.declareObject(constructorArg(),
70+
(p, c) -> GetServiceAccountCredentialsResponse.parseIndexTokenInfos(p), new ParseField("tokens"));
71+
PARSER.declareObject(constructorArg(),
72+
(p, c) -> ServiceAccountCredentialsNodesResponse.fromXContent(p), new ParseField("nodes_credentials"));
8673
}
8774

8875
public static GetServiceAccountCredentialsResponse fromXContent(XContentParser parser) throws IOException {
8976
return PARSER.parse(parser, null);
9077
}
9178

79+
static List<ServiceTokenInfo> parseIndexTokenInfos(XContentParser parser) throws IOException {
80+
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser);
81+
final List<ServiceTokenInfo> indexTokenInfos = new ArrayList<>();
82+
XContentParser.Token token;
83+
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
84+
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser);
85+
indexTokenInfos.add(new ServiceTokenInfo(parser.currentName(), "index"));
86+
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
87+
ensureExpectedToken(XContentParser.Token.END_OBJECT, parser.nextToken(), parser);
88+
}
89+
return indexTokenInfos;
90+
}
9291
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.client.security;
10+
11+
import org.elasticsearch.client.NodesResponseHeader;
12+
import org.elasticsearch.client.security.support.ServiceTokenInfo;
13+
import org.elasticsearch.common.xcontent.XContentParser;
14+
import org.elasticsearch.common.xcontent.XContentParserUtils;
15+
16+
import java.io.IOException;
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
20+
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
21+
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureFieldName;
22+
23+
public class ServiceAccountCredentialsNodesResponse {
24+
25+
private final NodesResponseHeader header;
26+
private final List<ServiceTokenInfo> fileTokenInfos;
27+
28+
public ServiceAccountCredentialsNodesResponse(
29+
NodesResponseHeader header, List<ServiceTokenInfo> fileTokenInfos) {
30+
this.header = header;
31+
this.fileTokenInfos = fileTokenInfos;
32+
}
33+
34+
public NodesResponseHeader getHeader() {
35+
return header;
36+
}
37+
38+
public List<ServiceTokenInfo> getFileTokenInfos() {
39+
return fileTokenInfos;
40+
}
41+
42+
public static ServiceAccountCredentialsNodesResponse fromXContent(XContentParser parser) throws IOException {
43+
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser);
44+
NodesResponseHeader header = null;
45+
List<ServiceTokenInfo> fileTokenInfos = List.of();
46+
XContentParser.Token token;
47+
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
48+
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser);
49+
if ("_nodes".equals(parser.currentName())) {
50+
if (header == null) {
51+
header = NodesResponseHeader.fromXContent(parser, null);
52+
} else {
53+
throw new IllegalArgumentException("expecting only a single [_nodes] field, multiple found");
54+
}
55+
} else if ("file_tokens".equals(parser.currentName())) {
56+
fileTokenInfos = parseFileToken(parser);
57+
} else {
58+
throw new IllegalArgumentException("expecting field of either [_nodes] or [file_tokens], found ["
59+
+ parser.currentName() + "]");
60+
}
61+
}
62+
return new ServiceAccountCredentialsNodesResponse(header, fileTokenInfos);
63+
}
64+
65+
static List<ServiceTokenInfo> parseFileToken(XContentParser parser) throws IOException {
66+
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
67+
XContentParser.Token token;
68+
final ArrayList<ServiceTokenInfo> fileTokenInfos = new ArrayList<>();
69+
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
70+
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser);
71+
final String tokenName = parser.currentName();
72+
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
73+
ensureFieldName(parser, parser.nextToken(), "nodes");
74+
parser.nextToken();
75+
final List<String> nodeNames = XContentParserUtils.parseList(parser, XContentParser::text);
76+
ensureExpectedToken(XContentParser.Token.END_OBJECT, parser.nextToken(), parser);
77+
fileTokenInfos.add(new ServiceTokenInfo(tokenName, "file", nodeNames));
78+
}
79+
return fileTokenInfos;
80+
}
81+
}

client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/ServiceTokenInfo.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,25 @@
88

99
package org.elasticsearch.client.security.support;
1010

11+
import org.elasticsearch.core.Nullable;
12+
13+
import java.util.Collection;
1114
import java.util.Objects;
1215

1316
public class ServiceTokenInfo {
1417
private final String name;
1518
private final String source;
19+
@Nullable
20+
private final Collection<String> nodeNames;
1621

1722
public ServiceTokenInfo(String name, String source) {
23+
this(name, source, null);
24+
}
25+
26+
public ServiceTokenInfo(String name, String source, Collection<String> nodeNames) {
1827
this.name = Objects.requireNonNull(name, "token name is required");
1928
this.source = Objects.requireNonNull(source, "token source is required");
29+
this.nodeNames = nodeNames;
2030
}
2131

2232
public String getName() {
@@ -27,23 +37,27 @@ public String getSource() {
2737
return source;
2838
}
2939

40+
public Collection<String> getNodeNames() {
41+
return nodeNames;
42+
}
43+
3044
@Override
3145
public boolean equals(Object o) {
3246
if (this == o)
3347
return true;
3448
if (o == null || getClass() != o.getClass())
3549
return false;
3650
ServiceTokenInfo that = (ServiceTokenInfo) o;
37-
return name.equals(that.name) && source.equals(that.source);
51+
return Objects.equals(name, that.name) && Objects.equals(source, that.source) && Objects.equals(nodeNames, that.nodeNames);
3852
}
3953

4054
@Override
4155
public int hashCode() {
42-
return Objects.hash(name, source);
56+
return Objects.hash(name, source, nodeNames);
4357
}
4458

4559
@Override
4660
public String toString() {
47-
return "ServiceTokenInfo{" + "name='" + name + '\'' + ", source='" + source + '\'' + '}';
61+
return "ServiceTokenInfo{" + "name='" + name + '\'' + ", source='" + source + '\'' + ", nodeNames=" + nodeNames + '}';
4862
}
4963
}

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.action.LatchedActionListener;
1515
import org.elasticsearch.action.support.PlainActionFuture;
1616
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
17+
import org.elasticsearch.client.NodesResponseHeader;
1718
import org.elasticsearch.client.RequestOptions;
1819
import org.elasticsearch.client.RestHighLevelClient;
1920
import org.elasticsearch.client.security.AuthenticateResponse;
@@ -122,6 +123,7 @@
122123
import java.util.ArrayList;
123124
import java.util.Arrays;
124125
import java.util.Base64;
126+
import java.util.Collection;
125127
import java.util.Collections;
126128
import java.util.Comparator;
127129
import java.util.HashMap;
@@ -2745,17 +2747,23 @@ public void testGetServiceAccountCredentials() throws IOException {
27452747

27462748
// tag::get-service-account-credentials-response
27472749
final String principal = getServiceAccountCredentialsResponse.getPrincipal(); // <1>
2748-
final String nodeName = getServiceAccountCredentialsResponse.getNodeName(); // <2>
2749-
final List<ServiceTokenInfo> serviceTokenInfos = getServiceAccountCredentialsResponse.getServiceTokenInfos(); // <3>
2750-
final String tokenName = serviceTokenInfos.get(0).getName(); // <4>
2751-
final String tokenSource = serviceTokenInfos.get(0).getSource(); // <5>
2750+
final List<ServiceTokenInfo> indexTokenInfos = getServiceAccountCredentialsResponse.getIndexTokenInfos(); // <2>
2751+
final String tokenName = indexTokenInfos.get(0).getName(); // <3>
2752+
final String tokenSource = indexTokenInfos.get(0).getSource(); // <4>
2753+
final Collection<String> nodeNames = indexTokenInfos.get(0).getNodeNames(); // <5>
2754+
final List<ServiceTokenInfo> fileTokenInfos
2755+
= getServiceAccountCredentialsResponse.getNodesResponse().getFileTokenInfos(); // <6>
2756+
final NodesResponseHeader fileTokensResponseHeader
2757+
= getServiceAccountCredentialsResponse.getNodesResponse().getHeader(); // <7>
2758+
final int nSuccessful = fileTokensResponseHeader.getSuccessful(); // <8>
2759+
final int nFailed = fileTokensResponseHeader.getFailed(); // <9>
27522760
// end::get-service-account-credentials-response
27532761
assertThat(principal, equalTo("elastic/fleet-server"));
27542762
// Cannot assert exactly one token because there are rare occasions where tests overlap and it will see
27552763
// token created from other tests
2756-
assertThat(serviceTokenInfos.size(), greaterThanOrEqualTo(1));
2757-
assertThat(serviceTokenInfos.stream().map(ServiceTokenInfo::getName).collect(Collectors.toSet()), hasItem("token2"));
2758-
assertThat(serviceTokenInfos.stream().map(ServiceTokenInfo::getSource).collect(Collectors.toSet()), hasItem("index"));
2764+
assertThat(indexTokenInfos.size(), greaterThanOrEqualTo(1));
2765+
assertThat(indexTokenInfos.stream().map(ServiceTokenInfo::getName).collect(Collectors.toSet()), hasItem("token2"));
2766+
assertThat(indexTokenInfos.stream().map(ServiceTokenInfo::getSource).collect(Collectors.toSet()), hasItem("index"));
27592767
}
27602768

27612769
{
@@ -2787,8 +2795,8 @@ public void onFailure(Exception e) {
27872795

27882796
assertNotNull(future.actionGet());
27892797
assertThat(future.actionGet().getPrincipal(), equalTo("elastic/fleet-server"));
2790-
assertThat(future.actionGet().getServiceTokenInfos().size(), greaterThanOrEqualTo(1));
2791-
assertThat(future.actionGet().getServiceTokenInfos().stream().map(ServiceTokenInfo::getName).collect(Collectors.toSet()),
2798+
assertThat(future.actionGet().getIndexTokenInfos().size(), greaterThanOrEqualTo(1));
2799+
assertThat(future.actionGet().getIndexTokenInfos().stream().map(ServiceTokenInfo::getName).collect(Collectors.toSet()),
27922800
hasItem("token2"));
27932801
}
27942802
}

0 commit comments

Comments
 (0)