Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccessControlException from ClassGeneratingPropertyAccessorFactory [DATACMNS-1066] #1514

Closed
spring-projects-issues opened this issue May 11, 2017 · 16 comments
Assignees
Milestone

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented May 11, 2017

Balasubramani opened DATACMNS-1066 and commented

I am upgrading spring boot version from 1.3.7 to 1.5.3. When doing that spring-data-commons got updated from 1.11.4 to 1.13.3. In the new version, when I try to create/update any domain object, spring is throwing below exception. I see that new class which is introduced in 1.13.3 version ClassGeneratingPropertyAccessorFactory is causing the exception. When I add this access in my tomcat catalina.policy file, there is no issue with saving the domain object. But our IT team is not ready to provide this permission, as it is vulnerable to security. We have Auditing enabled using @EntityListeners( { AuditingEntityListener.class } ) in our domain class and using JpaRepository in our repository. We dont have any other special setup enabled in our Domain/Repository. We did not face any issue when in Spring boot 1.3.7/spring-data-commons 1.11.4. Can you please help us to resolve the issue without adding entry in catalina.policy?

java.lang.RuntimeException: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.catalina.loader")
                at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.createAccessorClass(ClassGeneratingPropertyAccessorFactory.java:170)
                at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.potentiallyCreateAndRegisterPersistentPropertyAccessorClass(ClassGeneratingPropertyAccessorFactory.java:154)
                at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.getPropertyAccessor(ClassGeneratingPropertyAccessorFactory.java:80)
                at org.springframework.data.mapping.model.BasicPersistentEntity.getPropertyAccessor(BasicPersistentEntity.java:425)
                at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.getBeanWrapperFor(MappingAuditableBeanWrapperFactory.java:89)
                at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:149)
                at org.springframework.data.auditing.AuditingHandler.markCreated(AuditingHandler.java:125)
                at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForCreate(AuditingEntityListener.java:83)
                at sun.reflect.GeneratedMethodAccessor936.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                at java.lang.reflect.Method.invoke(Unknown Source)
                at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:35)
                at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:94)
                at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.preCreate(CallbackRegistryImpl.java:54)
                at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:66)
                at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
                at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
                at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
                at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775)
                at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
                at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753)
                at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
                at sun.reflect.GeneratedMethodAccessor935.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                at java.lang.reflect.Method.invoke(Unknown Source)
                at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
                at com.sun.proxy.$Proxy322.persist(Unknown Source)
                at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:508)
                at sun.reflect.GeneratedMethodAccessor942.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                at java.lang.reflect.Method.invoke(Unknown Source)
                at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504)
                at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489)
                at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
                at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
                at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)’

Affects: 1.13.3 (Ingalls SR3)

Attachments:

Referenced from: commits 5dba2f4, 5f9d90e, 679f30e, 650a18a

Backported to: 1.13.4 (Ingalls SR4)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 11, 2017

Oliver Drotbohm commented

What do your domain types involved look like?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 11, 2017

Balasubramani commented

our domain class packages starts with com.biw.*. Is this what you are looking for? Below is our sample domain class. All our domain classes are extending BaseEntity for auditing columns

BaseEntity.Java

package com.bala.domain;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@MappedSuperclass
@EntityListeners( { AuditingEntityListener.class } )
public class BaseEntity implements Serializable
{

  private static final long serialVersionUID = 1L;

  @Transient
  private Long createdUserId;

  @CreatedDate
  @Column( name = "date_created" )
  @Temporal( TemporalType.TIMESTAMP )
  private Date dateCreated;

  @LastModifiedDate
  @Column( name = "date_modified" )
  @Temporal( TemporalType.TIMESTAMP )
  private Date dateModified;

  @CreatedBy
  @Column( name = "created_by" )
  private Long createdBy;

  @LastModifiedBy
  @Column( name = "modified_by" )
  private Long modifiedBy;

  @Column( name = "version" )
  @Version
  private Long version;

  public Long getCreatedUserId()
  {
    return createdUserId;
  }

  public void setCreatedUserId( Long createdUserId )
  {
    this.createdUserId = createdUserId;
  }

  public Date getDateCreated()
  {
    return dateCreated;
  }

  public void setDateCreated( Date dateCreated )
  {
    this.dateCreated = dateCreated;
  }

  public Date getDateModified()
  {
    return dateModified;
  }

  public void setDateModified( Date dateModified )
  {
    this.dateModified = dateModified;
  }

  public Long getCreatedBy()
  {
    return createdBy;
  }

  public void setCreatedBy( Long createdBy )
  {
    this.createdBy = createdBy;
  }

  public Long getModifiedBy()
  {
    return modifiedBy;
  }

  public void setModifiedBy( Long modifiedBy )
  {
    this.modifiedBy = modifiedBy;
  }

  public Long getVersion()
  {
    return version;
  }

  public void setVersion( Long version )
  {
    this.version = version;
  }
}

Domain Class

package com.bala.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "BALA_LOG")
public class CommLog extends BaseEntity {

	private static final long serialVersionUID = 1L;

	@Id
	@SequenceGenerator(name = "BALA_LOG_ID_GENERATOR", sequenceName = "BALA_LOG_SEQ", allocationSize = 1)
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BALA_LOG_ID_GENERATOR")
	private Long id;

	@Column(name = "USER_ID")
	private Long senderId;

	@Column(name = "TEXT")
	private String text;

	@Column(name = "SUBJECT")
	private String subject;

	@Column(name = "SENDER_EMAIL_ADDRESS")
	private String senderEmail;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public Long getSenderId() {
		return senderId;
	}

	public void setSenderId(Long senderId) {
		this.senderId = senderId;
	}

	public String getSenderEmail() {
		return senderEmail;
	}

	public void setSenderEmail(String senderEmail) {
		this.senderEmail = senderEmail;
	}

	@Override
	public String toString() {
		return "CommLog [id=" + id + ", senderId=" + senderId + ", text=" + text + ", subject=" + subject
				+ ", senderEmail=" + senderEmail + "]";
	}

}

Repository

package com.bala.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.bala.domain.CommLog;

@Repository
public interface CommLogRepository extends JpaRepository<CommLog, Long>
{
}

Let me know if you need more information..

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 11, 2017

Balasubramani commented

Added sample domain, base entity and repository

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 11, 2017

Oliver Drotbohm commented

Is there a chance you can strip down the project to a minimally reproducing sample? If I see things correctly, there should be a root cause for the exception you showed

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 11, 2017

Balasubramani commented

Attached Sample Project..

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 11, 2017

Oliver Drotbohm commented

The project doesn't build as it seems to try to resolve dependencies from a custom repo I don't have access to. Please make sure I can run the build locally and see a test fail that shows the exception you reported

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 12, 2017

Balasubramani commented

Sorry, I forgot to change the repository.. I have attached updated file. Run deploy task which will copy the war file to 'TOMCAT_HOME'/webapps folder. 'TOMCAT_HOME' is system variable to your tomcat direcory. Let me know if you this works for you..

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 12, 2017

Oliver Drotbohm commented

I'm sorry, but I am not going to deploy anything. Please make sure the error can be reproduced by running mvn clean test, thanks!

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 15, 2017

Balasubramani commented

Hi, Sorry for late response. I was trying to reproduce this issue by running mvn clean test but i am not sure how to enable the tomcat security policies while running the test cases. I will try for some more time and let you know...

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 15, 2017

Balasubramani commented

I am not able to enable the tomcat security settings while running the mvn test. It would be helpful if you help me how to enable tomcat security policies while running the test.

Also if I run start tomcat without security mode, I am not getting access control exception issue. It happens only when we start tomcat in secuiry mode

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 16, 2017

Oliver Drotbohm commented

Okay, so it looks like it's a general problem with a SecurityManager in place. I'll see what we can do here to back off in a better way (essentially falling back to reflection).

One thing you might be able to help with. Are you sure that there's not a root cause exception to the one you showed? I'd love to see the complete stack trace for the exception you get and have the feeling the one shown above is just a part of it

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 16, 2017

Balasubramani commented

Yes, What i was provided was part of exception. I just attached complete stacktrace of exception. Please let me know if any thing needed

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 16, 2017

Balasubramani commented

Attached full stacktrace

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 16, 2017

Oliver Drotbohm commented

Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.catalina.loader")
        at java.security.AccessControlContext.checkPermission(Unknown Source) ~[na:1.8.0_111]
        at java.security.AccessController.checkPermission(Unknown Source) [na:1.8.0_111]
        at java.lang.SecurityManager.checkPermission(Unknown Source) ~[na:1.8.0_111]
        at java.lang.SecurityManager.checkPackageAccess(Unknown Source) ~[na:1.8.0_111]
        at java.lang.Class.checkPackageAccess(Unknown Source) ~[na:1.8.0_111]
        at java.lang.Class.checkMemberAccess(Unknown Source) ~[na:1.8.0_111]
        at java.lang.Class.getDeclaredMethods(Unknown Source) ~[na:1.8.0_111]
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:613) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]
        at org.springframework.util.ReflectionUtils.findMethod(ReflectionUtils.java:179) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]
        at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$Evil.defineClass(ClassGeneratingPropertyAccessorFactory.java:1472) ~[spring-data-commons-1.13.3.RELEASE.jar:na]
        at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.generateCustomAccessorClass(ClassGeneratingPropertyAccessorFactory.java:282) ~[spring-data-commons-1.13.3.RELEAS
E.jar:na]
        at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.createAccessorClass(ClassGeneratingPropertyAccessorFactory.java:168) ~[spring-data-commons-1.13.3.RELEASE.jar:na]
        ... 266 common frames omitted

That was the bit I was looking for. Thanks for the help, we're gonna look into this!

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 16, 2017

Oliver Drotbohm commented

I've committed an additional check on the availability of the method on ClassLoader that we need and opt out of using class generation if that fails. Would you mind giving the latest snapshots a try?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 16, 2017

Balasubramani commented

Thanks for fix. I tried with snapshot version and it works fine. I will use once it is released

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants