Visitar URL original
chore: Manifest and SHA update for RHOAI 3.5 release by jyejare · Pull Request #16 · opendatahub-io/feast-module-operator · GitHub
Skip to content

chore: Manifest and SHA update for RHOAI 3.5 release - #16

Merged
jyejare merged 1 commit into
mainfrom
update_sha_for_3_5
Jul 29, 2026
Merged

jyejare merged 1 commit into
mainfrom
update_sha_for_3_5

Conversation

@jyejare

@jyejare jyejare commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

Update the SHA and the manifests from upstream for RHOAI 3.5 release.

How Has This Been Tested?

Merge criteria:

  • The commits are squashed in a cohesive manner and have meaningful messages.
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work

Summary by CodeRabbit

  • New Features

    • Added OpenLineage consumer configuration and a sample FeatureStore setup.
    • Expanded supported schema options, including Aerospike, ScyllaDB, and projected pod certificates.
    • Added permissions needed for Spark applications and OpenShift API server access.
  • Updates

    • Upgraded Feast Operator and Feature Server images to version 0.65.0.
    • Refreshed FeatureStore resource schema definitions.
  • Bug Fixes

    • Removed obsolete selector migration jobs from OpenDataHub and RHOAI deployments.

Signed-off-by: Jitendra Yejare <11752425+jyejare@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Updates the Feast Operator manifests from version 0.64.0 to 0.65.0 and refreshes pinned Feast manifest commits. Generated FeatureStore CRD schemas gain EnvFiles, OpenLineage consumer, datastore, and projected-volume fields. RBAC rules are revised for core, OpenShift, and Spark resources. Selector-migration Jobs are removed from both overlays. An OpenLineage consumer sample with Secrets and a FeatureStore resource is added.

Estimated code review effort: 4 (Complex) | ~45 minutes

🚥 Pre-merge checks | ✅ 10
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: updating manifests and pinned SHAs for the RHOAI 3.5 release.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Contribution Quality And Spam Detection ✅ Passed PASS: Release-manifest sync with a normal commit message and broad upstream bump; only standard checklist boilerplate appears, not enough for a multi-signal spam/quality fail.
No Hardcoded Secrets ✅ Passed No real hardcoded secrets found; only placeholder sample api_key values and doc strings. No CWE-798/CWE-321 issue present.
No Weak Cryptography ✅ Passed PASS: Diff only updates manifests and git commit SHAs; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret compares. CWE-327/CWE-208 not triggered.
No Injection Vectors ✅ Passed No CWE-89/78/94/502/79 sinks: changed shell script uses fixed URLs/SHAs and quoted vars; the rest are static YAML manifest updates.
No Privileged Containers ✅ Passed No added privileged:true/hostNetwork/hostPID/allowPrivilegeEscalation:true/runAsUser:0/SYS_ADMIN found; deleted jobs were non-root and dropped ALL caps (CWE-269).
No Sensitive Data In Logs ✅ Passed No logging statements emit secrets/PII; the shell script only echoes non-sensitive status, and manifests contain secret refs/placeholders, not logs. No CWE-532.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
config/manifests/feastoperator/rbac/role.yaml (1)

113-139: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the customresourcedefinitions RBAC rule before merging.

feastoperator_controller.go still watches extv1.CustomResourceDefinition{} and comments +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions, but config/manifests/feastoperator/rbac/role.yaml omitted the generated apiextensions.k8s.io entry. This will let the controller fail with 403 Forbidden when installing/upgrading clusters with CRD-related flows unless the controller is changed to stop watching CRDs (CWE-269: Improper Restriction of Privileges).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/rbac/role.yaml` around lines 113 - 139, The
RBAC role is missing permission to access customresourcedefinitions. Restore the
generated apiextensions.k8s.io customresourcedefinitions rule in the role
manifest, matching the controller’s kubebuilder RBAC declaration and required
watch-related verbs, without changing the CRD watch behavior.
🧹 Nitpick comments (2)
config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml (2)

35-38: 🔒 Security & Privacy | 🔵 Trivial

Use TLS for cross-pod API-key transport.

If this target is a Kubernetes Service or Marquez instance rather than strictly loopback development, http:// sends the API key without transport encryption (CWE-319). Use HTTPS and configure the service CA; verify that localhost is intentional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`
around lines 35 - 38, Update the OpenLineage transport configuration around
transportUrl to use an HTTPS endpoint instead of HTTP, and configure the
corresponding service CA for TLS verification. Confirm that the localhost target
is intentional; if it is only a development default, replace it with the
appropriate Kubernetes Service or Marquez hostname while preserving
transportEndpoint and apiKeySecretRef.

49-63: 🔒 Security & Privacy | 🔵 Trivial

Verify network isolation for the enabled consumer.

namespaceMapping controls lineage visibility, not network reachability. Confirm the release overlays apply a NetworkPolicy restricting POST /api/v1/lineage to approved producer workloads; otherwise any reachable tenant with the known sample credential can inject lineage data (CWE-284).

As per path instructions, Kubernetes configuration requires NetworkPolicies for multi-tenancy isolation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`
around lines 49 - 63, Update the enabled consumer configuration around
namespaceMapping and its release overlays to include a Kubernetes NetworkPolicy
restricting POST /api/v1/lineage access to approved producer workloads. Preserve
the existing namespaceMapping visibility rules and ensure the policy is applied
for this multi-tenant deployment.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml`:
- Around line 855-907: Update the upstream OpenLineageConsumer schema constraint
so consumer.enabled: true requires a non-empty apiKeySecretRef.name, then
regenerate both schema copies:
config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml lines
855-907 and 7144-7196. Ensure the CEL/required constraint is present in both the
admission-enforced spec schema and the status.applied mirror.

