Skip to content

Commit

Permalink
Adding deprecation warning for data_frame_transforms roles (elastic#1…
Browse files Browse the repository at this point in the history
…17521)

* Adding deprecation warning for data_frame_transforms roles

* Updating deprecation warning URL

---------

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
dan-rubinstein and elasticmachine authored Dec 9, 2024
1 parent 31678a3 commit 98e69c8
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,12 @@ public class TransformDeprecations {

public static final String MAX_PAGE_SEARCH_SIZE_BREAKING_CHANGES_URL = "https://ela.st/es-deprecation-7-transform-max-page-search-size";

public static final String DATA_FRAME_TRANSFORMS_ROLES_BREAKING_CHANGES_URL =
"https://ela.st/es-deprecation-9-data-frame-transforms-roles";

public static final String DATA_FRAME_TRANSFORMS_ROLES_IS_DEPRECATED = "This transform configuration uses one or more obsolete roles "
+ "prefixed with [data_frame_transformers_] which will be unsupported after the next upgrade. Switch to a user with the equivalent "
+ "roles prefixed with [transform_] and use [/_transform/_upgrade] to upgrade all transforms to the latest roles.";;

private TransformDeprecations() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xpack.core.ClientHelper;
import org.elasticsearch.xpack.core.common.time.TimeUtils;
import org.elasticsearch.xpack.core.common.validation.SourceDestValidator;
import org.elasticsearch.xpack.core.common.validation.SourceDestValidator.SourceDestValidation;
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue;
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue.Level;
import org.elasticsearch.xpack.core.security.authc.support.AuthenticationContextSerializer;
import org.elasticsearch.xpack.core.security.xcontent.XContentUtils;
import org.elasticsearch.xpack.core.transform.TransformConfigVersion;
import org.elasticsearch.xpack.core.transform.TransformDeprecations;
Expand All @@ -41,6 +43,7 @@
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
Expand All @@ -49,6 +52,7 @@

import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.AUTHENTICATION_KEY;

/**
* This class holds the configuration details of a data frame transform
Expand All @@ -65,6 +69,10 @@ public final class TransformConfig implements SimpleDiffable<TransformConfig>, W
public static final ParseField HEADERS = new ParseField("headers");
/** Version in which {@code FieldCapabilitiesRequest.runtime_fields} field was introduced. */
private static final TransportVersion FIELD_CAPS_RUNTIME_MAPPINGS_INTRODUCED_TRANSPORT_VERSION = TransportVersions.V_7_12_0;
private static final List<String> DEPRECATED_DATA_FRAME_TRANSFORMS_ROLES = List.of(
"data_frame_transforms_admin",
"data_frame_transforms_user"
);

/** Specifies all the possible transform functions. */
public enum Function {
Expand Down Expand Up @@ -374,7 +382,7 @@ public ActionRequestValidationException validate(ActionRequestValidationExceptio
* @param namedXContentRegistry XContent registry required for aggregations and query DSL
* @return The deprecations of this transform
*/
public List<DeprecationIssue> checkForDeprecations(NamedXContentRegistry namedXContentRegistry) {
public List<DeprecationIssue> checkForDeprecations(NamedXContentRegistry namedXContentRegistry) throws IOException {

List<DeprecationIssue> deprecations = new ArrayList<>();

Expand Down Expand Up @@ -404,9 +412,38 @@ public List<DeprecationIssue> checkForDeprecations(NamedXContentRegistry namedXC
if (retentionPolicyConfig != null) {
retentionPolicyConfig.checkForDeprecations(getId(), namedXContentRegistry, deprecations::add);
}

var deprecatedTransformRoles = getRolesFromHeaders().stream().filter(DEPRECATED_DATA_FRAME_TRANSFORMS_ROLES::contains).toList();
if (deprecatedTransformRoles.isEmpty() == false) {
deprecations.add(
new DeprecationIssue(
Level.CRITICAL,
"Transform [" + id + "] uses deprecated transform roles " + deprecatedTransformRoles,
TransformDeprecations.DATA_FRAME_TRANSFORMS_ROLES_BREAKING_CHANGES_URL,
TransformDeprecations.DATA_FRAME_TRANSFORMS_ROLES_IS_DEPRECATED,
false,
null
)
);
}

return deprecations;
}

private List<String> getRolesFromHeaders() throws IOException {
if (headers == null) {
return Collections.emptyList();
}

var encodedAuthenticationHeader = ClientHelper.filterSecurityHeaders(headers).getOrDefault(AUTHENTICATION_KEY, "");
if (encodedAuthenticationHeader.isEmpty()) {
return Collections.emptyList();
}

var decodedAuthenticationHeader = AuthenticationContextSerializer.decode(encodedAuthenticationHeader);
return Arrays.asList(decodedAuthenticationHeader.getEffectiveSubject().getUser().roles());
}

@Override
public void writeTo(final StreamOutput out) throws IOException {
out.writeString(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import org.elasticsearch.xpack.core.common.validation.SourceDestValidator.SourceDestValidation;
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue;
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue.Level;
import org.elasticsearch.xpack.core.security.authc.AuthenticationTestHelper;
import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.core.transform.AbstractSerializingTransformTestCase;
import org.elasticsearch.xpack.core.transform.TransformConfigVersion;
import org.elasticsearch.xpack.core.transform.TransformDeprecations;
Expand All @@ -44,6 +46,7 @@
import java.util.Map;

import static org.elasticsearch.test.TestMatchers.matchesPattern;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.AUTHENTICATION_KEY;
import static org.elasticsearch.xpack.core.transform.transforms.DestConfigTests.randomDestConfig;
import static org.elasticsearch.xpack.core.transform.transforms.SourceConfigTests.randomInvalidSourceConfig;
import static org.elasticsearch.xpack.core.transform.transforms.SourceConfigTests.randomSourceConfig;
Expand All @@ -58,6 +61,8 @@ public class TransformConfigTests extends AbstractSerializingTransformTestCase<T

private String transformId;
private boolean runWithHeaders;
private static final String DATA_FRAME_TRANSFORMS_ADMIN_ROLE = "data_frame_transforms_admin";
private static final String DATA_FRAME_TRANSFORMS_USER_ROLE = "data_frame_transforms_user";

public static TransformConfig randomTransformConfigWithoutHeaders() {
return randomTransformConfigWithoutHeaders(randomAlphaOfLengthBetween(1, 10));
Expand Down Expand Up @@ -165,6 +170,25 @@ public static TransformConfig randomTransformConfigWithSettings(SettingsConfig s
);
}

public static TransformConfig randomTransformConfigWithHeaders(Map<String, String> headers) {
return new TransformConfig(
randomAlphaOfLengthBetween(1, 10),
randomSourceConfig(),
randomDestConfig(),
randomBoolean() ? null : TimeValue.timeValueMillis(randomIntBetween(1_000, 3_600_000)),
randomBoolean() ? null : randomSyncConfig(),
headers,
randomBoolean() ? null : PivotConfigTests.randomPivotConfig(),
randomBoolean() ? null : LatestConfigTests.randomLatestConfig(),
randomBoolean() ? null : randomAlphaOfLengthBetween(1, 1000),
randomBoolean() ? null : SettingsConfigTests.randomSettingsConfig(),
randomBoolean() ? null : randomMetadata(),
randomBoolean() ? null : randomRetentionPolicyConfig(),
randomBoolean() ? null : Instant.now(),
TransformConfigVersion.CURRENT.toString()
);
}

public static TransformConfig randomTransformConfig(
String id,
TransformConfigVersion version,
Expand Down Expand Up @@ -915,10 +939,13 @@ public void testGroupByStayInOrder() throws IOException {
}
}

public void testCheckForDeprecations() {
public void testCheckForDeprecations_NoDeprecationWarnings() throws IOException {
String id = randomAlphaOfLengthBetween(1, 10);
assertThat(randomTransformConfig(id, TransformConfigVersion.CURRENT).checkForDeprecations(xContentRegistry()), is(empty()));
}

public void testCheckForDeprecations_WithDeprecatedFields_VersionCurrent() throws IOException {
String id = randomAlphaOfLengthBetween(1, 10);
TransformConfig deprecatedConfig = randomTransformConfigWithDeprecatedFields(id, TransformConfigVersion.CURRENT);

// check _and_ clear warnings
Expand All @@ -940,8 +967,11 @@ public void testCheckForDeprecations() {
)
)
);
}

deprecatedConfig = randomTransformConfigWithDeprecatedFields(id, TransformConfigVersion.V_7_10_0);
public void testCheckForDeprecations_WithDeprecatedFields_Version_7_10() throws IOException {
String id = randomAlphaOfLengthBetween(1, 10);
TransformConfig deprecatedConfig = randomTransformConfigWithDeprecatedFields(id, TransformConfigVersion.V_7_10_0);

// check _and_ clear warnings
assertWarnings(TransformDeprecations.ACTION_MAX_PAGE_SEARCH_SIZE_IS_DEPRECATED);
Expand All @@ -962,8 +992,11 @@ public void testCheckForDeprecations() {
)
)
);
}

deprecatedConfig = randomTransformConfigWithDeprecatedFields(id, TransformConfigVersion.V_7_4_0);
public void testCheckForDeprecations_WithDeprecatedFields_Version_7_4() throws IOException {
String id = randomAlphaOfLengthBetween(1, 10);
TransformConfig deprecatedConfig = randomTransformConfigWithDeprecatedFields(id, TransformConfigVersion.V_7_4_0);

// check _and_ clear warnings
assertWarnings(TransformDeprecations.ACTION_MAX_PAGE_SEARCH_SIZE_IS_DEPRECATED);
Expand Down Expand Up @@ -994,6 +1027,44 @@ public void testCheckForDeprecations() {
);
}

public void testCheckForDeprecations_WithDeprecatedTransformUserAdmin() throws IOException {
testCheckForDeprecations_WithDeprecatedRoles(List.of(DATA_FRAME_TRANSFORMS_ADMIN_ROLE));
}

public void testCheckForDeprecations_WithDeprecatedTransformUserRole() throws IOException {
testCheckForDeprecations_WithDeprecatedRoles(List.of(DATA_FRAME_TRANSFORMS_USER_ROLE));
}

public void testCheckForDeprecations_WithDeprecatedTransformRoles() throws IOException {
testCheckForDeprecations_WithDeprecatedRoles(List.of(DATA_FRAME_TRANSFORMS_ADMIN_ROLE, DATA_FRAME_TRANSFORMS_USER_ROLE));
}

private void testCheckForDeprecations_WithDeprecatedRoles(List<String> roles) throws IOException {
var authentication = AuthenticationTestHelper.builder()
.realm()
.user(new User(randomAlphaOfLength(10), roles.toArray(String[]::new)))
.build();
Map<String, String> headers = Map.of(AUTHENTICATION_KEY, authentication.encode());
TransformConfig deprecatedConfig = randomTransformConfigWithHeaders(headers);

// important: checkForDeprecations does _not_ create new deprecation warnings
assertThat(
deprecatedConfig.checkForDeprecations(xContentRegistry()),
equalTo(
List.of(
new DeprecationIssue(
Level.CRITICAL,
"Transform [" + deprecatedConfig.getId() + "] uses deprecated transform roles " + roles,
TransformDeprecations.DATA_FRAME_TRANSFORMS_ROLES_BREAKING_CHANGES_URL,
TransformDeprecations.DATA_FRAME_TRANSFORMS_ROLES_IS_DEPRECATED,
false,
null
)
)
)
);
}

public void testSerializingMetadataPreservesOrder() throws IOException {
String json = Strings.format("""
{
Expand Down

0 comments on commit 98e69c8

Please sign in to comment.