How to handle contract to contract address verification (e.g minter roles)

Hello everyone, sorry for the weird title I'm just not sure how to explain it.

Basically what I want to do is I have contract A, contract B, contract C. I have my operator wallet (EOA). What I want to do is

Operator(EOA) calls a function that contract A expects contract B address to be calling from. So I expect the msg.sender to be contract B address when calling a function to contract A.

I heard that you can do it with delegatecall but it doesn't work with openzeppelin upgradeable contracts.

Same with Contract C I make an external call(through operator EOA) to C which calls contract A and B with the msg.sender being C.

Let me know if there's any way to achieve this through upgradeable contracts since it doesnt work.