Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Introducing LDAP support #301

Merged
merged 1 commit into from
Sep 4, 2015
Merged

Introducing LDAP support #301

merged 1 commit into from
Sep 4, 2015

Conversation

mssola
Copy link
Collaborator

@mssola mssola commented Sep 2, 2015

This is an introduction to LDAP support. There are some questions that need to
be addressed, but at least the basic structure is in place now.

Fixes #150

Signed-off-by: Miquel Sabaté Solà [email protected]

@mssola mssola force-pushed the ldap branch 2 times, most recently from ccc8c66 to 10f5ae7 Compare September 2, 2015 14:17
@mssola
Copy link
Collaborator Author

mssola commented Sep 2, 2015

This is an introduction to LDAP support. This PR includes the code that allows an LDAP user to authenticate in Portus. Some considerations:

  • I've added the ldap_name column inside of the users table. This column will be non-empty for LDAP users.
  • The ldap_name and the username will have the same value if the LDAP name does not contain any character forbidden by Docker.
  • Because of the previous point, an LDAP user (that has signed in at least once) can authenticate itself with either the ldap_name or username.

The thing is that we need to register LDAP users in Portus' DB, but we want to do this transparently to LDAP users. Therefore, when an LDAP user signs in Portus for the first time, it will be created automatically in Portus' database, and a proper username will be created for said user if its username is not valid for Docker (as explained previously).

But of course we've got a problem, since we require the email column to be filled when creating a user, and LDAP makes no guarantees of providing an email for each user. The decision here is to drop this requirement for LDAP users that haven't filled up their emails yet on Portus. You can see that in the User#email_required? method, that is then picked up by Devise to do the magic. Now, isn't this dangerous ? Yes it is, that's why I've added a hook that redirects any LDAP user with an empty email to its profile page. Moreover, this profile page has been tweaked a bit, to reflect better what the user should do:

wave8

This situation can be better. Basically we can add a configuration option in the config.yml file that:

  1. Allows the admin to specify the key on the LDIF of the user where Portus can fetch the user's email.
  2. Allows an alternative scheme where the admin just specifies the hostname of the mailing server. Example: the admin sets "@organization.com", so Portus will automatically guess "[email protected]".

My idea is that if the admin set neither of the previous options, Portus would fallback to the current behavior. This way we would act safely, while being as clever as possible. The implementation of the above points should be done in another PR though.

There are more crazy ideas that are related to LDAP support. One that occurred to me is to automatically create namespaces/teams from the organizations defined in the LDAP server (with users also being mapped into it automatically).

