[ https://issues.apache.org/jira/browse/DRILL-5726?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Arina Ielchiieva updated DRILL-5726: ------------------------------------ Description: 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. was: 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. *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) _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. > 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 > 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)