-
Notifications
You must be signed in to change notification settings - Fork 388
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
Privileged access subsystem #393
Conversation
73c3d41
to
640d054
Compare
Did you consider storing client side information in the designated codechecker workspace? Does it make sense to have a global one? |
If a user wants only to check the results and use only the command line no workspace is required. It is possible to store multiple server authentication credentials in one file. |
@@ -40,7 +40,7 @@ Tested on Ubuntu LTS 14.04.2 | |||
|
|||
# get ubuntu packages | |||
# clang-3.6 can be replaced by any later versions of clang | |||
sudo apt-get install clang-3.6 doxygen build-essential thrift-compiler python-virtualenv gcc-multilib git wget | |||
sudo apt-get install clang-3.6 doxygen build-essential thrift-compiler python-virtualenv gcc-multilib git wget libldap2-dev libsasl2-dev libssl-dev | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is ldap a strong dependency or only an optional one? I think in case this is optional (it should be IMO), lets have a separate list with optional dependencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think installing these extra requirements could go into the separate authentication documentation and start that if the user requires authentication he should install these extra packages and python modules.
ret = run_cmd(auth_cmd, thrift_files_dir, env, silent=silent) | ||
if ret: | ||
LOG.error('Failed to generate authentication interface files') | ||
return ret |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be some repetition. Does a local function make this code shorter overall?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far we generated the source files with Thrift files differently for the report server (python only) and the report viewer (python and javascript). The authentication is python only which could be refactored into a separate function with the report server source file generation. I'm not sure it will be so much shorter, right now the generate_thrift_files function is not that long. If you think it is better you can refactor it into a separate function.
# ------------------------------ | ||
# ----------- SERVER ----------- | ||
class _Session(): | ||
'''A session for an authenticated, privileged client connection''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
End comments with periods.
persistency hash is intended to be used for the "session recycle" | ||
feature to prevent NAT endpoints from accidentally getting each | ||
other's session.''' | ||
return hashlib.sha256(auth_string + "@" + client_addr + ":" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the port included in the addr? Can multiple sessions from the same client interfere?
self.last_access = datetime.now() | ||
|
||
|
||
class sessionManager: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this start with a lowercase letter on purpose?
ret = self.__save["credentials"].get(host + ":" + port) | ||
if not ret: | ||
ret = self.__save["credentials"].get(host) | ||
if not ret: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you do not need all the indentation.
return ret | ||
|
||
def saveToken(self, host, port, token, destroy=False): | ||
if not destroy: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverse the branches and remove the not.
|
||
// handles creating a session token for the user | ||
string performLogin(1: string auth_method, | ||
2: string auth_string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it good practice to have one auth string instead of separate user/password etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was done this way to make sure that further extensions in auth methods (such as, e.g. SSH key based one) is most easily done without further breaking the Authentication API.
# ------------------------------------------------------------ | ||
|
||
def ThriftClientCall(function): | ||
# print type(function) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented code.
# import only if necessary; some tests may not add this to PYTHONPATH | ||
from codechecker_lib import session_manager | ||
from codeCheckerDBAccess import codeCheckerDBAccess | ||
from codeCheckerDBAccess.constants import MAX_QUERY_SIZE | ||
|
||
self.max_query_size = MAX_QUERY_SIZE | ||
transport = THttpClient.THttpClient(host, port, uri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the login done through https?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. (Docs will be updated.)
To-Do:
|
@@ -0,0 +1,145 @@ | |||
CodeChecker authentication subsytem | |||
=================================== | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A new additional package dependencies section could be created here, what packages should be installed by the user.
# | ||
# Create a dummy authentication-enabled configuration and an auth-enabled server | ||
session_cfg_file = os.path.join(pkg_root, "config", "session_config.json") | ||
with open(session_cfg_file, 'r') as scfg: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we open the file only once? (read up the config modify it and write out)
import json | ||
import hashlib | ||
import time | ||
import ldap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
importing ldap modules could be done optionally and if importing fails only the ldap authentication method will be disabled.
try:
import ldap
import ldap.sasl
except ImportError:
# no ldap authentication is available
|
||
The `CodeChecker cmd` client needs to be authenticated for a server before any data communication could take place. | ||
|
||
The client's configuration file is expected to be at `~/.codechecker_passwords.json`, which is created at the first command executed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please extend the documentation that the user should modify the access rights to the password file so only he can access it: chmod 0600 ~/.codechecker_password.json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😏 Better idea is to create the file initially as 0600
. Though I added it to the documentation and a warning (in ssh
style) for the user if the file is with the wrong permissions.
Please update your branch, so all the tests can run on Linux and on OSX too. The CI is fixed now. Thanks! |
Should I cherry-pick the test fixing changes or should I do a full rebase? With this many commits in the history – and the reviews – I would vote for cherry picking. |
I think rebasing is usually a cleaner solution for the history's sake. |
037f0c9
to
6e50896
Compare
66d4102
to
a731109
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any commits you could squash?
with open(session_cfg_file, 'w') as scfg: | ||
json.dump(self.__save, scfg, indent=2, sort_keys=True) | ||
with open(self.token_file, 'w') as scfg: | ||
fcntl.lockf(scfg, fcntl.LOCK_EX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this way of locking unix specific? Will it work on OSX and maybe later on Windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. It will work on OS X but will definitely not work on Windows, the filesystem concept of the two system families are entirely different.
Maybe we could use the package portalocker? It is essentially just a branching wrapper, but it looks like it could work good enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nice to use a platform independent solution. portalocker seems to be a nice choice.
As for squashing: not really without messing up order (I have done some reordering in this last rebase.) I could squash the first two commits as they are one unit, I could also reorder the "update due to reviews" stuff and put it with the "misc." changes as one commit at the end, though. But putting any more commits together would create a big list of unrelated stuff in one commit... |
Let's squash that few commits you mentioned and keep the rest. |
- Added a new Thrift service for handling authentication requests (not yet documented) - Added proper HTTP responses for the browser-based auth realm to work - Added wrapper for authentication requests on the command-line client - Implemented persistency for sessions (server) and valid tokens (client)
…y-based authentication
… logins to prevent memory leaks
- User credential file is chmod 0600 at creation (if already exists and not this mode, the user is warned) - Active tokens are stored away from the credentials, in the /tmp folder - Server configuration is put into the workspace where the server is running instead of using an install-global file
a731109
to
3d6f5b9
Compare
This merge requests contains the privileged access infrastructure — closes #339.
If a user is authenticated (via any means described below), full access to the server is given: they can view results and destroy them. If the user is not authenticated, the entire access is denied – there are no further fine-graining, as per discussed with @dkrupp and @gyorb.
The changes — summed up
/Authentication
was implemented, this handles authentication requestsCodeChecker cmd
client fail on an exception — clients are expected to handle authentication before live request.config/session_config.json
andconfig/session_client.json
. Both are created as working and descriptive templates.WORKSPACE/session_config.json
for every server started and contains the authentication setup.~/.codechecker_passwords.json
as it contains per-user credentials.HTTP WWW-Authenticate
header)CodeChecker cmd
got a new subcommand:login
. With this, users can authenticate on a server and kill their session.~/.codechecker_passwords.json
file can contain preconfigured credentials — if they are valid, executing a live query without a session will automatically log the user in for screen security and convenience.Full documentation for public use is available in
docs/authentication.md
.