Moreover, the configuration format has changed a little (and it needs further changing but I'll do that later on another PR). Notice that now each key defines a enabled key. This is in concordance with other projects like Docker's Distribution or Gitlab. This allows us to add the handy enabled? method. So from anywhere of the code, the developer can always check whether LDAP is enabled with:

APP_CONFIG.enabled?("ldap")

The specific configuration options for LDAP support are quite basic:

  • hostname: the hostname of the LDAP server.
  • port: the port of the LDAP server.
  • base: the base where users are located. This is usually a string like "ou=users,dc=example,dc=com". By default it's empty, which is the simplest way in which an LDAP directory can be structured.

@mssola
Copy link
Collaborator Author

mssola commented Sep 2, 2015

By the way, notice that LDAP users would need to use their username in order to pull/push inside of the docker client.

@mssola
Copy link
Collaborator Author

mssola commented Sep 2, 2015

Travis' failure is regarding a change from @jordimassaguerpla that will be superseded by #297. That's why I didn't fix it.

format: { with: /\A[a-z0-9]{4,30}\Z/,
message: 'Accepted format: "\A[a-z0-9]{4,30}\Z"' }
format: { with: USERNAME_FORMAT,
message: "Only alphanumeric characters are allowed" }
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't we say also "minimum 4 and maximum 30"?

Copy link
Member

Choose a reason for hiding this comment

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

+1

@jordimassaguerpla
Copy link
Member

a part from the small issue with the message, all the rest lgtm, but I am no expert. Let's see what flavio says.

@@ -136,6 +136,7 @@
t.datetime "updated_at"
t.boolean "admin", limit: 1, default: false
t.boolean "enabled", limit: 1, default: true
t.string "ldap_name", limit: 255, default: ""
Copy link
Member

Choose a reason for hiding this comment

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

Do you think two different users can end up having the same ldap_name? I think we should add a unique index on it.

@flavio
Copy link
Member

flavio commented Sep 2, 2015

We have to make sure the LDAP server is always contacted, the password inside of our DB should be omitted for users registered via LDAP

@flavio
Copy link
Member

flavio commented Sep 2, 2015

We should also notice clashes inside of the ldap_name and prompt the user to provide a custom name. We should propose a unique name, like "#{name_already_taken}#{counter}".

@flavio
Copy link
Member

flavio commented Sep 2, 2015

LGTM 👏

@flavio
Copy link
Member

flavio commented Sep 2, 2015

One last thing about the screenshot you posted: IMHO the form should fill the entire page, right now there's a lot of empty space on the right side of the screen. However I think that's a problem that has always afflicted the page.

@mssola
Copy link
Collaborator Author

mssola commented Sep 3, 2015

@flavio on the layout of the profile page, yes, this has been like that since always. We can fix that in another PR.

@mssola
Copy link
Collaborator Author

mssola commented Sep 3, 2015

Implemented the code to avoid name clashes:

  1. On creation, if the name clashes it will call generate_random_name. This function will try to get a free name with the format "#{username}#{random_number}". If it doesn't work, then it will raise an exception as expected by Devise.
  2. I've added a unique index to ldap_name.

@flavio
Copy link
Member

flavio commented Sep 3, 2015

generate_randome_name looks good to me. I just realized another possible problem: what about ldap names that are shorter than 4 characters? These would not be accepted by Docker.

@mssola
Copy link
Collaborator Author

mssola commented Sep 3, 2015

@flavio I say let the generate_random_name method handle that too. So if the LDAP name is just "a", this method would produce something like "a123". Of course, this is a bit ugly, but it would be fixed if we allow users to change their user name.

@flavio
Copy link
Member

flavio commented Sep 3, 2015

Sorry, I missed that. LGTM

@mssola
Copy link
Collaborator Author

mssola commented Sep 3, 2015

@flavio you didn't miss it, it's not implemented yet :D

@mssola mssola force-pushed the ldap branch 3 times, most recently from f3ecda9 to e397a8e Compare September 3, 2015 14:28
@mssola
Copy link
Collaborator Author

mssola commented Sep 3, 2015

This should be it. Last changes:

  1. LDAP users won't be able to change their passwords through Portus' profile page.
  2. If LDAP is disabled or the current user does not exist in the given LDAP server, then LDAP authenticatable is discarded. Otherwise the other strategies are discarded.
  3. More documentation, more tests.

fail!(:invalid_login)
end
else
# rubocop:disable Style/SignalException
Copy link
Member

Choose a reason for hiding this comment

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

Being there means:

  1. ldap is disabled
  2. ldap is enabled, but the user cannot be found on the remote server

The next action is fail which moves to the next authentication strategy (portus' db). I think it would be better to distinguish the second case and fail immediately. I think that once LDAP is enable we should not allow a mixed authentication strategy.

Did I get something wrong?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure. I'd be for with a mixed authentication strategy. For example, how would you create the admin user if LDAP is enabled if you don't allow a mixed solution ?

@mssola mssola force-pushed the ldap branch 2 times, most recently from 205e5e0 to 297edab Compare September 4, 2015 08:12
This is an introduction to LDAP support. There are some questions that need to
be addressed, but at least the basic structure is in place now.

Fixes SUSE#150

Signed-off-by: Miquel Sabaté Solà <[email protected]>
@mssola
Copy link
Collaborator Author

mssola commented Sep 4, 2015

After a bit of discussion, we're going for a "strict" LDAP support. That is, if LDAP support is enabled, then only LDAP users can log in Portus. This can be put as a configurable value in the future if users request the "mixed" approach. With this, I've updated the patch so:

  • The sign up page is not accessible if LDAP support is enabled.
  • The first LDAP user to sign in will be an admin. This is stated in the login form, and the wiki will be updated accordingly.

I've updated the patch to reflect this changes.

@flavio
Copy link
Member

flavio commented Sep 4, 2015

LGTM. BTW, in the future it would be better to avoid the merge of all the commits for big pull requests like this; it's painful to review the whole diff all the times to spot only a few changes.

Proposal: for PR like this one let's merge the the commits only before doing the real merge.

@mssola
Copy link
Collaborator Author

mssola commented Sep 4, 2015

@flavio sounds reasonable to me

mssola added a commit that referenced this pull request Sep 4, 2015
Introducing LDAP support
@mssola mssola merged commit 2da3f91 into SUSE:master Sep 4, 2015
@mssola mssola deleted the ldap branch September 4, 2015 11:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants