Skip to content

(auto) index creation failed with SecurityEvaluationContextExtension on classpath #4913

Closed as not planned
@NiasSt90

Description

@NiasSt90

If you enable the automatic index creation with spring.data.mongodb.auto-index-creation=true or use the other documented ways to automatically create indexes on startup, it fails if you have spring-security-data extension on your classpath

<groupId>org.springframework.security</groupId>
<artifactId>spring-security-data</artifactId>

because there is no SecurityContext active to initialize then context (getRootObject) in SecurityEvaluationContextExtension.

It fails because the (default) EvaluationContext used for index creation search for all available extensions and find the problematic one SecurityEvaluationContextExtension.

My current workaround was to programmatically create the indexes and wrap the call with a fake-SecurityContext.

	@EventListener(ContextRefreshedEvent.class)
	public void initIndicesAfterStartup() throws Exception {
		runWithSystemContext(this::createIndexes);
	}

	private Boolean createIndexes() {
		MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
				.getConverter().getMappingContext();
		IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
		mappingContext.getPersistentEntities()
				.stream()
				.filter(it -> it.isAnnotationPresent(Document.class))
				.forEach(it -> {
					IndexOperations indexOps = mongoTemplate.indexOps(it.getType());
					resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex);
				});
		return true;
	}


    static <T> T runWithSystemContext(Callable<T> runnable) throws Exception {
		SecurityContext originalContext = SecurityContextHolder.getContext();
		SecurityContext systemContext = SecurityContextHolder.createEmptyContext();
		Authentication authentication = new UsernamePasswordAuthenticationToken("system", null, null);
		systemContext.setAuthentication(authentication);
		try {
			SecurityContextHolder.setContext(systemContext);
			return runnable.call();
		} finally {
			SecurityContextHolder.setContext(originalContext);
		}
	}

complete Stacktrace for the error:

java.lang.IllegalArgumentException: Authentication object cannot be null
at org.springframework.security.access.expression.SecurityExpressionRoot.(SecurityExpressionRoot.java:76) ~[spring-security-core-5.7.11.jar:5.7.11]
at org.springframework.security.data.repository.query.SecurityEvaluationContextExtension$1.(SecurityEvaluationContextExtension.java:124) ~[spring-security-data-5.7.11.jar:5.7.11]
at org.springframework.security.data.repository.query.SecurityEvaluationContextExtension.getRootObject(SecurityEvaluationContextExtension.java:124) ~[spring-security-data-5.7.11.jar:5.7.11]
at org.springframework.security.data.repository.query.SecurityEvaluationContextExtension.getRootObject(SecurityEvaluationContextExtension.java:89) ~[spring-security-data-5.7.11.jar:5.7.11]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider$EvaluationContextExtensionAdapter.(ExtensionAwareEvaluationContextProvider.java:415) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider.lambda$toAdapters$3(ExtensionAwareEvaluationContextProvider.java:202) ~[spring-data-commons-2.7.18.jar:2.7.18]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider.toAdapters(ExtensionAwareEvaluationContextProvider.java:203) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider.access$000(ExtensionAwareEvaluationContextProvider.java:67) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider$ExtensionAwarePropertyAccessor.(ExtensionAwareEvaluationContextProvider.java:225) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider.doGetEvaluationContext(ExtensionAwareEvaluationContextProvider.java:131) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider.getEvaluationContext(ExtensionAwareEvaluationContextProvider.java:111) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.spel.ExtensionAwareEvaluationContextProvider.getEvaluationContext(ExtensionAwareEvaluationContextProvider.java:67) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.mapping.model.BasicPersistentEntity.getEvaluationContext(BasicPersistentEntity.java:557) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity.getEvaluationContext(BasicMongoPersistentEntity.java:219) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.getEvaluationContextForProperty(MongoPersistentEntityIndexResolver.java:664) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.resolveCompoundIndexKeyFromStringDefinition(MongoPersistentEntityIndexResolver.java:499) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.createCompoundIndexDefinition(MongoPersistentEntityIndexResolver.java:437) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.createCompoundIndexDefinitions(MongoPersistentEntityIndexResolver.java:427) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.potentiallyCreateCompoundIndexDefinitions(MongoPersistentEntityIndexResolver.java:285) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.resolveIndexForEntity(MongoPersistentEntityIndexResolver.java:127) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.resolveIndexFor(MongoPersistentEntityIndexResolver.java:104) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at org.springframework.data.mongodb.core.index.IndexResolver.resolveIndexFor(IndexResolver.java:79) ~[spring-data-mongodb-3.4.18.jar:3.4.18]
at de.onestytech.bvo.documentstorage.config.MongoIndexCreator.lambda$createIndexes$1(MongoIndexCreator.java:45) ~[classes/:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
at de.onestytech.bvo.documentstorage.config.MongoIndexCreator.createIndexes(MongoIndexCreator.java:43) ~[classes/:na]
at de.onestytech.bvo.documentstorage.config.MongoIndexCreator.initIndicesAfterStartup(MongoIndexCreator.java:31) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[na:na]
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:429) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:386) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:949) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:594) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) ~[spring-boot-2.7.18.jar:2.7.18]

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions