Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/_includes/themes/zeppelin/_navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<li><a href="{{BASE_PATH}}/rest-api/rest-interpreter.html">Interpreter API</a></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-notebook.html">Notebook API</a></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-configuration.html">Configuration API</a></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-credential.html">Credential API</a></li>
<li role="separator" class="divider"></li>
<li class="title"><span><b>Security</b><span></li>
<li><a href="{{BASE_PATH}}/security/authentication.html">Authentication for NGINX</a></li>
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ Join to our [Mailing list](https://zeppelin.apache.org/community.html) and repor
* [Interpreter API](./rest-api/rest-interpreter.html)
* [Notebook API](./rest-api/rest-notebook.html)
* [Configuration API](./rest-api/rest-configuration.html)
* [Credential API](./rest-api/rest-credential.html)
* Security: available security support in Apache Zeppelin
* [Authentication for NGINX](./security/authentication.html)
* [Shiro Authentication](./security/shiroauthentication.html)
Expand Down
181 changes: 181 additions & 0 deletions docs/rest-api/rest-credential.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
---
layout: page
title: "Credentials REST API"
description: ""
group: rest-api
---
<!--
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
{% include JB/setup %}

## Zeppelin REST API
Zeppelin provides several REST APIs for interaction and remote activation of zeppelin functionality.

All REST APIs are available starting with the following endpoint `http://[zeppelin-server]:[zeppelin-port]/api`. Note that zeppelin REST APIs receive or return JSON objects, it is recommended for you to install some JSON viewers such as [JSONView](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc).

If you work with Zeppelin and find a need for an additional REST API, please [file an issue or send us mail](http://zeppelin.apache.org/community.html).

<br />
## Credential REST API List

### List Credential information
<table class="table-credential">
<col width="200">
<tr>
<td>Description</td>
<td>This ```GET``` method returns all key/value pairs of credential information on the server.</td>
</tr>
<tr>
<td>URL</td>
<td>```http://[zeppelin-server]:[zeppelin-port]/api/credential```</td>
</tr>
<tr>
<td>Success code</td>
<td>200</td>
</tr>
<tr>
<td> Fail code</td>
<td> 500 </td>
</tr>
<tr>
<td> sample JSON response
</td>
<td>
<pre>
{
"status": "OK",
"message": "",
"body": {
"userCredentials":{
"entity1":{
"username":"user1",
"password":"password1"
},
"entity2":{
"username":"user2",
"password":"password2"
}
}
}
}</pre></td>
</tr>
</table>

<br/>
### Create an Credential Information
<table class="table-credential">
<col width="200">
<tr>
<td>Description</td>
<td>This ```PUT``` method creates an credential information with new properties.</td>
</tr>
<tr>
<td>URL</td>
<td>```http://[zeppelin-server]:[zeppelin-port]/api/credential/```</td>
</tr>
<tr>
<td>Success code</td>
<td>200</td>
</tr>
<tr>
<td>Fail code</td>
<td> 500 </td>
</tr>
<tr>
<td>Sample JSON input</td>
<td>
<pre>
{
"entity": "e1",
"username": "user",
"password": "password"
}
</pre>
</td>
</tr>
<tr>
<td>Sample JSON response</td>
<td>
<pre>
{
"status": "OK"
}
</pre>
</td>
</tr>
</table>


<br/>
### Delete all Credential Information

<table class="table-credential">
<col width="200">
<tr>
<td>Description</td>
<td>This ```DELETE``` method deletes credential information.</td>
</tr>
<tr>
<td>URL</td>
<td>```http://[zeppelin-server]:[zeppelin-port]/api/credential```</td>
</tr>
<tr>
<td>Success code</td>
<td>200</td>
</tr>
<tr>
<td> Fail code</td>
<td> 500 </td>
</tr>
<tr>
<td>Sample JSON response</td>
<td>
<code>{"status":"OK"}</code>
</td>
</tr>
</table>


<br/>
### Delete an Credential entity

<table class="table-credential">
<col width="200">
<tr>
<td>Description</td>
<td>This ```DELETE``` method deletes an given credential entity.</td>
</tr>
<tr>
<td>URL</td>
<td>```http://[zeppelin-server]:[zeppelin-port]/api/credential/[entity]```</td>
</tr>
<tr>
<td>Success code</td>
<td>200</td>
</tr>
<tr>
<td> Fail code</td>
<td> 500 </td>
</tr>
<tr>
<td>Sample JSON response</td>
<td>
<code>{"status":"OK"}</code>
</td>
</tr>
</table>


<br/>

Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Class defining credentials for data source authorization
Expand All @@ -44,6 +45,7 @@ public Credentials(Boolean credentialsPersist, String credentialsPath) {
credentialsFile = new File(credentialsPath);
}
credentialsMap = new HashMap<>();

if (credentialsPersist) {
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
Expand All @@ -62,6 +64,28 @@ public UserCredentials getUserCredentials(String username) {

public void putUserCredentials(String username, UserCredentials uc) throws IOException {
credentialsMap.put(username, uc);
saveCredentials();
}

public UserCredentials removeUserCredentials(String username) throws IOException {
UserCredentials uc;
uc = credentialsMap.remove(username);
saveCredentials();
return uc;
}

public boolean removeCredentialEntity(String username, String entity) throws IOException {
UserCredentials uc = credentialsMap.get(username);
if (uc != null && uc.existUsernamePassword(entity) == false) {
return false;
}

uc.removeUsernamePassword(entity);
saveCredentials();
return true;
}

public void saveCredentials() throws IOException {
if (credentialsPersist) {
saveToFile();
}
Expand Down Expand Up @@ -118,5 +142,4 @@ private void saveToFile() throws IOException {
LOG.error("Error saving credentials file", e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,14 @@

package org.apache.zeppelin.user;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* User Credentials POJO
*/
public class UserCredentials {
private Map<String, UsernamePassword> userCredentials;

public UserCredentials() {
this.userCredentials = new HashMap<>();
}
private Map<String, UsernamePassword> userCredentials = new ConcurrentHashMap<>();

public UsernamePassword getUsernamePassword(String entity) {
return userCredentials.get(entity);
Expand All @@ -38,6 +34,14 @@ public void putUsernamePassword(String entity, UsernamePassword up) {
userCredentials.put(entity, up);
}

public void removeUsernamePassword(String entity) {
userCredentials.remove(entity);
}

public boolean existUsernamePassword(String entity) {
return userCredentials.containsKey(entity);
}

@Override
public String toString() {
return "UserCredentials{" +
Expand Down
66 changes: 60 additions & 6 deletions zeppelin-server/src/main/java/org/apache/zeppelin/rest/CredentialRestApi.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.zeppelin.rest;

import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.zeppelin.user.Credentials;
Expand Down Expand Up @@ -50,34 +51,87 @@ public class CredentialRestApi {
private HttpServletRequest servReq;

public CredentialRestApi() {

}

public CredentialRestApi(Credentials credentials) {
this.credentials = credentials;
}

/**
* Update credentials for current user
* Put User Credentials REST API
* @param message - JSON with entity, username, password.
* @return JSON with status.OK
* @throws IOException, IllegalArgumentException
*/
@PUT
public Response putCredentials(String message) throws IOException {
public Response putCredentials(String message) throws IOException, IllegalArgumentException {
Map<String, String> messageMap = gson.fromJson(message,
new TypeToken<Map<String, String>>(){}.getType());
String entity = messageMap.get("entity");
String username = messageMap.get("username");
String password = messageMap.get("password");

if (entity == null || username == null || password == null) {
return new JsonResponse(Status.BAD_REQUEST, "", "").build();
if (Strings.isNullOrEmpty(entity)
|| Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(password) ) {
return new JsonResponse(Status.BAD_REQUEST).build();
}

String user = SecurityUtils.getPrincipal();
logger.info("Update credentials for user {} entity {}", user, entity);
UserCredentials uc = credentials.getUserCredentials(user);
uc.putUsernamePassword(entity, new UsernamePassword(username, password));
credentials.putUserCredentials(user, uc);
return new JsonResponse(Status.OK, "", "").build();
return new JsonResponse(Status.OK).build();
}

/**
* Get User Credentials list REST API
* @param
* @return JSON with status.OK
* @throws IOException, IllegalArgumentException
*/
@GET
public Response getCredentials(String message) throws
IOException, IllegalArgumentException {
String user = SecurityUtils.getPrincipal();
logger.info("getCredentials credentials for user {} ", user);
UserCredentials uc = credentials.getUserCredentials(user);
return new JsonResponse(Status.OK, uc).build();
}

/**
* Remove User Credentials REST API
* @param
* @return JSON with status.OK
* @throws IOException, IllegalArgumentException
*/
@DELETE
public Response removeCredentials(String message) throws
IOException, IllegalArgumentException {
String user = SecurityUtils.getPrincipal();
logger.info("removeCredentials credentials for user {} ", user);
UserCredentials uc = credentials.removeUserCredentials(user);
if (uc == null) {
return new JsonResponse(Status.NOT_FOUND).build();
}
return new JsonResponse(Status.OK).build();
}

/**
* Remove Entity of User Credential entity REST API
* @param
* @return JSON with status.OK
* @throws IOException, IllegalArgumentException
*/
@DELETE
@Path("{entity}")
public Response removeCredentialEntity(@PathParam("entity") String entity) throws
IOException, IllegalArgumentException {
String user = SecurityUtils.getPrincipal();
logger.info("removeCredentialEntity for user {} entity {}", user, entity);
if (credentials.removeCredentialEntity(user, entity) == false) {
return new JsonResponse(Status.NOT_FOUND).build();
}
return new JsonResponse(Status.OK).build();
}
}
Loading