[
https://issues.apache.org/jira/browse/DRILL-5726?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Arina Ielchiieva updated DRILL-5726:
------------------------------------
Labels: ready-to-commit (was: )
> Support Impersonation without authentication for REST API
> ---------------------------------------------------------
>
> Key: DRILL-5726
> URL: https://issues.apache.org/jira/browse/DRILL-5726
> Project: Apache Drill
> Issue Type: Improvement
> Affects Versions: 1.11.0
> Reporter: Arina Ielchiieva
> Assignee: Arina Ielchiieva
> Labels: ready-to-commit
> Fix For: 1.12.0
>
> Attachments: login_page.JPG, query_page_with_user_name.JPG
>
>
> Today if a user is not authenticated via REST API then there is no way to
> provide a user name for executing queries. It will by default be executed as
> "anonymous" user. This doesn't work when impersonation without authentication
> is enabled on Drill server side, since anonymous user doesn't exist the query
> will fail. We need a way to provide a user name when impersonation is enabled
> on Drill side and query is executed from REST API.
> There are two approaches to achieve that:
> *1. Use form-based authentication*
> On Web UI user will be prompted to enter only login, then session for that
> user will be created, user will be treated as admin. Form-based
> authentication will cache user information, so user won't need to set user
> name each time he / she wants to execute the query. Log in / out options will
> be also available. Example screenshot of login page is attached
> (login_page.JPG).
> From the programmatic perspective, user would need first to authenticate and
> use cookie to get query result.
> *2. Use {{User-Name}} header in request*
> On Web UI on Query page additional input field will appear. User would need
> to enter user name before issuing the query. Example screenshot of query page
> is attached (query_page_with_user_name.JPG). Under the hood with user name
> would be added to client request as request header. On server side this
> header would be used to create user session principal. From the programmatic
> perspective, user would need to add header when issuing the request.
> *_From the two above options second was chosen as it would ease REST API
> usage from the programmatic perspective, plus using form-based authentication
> may lead to false assumption that user is authenticated which is in reality
> is not true._*
> *Implementation details of the second approach:*
> _Note: the below implementation will take affect only if authentication is
> disabled and impersonation is enabled. By means of freemarker page won't
> include js lib and script if condition is not met._
> On the client side additional input field was added to the query page. When
> client is submitting the query, request would be changed using ajax to add
> {{User-Name}} header which would be taken from the new input field. On the
> server side, this header would be used to create session principal with
> provided user name and admin rights. If user name header was not provided
> (null or empty), the default anonymous principal will be used only in case
> when it is not POST request to /query or /query.json. If it is POST request
> to /query or /query.json {{User-Name}} header is required, so error will be
> thrown. Also adding {{User Name}} input parameter is required from Web UI.
> User won't be able to send request until field is filled in.
> *Adding user name header approaches:*
> _Web UI_
> enter user name in the User Name input field on Query page before submiiting
> the query (query_page_with_user_name.JPG), this step is required.
> _sqlline_
> {code}./drill-localhost -n user1{code}
> _curl_
> {code} curl -v -H "Content-Type: application/json" -H "User-Name: user1" -d
> '{"queryType":"SQL", "query": "select * from sys.version"}'
> http://localhost:8047/query.json {code}
> _Java way_
> {code}
> String url = "http://localhost:8047/query.json";
> URLConnection connection = new URL(url).openConnection();
> connection.setDoOutput(true); // Triggers POST.
> connection.addRequestProperty("User-Name", "user1");
> connection.setRequestProperty("Content-Type", "application/json");
> String data = "{\"queryType\":\"SQL\", \"query\": \"select * from
> sys.version\"}";
> try (OutputStream output = connection.getOutputStream()) {
> output.write(data.getBytes(StandardCharsets.UTF_8.name()));
> }
> try (InputStream response = connection.getInputStream()) {
> String result = IOUtils.toString(response);
> System.out.println(result);
> }
> {code}
> Note: {{Apache HttpClient}} can be used as well.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)