From ab29e481fadd58fb9bdb0397f7e8e54793c84c18 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Fri, 6 Feb 2026 18:51:53 -0500 Subject: [PATCH] Remove contact as a supported object type in EPP (#2954) This primarily affects the EPP greeting. We already were erroring out when any contact flows attempted to be run; this should just prevent registrars from even trying them at all. This PR is designed to be minimally invasive, and does not remove any of the contact flows or Jakarta XML/XJC objects/files themselves. That can be done later as a follow-up. Also note that the contact namespace urn:ietf:params:xml:ns:contact-1.0 is still present for now in RDE exports, but I'll remove that subsequently as well. This is a redo of PR #2932, which had been reverted, but now controlled via FeatureFlag so that it won't be enabled until we schedule it to do so (and only after sufficient time has passed after notifying registrars in advance). BUG= http://b/475506288 --- .../registry/flows/session/LoginFlow.java | 12 ++++++--- .../registry/model/common/FeatureFlag.java | 6 ++++- .../model/eppcommon/ProtocolDefinition.java | 11 +++++--- .../flows/domain/DomainCheckFlowTest.java | 1 - .../flows/session/LoginFlowTestCase.java | 25 +++++++++++++++++++ .../registry/model/eppinput/EppInputTest.java | 5 +--- .../google/registry/flows/greeting.xml | 1 - .../resources/google/registry/flows/login.xml | 1 - .../registry/flows/login_update_password.xml | 1 - .../flows/login_valid_fee_extension.xml | 1 - .../registry/flows/login_wrong_case.xml | 1 - .../registry/flows/session/greeting.xml | 1 - .../flows/session/login_invalid_extension.xml | 1 - .../flows/session/login_invalid_language.xml | 1 - .../flows/session/login_invalid_types.xml | 1 - .../flows/session/login_invalid_version.xml | 1 - .../flows/session/login_set_new_password.xml | 1 - .../registry/flows/session/login_valid.xml | 1 - .../session/login_with_contact_objuri.xml | 18 +++++++++++++ .../google/registry/flows/syntax_error.xml | 1 - .../registry/model/eppinput/login_valid.xml | 1 - .../model/eppinput/login_wrong_case.xml | 1 - .../sql/schema/db-schema.sql.generated | 2 +- .../registry/client/resources/login.xml | 1 - .../monitoring/blackbox/message/greeting.xml | 1 - .../monitoring/blackbox/message/login.xml | 1 - 26 files changed, 66 insertions(+), 32 deletions(-) create mode 100644 core/src/test/resources/google/registry/flows/session/login_with_contact_objuri.xml diff --git a/core/src/main/java/google/registry/flows/session/LoginFlow.java b/core/src/main/java/google/registry/flows/session/LoginFlow.java index 11d58c4a1..2caaa6de8 100644 --- a/core/src/main/java/google/registry/flows/session/LoginFlow.java +++ b/core/src/main/java/google/registry/flows/session/LoginFlow.java @@ -15,6 +15,7 @@ package google.registry.flows.session; import static com.google.common.collect.Sets.difference; +import static google.registry.model.common.FeatureFlag.FeatureName.PROHIBIT_CONTACT_OBJECTS_ON_LOGIN; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.nullToEmpty; @@ -39,6 +40,7 @@ import google.registry.flows.TlsCredentials.BadRegistrarIpAddressException; import google.registry.flows.TlsCredentials.MissingRegistrarCertificateException; import google.registry.flows.TransportCredentials; import google.registry.flows.TransportCredentials.BadRegistrarPasswordException; +import google.registry.model.common.FeatureFlag; import google.registry.model.eppcommon.ProtocolDefinition; import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension; import google.registry.model.eppinput.EppInput; @@ -114,9 +116,13 @@ public class LoginFlow implements MutatingFlow { } Services services = login.getServices(); stopwatch.tick("LoginFlow getServices"); - Set unsupportedObjectServices = difference( - nullToEmpty(services.getObjectServices()), - ProtocolDefinition.SUPPORTED_OBJECT_SERVICES); + + Set unsupportedObjectServices = + difference( + nullToEmpty(services.getObjectServices()), + FeatureFlag.isActiveNow(PROHIBIT_CONTACT_OBJECTS_ON_LOGIN) + ? ProtocolDefinition.SUPPORTED_OBJECT_SERVICES + : ProtocolDefinition.SUPPORTED_OBJECT_SERVICES_WITH_CONTACT); stopwatch.tick("LoginFlow difference unsupportedObjectServices"); if (!unsupportedObjectServices.isEmpty()) { throw new UnimplementedObjectServiceException(); diff --git a/core/src/main/java/google/registry/model/common/FeatureFlag.java b/core/src/main/java/google/registry/model/common/FeatureFlag.java index 3c96e820b..efaa8bee7 100644 --- a/core/src/main/java/google/registry/model/common/FeatureFlag.java +++ b/core/src/main/java/google/registry/model/common/FeatureFlag.java @@ -64,6 +64,7 @@ public class FeatureFlag extends ImmutableObject implements Buildable { /** The names of the feature flags that can be individually set. */ public enum FeatureName { + /** Feature flag name used for testing only. */ TEST_FEATURE(FeatureStatus.INACTIVE), @@ -76,7 +77,10 @@ public class FeatureFlag extends ImmutableObject implements Buildable { /** * If we're including the upcoming domain drop date in the exported list of registered domains. */ - INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS(FeatureStatus.INACTIVE); + INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS(FeatureStatus.INACTIVE), + + /** If we're prohibiting the inclusion of the contact object URI on login. */ + PROHIBIT_CONTACT_OBJECTS_ON_LOGIN(FeatureStatus.INACTIVE); private final FeatureStatus defaultStatus; diff --git a/core/src/main/java/google/registry/model/eppcommon/ProtocolDefinition.java b/core/src/main/java/google/registry/model/eppcommon/ProtocolDefinition.java index 1e6d8f1c5..bdc8a146b 100644 --- a/core/src/main/java/google/registry/model/eppcommon/ProtocolDefinition.java +++ b/core/src/main/java/google/registry/model/eppcommon/ProtocolDefinition.java @@ -46,10 +46,13 @@ public class ProtocolDefinition { public static final String LANGUAGE = "en"; public static final ImmutableSet SUPPORTED_OBJECT_SERVICES = - ImmutableSet.of( - "urn:ietf:params:xml:ns:host-1.0", - "urn:ietf:params:xml:ns:domain-1.0", - "urn:ietf:params:xml:ns:contact-1.0"); + ImmutableSet.of("urn:ietf:params:xml:ns:host-1.0", "urn:ietf:params:xml:ns:domain-1.0"); + + public static final ImmutableSet SUPPORTED_OBJECT_SERVICES_WITH_CONTACT = + new ImmutableSet.Builder() + .addAll(SUPPORTED_OBJECT_SERVICES) + .add("urn:ietf:params:xml:ns:contact-1.0") + .build(); /** Enum representing which environments should have which service extensions enabled. */ private enum ServiceExtensionVisibility { diff --git a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java index 295903ff3..ef3a6e514 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java @@ -1151,7 +1151,6 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase { sessionMetadata.setRegistrarId(null); // Don't implicitly log in (all other flows need to). registrar = loadRegistrar("NewRegistrar"); registrarBuilder = registrar.asBuilder(); + persistResource( + new FeatureFlag.Builder() + .setFeatureName(PROHIBIT_CONTACT_OBJECTS_ON_LOGIN) + .setStatusMap(ImmutableSortedMap.of(START_OF_TIME, FeatureStatus.ACTIVE)) + .build()); } // Can't inline this since it may be overridden in subclasses. @@ -117,6 +127,21 @@ public abstract class LoginFlowTestCase extends FlowTestCase { doFailingTest("login_invalid_extension.xml", UnimplementedExtensionException.class); } + @Test + void testFailure_invalidContactObjectUri() { + doFailingTest("login_with_contact_objuri.xml", UnimplementedObjectServiceException.class); + } + + @Test + void testSuccess_contactObjectUri_worksWhenNotProhibited() throws Exception { + persistResource( + FeatureFlag.get(PROHIBIT_CONTACT_OBJECTS_ON_LOGIN) + .asBuilder() + .setStatusMap(ImmutableSortedMap.of(START_OF_TIME, FeatureStatus.INACTIVE)) + .build()); + doSuccessfulTest("login_with_contact_objuri.xml"); + } + @Test void testFailure_invalidTypes() { doFailingTest("login_invalid_types.xml", UnimplementedObjectServiceException.class); diff --git a/core/src/test/java/google/registry/model/eppinput/EppInputTest.java b/core/src/test/java/google/registry/model/eppinput/EppInputTest.java index 68d824fdd..43da2566a 100644 --- a/core/src/test/java/google/registry/model/eppinput/EppInputTest.java +++ b/core/src/test/java/google/registry/model/eppinput/EppInputTest.java @@ -68,10 +68,7 @@ class EppInputTest { assertThat(loginCommand.options.version).isEqualTo("1.0"); assertThat(loginCommand.options.language).isEqualTo("en"); assertThat(loginCommand.services.objectServices) - .containsExactly( - "urn:ietf:params:xml:ns:host-1.0", - "urn:ietf:params:xml:ns:domain-1.0", - "urn:ietf:params:xml:ns:contact-1.0"); + .containsExactly("urn:ietf:params:xml:ns:host-1.0", "urn:ietf:params:xml:ns:domain-1.0"); assertThat(loginCommand.services.serviceExtensions) .containsExactly("urn:ietf:params:xml:ns:launch-1.0", "urn:ietf:params:xml:ns:rgp-1.0"); } diff --git a/core/src/test/resources/google/registry/flows/greeting.xml b/core/src/test/resources/google/registry/flows/greeting.xml index f039bfca7..4482b7f27 100644 --- a/core/src/test/resources/google/registry/flows/greeting.xml +++ b/core/src/test/resources/google/registry/flows/greeting.xml @@ -6,7 +6,6 @@ 1.0 en urn:ietf:params:xml:ns:host-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:domain-1.0 urn:ietf:params:xml:ns:launch-1.0 diff --git a/core/src/test/resources/google/registry/flows/login.xml b/core/src/test/resources/google/registry/flows/login.xml index 00dd038af..922f68ca6 100644 --- a/core/src/test/resources/google/registry/flows/login.xml +++ b/core/src/test/resources/google/registry/flows/login.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:launch-1.0 urn:ietf:params:xml:ns:rgp-1.0 diff --git a/core/src/test/resources/google/registry/flows/login_update_password.xml b/core/src/test/resources/google/registry/flows/login_update_password.xml index 07011f4e9..dc832cf97 100644 --- a/core/src/test/resources/google/registry/flows/login_update_password.xml +++ b/core/src/test/resources/google/registry/flows/login_update_password.xml @@ -11,7 +11,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:launch-1.0 urn:ietf:params:xml:ns:rgp-1.0 diff --git a/core/src/test/resources/google/registry/flows/login_valid_fee_extension.xml b/core/src/test/resources/google/registry/flows/login_valid_fee_extension.xml index c84fc3279..f46647f74 100644 --- a/core/src/test/resources/google/registry/flows/login_valid_fee_extension.xml +++ b/core/src/test/resources/google/registry/flows/login_valid_fee_extension.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:launch-1.0 urn:ietf:params:xml:ns:rgp-1.0 diff --git a/core/src/test/resources/google/registry/flows/login_wrong_case.xml b/core/src/test/resources/google/registry/flows/login_wrong_case.xml index c0c8716a1..514909845 100644 --- a/core/src/test/resources/google/registry/flows/login_wrong_case.xml +++ b/core/src/test/resources/google/registry/flows/login_wrong_case.xml @@ -11,7 +11,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:launch-1.0 urn:ietf:params:xml:ns:rgp-1.0 diff --git a/core/src/test/resources/google/registry/flows/session/greeting.xml b/core/src/test/resources/google/registry/flows/session/greeting.xml index f039bfca7..4482b7f27 100644 --- a/core/src/test/resources/google/registry/flows/session/greeting.xml +++ b/core/src/test/resources/google/registry/flows/session/greeting.xml @@ -6,7 +6,6 @@ 1.0 en urn:ietf:params:xml:ns:host-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:domain-1.0 urn:ietf:params:xml:ns:launch-1.0 diff --git a/core/src/test/resources/google/registry/flows/session/login_invalid_extension.xml b/core/src/test/resources/google/registry/flows/session/login_invalid_extension.xml index 45d022c24..40fd1d3de 100644 --- a/core/src/test/resources/google/registry/flows/session/login_invalid_extension.xml +++ b/core/src/test/resources/google/registry/flows/session/login_invalid_extension.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 http://custom/obj1ext-1.0 diff --git a/core/src/test/resources/google/registry/flows/session/login_invalid_language.xml b/core/src/test/resources/google/registry/flows/session/login_invalid_language.xml index 8e4a2290a..8324b1cb2 100644 --- a/core/src/test/resources/google/registry/flows/session/login_invalid_language.xml +++ b/core/src/test/resources/google/registry/flows/session/login_invalid_language.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 ABC-12345 diff --git a/core/src/test/resources/google/registry/flows/session/login_invalid_types.xml b/core/src/test/resources/google/registry/flows/session/login_invalid_types.xml index 480ead567..a3625b3ef 100644 --- a/core/src/test/resources/google/registry/flows/session/login_invalid_types.xml +++ b/core/src/test/resources/google/registry/flows/session/login_invalid_types.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:foo-1.0 diff --git a/core/src/test/resources/google/registry/flows/session/login_invalid_version.xml b/core/src/test/resources/google/registry/flows/session/login_invalid_version.xml index 3469a5f79..2ce50ce3a 100644 --- a/core/src/test/resources/google/registry/flows/session/login_invalid_version.xml +++ b/core/src/test/resources/google/registry/flows/session/login_invalid_version.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 ABC-12345 diff --git a/core/src/test/resources/google/registry/flows/session/login_set_new_password.xml b/core/src/test/resources/google/registry/flows/session/login_set_new_password.xml index 2fd6ba91c..eedc98b09 100644 --- a/core/src/test/resources/google/registry/flows/session/login_set_new_password.xml +++ b/core/src/test/resources/google/registry/flows/session/login_set_new_password.xml @@ -11,7 +11,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 ABC-12345 diff --git a/core/src/test/resources/google/registry/flows/session/login_valid.xml b/core/src/test/resources/google/registry/flows/session/login_valid.xml index 210c07aa3..a854beb05 100644 --- a/core/src/test/resources/google/registry/flows/session/login_valid.xml +++ b/core/src/test/resources/google/registry/flows/session/login_valid.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 ABC-12345 diff --git a/core/src/test/resources/google/registry/flows/session/login_with_contact_objuri.xml b/core/src/test/resources/google/registry/flows/session/login_with_contact_objuri.xml new file mode 100644 index 000000000..210c07aa3 --- /dev/null +++ b/core/src/test/resources/google/registry/flows/session/login_with_contact_objuri.xml @@ -0,0 +1,18 @@ + + + + NewRegistrar + foo-BAR2 + + 1.0 + en + + + urn:ietf:params:xml:ns:host-1.0 + urn:ietf:params:xml:ns:domain-1.0 + urn:ietf:params:xml:ns:contact-1.0 + + + ABC-12345 + + diff --git a/core/src/test/resources/google/registry/flows/syntax_error.xml b/core/src/test/resources/google/registry/flows/syntax_error.xml index b25f3360e..858dde672 100644 --- a/core/src/test/resources/google/registry/flows/syntax_error.xml +++ b/core/src/test/resources/google/registry/flows/syntax_error.xml @@ -12,7 +12,6 @@ xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"> urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:secDNS-1.1 diff --git a/core/src/test/resources/google/registry/model/eppinput/login_valid.xml b/core/src/test/resources/google/registry/model/eppinput/login_valid.xml index 9844b2f7a..cbd3f8897 100644 --- a/core/src/test/resources/google/registry/model/eppinput/login_valid.xml +++ b/core/src/test/resources/google/registry/model/eppinput/login_valid.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:launch-1.0 urn:ietf:params:xml:ns:rgp-1.0 diff --git a/core/src/test/resources/google/registry/model/eppinput/login_wrong_case.xml b/core/src/test/resources/google/registry/model/eppinput/login_wrong_case.xml index c445ab412..6b36afa25 100644 --- a/core/src/test/resources/google/registry/model/eppinput/login_wrong_case.xml +++ b/core/src/test/resources/google/registry/model/eppinput/login_wrong_case.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:launch-1.0 urn:ietf:params:xml:ns:rgp-1.0 diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index b2110ff2b..b75a1d74e 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -467,7 +467,7 @@ ); create table "FeatureFlag" ( - feature_name text not null check (feature_name in ('TEST_FEATURE','MINIMUM_DATASET_CONTACTS_OPTIONAL','MINIMUM_DATASET_CONTACTS_PROHIBITED','INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS')), + feature_name text not null check (feature_name in ('TEST_FEATURE','MINIMUM_DATASET_CONTACTS_OPTIONAL','MINIMUM_DATASET_CONTACTS_PROHIBITED','INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS','PROHIBIT_CONTACT_OBJECTS_ON_LOGIN')), status hstore not null, primary key (feature_name) ); diff --git a/load-testing/src/main/java/google/registry/client/resources/login.xml b/load-testing/src/main/java/google/registry/client/resources/login.xml index 4ff8ac658..e8bb28637 100644 --- a/load-testing/src/main/java/google/registry/client/resources/login.xml +++ b/load-testing/src/main/java/google/registry/client/resources/login.xml @@ -11,7 +11,6 @@ urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 epp-client-login-@@NOW@@-@@CHANNEL_NUMBER@@ diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/message/greeting.xml b/prober/src/main/resources/google/registry/monitoring/blackbox/message/greeting.xml index 076112cbd..b87890c14 100644 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/message/greeting.xml +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/message/greeting.xml @@ -5,7 +5,6 @@ 1.0 en - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:domain-1.0 urn:ietf:params:xml:ns:host-1.0 diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/message/login.xml b/prober/src/main/resources/google/registry/monitoring/blackbox/message/login.xml index b4c72cd61..a0e87ff54 100644 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/message/login.xml +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/message/login.xml @@ -10,7 +10,6 @@ urn:ietf:params:xml:ns:domain-1.0 - urn:ietf:params:xml:ns:contact-1.0 urn:ietf:params:xml:ns:host-1.0 urn:ietf:params:xml:ns:launch-1.0