This application demonstrates how to create and write to files impersonating another user by
using the API hdfsConnectAsUser().
Before running this application, ensure that you have access to a cluster running MapR filesystem.
To build and run it, download it from this page and copy it to a MapR client or to a system
with the mapr-core package installed. Then, modify the run.sh script in Building and Running C Applications on filesystem Clients to point to this sample
application. Run the script and then run the application.
The application includes these header files:
stdio.h
hdfs.h
stdlib.h
string.h
hdfs.h.The application performs the actions that are described in the following sections.
After compiling the application, type the following command to launch the application and pass in the two usernames (to impersonate) and host name:
hdfs_connect_as_user <username1> <username2> <hostname>if (argc < 4) {
fprintf (stderr, "Provide two usernames to impersonate and the host name\n");
printf ("USAGE: ./hdfs_connect_as_user mapruser1 mapruser2 10.10.xx.xxx\n");
exit(EXIT_FAILURE);
}The application stores the values of the arguments in character arrays. The application uses the port, 7222, to connect to the given host, and uses character arrays for user directory and file path.
char *impersonate_user1 = argv[1];
char *impersonate_user2 = argv[2];
char *host_addr = argv[3];
int port_num = 7222;
char user1_dir[100];
char writePath[100];
int ret_val;The application creates a default path for the user directory and file.
sprintf(user1_dir, "/tmp/%s_dir", impersonate_user1);
sprintf(writePath, "%s/test_file", user1_dir);The hdfsSetRpcTimeout() is specific to the libMapRClient version of
libhdfs and takes a value that is specified in seconds. The default is 99
seconds. If you change this value, set it either to 0 (which eliminates timeouts) or to a
value greater than 30.
int err = hdfsSetRpcTimeout(30);
if (err) {
fprintf(stderr, "Failed to set rpc timeout!\n");
exit(-1);
}The application connects to the filesystem as the impersonated user
(<username1>) using hdfsConnectAsUser(). If successful,
this operation returns a handle to the filesystem.
printf("Impersonate user: %s\n", impersonate_user1);
printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user1);
hdfsFS fs_handle = hdfsConnectAsUser(host_addr, port_num, impersonate_user1);
if (fs_handle == NULL) {
printf("hdfsConnectAsUser() failed.\n");
exit(EXIT_FAILURE);
}The application creates a directory under /tmp as the impersonated user
(<username1>).
printf("User1: Create a directory : %s\n", user1_dir);
ret_val = hdfsCreateDirectory(fs_handle, user1_dir);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsCreateDirectory() failed.\n");
exit(EXIT_FAILURE);
}hdfsOpenFile() function: O_WRONLY|O_CREAT. This flag creates the file and opens it for
writing.For more details, see hdfsOpenFile() documentation.
printf("User1: Create and write to the file as user1 : %s\n", writePath);
hdfsFile writeFile = hdfsOpenFile(fs_handle, writePath, O_WRONLY|O_CREAT, 0, 0, 0);
if(!writeFile) {
printf("hdfsOpenFile() failed.\n");
exit(EXIT_FAILURE);
}The application writes to the open file as the impersonated user (<username1>).
char* buffer = "Hello, from user 1!";
tSize num_written_bytes = hdfsWrite(fs_handle, writeFile, (void*)buffer, strlen(buffer)+1);
if (hdfsFlush(fs_handle, writeFile)) {
printf("failed to flush %s\n", writePath);
exit(EXIT_FAILURE);
}The application closes the file after successfully writing to the file as the impersonated user (<username1>).
printf("User1: Close file %s.\n", writePath);
hdfsCloseFile(fs_handle, writeFile);The application connects to the filesystem as the second user (<username2>)
using hdfsConnectAsUser() and returns a handle to the filesystem.
printf("Impersonate user: %s\n", impersonate_user2);
printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user2);
hdfsFS fs_handle2 = hdfsConnectAsUser(host_addr, port_num, impersonate_user2);
if (fs_handle2 == NULL) {
printf("hdfsConnectAsUser() failed.\n");
exit(EXIT_FAILURE);
}The application tries to open the file created by the impersonated user (<username1>) and write to the file as the impersonating user (<username2>). This operation fails as the impersonating user (<username2>) is denied access to the file created by the impersonated user (<username1>) and the application returns error EACCES.
printf("User2: Try opening file created by user1 for writing : %s\n", writePath);
hdfsFile writeFile2 = hdfsOpenFile(fs_handle2, writePath, O_WRONLY, 0, 0, 0);
int errNum = errno;
if(writeFile2) {
printf("User2: hdfsOpenFile() should have failed for %s.\n", impersonate_user2);
exit(EXIT_FAILURE);
} else {
if (errNum == EACCES) {
printf("User2: As expected hdfsOpenFile() with EACCES.\n");
} else {
printf("User2: hdfsOpenFile() failed with errno:%d expected %d.\n", errNum, EACCES);
exit(EXIT_FAILURE);
}
}The application deletes a directory as the impersonated user (<username1>) using the filesystem handle created for this user.
printf("Delete directory : %s\n", user1_dir);
ret_val = hdfsDelete(fs_handle, user1_dir, 1);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsDelete() failed.\n");
exit(EXIT_FAILURE);
}The application disconnect the impersonating user (<username2>) from the filesystem.
printf("Disconnect the impersonation user2.\n");
ret_val = hdfsDisconnect(fs_handle2);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsDisconnect() failed.\n");
exit(EXIT_FAILURE);
}The application disconnect the impersonated user (<username1>) from the filesystem.
printf("Disconnect the impersonation user1.\n");
ret_val = hdfsDisconnect(fs_handle);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsDisconnect() failed.\n");
exit(EXIT_FAILURE);
}/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hdfs.h"
int main(int argc, char *argv[]) {
if (argc < 4) {
fprintf (stderr, "Provide two usernames to impersonate and the host name\n");
printf ("USAGE: ./connectAsUser mapruser1 mapruser2 10.10.xx.xxx\n");
exit(EXIT_FAILURE);
}
char *impersonate_user1 = argv[1];
char *impersonate_user2 = argv[2];
char *host_addr = argv[3];
int port_num = 7222;
char user1_dir[100];
char writePath[100];
int ret_val;
/* Populate the directory patha nd file path */
sprintf(user1_dir, "/tmp/%s_dir", impersonate_user1);
sprintf(writePath, "%s/test_file", user1_dir);
/* Impersonate as user1 using hdfsConnectAsUser(). */
printf("Impersonate user: %s\n", impersonate_user1);
printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user1);
hdfsFS fs_handle = hdfsConnectAsUser(host_addr, port_num, impersonate_user1);
if (fs_handle == NULL) {
printf("hdfsConnectAsUser() failed.\n");
exit(EXIT_FAILURE);
}
/* Create a directory under /tmp. This is done as the impersonated user1. */
printf("User1: Create a directory : %s\n", user1_dir);
ret_val = hdfsCreateDirectory(fs_handle, user1_dir);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsCreateDirectory() failed.\n");
exit(EXIT_FAILURE);
}
/*
* Create and write a file using the filesystem
* handle from impersonate_user1.
*/
printf("User1: Create and write to the file as user1 : %s\n", writePath);
hdfsFile writeFile = hdfsOpenFile(fs_handle, writePath, O_WRONLY|O_CREAT, 0, 0, 0);
if(!writeFile) {
printf("hdfsOpenFile() failed.\n");
exit(EXIT_FAILURE);
}
char* buffer = "Hello, from user 1!";
tSize num_written_bytes = hdfsWrite(fs_handle, writeFile, (void*)buffer, strlen(buffer)+1);
if (hdfsFlush(fs_handle, writeFile)) {
printf("failed to flush %s\n", writePath);
exit(EXIT_FAILURE);
}
printf("User1: Close file %s.\n", writePath);
hdfsCloseFile(fs_handle, writeFile);
/*
* Impersonate as user 2 and try to write the file create by user1.
* Writing to the file created by user1 will be denied with error EACCES.
*/
printf("Impersonate user: %s\n", impersonate_user2);
printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user2);
hdfsFS fs_handle2 = hdfsConnectAsUser(host_addr, port_num, impersonate_user2);
if (fs_handle2 == NULL) {
printf("hdfsConnectAsUser() failed.\n");
exit(EXIT_FAILURE);
}
printf("User2: Try opening file created by user1 for writing : %s\n", writePath);
hdfsFile writeFile2 = hdfsOpenFile(fs_handle2, writePath, O_WRONLY, 0, 0, 0);
int errNum = errno;
if(writeFile2) {
printf("User2: hdfsOpenFile() should have failed for %s.\n", impersonate_user2);
exit(EXIT_FAILURE);
} else {
if (errNum == EACCES) {
printf("User2: As expected hdfsOpenFile() with EACCES.\n");
} else {
printf("User2: hdfsOpenFile() failed with errno:%d expected %d.\n", errNum, EACCES);
exit(EXIT_FAILURE);
}
}
/* Delete the directory. This is done using the fliesystem handle creatd for user1. */
printf("Delete directory : %s\n", user1_dir);
ret_val = hdfsDelete(fs_handle, user1_dir, 1);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsDelete() failed.\n");
exit(EXIT_FAILURE);
}
/* Disconnect the impersonation user1 */
printf("Disconnect the impersonation user1.\n");
ret_val = hdfsDisconnect(fs_handle);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsDisconnect() failed.\n");
exit(EXIT_FAILURE);
}
/* Disconnect the impersonation user2 */
printf("Disconnect the impersonation user2.\n");
ret_val = hdfsDisconnect(fs_handle2);
if (ret_val != EXIT_SUCCESS) {
printf("hdfsDisconnect() failed.\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}