In `@config/manifests/feastoperator/default/related_image_fs_patch.yaml`:
- Line 12: Replace the mutable Feast image tags with their verified immutable
SHA256 digests: update the feature-server image in
config/manifests/feastoperator/default/related_image_fs_patch.yaml (line 12),
and pin both operator and feature-server images in
config/manifests/feastoperator/overlays/odh/params.env (lines 1-2) and
config/manifests/feastoperator/overlays/rhoai/params.env (lines 1-2).

In `@config/manifests/feastoperator/rbac/role.yaml`:
- Around line 11-20: Remove the deletecollection verb from the services and
persistentvolumeclaims permissions in the ClusterRole, retaining only the
minimum verbs required by the controller. If bulk deletion is genuinely
required, replace the cluster-wide grant with namespace-scoped Roles limited to
managed namespaces.
- Around line 53-63: Reduce the serviceaccounts rule in the ClusterRole to the
controller’s verified minimum permissions: inspect its reconciliation code and
retain only the verbs actually required for tenant service-account provisioning,
removing unused update/delete (and create if unneeded). Ensure the resulting
permissions do not provide unnecessary privilege-escalation capability alongside
the existing ClusterRole and ClusterRoleBinding rules.
- Around line 30-40: Restrict the pod permissions in the cluster-scoped RBAC
rule by removing delete and deletecollection, and grant those verbs only through
namespace-scoped Role bindings in the namespaces where the operator creates
feature-server or Spark job pods. Preserve only the minimum required pod verbs
in the cluster-wide rule.
- Around line 21-29: Replace the ClusterRole’s cluster-wide Secret access with
namespaced Role resources and corresponding bindings only in namespaces where
FeatureStore CRs and their required Secrets reside. Remove cluster-scoped
get/list/watch permissions on secrets, and retain only the minimum permissions
needed for the controller’s operation.

In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`:
- Around line 1-7: Remove both plaintext Secret resources, including
openlineage-producer-secret and the second resource in this manifest. Replace
them with a SealedSecret or ExternalSecret reference, or require pre-provisioned
Secrets, so the sample contains no API key values or secret allowlist pragmas.
- Around line 35-38: Align the OpenLineage settings around transportUrl and
apiKeySecretRef: for the localhost self-ingestion target, use
openlineage-consumer-secret and the Feast consumer authentication contract; for
external Marquez/OpenLineage targets, retain openlineage-producer-secret.
Reconcile the HTTP authentication configuration with Feast 0.65.0 so credentials
are sent through the OpenLineage client’s Authorization Bearer header rather
than X-API-Key.
- Around line 35-36: Update the OpenLineage configuration values around
transportUrl and transportEndpoint so their client-composed result is
/api/v1/lineage, preserving the intended localhost server and lineage route.
Ensure the endpoint formatting prevents the client from dropping the /api
prefix.

In `@hack/scripts/get-manifests.sh`:
- Around line 14-18: Update get-manifests.sh to fetch the intended Feast 0.65.0
manifest snapshot using immutable release tags rather than raw commit SHA pins
for both OPENDATAHUB and red-hat-data-services sources. Ensure
infra/feast-operator/config matches the RHOAI 3.5 manifests before committing
the updated references.

---

Outside diff comments:
In `@config/manifests/feastoperator/rbac/role.yaml`:
- Around line 113-139: The RBAC role is missing permission to access
customresourcedefinitions. Restore the generated apiextensions.k8s.io
customresourcedefinitions rule in the role manifest, matching the controller’s
kubebuilder RBAC declaration and required watch-related verbs, without changing
the CRD watch behavior.

---

Nitpick comments:
In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`:
- Around line 35-38: Update the OpenLineage transport configuration around
transportUrl to use an HTTPS endpoint instead of HTTP, and configure the
corresponding service CA for TLS verification. Confirm that the localhost target
is intentional; if it is only a development default, replace it with the
appropriate Kubernetes Service or Marquez hostname while preserving
transportEndpoint and apiKeySecretRef.
- Around line 49-63: Update the enabled consumer configuration around
namespaceMapping and its release overlays to include a Kubernetes NetworkPolicy
restricting POST /api/v1/lineage access to approved producer workloads. Preserve
the existing namespaceMapping visibility rules and ensure the policy is applied
for this multi-tenant deployment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 63c90dec-46de-449b-8489-eaa28eec6b20

📥 Commits

Reviewing files that changed from the base of the PR and between 5d86514 and 69418a2.

📒 Files selected for processing (13)
  • config/manifests/feastoperator/component_metadata.yaml
  • config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml
  • config/manifests/feastoperator/default/related_image_fs_patch.yaml
  • config/manifests/feastoperator/manager/kustomization.yaml
  • config/manifests/feastoperator/overlays/odh/kustomization.yaml
  • config/manifests/feastoperator/overlays/odh/params.env
  • config/manifests/feastoperator/overlays/odh/selector_migration_job.yaml
  • config/manifests/feastoperator/overlays/rhoai/kustomization.yaml
  • config/manifests/feastoperator/overlays/rhoai/params.env
  • config/manifests/feastoperator/overlays/rhoai/selector_migration_job.yaml
  • config/manifests/feastoperator/rbac/role.yaml
  • config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml
  • hack/scripts/get-manifests.sh
💤 Files with no reviewable changes (4)
  • config/manifests/feastoperator/overlays/odh/selector_migration_job.yaml
  • config/manifests/feastoperator/overlays/rhoai/selector_migration_job.yaml
  • config/manifests/feastoperator/overlays/rhoai/kustomization.yaml
  • config/manifests/feastoperator/overlays/odh/kustomization.yaml

Comment on lines +855 to +907
consumer:
description: |-
Consumer configures the OpenLineage consumer (event receiver) that enables
Feast to receive and display lineage from...
properties:
apiKeySecretRef:
description: |-
Reference to a Secret containing the key "api_key" that producers must
provide in the X-API-Key header when sending...
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty.
type: string
type: object
x-kubernetes-map-type: atomic
connectionStringSecretRef:
description: |-
Reference to a Secret containing the key "connection_string" for a separate
lineage database.
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty.
type: string
type: object
x-kubernetes-map-type: atomic
enabled:
description: Enable the OpenLineage consumer.
type: boolean
namespaceMapping:
additionalProperties:
type: string
description: |-
NamespaceMapping maps OpenLineage namespaces to Feast projects for
RBAC-based filtering of lineage data in the UI.
type: object
storeType:
default: sql
description: StoreType is the storage backend for lineage
events. Currently only "sql" is supported.
enum:
- sql
type: string
required:
- enabled
type: object

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

OpenLineage consumer permits enabled: true with no API key at both schema sites (CWE-306). Single root cause: the upstream OpenLineageConsumer type marks only enabled as required, and controller-gen emits that struct twice, so neither copy constrains apiKeySecretRef/connectionStringSecretRef.

  • config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml#L855-L907: add the upstream CEL/required constraint so the regenerated spec schema rejects consumer.enabled: true without a non-empty apiKeySecretRef.name; this is the admission-enforced path.
  • config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml#L7144-L7196: regenerate so the status.applied mirror carries the same constraint, keeping reported state consistent with the validated spec.
📍 Affects 1 file
  • config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml#L855-L907 (this comment)
  • config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml#L7144-L7196
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml` around
lines 855 - 907, Update the upstream OpenLineageConsumer schema constraint so
consumer.enabled: true requires a non-empty apiKeySecretRef.name, then
regenerate both schema copies:
config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml lines
855-907 and 7144-7196. Ensure the CEL/required constraint is present in both the
admission-enforced spec schema and the status.applied mirror.

env:
- name: RELATED_IMAGE_FEATURE_SERVER
value: quay.io/feastdev/feature-server:0.64.0
value: quay.io/feastdev/feature-server:0.65.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Use immutable image digests for all Feast release images.

These mutable 0.65.0 tags allow registry retagging to change code on later deployments, a CWE-494 supply-chain exposure.

  • config/manifests/feastoperator/default/related_image_fs_patch.yaml#L12-L12: replace the feature-server tag with its verified @sha256: digest.
  • config/manifests/feastoperator/overlays/odh/params.env#L1-L2: pin the operator and feature-server images by digest.
  • config/manifests/feastoperator/overlays/rhoai/params.env#L1-L2: pin the operator and feature-server images by digest.
📍 Affects 3 files
  • config/manifests/feastoperator/default/related_image_fs_patch.yaml#L12-L12 (this comment)
  • config/manifests/feastoperator/overlays/odh/params.env#L1-L2
  • config/manifests/feastoperator/overlays/rhoai/params.env#L1-L2
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/default/related_image_fs_patch.yaml` at line
12, Replace the mutable Feast image tags with their verified immutable SHA256
digests: update the feature-server image in
config/manifests/feastoperator/default/related_image_fs_patch.yaml (line 12),
and pin both operator and feature-server images in
config/manifests/feastoperator/overlays/odh/params.env (lines 1-2) and
config/manifests/feastoperator/overlays/rhoai/params.env (lines 1-2).

Comment on lines +11 to 20
- persistentvolumeclaims
- services
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Cluster-wide deletecollection on services/PVCs — bulk-deletion attack surface (CWE-269).

This ClusterRole grants deletecollection on services and persistentvolumeclaims with no namespace scoping or resourceNames. Combined with the ClusterRoleBinding to controller-manager (role_binding.yaml), any compromise of that SA lets an attacker wipe all Services/PVCs in every namespace in one call — a cluster-wide DoS/data-loss vector, not just a single reconcile target.

Scope this down: drop deletecollection unless the controller genuinely needs bulk-delete across all namespaces, or move to namespaced Roles per managed namespace.

As per path instructions, "Verify minimum required permissions only" for RBAC in **/rbac/**/*.yaml.

🧰 Tools
🪛 Trivy (0.72.0)

[error] 7-20: Manage Kubernetes networking

ClusterRole 'manager-role' should not have access to resources ["services", "endpoints", "endpointslices", "networkpolicies", "ingresses"] for verbs ["create", "update", "patch", "delete", "deletecollection", "impersonate", "*"]

Rule: KSV-0056

Learn more

(IaC/Kubernetes)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/rbac/role.yaml` around lines 11 - 20, Remove
the deletecollection verb from the services and persistentvolumeclaims
permissions in the ClusterRole, retaining only the minimum verbs required by the
controller. If bulk deletion is genuinely required, replace the cluster-wide
grant with namespace-scoped Roles limited to managed namespaces.

Source: Path instructions

Comment on lines 21 to 29
- apiGroups:
- ""
resources:
- namespaces
- secrets
verbs:
- get
- list
- patch
- update
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

ClusterRole grants read access to every Secret in the cluster (CWE-200).

get/list/watch on secrets here is unscoped by the ClusterRole — this is not "read a specific Secret," it's "read all Secrets in all namespaces." A compromised controller-manager SA can exfiltrate credentials belonging to unrelated tenants/workloads, not just Feast's own OpenLineage API-key Secrets (see v1_featurestore_openlineage_consumer.yaml).

Trivy flags this as KSV-0041. Read-only verbs reduce but don't eliminate the risk given cluster-wide scope. Prefer namespaced Roles bound only in namespaces where FeatureStore CRs and their Secrets actually live.

As per path instructions, RBAC security requires "Prefer Role over ClusterRole (namespace scoping)" and "Verify minimum required permissions only."

🧰 Tools
🪛 Trivy (0.72.0)

[error] 21-29: Manage secrets

ClusterRole 'manager-role' shouldn't have access to manage resource 'secrets'

Rule: KSV-0041

Learn more

(IaC/Kubernetes)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/rbac/role.yaml` around lines 21 - 29, Replace
the ClusterRole’s cluster-wide Secret access with namespaced Role resources and
corresponding bindings only in namespaces where FeatureStore CRs and their
required Secrets reside. Remove cluster-scoped get/list/watch permissions on
secrets, and retain only the minimum permissions needed for the controller’s
operation.

