semaphoreui / semaphore

Modern UI for Ansible
https://semaphoreui.com
MIT License
9.48k stars 979 forks source link

oAuth2 / OpenID connect authentication using oauth2-proxy #973

Open ccuz opened 1 year ago

ccuz commented 1 year ago

Idea I was digging into semaphore code, but see that user management is either local or LDAP. What about supporting a oauth2-proxy https://oauth2-proxy.github.io/oauth2-proxy/docs/ instance in front of semaphore instance and then extracting the authenticated username (and role) out of the HTTP-header JWT-token coming from oauth2-proxy. As the JWT-token has to be signed by the IdP-privatekey, Semaphore would just need IdP-publickey to ensure JWT-token was not tempered before extracting the user's details.

Impact

Note: oauth2-proxy may just be one such proxy, in a K8s deployment, Istio may just do the same https://getindata.com/blog/OAuth2-based-authentication-on-Istio-powered-Kubernetes-clusters/.

cf-sewe commented 1 year ago

Great request! Pomerium is also one of the well known authentication proxies. https://www.pomerium.com/docs/production/security#user-identity-and-context

ccuz commented 1 year ago

After reading the existing login code, it may already work as HTTP Header 'Authorization bearer' is already extracted https://github.com/ansible-semaphore/semaphore/blob/f674738f54258b976265f53fe228d45f8ba7efc5/api/auth.go#L21 into a userID: "userID = token.UserID". Basically Semaphore has the concept of local and remote user. Local user are only existing within the DB and are managed by their password as store in the DB (encrypted using 'access_key_encryption'). Remote user, are authenticated using LDAP and exists in the DB without any password. The entered password in the login-mask is used to connect to LDAP server using the provided username/password. If user information are read, userid get extracted from 'uid' mapped field. A user is created in the DB with this uid with flag remote. From there on, this user and rights can be managed within semaphore. Thus for OpenId-Connect/OAuth2, if a token exists in the Header, it may just need to be added to the DB if not yet existing, similar to LDAP.

Extending on existing Nginx proxy to provide HTTPS, one could just follow https://dev.to/apisix/api-security-with-oidc-by-using-apache-apisix-and-microsoft-azure-ad-50h3 to see if this works in front of Semaphore.

bendem commented 1 year ago
  • No more user-list in token-based auth

Generally, applications create a user in db when they first see them so they can manipulated by admins (added to teams, linked to builds...).

tboerger commented 2 months ago

Can we close this issue since oidc providers have been integrated?

fiftin commented 6 days ago

Hi @cf-sewe, Are you still Semaphore user?

cf-sewe commented 5 days ago

I introduced and usesd Semaphore as a trial in the company I work for in 2022 until 2023. But after a while I noticed that the team did not really pick up on it. I was also a bit worried about the projects future - thats why we decided to reduce products and now use Jenkins (which we already had in place) to run Ansible playbooks. Its of course not as user friendly as Semaphore, but for now does the job.

I was quite surprised to see the pickup of development velocity and still follow whats going on here. I noticed that you recently developed some really great features; also suitable for business use.

Regarding the feature discussed here I personally still think that its probably nice to be able to delegate authentication to an external component and then rely on information provided by that, e.g. the users name set as a HTTP header. Like Authelia supports: https://www.authelia.com/integration/trusted-header-sso/introduction/.

tboerger commented 5 days ago

But why should you require the header if the IdP is already fully integrated based on OpenIDConnect?