-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Periodically refresh git OAuth2-tokens for GitLab and Bitbucket (expiration 2h) #21291
Comments
Hi Nils, right now the tokens are validated only during workspace startup, and didn't refreshed during runtime. |
Generally you're right. GitLabs Access Tokens are quite "short-living". Most applications we have integrated with, use something from a couple of days to months, but still require tokens to get refreshed as well. GitLab allows creating tokens that don't expire, but that's deprecated. I'll check if restarting the workspace solves the issue... |
@mshaposhnik Simply restarting a workspace does not fix it. It looks like the authentication procedure is skipped in this case. Starting a new workspace works. This seems to update the token. |
Right, i've looked again and seems validation is now possible only on factory acceptance stage, when all the necessary conditions are met (e.g. we know the remote URL, user is able to interact with OAuth and workspace is running). Even on WS startup we did not have them, so all we can is to cleanup outdated token which is not helps much with UX. We will continue to think about possible solution. |
@mshaposhnik Since GitLab has now removed the Git credential secret-file is also mounted read only, which prevents users from making any change to the file. Am I missing something? From a user perspective this actually makes the GitLab integration unusable after 2h since they won't be able to push and pull their changes. Bottom lined: If a user opens a new workspace from a GitLab repository that's what he could do in order to get changes back to the origin after 2h:
I'm not sure if the setting in /config/initializers/doorkeeper.rb will allow to set expiration to a much higher value (e.g. 1 Month). We'll give it a try (https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/doorkeeper.rb#L38) At least gitlab.com does not have this option. Same should be the case on Bitbucket. At least the documentation mentions "Our access tokens expire in two hours."(https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/#OAuthonBitbucketCloud-Refreshtokens). From what I can see, one solution could be to store the refresh token and expiration info in Despite the expiration issue, OAuth integration acutally performs quite well in the latest release. :) References: |
changing |
Based on your feedback @nils-mosbach I think this is becoming critical. I am setting the priority to P1. The DevWorkspace controller cannot periodically refresh the tokens (its responsibility is to reconcile DevWorkspaces) but there are a couple of things that come to my mind. First, if OAuth is configured and there is a secret with a previously generated token, Che should always check it at startup. If the token has expired, Che should generate a new one. That has been fixed for GitHub but not for GitLab and Bitbucket. @vinokurig can you confirm? Second, those short lived tokens look problematic for development. When using a workspace for more than 2 hours the token should be refreshed at runtime but with current mechanism (secret mount) that requires a workspace restart. An hybrid mechanism (OAuth token for workspace startup and SSH key mounted in the workspace) looks like a better solution. @nils-mosbach what do you think? |
I would say that this issue is similar to #21421 but for GitLab and Bitbucket. |
@l0rd Gitlab and Bitbucket already work like GitHub in the scope of #21421. The reason of this issue is to catch an event when an oauth token has expired and regenerate it. |
I do not think we need to refresh the token during runtime, refreshing it during workspace startup should be enough. @vinokurig I actually thought that the token is refreshed during workspace startup already if expired, no? |
Unfortunatelly no, we check it only when creating a new factory. |
@vinokurig ok, so I believe we need to check it on workspace startup and if there is exception - renew the token |
From a user perspective I consider it mandatory that tickets are refreshed during workspace runtime. I guess that most developers tend to spend more than two hours on a project/ task/ workspace. I don't think users get the reason when and why they must restart in order to push changes. That also leads to bad habbits, like "do it quick, otherwise you have to restart". The idea of using oauth is that users don't have to deal with authentication.
Problem here would be that if I have a devfile that points to the origin I'm not a 100% sure which solution would be the best. @l0rd You're right, devworkspace Operator would definately the wrong place. I'm summarizing a couple of ideas. Remove read only flag I would at least remove the - mountPath: /.git-credentials/credentials
name: devworkspace-merged-git-credentials
readOnly: true # remove this flag
subPath: credentials Store refresh token I think we should include the refresh token in the Allow for kubernetes updates on secret contents Correct me if I'm wrong, but from what I know, secret file mounts are updated if you don't use subPath. That might allow updating the token without restarting the workspace. So it doesn't depend which process updates the secret, credentials should get updated in the running workspaces. since - mountPath: /.git-credentials
name: devworkspace-merged-git-credentials Update access tokens based on refresh tokens At the end we might just call the refresh url of the OAuth provider and pass the updated token to the secret. I'm not sure whats the best place to do this right now, but as a quick solution I could think of a VSCode Plugin that handles refreshing tokens. Another idea would be if che server is responsible for creating these secrets we could create an endpoint that's triggered after a couple of minutes like "refresh-my-tokens". That could also be done by a vscode plugin, or by the same mechanism that triggers the keep-alive-signal for active workspaces (which otherwise suspend after 15'). But I'm not a 100% sure how that's implemented at the moment. Dashboard could handle this api endpoint as well, if che-server should be depracted. Or we integrate this in the workspace keep-alive logic, if that's an option. @l0rd what do you think? |
I think we can split this in 2 separate issues:
with the first one easier to address and that I would prioritize as that's look like a quick win. |
@nils-mosbach thanks for your analysis and yes, you are right and I was wrong about secrets that get updated automatically (without the need to restart a workspace). I am still divided between periodically refreshing the PAT or using SSH key instead. An HTTPS to GIT+SSH link converter looks simpler to write and maintain than a token refresher job (not to mention the security impications). So my proposal is to work on alternate flow that uses an |
From a users perspective PAT is a really nice option. For internal users, I find SSH a good option. If dealing with users outside of the organisation, starting a new workspace, create ssh keys, go to GitLab and paste them, and then clone the repo which you actually want to use will lead to a lot of support. I would at least remove the read only flag of the git-settings-mount, so Git can deal with the situation. If updating tokens in a vscode plugin is an option, I'll be happy to create the plugin. Since there's already a kube client initialized for reading exposed ports, periodically running a job that fetches a new token and updates the current secret wouldn't be a big deal. The only thing is, that it would be nice if someone could make the change that will add the refresh token and url in the secret. We could also add an annotion on the secret for this case e.g. From a security point of view I don't think this is way more insecure than using GitHub Tokens that don't expire. |
@nils-mosbach If you want to work on a PAT refresher VS Code extension I am happy with that. I prefer my team not to maintain that extra code but you are more than welcome to work on that. Initially it can be an external VS Code extension available on open-vsx and in the future we may consider making it a built-in. We can create a git repo in the che-incubator org for that. If I understand correctly, a prerequisite for this extension is that the PAT should be editable. Can the extension edit the PAT by patching the Kubernetes secret that contains the it? So that the fresh PAT is always available through the Kubernetes Secret API (and we don't require to mount the secret in RW mode). |
I've tried patching the secret using kubectl in a developer container and that works for both (devworkspace-merged-git-credentials and git-credentials-secret-hifkp). I think we need to decide if using OAuth/PAT/https should be a supported option next to SSH. I'm totally fine with a decision if Che only supports PAT for fetching devfiles from repositories and Git-Links in projects must be SSH. I would still prefer using OAuth/Pat since that makes onboarding way easier in case of a greater user base. From testings we've done internally teams won't use PAT, because it "breaks every two hours and you're stuck". I'm happy to do most of the heavy lifting to get PAT with expiring tokens working. So while digging through the code base I think we need to change the following: [Che-Server] Write refresh tokens to secrets
|
I don't think we should use the |
True. We could fetch new access tokens e.g. every 60'-90'. In this case tokens should get updated before they expire. At least for GitLab and Bitbucket that have a limit of 2h. That makes the implementation easier. |
@nils-mosbach I am currently in vacation and will be back the 30th of August. We can setup a call next week if that works for you. I am just nothing a few things:
|
@l0rd sure, works for me. I'll drop a PM on mattermost. Thanks. |
It's worth noting that since git config and credentials are mounted via configmap/secret, the The short expiry on GitLab PATs poses a fairly significant problem. From a cursory look, it appears that this is handled in other IDEs/editors by requiring reauthentication with GitLab every two hours. For our case, since the git credentials are currently mounted via |
True. The idea behind the Regarding
From what I can see .git-credentials is only used by devworkspaces. But if we expect other applications write to |
After some discussion with @nils-mosbach and @l0rd, I've prepared some DevWorkspace Operator changes to test mounting the git credentials file from the configmap directly. The resulting image is available as The goal of these changes is to enable one piece of the discussion above: currently we use subpath mounts, which prevent changes from being propagated to the running workspace (see issue: devfile/devworkspace-operator#915) I've tested the linked changes and updates to the secret storing my PAT are propagated into the workspace after around 20 seconds (on minikube -- this could potentially vary depending on the cluster). Additionally, it's currently necessary to trigger an event on any DevWorkspace CR in order to cause the DevWorkspace Operator to update the merged git-credentials secret -- I do this by adding an annotation to the workspace (see issue: devfile/devworkspace-operator#914). Edit to add: Note also that these changes result in the same path/file being mounted for Che, as the Che currently uses |
#21640 has been solved. So the problem now is about periodically update the token when a user is using a workspace for more than 2 hours. We are probably not going to work on this right now as there can be some workarounds:
|
Issues go stale after Mark the issue as fresh with If this issue is safe to close now please do so. Moderators: Add |
/remove-lifecycle stale |
@l0rd Do you have an example of a script to refresh the OAuth token for GitLab? |
@cgruver no, we never looked at it. |
Hey all, checking in to see if there has been any movement on this issue? @l0rd you mention manually executing a script to refresh the token but how would I get access to the new token that gets sent to the OAuth callback url? Or is there some api to tell the devspaces service to go ahead and refresh it and push the new token into the secret? |
Issues go stale after Mark the issue as fresh with If this issue is safe to close now please do so. Moderators: Add |
lifecycle/frozen |
Summary
Configuring OAuth2 (e.g. GitLab) for accessing private projects is straight forward as described by:
https://www.eclipse.org/che/docs/che-7/administration-guide/configuring-authorization/#configuring-gitlab-oauth2-with-devworkspace-engine_che
The token is stored in a Kubernetes secret and is mounted to the dev-container. That OAuth2 token is then passed to the git credential store. Which works as expected.
Problem is that tokens provided by GitLab expire after 2h. So after this time authentication fails for all Git operations (push, pull, ...). The only way I found is to delete the secrets in the users namespace that are created by che-server. Next time a user starts a workspace, new tokens/ secrets are created.
How should that be handled?
Relevant information
Che: Next
Devworkspace-Operator: 0.13.0
Kubernetes
GitLab OnPremise
The text was updated successfully, but these errors were encountered: