hdfs_connect_as_user.c

This application demonstrates how to create and write to files impersonating another user by using the API hdfsConnectAsUser(): hdfs_connect_as_user.c

Before running this application, ensure that you have access to a cluster running MapR-FS.

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 MapR-FS 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
Note: The impersonation APIs are defined in hdfs.h.

The application performs the actions that are described in the following sections.

Takes two usernames and a hostname as input

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);
}

Stores the values of the arguments

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;

Populates the directory path and file path

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);

Sets an RPC timeout

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);
}

Connects to the filesystem as the impersonated user

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);
}

Creates a directory as the impersonated user

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);
}

Creates and opens a file

The application creates a file and opens the file, passing the following values to the hdfsOpenFile() function:
  • The handle to the filesystem.
  • A flag to indicate the mode in which to open the file. In this case, the flag is 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);
}

Writes to the open file

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);
}

Closes the file

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);

Connects to the filesystem as the impersonating user

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);
}

Tries to write to the file as the impersonating user

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);
    }
}

Disconnects the impersonating user

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);
}

Deletes a directory

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);
}

Disconnects the impersonated user

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);
}