Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-53460

JEP-200 com.amazonaws.services.kinesis.producer.KinesisProducer for security reasons

    • Icon: Task Task
    • Resolution: Not A Defect
    • Icon: Major Major
    • other

      trying to crate a java plugin for jenkins but when testing it I get the follwing error:

       

      ava.lang.UnsupportedOperationException: Refusing to marshal com.amazonaws.services.kinesis.producer.KinesisProducer for security reasons; see https://jenkins.io/redirect/class-filter/ at hudson.util.XStream2$BlacklistedTypesConverter.marshal(XStream2.java:546)

       

      reading a bit found out the amazon library may have been blacklisted, didn't find any workaorund for that.

          [JENKINS-53460] JEP-200 com.amazonaws.services.kinesis.producer.KinesisProducer for security reasons

          Oleg Nenashev added a comment -

          The library is not blacklisted. it is "NOT whitelisted".

          I am not sure what is the particular reason to store this class on the disk, so I cannot advice.

           

          Oleg Nenashev added a comment - The library is not blacklisted. it is "NOT whitelisted". I am not sure what is the particular reason to store this class on the disk, so I cannot advice.  

          juan perez added a comment -

          Hi Oleg,

          sorry not sure I follow you, when you say a particular reason to store this class you mean to whitelist the class?

          I am just trying to create a custom plugin that sends build reports to an amazon kinesis stream using KPL library (the blacklisted one). 

           

          juan perez added a comment - Hi Oleg, sorry not sure I follow you, when you say a particular reason to store this class you mean to whitelist the class? I am just trying to create a custom plugin that sends build reports to an amazon kinesis stream using KPL library (the blacklisted one).   

          Oleg Nenashev added a comment -

          I can explain  the root cause if you provide a full stacktrace and code samples for your plugin.

          The problem here is not with the library being used. The problem is that "KinesisProducer" class is being serialized to the disk, likely as a part of the Job configuration or build.xml field. In order to perform such serialization, the classes would need to be whitelisted. But nothing blocks you from using the class in your code (local variables, transient fields, etc.)

           

           

           

          Oleg Nenashev added a comment - I can explain  the root cause if you provide a full stacktrace and code samples for your plugin. The problem here is not with the library being used. The problem is that "KinesisProducer" class is being serialized to the disk, likely as a part of the Job configuration or build.xml field. In order to perform such serialization, the classes would need to be whitelisted. But nothing blocks you from using the class in your code (local variables, transient fields, etc.)      

          juan perez added a comment -

          Hi Oleg,

          Thanks for the reply yes attached the full stack trace (jenkinsStackTrace.txt). Following relevant code:

           

           

          import com.amazonaws.services.kinesis.producer.Attempt;
          import com.amazonaws.services.kinesis.producer.KinesisProducerConfiguration;
          import com.amazonaws.services.kinesis.producer.KinesisProducer;
          import com.amazonaws.services.kinesis.producer.UserRecordFailedException;
          import com.amazonaws.services.kinesis.producer.UserRecordResult;
          

           

           

              @Override
              public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
                  JsonObject build_identifier = new JsonObject();
                  build_identifier.addProperty("project_id", this.project_id);
                  build_identifier.addProperty("product_name", this.product_name);
                  build_identifier.addProperty("version", this.version);
                  build_identifier.addProperty("channel_id", this.channel_id);
                  throw new IOException(build_identifier.toString());
                  listener.getLogger().println("New created json : "+ build_identifier.toString());
                  sendReportToKinesis(build_identifier.toString(),listener);
                  return true;
              }
          

           

           

              private void sendReportToKinesis(String jsonString, BuildListener listener) {
                 String partitionKey = this.project_id + this.product_name;
                 byte[] reportBytes = jsonString.getBytes(StandardCharsets.UTF_8);
                 ListenableFuture<UserRecordResult> f = kinesisProducer.addUserRecord(
                 "joan_testkinessisstream",
                 partitionKey,
                 ByteBuffer.wrap(reportBytes)
                );
              Futures.addCallback(f, new FutureCallback<UserRecordResult>() {
                 @Override
                 public void onSuccess(UserRecordResult userRecordResult) {
                 }
                 @Override
                 public void onFailure(Throwable throwable) {
                     listener.getLogger().println("Error sending the string to AWS Kinesis");
                 }
              });
              }
          

           

           

          juan perez added a comment - Hi Oleg, Thanks for the reply yes attached the full stack trace ( jenkinsStackTrace.txt ). Following relevant code:     import com.amazonaws.services.kinesis.producer.Attempt; import com.amazonaws.services.kinesis.producer.KinesisProducerConfiguration; import com.amazonaws.services.kinesis.producer.KinesisProducer; import com.amazonaws.services.kinesis.producer.UserRecordFailedException; import com.amazonaws.services.kinesis.producer.UserRecordResult;         @Override     public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {         JsonObject build_identifier = new JsonObject();         build_identifier.addProperty( "project_id" , this .project_id);         build_identifier.addProperty( "product_name" , this .product_name);         build_identifier.addProperty( "version" , this .version);         build_identifier.addProperty( "channel_id" , this .channel_id);         throw new IOException(build_identifier.toString());         listener.getLogger().println( "New created json : " + build_identifier.toString());         sendReportToKinesis(build_identifier.toString(),listener);         return true ;     }         private void sendReportToKinesis( String jsonString, BuildListener listener) {     String partitionKey = this .project_id + this .product_name;     byte [] reportBytes = jsonString.getBytes(StandardCharsets.UTF_8);     ListenableFuture<UserRecordResult> f = kinesisProducer.addUserRecord(     "joan_testkinessisstream" ,     partitionKey,   ByteBuffer.wrap(reportBytes)     );    Futures.addCallback(f, new FutureCallback<UserRecordResult>() {     @Override public void onSuccess(UserRecordResult userRecordResult) {     }     @Override     public void onFailure(Throwable throwable) {     listener.getLogger().println( "Error sending the string to AWS Kinesis" );     }     });     }    

          Oleg Nenashev added a comment -

          The reported code is unrelated. The issue happens when the project is saved, likely the class ia created in the constructor

          Oleg Nenashev added a comment - The reported code is unrelated. The issue happens when the project is saved, likely the class ia created in the constructor

          juan perez added a comment -

          Yes class is created in the constructor:

           

              @DataBoundConstructor
              public Analytics(String ctsm_is_id, String project_id, String product_name, String version, String channel_id, String AWS_id){
                  this.project_id = project_id;
                  this.product_name = product_name;
                  this.version = version;
                  this.channel_id = channel_id;
                  this.AWS_id = AWS_id;
           
                  this.kinesisProducer = createKinessisProducer();
          

           

              }

          juan perez added a comment - Yes class is created in the constructor:       @DataBoundConstructor     public Analytics( String ctsm_is_id, String project_id, String product_name, String version, String channel_id, String AWS_id){         this .project_id = project_id;         this .product_name = product_name;         this .version = version;         this .channel_id = channel_id;         this .AWS_id = AWS_id;           this .kinesisProducer = createKinessisProducer();       }

          Oleg Nenashev added a comment -

          I would suggest creating it on-demand in methods. If you want to optimize performance, you can cache it in a static variable or transuent field (will require restart handling then)

          Oleg Nenashev added a comment - I would suggest creating it on-demand in methods. If you want to optimize performance, you can cache it in a static variable or transuent field (will require restart handling then)

          juan perez added a comment -

          You were right, removed the class creation from the constructor and gave me no error.

          juan perez added a comment - You were right, removed the class creation from the constructor and gave me no error.

          Oleg Nenashev added a comment -

          Thanks for the update

          Oleg Nenashev added a comment - Thanks for the update

            oleg_nenashev Oleg Nenashev
            joanperez juan perez
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: