Problem/Motivation

#3324150: Add validation constraints to config_entity.dependencies added ConfigEntityValidationTestBase in December 2022. We've been expanding it ever since.

While working on #3425349: [PP-1] Deprecate \Drupal\ckeditor5\Plugin\Editor\CKEditor5::validatePair() and `type: ckeditor5_valid_pair__format_and_editor`, it became apparent that:

$config_entity = Editor::load('basic_html');
$violations = ConfigEntityAdapter::createFromEntity($config_entity)->validate();

and

$config_entity = Editor::load('basic_html');
$violations = \Drupal::service('config.typed')->createFromNameAndData(
  $config_entity->getConfigDependencyName(),
  $config_entity->toArray()
)->validate();

leads to different results 😱

The first has two constraints at the root level (ImmutableProperties + RequiredConfigDependencies, defined in the entity type definition), the second has two different constraints at the root level (CKEditor5FundamentalCompatibility + CKEditor5MediaAndFilterSettingsInSync, defined in the config schema definition).

This has security implications: the same config can in principle be considered valid or invalid depending on how it is validated. Not good 🙈

Steps to reproduce

Validating using ConfigEntityAdapter vs using the "plain config object" by using ::createFromNameAndData() .

Proposed resolution

This is an oversight in ConfigEntityAdapter::createFromEntity() (which was introduced in #1818574: Support config entities in typed data EntityAdapter but then subsequently not really used; that's only started to happen recently!).

Remaining tasks

  1. ✅ Test coverage: https://git.drupalcode.org/project/drupal/-/merge_requests/6997/diffs?co...
  2. Fix. Either:
    1. Ensure validation using either approach yields the same results
    2. Not viable, see #7: Only allow one of the two; in that case the ConfigEntityAdapter one is probably preferred.

User interface changes

None.

API changes

API addition:

  • ConfigEntityAdapter::getConfigTypedData() (was a private API before, now a public one)

Data model changes

None.

Release notes snippet

None.

CommentFileSizeAuthor
#20 3427106-nr-bot.txt90 bytesneeds-review-queue-bot

Issue fork drupal-3427106

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Wim Leers created an issue. See original summary.

wim leers’s picture

Issue summary: View changes
wim leers’s picture

Issue summary: View changes
wim leers’s picture

AFAICT

  1. Ensure validation using either approach yields the same results

is actually impossible, because ImmutablePropertiesConstraintValidator requires a config object rather than an array to work: it is otherwise impossible to know the original ID (to verify no disallowed property mutation is occurring). And config entities cannot be loaded by UUID; otherwise that'd be a viable alternative.

So … switching to approach #2: Only allow one of the two; in that case the ConfigEntityAdapter one is probably preferred. 😞

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Needs work » Needs review

Actually, approach #2 is not a viable approach, because it prevents the validation that is executed by ConfigSchemaChecker during ConfigInstaller. So we MUST have both. Fortunately, I found a way forward (ironically, thanks to reading the code in ConfigInstaller 😄🥳👍).

There's two things to still iron out:

  1. The one @todo
  2. Figure out how/why the ContentTranslationSynchronizedFields constraint is being added to config entity types 🤯
wim leers’s picture

Issue summary: View changes

99% if not 100% of the failing kernel tests will be fixed by the todo other than the one I just added.

wim leers’s picture

Issue summary: View changes
Issue tags: +Needs change record

One of the two @todos is solved. The MR is now 99.9% green.

phenaproxima’s picture

Status: Needs review » Needs work

Some comments, but I think I see the nature of the problem and why this fix is so important.

What gives me pause is the fact that these two "sides" of validation (config schema and ConfigEntityAdapter) have to stay actively in sync with each other means we haven't necessarily fixed this problem, just mitigated it, or moved it to where it's less likely to cause trouble (not to mention added test coverage). That's probably good enough to get past the critical problem, but to me it still smacks of the "more than one way of doing things, even important things" problem.

Not sure if I have any ideas on how to resolve that once and for all...but that's not necessarily the goal of this issue anyway. Just thought I'd call it out and be transparent about my thinking.

wim leers’s picture

just mitigated it

Interesting take!

to me it still smacks of the "more than one way of doing things, even important things" problem.

This is definitely true.

Overall, I think @phenaproxima is saying that he is not fully satisfied with the solution in that The Proper Solution would be to not have two distinct mechanisms. I echo that desire but … the fact/reality is that all this wasn't fully thought through when config schema was added to Drupal core. The only way to eventually get to such a point where there's only one way, is to first make it all validatable, and then introduce a deprecation that disallows one or the other.

Meanwhile, before we get to such a HUGE refactoring, let's get things that we have today working :)

phenaproxima’s picture

Nope, we're in full agreement. You know me...I like pragmatism.

borisson_’s picture

I agree with this being a good stop gap solution, we can improve the situation further down the line but this is already a good improvement and we have the test coverage to prove that this is an improvement.
I found one extra nitpick.

wim leers’s picture

I processed the feedback at a high level, but I won't have time to push this forward. Would be great if one of you could push it forward 🙏

phenaproxima’s picture

Status: Needs work » Needs review
phenaproxima’s picture

Issue tags: -Needs change record

Wrote a change record. It's a bit punchier than my usual style, but hopefully it's clear.

wim leers’s picture

It's a bit punchier than my usual style

🤣

Clarified the CR.

Reviewed and removed one obsolete @todo. I +1'd your request for a clarifying comment in one place (could you add it? 🙏) and added remarks on the trickier bits of the MR.

I cannot RTBC this since I wrote ~99% of this, but I think that once you agree this makes sense, that you can still RTBC it, @phenaproxima: you've just implemented your own review remarks, but I still wrote ~99%, so should be fine :)

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

Looks great to me.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

wim leers’s picture

Status: Needs work » Needs review

Merged in upstream changes.

This conflicted with #2575105: Use cache collector for state (for updating expectations in StandardPerformanceTest) and with #1170362: Install profile is disabled for lots of different reasons and core doesn't allow for that (for updating ModuleInstaller).

This seemed like a trivial conflict resolution, but let's await test results first.

wim leers’s picture

Assigned: Unassigned » wim leers

A single kernel test and a single functional test failed — looks like I resolved the conflict with #1170362: Install profile is disabled for lots of different reasons and core doesn't allow for that incorrectly after all.

phenaproxima’s picture

Status: Needs review » Needs work
wim leers’s picture

Assigned: wim leers » Unassigned

https://www.drupal.org/project/experience_builder is why I haven't had time for this 😬

rpayanm made their first commit to this issue’s fork.

joachim’s picture

The IS should explain the consequences of this bug more clearly. For instance, top-level constraints are not validated with this method:

$violations = ConfigEntityAdapter::createFromEntity($config_entity)->validate();

Also, the CR needs some editing for style. It should explain what is new, and how it has changed. The chatty style isn't appropriate.

borisson_’s picture

updated the CR to be a bit easier.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.