Source: Path instructions

Comment on lines 30 to 40
- apiGroups:
- ""
resources:
- persistentvolumeclaims
- serviceaccounts
- services
- pods
verbs:
- create
- delete
- deletecollection
- get
- list
- update
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Cluster-wide pod delete/deletecollection — mass pod-termination surface (CWE-269).

New verbs delete and deletecollection on pods at cluster scope mean the operator SA can terminate every pod in every namespace in a single call. If this SA's token leaks (e.g. via a compromised sidecar or misconfigured mount), the blast radius is cluster-wide pod deletion, not just Feast-managed pods.

If this is only needed to clean up feature-server/spark job pods the operator itself creates, scope it to a Role in the target namespace(s) instead of the cluster-scoped rule.

As per path instructions, "Verify minimum required permissions only" for RBAC rules.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/rbac/role.yaml` around lines 30 - 40, Restrict
the pod permissions in the cluster-scoped RBAC rule by removing delete and
deletecollection, and grant those verbs only through namespace-scoped Role
bindings in the namespaces where the operator creates feature-server or Spark
job pods. Preserve only the minimum required pod verbs in the cluster-wide rule.

Source: Path instructions

Comment on lines 53 to +63
- apiGroups:
- apiextensions.k8s.io
- ""
resources:
- customresourcedefinitions
- serviceaccounts
verbs:
- create
- delete
- get
- list
- update
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

serviceaccounts create/update/delete + existing RBAC-object create rights = privilege-escalation primitive (CWE-269).

This rule grants create,update,delete on serviceaccounts cluster-wide. The same ClusterRole (unchanged rule, lines 162-176) can also create clusterrolebindings/clusterroles. Together, a compromised operator identity can mint a new SA and bind it to an arbitrary powerful ClusterRole — a classic RBAC self-escalation path (mitigated only by the absence of bind/escalate verbs, which K8s enforces separately, but still worth minimizing).

Confirm update/delete are actually required by the controller (vs. just create/get/list/watch for tenant SA provisioning) and drop what's unused.

As per path instructions, RBAC security requires verifying "minimum required permissions only" and avoiding patterns that "enable privilege escalation."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/manifests/feastoperator/rbac/role.yaml` around lines 53 - 63, Reduce
the serviceaccounts rule in the ClusterRole to the controller’s verified minimum
permissions: inspect its reconciliation code and retain only the verbs actually
required for tenant service-account provisioning, removing unused update/delete
(and create if unneeded). Ensure the resulting permissions do not provide
unnecessary privilege-escalation capability alongside the existing ClusterRole
and ClusterRoleBinding rules.

Source: Path instructions

Comment on lines +1 to +7
apiVersion: v1
kind: Secret
metadata:
name: openlineage-producer-secret
namespace: feast
stringData:
api_key: "your-marquez-api-key" #pragma: allowlist secret

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Remove plaintext API keys from the sample.

These predictable credentials are committed to Git, and #pragma: allowlist secret only suppresses detection; it does not protect the key. Anyone applying this sample can authenticate as a producer or inject lineage events. This violates CWE-798.

Remove both Secret resources and require SealedSecrets, ExternalSecrets, or pre-provisioned Secrets.

As per path instructions, Kubernetes configuration must contain no plain-text secrets and should use SealedSecrets or external-secrets.

Also applies to: 9-15

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`
around lines 1 - 7, Remove both plaintext Secret resources, including
openlineage-producer-secret and the second resource in this manifest. Replace
them with a SealedSecret or ExternalSecret reference, or require pre-provisioned
Secrets, so the sample contains no API key values or secret allowlist pragmas.

Source: Path instructions

Comment on lines +35 to +36
transportUrl: "http://localhost:8080/api"
transportEndpoint: "v1/lineage"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## candidate file"
if [ -f config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml ]; then
  sed -n '1,90p' config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml
else
  echo "missing file"
fi

echo "## related feeds"
rg -n "transportUrl|transportEndpoint|openlineage|Lineage|featurestore" config/manifests/feastoperator -g '*.yaml' -g '*.yml' || true

echo "## repository manifests mentioning localhost:8088?8080 API"
rg -n "localhost:80(080|88)|/api/v1/lineage|v1/lineage|transportUrl|transportEndpoint" config/manifests/feastoperator || true

echo "## files with OpenLineage docs/versions"
rg -n "OpenLineage|openlineage|VERSION|feast.*version|feastoperator" . -g '!**/.git/**' -g '!vendor/**' | head -200

Repository: opendatahub-io/feast-module-operator

Length of output: 27888


🌐 Web query:

OpenLineage Python HTTPTransport join URL transportUrl transportEndpoint raw http.py

💡 Result:

In the OpenLineage Python client, the HttpTransport mechanism handles the construction of the final request URL by joining a base URL and an endpoint path [1][2]. When configuring HttpTransport, you provide a required url (the base URL) and an optional endpoint [1][3]. If the endpoint is not explicitly provided, it defaults to api/v1/lineage [1][4]. The client's implementation ensures the final target URL is formed by correctly appending the endpoint to the base URL (e.g., url + / + endpoint) [1][5]. Key technical aspects include: 1. Configuration: You define the transport via environment variables (OPENLINEAGE_URL, OPENLINEAGE_ENDPOINT) or a configuration dictionary passed to OpenLineageClient [1][6]. 2. URL Construction: Internally, the HttpTransport class manages these parameters. The url parameter serves as the base, and the endpoint is appended to it to determine the destination for POST requests [1][5]. 3. Implementation: In the source code (typically found in openlineage/client/transport/http.py), the HttpTransport class utilizes these configuration values to initialize the HTTP session and perform requests [2][5]. The recent refactoring of the Python HTTP transport (e.g., PR #3646) has consolidated header and session management to ensure consistency in how these requests are dispatched [7]. For further implementation details, you can review the official OpenLineage Python client repository, specifically the openlineage/client/transport/http.py module and its associated unit tests in test_http.py, which demonstrate the expected joining behavior [5][8].

Citations:


🌐 Web query:

OpenLineage Python client 0.9.0 client transport http.py URL join

💡 Result:

In the OpenLineage Python client version 0.9.0, the HTTP transport does not utilize a complex URL joiner; instead, it typically appends a default or user-configured endpoint path to the provided base URL [1][2]. By default, the OpenLineage HTTP transport appends the path /api/v1/lineage to the base URL provided in the configuration [3][2]. Historically, this endpoint was hardcoded, which led to issues when users needed to specify different paths [4]. While subsequent versions introduced an explicit endpoint configuration option to customize or override this behavior [4], in version 0.9.0, the core HTTP transport implementation essentially concatenates the configured base URL with the default endpoint [2]. Technical implementation details: 1. Base URL: The url parameter provided in the transport configuration (via yaml or environment variables) serves as the base for all HTTP requests [2]. 2. Default Endpoint: Unless specified otherwise, /api/v1/lineage is appended to the base URL [2]. 3. Concatenation: Developers working with the client often verify this behavior by checking the final constructed URL against the expected full path, such as http://backend:5000/api/v1/lineage [1]. If you are encountering issues with URL construction, ensure that your base URL does not contain a trailing slash that might conflict with the appended endpoint path, as standard string concatenation or simple URL joining methods may result in double slashes in the final request URL [1][2].

Citations:


🌐 Web query:

OpenLineage Python client 0.8.0 client transport http.py URL join

💡 Result:

In the OpenLineage Python client, the HTTP transport is configured using a base URL and an optional endpoint [1][2]. The client handles the construction of the final request URL by appending the specified endpoint to the base URL [1][2]. While the implementation details in the http.py module have evolved (for example, via refactors to standardize session and header management [3]), the standard behavior for URL resolution involves combining the configured base URL with the endpoint path, which defaults to api/v1/lineage if not otherwise specified [2][4]. Users do not typically need to manually perform a URL join; rather, they provide the url and endpoint in the HttpConfig or via environment variables (OPENLINEAGE_URL and OPENLINEAGE_ENDPOINT), and the internal HttpTransport logic manages the request formation [1][2]. When using the client, ensuring the base URL does not conflict with the appended endpoint path (such as trailing slashes) is standard practice in Python's request handling, which the client's internal transport logic is designed to accommodate [2]. If you are investigating specific behavior in version 0.8.0, note that this version is significantly older than the current releases. Modern versions of the OpenLineage Python client utilize a more robust configuration factory, and if you are experiencing issues with URL joining, it is recommended to verify the OPENLINEAGE_URL and OPENLINEAGE_ENDPOINT environment variables or the HttpConfig dictionary provided to the HttpTransport class [2][5].

Citations:


🌐 Web query:

Feast 0.65.0 OpenLineage version

💡 Result:

Feast version 0.65.0, released on July 20, 2026, introduced significant native support for OpenLineage [1][2][3]. Key highlights regarding this integration include: - OpenLineage Consumer: Feast 0.65.0 added an OpenLineage Consumer, which allows the system to receive, store, and visualize cross-producer lineage [1][4][2]. - Native Integration: The release provides native integration enabling automatic lineage tracking for ML feature engineering workflows [5][6]. It captures events without requiring code changes, provided the integration is enabled in the feature_store.yaml configuration file [5][6]. - Automatic Event Emission: The integration automatically emits OpenLineage events for key operations, specifically during feast apply (when registering feature definitions) and feast materialize (when populating the online store) [5][6][7]. - Configuration: To use this feature, users must enable it in their feature_store.yaml [5][6]. It is an optional dependency that can be installed via pip install feast[openlineage] [6][7]. This release represents a major update to Feast's lineage capabilities, shifting from simply emitting lineage events to also having the ability to consume and visualize them [1][2].

Citations:


🌐 Web query:

site:github.com/feast-dev/feast requirements.txt openlineage-python 0.65.0

💡 Result:

As of July 29, 2026, there is no standalone Python package named openlineage-python version 0.65.0. The version 0.65.0 mentioned in your query refers to a recent release of the Feast feature store project (feast-dev/feast), released on July 20, 2026 [1]. In the context of the Feast project, the dependency on openlineage-python is managed within the project's pyproject.toml file, which specifies a requirement of openlineage-python>=1.40.0 [2][3]. The Feast project includes openlineage-python as a dependency for its OpenLineage integration features [4][5][6]. If you are attempting to configure or manage requirements for a Python environment using these tools, you should reference the official Feast documentation or pyproject.toml for compatible versions, rather than seeking a version of openlineage-python that aligns with the Feast release number [2][3].

Citations:


🌐 Web query:

site:github.com/OpenLineage/OpenLineage client/python http.py join_url transportUrl transportEndpoint

💡 Result:

In the context of OpenLineage and related integrations, transportUrl and transportEndpoint are configuration parameters used to define the destination for lineage metadata events [1]. Specifically, transportUrl typically refers to the base URL of an OpenLineage-compatible server (such as Marquez), while transportEndpoint specifies the relative path or API endpoint to which the lineage events should be sent [1]. These parameters are often defined in configuration files (e.g., YAML) for various integrations, such as Feast, to enable HTTP transport for event emission [1]. The reference to join_url and http.py in a Python client context generally relates to internal utility functions used for constructing valid HTTP request URLs by joining a base URL with specific path components. While these are common patterns in networking and API client implementations, they are fundamental mechanisms for correctly formatting the destination addresses composed of transportUrl and transportEndpoint [2]. For example, a typical configuration setup for these values would look like this [1]: transportType: http transportUrl: "http://example-server.com:5000" transportEndpoint: "api/v1/lineage" The Python client or relevant integration logic would then use a utility (often named join_url or similar) to ensure the final request URL is correctly formed by combining these components [2].

Citations:


🌐 Web query:

http://localhost:8080/api http://localhost:8080 v1/lineage uri join Python

💡 Result:

The URI structure http://localhost:8080/api/v1/lineage is a common pattern for interacting with data lineage APIs in various data catalog and orchestration systems [1][2]. Because localhost:8080 is a default development port, this specific path appears in the documentation for several different projects, including EdgeQuake [3], Marquez [4], Feast [1], and other platforms using OpenLineage [1]. To interact with these endpoints using Python, you should generally avoid raw HTTP requests if an official SDK is available, as these provide structured objects instead of raw JSON [3][4]. If you are using a library like requests to manually query such an API, you can use the following pattern: import requests base_url = "http://localhost:8080/api/v1" lineage_endpoint = f"{base_url}/lineage" # Example: Fetching lineage for a specific entity or document # Note: Check the specific API documentation for required parameters like node_id or workspace_id params = {"node_id": "your-entity-id"} response = requests.get(lineage_endpoint, params=params) if response.status_code == 200: data = response.json print(data) else: print(f"Failed to fetch lineage: {response.status_code}") Key considerations for these APIs: 1. Path Variations: While /api/v1/lineage is common, many systems use sub-paths like /api/v1/lineage/documents/{id} or /api/v1/lineage/entities/{name} depending on the specific resource you are querying [3][5][2]. 2. Authentication: Many production or containerized instances require headers such as Authorization: Bearer <token> or workspace-specific headers (e.g., X-Workspace-ID) [6][5][7]. 3. SDKs: Always check if the specific tool you are using (e.g., OpenMetadata, Marquez) provides a native Python client, as these usually handle URL construction and authentication automatically [3][8][4].

Citations:


🌐 Web query:

"join_url" "http://localhost:8080/api" "v1/lineage"

💡 Result:

The URL http://localhost:8080/api/v1/lineage is a local development endpoint typically associated with data lineage management APIs [1]. Based on industry documentation, endpoints structured as /api/v1/lineage are used in data governance and metadata management platforms—most notably OpenMetadata—to programmatically add, update, or retrieve information about data dependencies (such as relationships between tables, dashboards, and pipelines) [1][2]. When interacting with this specific endpoint in a development environment: 1. Local context: The http://localhost:8080 base indicates a service running on your local machine, commonly configured in tools like OpenMetadata or similar containerized applications [3][4][2]. 2. Usage: This endpoint typically accepts PUT or GET requests to manage lineage graphs [1][2]. For example, in OpenMetadata, a PUT request to {base_url}/api/v1/lineage is used to define an edge between two entities (e.g., a source table and a target table) [1]. 3. Security: If you are accessing this on your local machine, ensure you have the correct authentication headers (such as a Bearer token) if the service is configured with security enabled [1][2]. If you are encountering connection issues with this URL, ensure that the corresponding service is active and listening on port 8080 [3][4]. If you are working with a different API that uses a parameter named join_url, note that this parameter is common in video conferencing integrations (e.g., Zoom, Microsoft Teams) for joining meetings, and is distinct from the /v1/lineage path mentioned [5][6][7].

Citations:


🌐 Web query:

urllib.parse urljoin "http://localhost:8080/api" "v1/lineage"

💡 Result:

Using urllib.parse.urljoin('http://localhost:8080/api', 'v1/lineage') will result in the URL 'http://localhost:8080/v1/lineage' [1][2]. This occurs because urljoin treats the base URL 'http://localhost:8080/api' as if it refers to a file or resource at the end of a directory structure [2][3]. When joining it with a relative path that does not start with a slash, the function removes the last segment of the base path (everything after the final '/') before appending the new component [2][4][5]. To obtain the expected path 'http://localhost:8080/api/v1/lineage', you should ensure the base URL ends with a trailing slash [2][3][6]. Example: from urllib.parse import urljoin print(urljoin('http://localhost:8080/api/', 'v1/lineage')) # Output: 'http://localhost:8080/api/v1/lineage' [2][3]

Citations:


🌐 Web query:

site:github.com/OpenLineage/OpenLineage "def join_url" "class HttpTransport" client/python src/openlineage/client/transport/http.py

💡 Result:

There is no join_url method defined in the HttpTransport class within the OpenLineage Python client's client/python/src/openlineage/client/transport/http.py file. The OpenLineage Python client handles URL construction and endpoint management primarily through the HttpConfig configuration object, which allows users to specify both a base url and a specific endpoint (or path) [1][2][3]. Historically, the OpenLineage Python client automatically appended a default path (e.g., /api/v1/lineage) to the configured OPENLINEAGE_URL [2]. To address limitations where this hardcoded path was not desired, the client was updated to allow explicit configuration of the endpoint via HttpConfig [4]. If you are looking for how the client manages URLs, it uses standard library utilities (such as urllib.parse) to join or manipulate paths when building request URLs [5][6]. Recent refactoring of the Python HTTP transport has centralized session management and header configuration, but it does not implement a custom join_url utility method within the HttpTransport class itself [3][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from urllib.parse import urljoin

cases = [
    ("http://localhost:8080/api", "v1/lineage"),
    ("http://localhost:8080/api/", "v1/lineage"),
    ("http://localhost:8080", "api/v1/lineage"),
    ("http://marquez.feast.svc.cluster.local:5000", "api/v1/lineage"),
]
for base, endpoint in cases:
    print(f"{base!r} + {endpoint!r} = {urljoin(base, endpoint)!r}")
PY

Repository: opendatahub-io/feast-module-operator

Length of output: 551


Fix the composed OpenLineage endpoint.

The OpenLineage HTTP client joins transportUrl and transportEndpoint; http://localhost:8080/api + v1/lineage resolves to /v1/lineage, not POST /api/v1/lineage, so Feast will not receive lineage events.

-    transportUrl: "http://localhost:8080/api"
+    transportUrl: "http://localhost:8080"
-    transportEndpoint: "v1/lineage"
+    transportEndpoint: "api/v1/lineage"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
transportUrl: "http://localhost:8080/api"
transportEndpoint: "v1/lineage"
transportUrl: "http://localhost:8080"
transportEndpoint: "api/v1/lineage"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`
around lines 35 - 36, Update the OpenLineage configuration values around
transportUrl and transportEndpoint so their client-composed result is
/api/v1/lineage, preserving the intended localhost server and lineage route.
Ensure the endpoint formatting prevents the client from dropping the /api
prefix.

Comment on lines +35 to +38
transportUrl: "http://localhost:8080/api"
transportEndpoint: "v1/lineage"
apiKeySecretRef:
name: openlineage-producer-secret

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euopipefail

echo "Files:"
fd -a 'v1_featurestore_openlineage_consumer\.yaml|openlineage|feastoperator|consumer.yaml' . | sed 's#^\./##' | head -200

echo
echo "Target file excerpt:"
cat -n config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,120p'

echo
echo "Search secret/object references:"
rg -n "openlineage-(producer|consumer)-secret|transportUrl|transportEndpoint|apiKeySecretRef|Authorization|X-API-Key|http.py|Producer|Consumer" config manifests -S || true

echo
echo "Diff stat/summary:"
git diff --stat || true
git diff -- config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,220p' || true

Repository: opendatahub-io/feast-module-operator

Length of output: 827


🏁 Script executed:

#!/bin/bash
set -euopipefail

echo "Target file excerpt:"
cat -n config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,140p'

echo
echo "Search secret/object references:"
rg -n "openlineage-(producer|consumer)-secret|transportUrl|transportEndpoint|apiKeySecretRef|Authorization|X-API-Key|http.py|Producer|Consumer" config manifests -S || true

echo
echo "Diff stat:"
git diff --stat || true
echo
echo "Target diff excerpt:"
git diff -- config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,260p' || true

Repository: opendatahub-io/feast-module-operator

Length of output: 827


🏁 Script executed:

#!/bin/bash
set -e

echo "Workdir:"
pwd || true
echo
echo "Target file excerpt:"
if [ -f config/_manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml ]; then
  cat -n config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,160p'
elif [ -f config/_manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml ]; then
  cat -n config/_manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,160p'
else
  fd -a 'v1_featurestore_openlineage_consumer\.yaml' . | sed -n '1,40p'
fi

echo
echo "Search secret/object references:"
rg -n "openlineage-(producer|consumer)-secret|transportUrl|transportEndpoint|apiKeySecretRef|Authorization|X-API-Key|http.py|Producer|Consumer" config manifests -S || true

echo
echo "Diff stat:"
git diff --stat || true
if [ -f config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml ]; then
  git diff -- config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,260p' || true
elif [ -f config/_manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml ]; then
  git diff -- config/_manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,260p' || true
fi

Repository: opendatahub-io/feast-module-operator

Length of output: 3989


🏁 Script executed:

#!/bin/bash
set -e

echo "Target sample:"
cat -n config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml | sed -n '1,90p'

echo
echo "CRD excerpts around producer/consumer validation:"
for line in 835 850 860 915 930 7125 7140 7150 7200 7220; do
  echo "--- lines $((line-8)) to $((line+8))"
  sed -n "$((line-8)),$((line+8))p" config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml | cat -n
done

echo
echo "Find Feast version references:"
rg -n "Feast|0\.65\.0|openlineage|OpenLineage|FeastAdapter|FeatureStore|materialization" README.md pyproject.toml setup.cfg setup.py config manifests -S || true

echo
echo "Search implementation references to producer/consumer/OpenLineage auth headers:"
rg -n "openlineage|OpenLineage|X-API-Key|Authorization|Bearer|apiKey|apiKeySecretRef|FeastAdapter|featurestore.*(producer|consumer)|producer|consumer" . -g '!config/manifests/feastoperator/crd/bases/feast.dev_featurestores.yaml' -S | rg -n "openlineage|X-API-Key|Authorization|Bearer|apiKey|api_key|FeastAdapter|producer|consumer" | sed -n '1,240p' || true

Repository: opendatahub-io/feast-module-operator

Length of output: 46243


🌐 Web query:

OpenLineage Python HTTPTransport HTTP header Authorization Bearer X-API-Key feast 0.65.0

💡 Result:

In Feast 0.65.0, the OpenLineage integration is configured within the feature_store.yaml file [1][2]. To use an Authorization Bearer token with the OpenLineage HTTP transport, you should leverage the built-in authentication support rather than attempting to pass an "X-API-Key" header manually [3][4]. The OpenLineage Python client supports api_key authentication directly, which automatically constructs the Authorization: Bearer <token> header [3][5]. 1. Configuration in feature_store.yaml: You can configure the authentication in your feature_store.yaml under the openlineage section [1][2]. While the standard Feast documentation lists api_key as a top-level option [1][2], the underlying OpenLineage Python client (which Feast uses) accepts an auth configuration block for more complex setups [3][4]. If your environment requires it, you can provide the API key as follows: openlineage: enabled: true transport_type: http transport_url: http://your-backend-url # The api_key option here is mapped to the OpenLineage client's auth configuration api_key: your_bearer_token 2. Using Custom Headers (if required): If you specifically need to pass a header named "X-API-Key" (rather than the standard Authorization header), the OpenLineage Python client supports custom_headers [5][6][7]. Note that this is typically done via the OpenLineage Python client's HttpConfig [5][6]. If you are configuring the transport via environment variables, you can set custom headers using OPENLINEAGETRANSPORTCUSTOM_HEADERS (e.g., as a JSON string) or through the HttpConfig object if you are initializing the client programmatically [3][5][6]. Summary for Feast 0.65.0: - Standard Bearer Auth: Use the api_key configuration option in feature_store.yaml [1][2]. The OpenLineage client handles the conversion to Authorization: Bearer <key> [5]. - Custom Headers: If you must use a header literally named X-API-Key, you would need to configure the custom_headers attribute of the OpenLineage HttpConfig [5][6]. Feast 0.65.0 introduced significant updates, including the ability for Feast to act as an OpenLineage consumer, but the producer-side HTTP transport configuration remains consistent with the standard OpenLineage Python client [8][9][10][2].

Citations:


Align OpenLineage producer credentials and header contract.

This sample points self-emitted lineage at localhost but uses openlineage-producer-secret, while the Feast consumer accepts openlineage-consumer-secret via X-API-Key. For self-ingestion, use the consumer contract for both halves; for an external Marquez/OpenLineage target, use the producer secret. Also reconcile Feast 0.65.0 OpenLineage HTTP auth — the OpenLineage Python client sends Authorization: Bearer, not X-API-Key by contract. CWE-306/494 authentication/authorization exposure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@config/manifests/feastoperator/samples/v1_featurestore_openlineage_consumer.yaml`
around lines 35 - 38, Align the OpenLineage settings around transportUrl and
apiKeySecretRef: for the localhost self-ingestion target, use
openlineage-consumer-secret and the Feast consumer authentication contract; for
external Marquez/OpenLineage targets, retain openlineage-producer-secret.
Reconcile the HTTP authentication configuration with Feast 0.65.0 so credentials
are sent through the OpenLineage client’s Authorization Bearer header rather
than X-API-Key.

Comment on lines +14 to +18
COMMIT_SHA="863b09f490926aec0df1b92d34d7acd8b26f2dde"
else
echo "Downloading manifests for RHOAI"
REPO_URL="https://github.com/red-hat-data-services/feast"
COMMIT_SHA="c6acffd77c392bdd4f99588a302071cfdee0f711"
COMMIT_SHA="90e6fe62d917887a17f0fe8a2bf489d5723777db"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

verify_sha() {
  local repo="$1"
  local sha="$2"
  local tmp_dir
  tmp_dir="$(mktemp -d)"
  trap 'rm -rf -- "$tmp_dir"' RETURN

  git -C "$tmp_dir" init -q
  git -C "$tmp_dir" remote add origin "$repo"
  git -C "$tmp_dir" fetch --depth 1 -q origin "$sha"
  test "$(git -C "$tmp_dir" rev-parse FETCH_HEAD)" = "$sha"
}

verify_sha \
  "https://github.com/opendatahub-io/feast" \
  "863b09f490926aec0df1b92d34d7acd8b26f2dde"

verify_sha \
  "https://github.com/red-hat-data-services/feast" \
  "90e6fe62d917887a17f0fe8a2bf489d5723777db"

Repository: opendatahub-io/feast-module-operator

Length of output: 174


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect the script and local RHOAI manifests without executing repository code.
printf '--- get-manifests.sh lines 1-45 ---\n'
sed -n '1,45p' hack/scripts/get-manifests.sh
printf '\n--- tracked files matching feast-operator/config (RHOAI/repo) ---\n'
git ls-files | rg '(^|/)(feast|rhoai|3\.5|RHOAI|RHOAI)' | sed -n '1,120p'
printf '\n--- path count ---\n'
git ls-files | rg '(^|/)infra/feast-operator/config' | wc -l
printf '\n--- sample manifest headers if present ---\n'
git ls-files | rg '(^|/)infra/feast-operator/config' | head -20 | xargs -r -n1 sh -c 'echo "--- $0"; sed -n "1,40p" "$0"' 2>/dev/null || true

Repository: opendatahub-io/feast-module-operator

Length of output: 265


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect the script and local RHOAI manifests without executing repository code.
printf '%s\n' '--- get-manifests.sh lines 1-45 ---'
sed -n '1,45p' hack/scripts/get-manifests.sh
printf '%s\n' '--- tracked files matching feast-operator/config ---'
git ls-files | rg '(^|/)(feast|rhoai|3\.5|RHOAI|RHOAI)\' || true
printf '%s\n' '\n--- tracked infra/feast-operator/config files ---'
git ls-files | rg '(^|/)infra/feast-operator/config/' || true
printf '%s\n' '\n--- path count ---'
git ls-files | rg '(^|/)infra/feast-operator/config' | wc -l
printf '%s\n' '\n--- sample manifest headers if present ---'
git ls-files | rg '(^|/)infra/feast-operator/config' | head -20 | xargs -r -n1 sh -c 'echo "--- $0"; sed -n "1,20p" "$0"' 2>/dev/null || true

Repository: opendatahub-io/feast-module-operator

Length of output: 1939


Pin manifests to a release, not arbitrary commits.

get-manifests.sh downloads directly from commit pins (OPENDATAHUB and red-hat-data-services) instead of an immutable tag, so a malformed upstream commit at either CWE-78 shell script target can supply invalid manifests at runtime. Pin these to the intended Feast 0.65.0 manifest snapshot and validate that infra/feast-operator/config matches RHOAI 3.5 manifests before checking them in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hack/scripts/get-manifests.sh` around lines 14 - 18, Update get-manifests.sh
to fetch the intended Feast 0.65.0 manifest snapshot using immutable release
tags rather than raw commit SHA pins for both OPENDATAHUB and
red-hat-data-services sources. Ensure infra/feast-operator/config matches the
RHOAI 3.5 manifests before committing the updated references.

@jyejare
jyejare merged commit a2e538d into main Jul 29, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants