azkaban-uncached

1. checking in new execute-as-user.c 2. modified ProcessJob

9/14/2015 4:08:27 PM

Details

diff --git a/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java b/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java
index 4e268a0..a9ec986 100644
--- a/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java
+++ b/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java
@@ -41,6 +41,7 @@ public class ProcessJob extends AbstractProcessJob {
   private static final String MEMCHECK_ENABLED = "memCheck.enabled";
   private static final String MEMCHECK_FREEMEMDECRAMT = "memCheck.freeMemDecrAmt";
   public static final String AZKABAN_MEMORY_CHECK = "azkaban.memory.check";
+  public static final String NATIVE_LIB_FOLDER = "azkaban.native.lib";
 
   public ProcessJob(final String jobId, final Props sysProps,
       final Props jobProps, final Logger log) {
@@ -81,8 +82,18 @@ public class ProcessJob extends AbstractProcessJob {
     info(commands.size() + " commands to execute.");
     File[] propFiles = initPropsFiles();
     Map<String, String> envVars = getEnvironmentVariables();
-
+    
+    info("printing sysProps to see what's there: ");
+    for(String k: sysProps.getKeySet()){
+    	info(String.format("key %s, value: %s", k, sysProps.getString(k)));
+    }
+    String nativeLibFolder = sysProps.getString(NATIVE_LIB_FOLDER);
+    String executeAsUserBinary = String.format("%s/%s", nativeLibFolder, "execute-as-user");
+    String userToProxy = jobProps.getString("user.to.proxy");
+        
     for (String command : commands) {
+      command = String.format("%s %s %s", executeAsUserBinary, userToProxy, command);
+      
       info("Command: " + command);
       AzkabanProcessBuilder builder =
           new AzkabanProcessBuilder(partitionCommandLine(command))
diff --git a/azkaban-common/src/main/java/azkaban/jobExecutor/utils/process/AzkabanProcess.java b/azkaban-common/src/main/java/azkaban/jobExecutor/utils/process/AzkabanProcess.java
index 9c3f092..1035be0 100644
--- a/azkaban-common/src/main/java/azkaban/jobExecutor/utils/process/AzkabanProcess.java
+++ b/azkaban-common/src/main/java/azkaban/jobExecutor/utils/process/AzkabanProcess.java
@@ -101,13 +101,16 @@ public class AzkabanProcess {
       }
 
       completeLatch.countDown();
+      
+      // try to wait for everything to get logged out before exiting
+      outputGobbler.awaitCompletion(5000);
+      errorGobbler.awaitCompletion(5000);
+      
       if (exitCode != 0) {
         throw new ProcessFailureException(exitCode, errorGobbler.getRecentLog());
       }
 
-      // try to wait for everything to get logged out before exiting
-      outputGobbler.awaitCompletion(5000);
-      errorGobbler.awaitCompletion(5000);
+
     } finally {
       IOUtils.closeQuietly(process.getInputStream());
       IOUtils.closeQuietly(process.getOutputStream());
diff --git a/azkaban-common/src/main/java/azkaban/jobtype/JobTypeManager.java b/azkaban-common/src/main/java/azkaban/jobtype/JobTypeManager.java
index 212f1a9..ccb74c1 100644
--- a/azkaban-common/src/main/java/azkaban/jobtype/JobTypeManager.java
+++ b/azkaban-common/src/main/java/azkaban/jobtype/JobTypeManager.java
@@ -340,6 +340,7 @@ public class JobTypeManager {
             jobProps, jobType));
       }
 
+      // TODO: should the logic below mirror the logic for PluginLoadProps?
       Props pluginJobProps = pluginSet.getPluginJobProps(jobType);
       if (pluginJobProps != null) {
         for (String k : pluginJobProps.getKeySet()) {
@@ -354,7 +355,7 @@ public class JobTypeManager {
       if (pluginLoadProps != null) {
         pluginLoadProps = PropsUtils.resolveProps(pluginLoadProps);
       } else {
-        pluginLoadProps = new Props();
+        pluginLoadProps = pluginSet.getCommonPluginLoadProps();
       }
 
       job =
diff --git a/azkaban-execserver/src/main/resources/execute-as-user.c b/azkaban-execserver/src/main/resources/execute-as-user.c
new file mode 100644
index 0000000..273605c
--- /dev/null
+++ b/azkaban-execserver/src/main/resources/execute-as-user.c
@@ -0,0 +1,111 @@
+#include <dirent.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <errno.h>
+#include <grp.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+  FILE *LOGFILE = NULL;
+  FILE *ERRORFILE = NULL;
+  int SETUID_OPER_FAILED=10;
+
+/**
+ *  * Change the real and effective user and group to abandon the super user
+ *   * priviledges.
+ *    */
+int change_user(uid_t user, gid_t group) {
+    if (user == getuid() && user == geteuid() &&
+            group == getgid() && group == getegid()) {
+        return 0;
+    }
+
+    if (seteuid(0) != 0) {
+        fprintf(LOGFILE, "unable to reacquire root - %s\n", strerror(errno));
+        fprintf(LOGFILE, "Real: %d:%d; Effective: %d:%d\n",
+                getuid(), getgid(), geteuid(), getegid());
+        return SETUID_OPER_FAILED;
+    }
+    if (setgid(group) != 0) {
+        fprintf(LOGFILE, "unable to set group to %d - %s\n", group,
+                strerror(errno));
+        fprintf(LOGFILE, "Real: %d:%d; Effective: %d:%d\n",
+                getuid(), getgid(), geteuid(), getegid());
+        return SETUID_OPER_FAILED;
+    }
+    if (setuid(user) != 0) {
+        fprintf(LOGFILE, "unable to set user to %d - %s\n", user, strerror(errno));
+        fprintf(LOGFILE, "Real: %d:%d; Effective: %d:%d\n",
+                getuid(), getgid(), geteuid(), getegid());
+        return SETUID_OPER_FAILED;
+    }
+
+    return 0;
+}
+
+int main(int argc, char **argv){
+    if (argc < 3) {
+        fprintf(ERRORFILE, "Requires at least 3 variables: ./execute-as-user uid command [args]");
+    }
+
+    if(!LOGFILE)
+        LOGFILE=stdout;
+    if(!ERRORFILE)
+        ERRORFILE=stderr;
+
+
+
+    char *uid = argv[1];
+
+    // for loop to calculate the length to malloc
+    int i;
+    int total_len = 0;
+    for(i=2;i<argc;i++){
+        total_len += strlen(argv[i])+1;
+    }
+    printf("total_len: %d\n", total_len);
+
+    // allocate memory and clear memory
+    char *cmd = malloc(total_len+2);
+    memset(cmd, ' ', total_len+2);
+
+    // change user 
+    struct passwd *userInfo = getpwnam(uid);
+    fprintf(LOGFILE, "Changing user: user: %s, uid: %d, gid: %d\n", uid, userInfo->pw_uid, userInfo->pw_gid);
+    int retval = change_user(userInfo->pw_uid, userInfo->pw_gid);
+    printf("retval: %d\n", retval);
+    if( retval != 0){
+        fprintf(LOGFILE, "Error changing user to %s\n", uid);
+        return SETUID_OPER_FAILED;
+    }
+
+    // create the command
+    char *cur = cmd;
+    int len;
+    for(i=2;i<argc;i++){
+        len = strlen(argv[i]);
+        memcpy(cur, argv[i], len);
+        cur+=len+1;
+        printf("%s\n", cmd);
+    }
+
+    retval = system(cmd);
+    fprintf(LOGFILE, "system call return value: %d", retval);
+
+    // sometimes system(cmd) returns 256, which is interpreted to 0, making a failed job a successful job
+    // hence this goofy piece of if statement.
+    if(retval != 0)
+        return 1;
+    else
+        return 0;
+
+}