Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oidc-agent-service does not persist on Mac #341

Open
nulltrope opened this issue Aug 11, 2021 · 8 comments
Open

oidc-agent-service does not persist on Mac #341

nulltrope opened this issue Aug 11, 2021 · 8 comments

Comments

@nulltrope
Copy link
Contributor

I'm not sure if this is the intended behavior or not, but oidc-agent (when launched with eval oidc-agent-service use``) does not persist when the shell session is restarted on Mac.

I haven't fully dug into the oidc-agent-service script but I am guessing because it simply sets an env var OIDC_SOCK that it will never persist between shell sessions.

Are there any plans to add support for persisting the agent between shell sessions? Unfortunately for Mac I think it would require integrating with launchd to ensure the process is tied to the user's login session instead of just the terminal session.

Also semi-related, sometimes when restarting oidc-agent in a new shell session, accounts are unloaded and need to be manually re-added. Unclear if that is a bug or feature, but I expected accounts to stay loaded even across agent restarts.

@zachmann
Copy link
Collaborator

For simple starts without any integration (see below), this behavior is expected.
As you already guessed, starting the agent with eval sets the environment variable OIDC_SOCK. This is also basically the same for oidc-agent and oidc-agent-service. The main difference here is, that oidc-agent uses a socket with a random name. oidc-agent-service will link this random socket to a well defined location, making integration a lot easier.

When you start the agent the env var is only set in that terminal, it won't be set in other already open terminals. But you can set the OIDC_SOCK env var also there.
Also note, that if you close that terminal, the agent should still be running, however you need the value of OIDC_SOCK to reach it.

For the integration/persistence:
On linux we have integration with Xsession, this way the agent is automatically started at the beginning and available throughout the whole session. But this won't work on MacOS.

The easiest way to achieve persistence / integration throughout terminals is to use oidc-agent-service (as you already do).
Starting the agent with eval `oidc-agent-service use` still sets the environment variable only in that shell. However, OIDC_SOCK will be set to well defined value, that doesn't change. It is /tmp/oidc-agent-service/$UID/oidc-agent.sock.
Including something like export OIDC_SOCK=/tmp/oidc-agent-service/1000/oidc-agent.sock in your .bashrc (or similar file) should do the trick.
Now the env var should be available in all terminals you open. Also the agent can be restarted (using oidc-agent-service without loosing this integration).

On your last point: It is expected that after a restart all loaded accounts are unloaded. The agent is always started with no accounts loaded.
(Note, that we have an auto-load feature so you don't have to load the accounts manually with oidc-add, instead if you use oidc-token with an account configuration that is not already loaded, the agent will prompt you for the encryption password and load the account before returning the access token. However, this requires our prompting utility oidc-prompt which on mac depends on pashua which can be installed with brew cask install pashua, but it is likely that you already did and knew this.

@nulltrope
Copy link
Contributor Author

It is /tmp/oidc-agent-service/$UID/oidc-agent.sock.
Including something like export OIDC_SOCK=/tmp/oidc-agent-service/1000/oidc-agent.sock in your .bashrc (or similar file) should do the trick.

I see, for some reason it was stored under /tmp/oidc-agent-service/502/oidc-agent.sock for me (I did start with oidc-agent-service in a previous session). I did confirm that setting the OIDC_SOCK env var to this location worked.

Perhaps a followup question would be: is there any appetite for adapting oidc-agent-service to run as a native launch daemon/agent under MacOS? I think there would be minimal (if any) code changes, and it would greatly improve the user experience on Mac. I believe it would also make logging much easier, which is a TODO item for Mac currently. If this seems like it would be worthwhile, I can at least do an initial investigation/proof of concept.

However, this requires our prompting utility oidc-prompt which on mac depends on pashua

I was a bit confused by this, because there are some features (such as oidc-add --print) which also require the encryption password, but do so in the terminal and do not require pashua. Is there any reason why providing the encryption password for auto-loading an account can't also just be provided in the terminal?

@zachmann
Copy link
Collaborator

Perhaps a followup question would be: is there any appetite for adapting oidc-agent-service to run as a native launch daemon/agent under MacOS? I think there would be minimal (if any) code changes, and it would greatly improve the user experience on Mac. I believe it would also make logging much easier, which is a TODO item for Mac currently. If this seems like it would be worthwhile, I can at least do an initial investigation/proof of concept.

I'm not familiar with how these things work on MacOS, so you should know this better. On Linux we are integrated with Xsession which calls oidc-agent-service use (with some checks) at the beginning of the session. A similar approach is absolutely appreciated also for MacOS. I would prefer a way with no changes to the existing code. However, it would not be a problem to add an additional command to oidc-agent-service, e.g. start-mac-service similar to start-from-x.
If it would be necessary we also can do changes to oidc-agent itself.
So feel free, to investigate and try this out. It is much appreciated. I'm no Mac user so it's a bit difficult for me to develop and test Mac features, but we are very happy to see oidc-agent also being used on Mac.

However, this requires our prompting utility oidc-prompt which on mac depends on pashua

I was a bit confused by this, because there are some features (such as oidc-add --print) which also require the encryption password, but do so in the terminal and do not require pashua. Is there any reason why providing the encryption password for auto-loading an account can't also just be provided in the terminal?

Yes there is a simple (technical) reason (well, actually there are two sides on that issue, the other side is privacy/security):

  • Privacy/Security: In the oidc-agent context oidc-gen and oidc-add are "trusted" application, it is ok, if the user gives them the encryption password, they decrypt the account config, and sent it to the agent. oidc-token on the other hand is just an application that wants to receive access tokens from the agent. In this way it is not different from other applications that want to do the same (we provide libraries for different languages, so that other applications can easily integrate with the agent). So when an application requests an AT for an account that is not loaded, we want to automatically load it, but therefore need the encryption password from the user. This password (and the decrypted config) should not be given to that applications (agent clients), so the agent has to ask the user itself.
  • Technical: And now comes the technical reason: While oidc-add/oidc-gen are called by the user from a terminal, oidc-agent runs as a daemon in the background and has no terminal attached. So it is just that oidc-add/oidc-gen can do the prompting easily on the terminal, while the agent just cannot do terminal prompting.

@marcvs
Copy link
Collaborator

marcvs commented Aug 17, 2021

As a more general piece of information: We currently have one person working on the windows integration. This will add some minimal GUI. I'm not sure how portable this is going to be, but I could imagine, that the ideas could be taken a step further in porting this to MacOs.

@nulltrope
Copy link
Contributor Author

@zachmann

Technical: And now comes the technical reason: While oidc-add/oidc-gen are called by the user from a terminal, oidc-agent runs as a daemon in the background and has no terminal attached. So it is just that oidc-add/oidc-gen can do the prompting easily on the terminal, while the agent just cannot do terminal prompting.

Ahh I see, that makes sense. Unfortunately that may make running oidc-agent under launchd a bit difficult because (from what I have read) Mac does not allow launchd-managed services to have any sort of GUI/prompts, but I would need to dig into it further.

@marcvs

As a more general piece of information: We currently have one person working on the windows integration. This will add some minimal GUI. I'm not sure how portable this is going to be, but I could imagine, that the ideas could be taken a step further in porting this to MacOs.

Thanks that is good to know- would definitely be interested in seeing some improvements there ported to Mac.

@nulltrope
Copy link
Contributor Author

@zachmann revisiting this after a bit- It sounds like natively integrating with launchd will be a pretty big lift, at least more than I have time to commit to right now.

I think a reasonable workaround would be just instructing users to add a line such as eval "$(oidc-agent-service use)" to their bashrc/zshrc file, which will effectively load or start the agent service at the beginning of any new session. This seems to work except the use command always prints the PID to the terminal, which is not desirable. Would it be possible to either edit the use command or add a new subcommand/flag to oidc-agent-service that silently starts the agent without printing anything to the terminal?

@zachmann
Copy link
Collaborator

zachmann commented Oct 7, 2021

Just append >/dev/null at the end, i.e. eval $(oidc-agent-service use) >/dev/null should do the trick.

@giffels
Copy link

giffels commented Jan 26, 2023

If it helps, I can shortly describe my favorite setup on Mac OS. I prefer to use the LaunchAgents mechanism to startup
daemons during the login process.

Installation

I used Homebrew to install oidc-agent as described in the documentation.

brew tap indigo-dc/oidc-agent
brew install oidc-agent

Setup a LaunchAgent

User defined LaunchAgents are located in /Users/<username>/Library/LaunchAgents. In that directory, I created a file called edu.kit.oidc-agent.plist. You can choose a different name as you like. The file contains the following xml style content.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>KeepAlive</key>
    <true/>
  <key>EnvironmentVariables</key>
    <dict>
      <key>OIDC_SOCK</key>
      <string>/Users/<username>/.cache/oidc-agent/oidc-agent.sock</string>
      <key>PATH</key>
      <string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/homebrew/bin</string>
    </dict>
  <key>Label</key>
  <string>oidc-agent</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/local/bin/oidc-agent</string>
    <string>-a</string>
    <string>/Users/<username>/.cache/oidc-agent/oidc-agent.sock</string>
    <string>-d</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>StandardErrorPath</key>
  <string>/usr/local/var/log/oidc-agent.log</string>
</dict>
</plist>

you have to replace <username> with the username on your system. Please, be aware that you can use only a limited set of environment variables here. $HOME does not work for example. In addition, if you use a ARM-based Mac, you have to exchange every /usr/local by /opt/homebrew, since the base directory of Homebrew changed for ARM-based Macs. Potentially, it also a good idea to manual create the directory /Users/<username>/.cache/oidc-agent/ before loading the LaunchAgent.

After creating the file, you can load it with

launchctl load -w edu.kit.oidc-agent.plist

Doing a simple ps aux | grep oidc should show that an agent is running.

ps aux | grep oidc                        
<username>          88214   0,0  0,0 34186308    208   ??  S    Mi02pm    0:00.03 /usr/local/bin/oidc-agent -a /Users/<username>/.cache/oidc-agent/oidc-agent.sock -d

Now the last step is to incude the following line in your .zshrc:

export OIDC_SOCK=/Users/<username>/.cache/oidc-agent/oidc-agent.sock 

and open a new shell or run source .zshrc.

Now LaunchAgent takes care that always an oidc-agent is running and points to the right socket.

To complete the oidc-agent setup follow the instructions in the documentation.

The instructions work at least on my Intel with MacOs Monterey Version 12.6.3, but I think they will work on other versions as well.

Hope that helps,
Manuel

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

No branches or pull requests

4 participants