Skip to content

[Transform] Behavior is not consistent between PUT and _preview wrt accessing remote index. #95367

Description

@przemekwitek

Elasticsearch Version

main

Installed Plugins

No response

Java Version

bundled

OS Version

Darwin Kernel Version 21.6.0

Problem Description

When the user configures remote index in their transform but does not have permissions to access it, _preview request will fail with error message: "Source indices have been deleted or closed.".
However, such a transform can be created via PUT and started via _start. It should not be possible.

Reported by @yangwan

Steps to Reproduce

  1. Configure a transform that accesses remote index.
  2. Set up permissions so that the user cannot access the remote index.
  3. Run GET _transform/_preview
  4. Run PUT _transform/my-transform with the same config
  5. Observe the difference between steps 3. and 4.

Logs (if relevant)

No response

Activity

  1. self-assigned this
    on Apr 19, 2023
  2. elasticsearchmachine commented on Apr 19, 2023

    @elasticsearchmachine
    Collaborator

    Pinging @elastic/ml-core (Team:ML)

  3. removed their assignment
    on Jun 21, 2024
  4. self-assigned this
    on Feb 12, 2026
  5. added 3 commits that reference this issue on Feb 12, 2026
    689237d
    805c1db
    c3e243b
  6. added 2 commits that reference this issue on Feb 13, 2026
    942d2b7
    af8358c
  7. added a commit that references this issue on Feb 13, 2026
    8cc0c96
  8. added a commit that references this issue on Feb 23, 2026
    2db163e
  9. darius-vil commented on May 27, 2026

    @darius-vil
    Contributor

    I'm reopening this, because #142403 didn't fully address the issue. From the looks of it, the issue was addressed only if the source index is local.

    For cross-cluster indexes, the issue persists. The PR did include multicluster tests that look sound, but these were never run, because at that time, the entire test suite was muted (and they still are). If you unmute the tests and run them - you'll get failures - all the cross-cluster tests that expect a "lacks the required permissions" don't match that exception.

    It also breaks down if the allow_partial_search_results cluster setting is set to false, because in this case, diagnoseSourceAccessFailure will be never triggered - the search will result in an exception instead of storing the failures in the response and we'll jump straight to the failure handler. This feels like an unaccounted side effect.

    I am also not too sure whether findClusterSecurityFailure is guaranteed to catch anything. This needs a further deep dive, but I see at least two layers where cross-cluster failures can be lost

    1. During index resolution. Looks like index resolution is intertwined with authorization (src). We send our request with LENIENT_EXPAND_OPEN, which has ignoreUnavailable=true and allowNoIndices=true set. I think as a result the indexes we have no access to would be quietly dropped, but no exception would be produced for SourceAccessDiagnostics to catch.
    2. If skip_unavailable=true is set. I think this also can result in an empty "successful" response in case of auth errors,

    What I'm going to do is:

    1. The top priority is to get the tests unmuted and running. They have been muted since Jan 2025
    2. I'll let some of the tests succeed when they shouldn't. This essentially means I'll bring them back to the state they were before [Transform] Fix transform validation to reject PUT and _start when user lacks remote index permissions #142403. I'll add TODOs behind the tests that should fail with security exceptions but don't
    3. I'll add test cases to confirm that the issue was fixed for local indexes.

    Maybe the idea behind SourceAccessDiagnostics needs a fresh look. Perhaps instead of trying to solve it here, we should push for the hasPrivilages endpoint to be fixed? I think this would solve the problem:

    // TODO: Remove this filter once https://github.com/elastic/elasticsearch/issues/67798 is fixed.
    String[] sourceIndex = hasLinkedProjects
    ? Strings.EMPTY_ARRAY
    : Arrays.stream(config.getSource().getIndex()).filter(not(RemoteClusterLicenseChecker::isRemoteIndex)).toArray(String[]::new);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions