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

3.8.3 and Electron JDBC Security error - SRCFG00027: Could not find a mapping #40065

Closed
tmulle opened this issue Apr 14, 2024 · 15 comments · Fixed by #40457
Closed

3.8.3 and Electron JDBC Security error - SRCFG00027: Could not find a mapping #40065

tmulle opened this issue Apr 14, 2024 · 15 comments · Fixed by #40457
Labels
area/security kind/bug Something isn't working triage/needs-reproducer We are waiting for a reproducer.
Milestone

Comments

@tmulle
Copy link

tmulle commented Apr 14, 2024

Describe the bug

Trying to update a project which uses 3.6.7 of quarkus to 3.8.3 and even 3.9.3 that uses the electron-jdbc-security extension and getting the error below when trying to start the application.

The program compiles just fine, it just fails starting up.

I also tried 3.7.0 and that fails..

Reverting back to 3.6.7 works, but just wondering if this is a bug or a migration step I need to do? I didn't find anything about this error or any migration steps with security in the change logs.

<dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-elytron-security-jdbc</artifactId>
        </dependency>
java.util.NoSuchElementException: SRCFG00027: Could not find a mapping for io.quarkus.security.runtime.SecurityConfig
    at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.doCreate(Unknown Source)
    at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.create(Unknown Source)
    at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.get(Unknown Source)
    at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.get(Unknown Source)
    at io.quarkus.arc.impl.CurrentInjectionPointProvider.get(CurrentInjectionPointProvider.java:48)
    at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.doCreate(Unknown Source)
    at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.create(Unknown Source)
    at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.create(Unknown Source)
    at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
    at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
    at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
    at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:32)
    at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
    at io.quarkus.arc.impl.ComputingCacheContextInstances.computeIfAbsent(ComputingCacheContextInstances.java:19)
    at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
    at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.get(Unknown Source)
    at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.get(Unknown Source)
    ```

### Expected behavior

_No response_

### Actual behavior

Quarkus fails startup with the exception

### How to Reproduce?

_No response_

### Output of `uname -a` or `ver`

_No response_

### Output of `java -version`

17

### Quarkus version or git rev

3.8.3 or 3.9.3

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

_No response_

### Additional information

_No response_
@tmulle tmulle added the kind/bug Something isn't working label Apr 14, 2024
@quarkus-bot
Copy link

quarkus-bot bot commented Apr 14, 2024

/cc @sberyozkin (security)

@sberyozkin
Copy link
Member

sberyozkin commented Apr 14, 2024

@tmulle Can you provide more information please, ideally a simple reproducer, sounds like a configuration mapping problem, also CC @radcortez

@radcortez radcortez added the triage/needs-reproducer We are waiting for a reproducer. label Apr 15, 2024
@radcortez
Copy link
Member

I tried to reproduce it with no luck. Maybe it requires some specific setup. Can you please provider a reproducer? Thank you!

@tmulle
Copy link
Author

tmulle commented Apr 15, 2024

Hi,

I will try but the project is using ebean for JPA persistence and it's our company code, so I can't use the same code base.

We're also using Primefaces Quarkus extension and lombok and mariadb as well as the BASIC AUTH and FORM features to provide login forms.

I will have to see if I can make a small reproducer, the problem is I have no idea WHERE it's breaking. I've tried commenting out the quarkus FORM/BASIC auth properties, and that still fails. I've tried commenting out openapi, etc.

I even tried updating all the dependencies to their latest versions and still the same error.

I am posting my application.properties and pom.xml but nothing looks out of the ordinary.

All I know is that Quarkus 3.6.7 works fine and then 3.7+ is when things break.

No code has changed, I just bumped the version of quarkus. Changing JUST the quarkus version back to 3.6.7 makes everything work again.

These are my application.properties for just the security/jdbc configs. There was nothing else in there except our own application properties.

I don't have any custom security code, I use the standard @Authenticated and @RolesAllowed for our security endpoints in the rest classes and the SecurityIdentity in our main login class so we can read the logged in user.

But to me, the error I'm getting looks like it is a quarkus.security.XXX config property issue? Not sure what though.
I compared mine to the sample in the getting started for security-jdbc and they look the same.

Thanks..


# Setup FORM auth
quarkus.http.auth.form.enabled=true
quarkus.http.auth.basic=true
quarkus.http.auth.form.landing-page=/public/index.xhtml
quarkus.http.auth.form.login-page=/public/login.xhtml
quarkus.http.auth.form.error-page=/public/login.xhtml

# Needed for hibernate security
quarkus.datasource.db-kind=mariadb
quarkus.datasource.username=<OUR_USER>
quarkus.datasource.password=<OUR_PWD>
quarkus.datasource.jdbc.url=jdbc:mariadb://localhost:3306/webDB?useLegacyDatetimeCode=false
quarkus.datasource.jdbc.driver=org.mariadb.jdbc.Driver

# Define how we are authenticating users and roles
quarkus.security.jdbc.enabled=true
quarkus.security.jdbc.principal-query.sql=<REDACTED_QUERY>
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.enabled=true
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.password-index=1
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.salt-index=-1
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.iteration-count-index=-1
quarkus.security.jdbc.principal-query.attribute-mappings.0.index=3 
quarkus.security.jdbc.principal-query.attribute-mappings.0.to=groups

# Deny access to any JAXRS endpoints - Must use specific annotations if need to expose to outside
quarkus.security.jaxrs.deny-unannotated-endpoints=true

# we want to secure anything under the "secure" path
quarkus.http.auth.permission.secured.paths=secure/*
quarkus.http.auth.permission.secured.policy=authenticated
quarkus.http.auth.permission.secured.auth-mechanism=form

# anything in "public" if allowed
quarkus.http.auth.permission.public.paths=public/*,showcase/*,templates/*
quarkus.http.auth.permission.public.policy=permit

This is my pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.acme</groupId>
    <artifactId>quarkus-ebean-supportsite</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <properties>
        <compiler-plugin.version>3.13.0</compiler-plugin.version>
        <ebean.migration.version>14.0.0</ebean.migration.version>
        <ebean.version>15.1.0</ebean.version>
        <maven.compiler.release>17</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        
        <omnifaces-quarkus.version>4.3.0</omnifaces-quarkus.version>
        <primefaces-quarkus.version>3.13.5</primefaces-quarkus.version>
        <myfaces.version>4.0.1</myfaces.version>
        <quarkus.version>3.9.3</quarkus.version>
        
        <poi.version>5.2.2</poi.version>
        <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
        <lombok.version>1.18.32</lombok.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-bom</artifactId>
                <version>${quarkus.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
       
        <!-- Faces -->
        <dependency>
            <groupId>org.apache.myfaces.core.extensions.quarkus</groupId>
            <artifactId>myfaces-quarkus</artifactId>
            <version>${myfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>io.quarkiverse.primefaces</groupId>
            <artifactId>quarkus-primefaces</artifactId>
            <version>${primefaces-quarkus.version}</version>
        </dependency>
        <dependency>
            <groupId>io.quarkiverse.primefaces</groupId>
            <artifactId>quarkus-primefaces-extensions</artifactId>
            <version>${primefaces-quarkus.version}</version>
        </dependency>
        <dependency>
            <groupId>io.quarkiverse.omnifaces</groupId>
            <artifactId>quarkus-omnifaces</artifactId>
            <version>${omnifaces-quarkus.version}</version>
        </dependency>

        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jackson</artifactId>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>io.quarkus</groupId>-->
<!--            <artifactId>quarkus-arc</artifactId>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>io.quarkus</groupId>-->
<!--            <artifactId>quarkus-smallrye-openapi</artifactId>-->
<!--        </dependency>-->
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-junit5</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.ebean</groupId>
            <artifactId>ebean-mariadb</artifactId>
            <version>${ebean.version}</version>
        </dependency>
        <!--    <dependency>-->
        <!--      <groupId>io.ebean</groupId>-->
        <!--      <artifactId>ebean-postgres</artifactId>-->
        <!--      <version>${ebean.version}</version>-->
        <!--    </dependency>-->
        <!--    <dependency>-->
        <!--      <groupId>org.postgresql</groupId>-->
        <!--      <artifactId>postgresql</artifactId>-->
        <!--      <version>42.3.3</version>-->
        <!--    </dependency>-->
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>2.6.0</version>
        </dependency>
        <!--            <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>1.2.11</version>
        </dependency>-->
        <dependency>
            <groupId>io.ebean</groupId>
            <artifactId>ebean-migration</artifactId>
            <version>${ebean.migration.version}</version>
        </dependency>
        <dependency>
            <groupId>io.ebean</groupId>
            <artifactId>querybean-generator</artifactId>
            <version>${ebean.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.ebean</groupId>
            <artifactId>ebean-test</artifactId>
            <version>13.6.6</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.validation</groupId>
            <artifactId>jakarta.validation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </dependency>
        <dependency>
            <groupId>org.w3c.css</groupId>
            <artifactId>sac</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.15.2</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.cssparser</groupId>
            <artifactId>cssparser</artifactId>
            <version>0.9.17</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.converter</artifactId>
            <version>1.0.5</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.document</artifactId>
            <version>1.0.5</version>
        </dependency>
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-elytron-security-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-jdbc-mariadb</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-youtube</artifactId>
            <version>v3-rev222-1.25.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>io.repaint.maven</groupId>
                <artifactId>tiles-maven-plugin</artifactId>
                <version>2.36</version>
                <extensions>true</extensions>
                <configuration>
                    <tiles>
                        <tile>io.ebean.tile:enhancement:${ebean.version}</tile>
                    </tiles>
                </configuration>
            </plugin>
            <plugin>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-maven-plugin</artifactId>
                <version>${quarkus.version}</version>
                <extensions>true</extensions>
                <executions>
                    <execution>
                        <goals>
                            <goal>build</goal>
                            <goal>generate-code</goal>
                            <goal>generate-code-tests</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler-plugin.version}</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>

                        <!-- additional annotation processor required as of Lombok 1.18.16 -->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>0.2.0</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <profiles>
        <profile>
            <id>native</id>
            <activation>
                <property>
                    <name>native</name>
                </property>
            </activation>
            <properties>
                <skipITs>false</skipITs>
                <quarkus.package.type>native</quarkus.package.type>
            </properties>
        </profile>
    </profiles>
</project>

@radcortez
Copy link
Member

Can you check which url check is triggering the exception and where it is being executed? I suspect that something is happening during static init, where this specific configuration is not yet available.

@tmulle
Copy link
Author

tmulle commented Apr 17, 2024

@radcortez

So, I found the issue, but not sure why 3.6.7 allowed it to work and not 3.7+.

Turns out they have @RolesAllowed annotations on their JPA model methods.

They are using Ebean's Model class, which looks like it is close to Panache's Active Record pattern.

They had defined utility methods on their entities like this:

@Entity
public class FailedLogin extends Model {
    @Id
    @GeneratedValue
    public long id;

    @Column(nullable = false)
    public String userEmail;
    @Column(nullable = false)
    public String ipAddr;
    @Column(nullable = false)
    public Date attempted;
    public String reason;

    @Transient
    private static final SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

    public FailedLogin(String userEmail, String ipAddr, Date attempted, String reason) {
        super();
        this.userEmail = userEmail;
        this.ipAddr = ipAddr;
        this.attempted = attempted;
        this.reason = reason;
    }

    public static Finder<Long, FailedLogin> find = new Finder<Long, FailedLogin>(FailedLogin.class);

    // count failed
    public static int countAllFailed(int minutes) {
        long t = System.currentTimeMillis() - (minutes * 60 * 1000);
        return find.query().where().gt("attempted", new Date(t)).findCount();
    }

 /**
     * Return all failed user logins
     *
     * @return JSON with id, email, loginDate, ipAddr, org, ogrCat
     */
   @RolesAllowed({"webadmin", "development", "support"})
    public static JsonObject getAllAsJson() {
        String sql = "SELECT ul.id, ul.user_email, ul.ip_addr, ul.attempted, u.state_code, u.country_code, o.org_name, o.org_cat from user_login ul LEFT OUTER JOIN user u ON ul.user_email = u.user_email LEFT OUTER JOIN org o ON u.org_org_id = o.org_id";
        List<FailedLogin> all = find.all();
        JsonObject result = new JsonObject();
        JsonArray an = new JsonArray();
        result.put("data", an);

        for (FailedLogin f : all) {
            an.add(f.toJson());
        }
        return result;
    }
 }

I went through an commented out every @RolesAllowed on their entity models and quarkus now starts up fine and the site runs.

So, question is: The @RolesAllowed is not supported on anything other than JAX-RS endpoints? We can't use them in domain models? Or service classes?

For reference here is the stack trace with the @RolesAllowed left in and trying to start Quarkus.
I see the FailedLogin class mentioned in the stack trace and then the error about SecurityConfig

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at io.quarkus.bootstrap.runner.QuarkusEntryPoint.doRun(QuarkusEntryPoint.java:62)
	at io.quarkus.bootstrap.runner.QuarkusEntryPoint.main(QuarkusEntryPoint.java:33)
Caused by: java.lang.ExceptionInInitializerError
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1160)
	at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(MethodHandleAccessorFactory.java:300)
	at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(MethodHandleAccessorFactory.java:103)
	at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(ReflectionFactory.java:200)
	at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Constructor.java:549)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:70)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	... 3 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.<clinit>(Unknown Source)
	... 16 more
Caused by: java.lang.ExceptionInInitializerError
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:534)
	at java.base/java.lang.Class.forName(Class.java:513)
	at io.quarkus.arc.runtime.InterceptedStaticMethodsRecorder.callInitializer(InterceptedStaticMethodsRecorder.java:17)
	at io.quarkus.deployment.steps.InterceptedStaticMethodsProcessor$callInitializer254957675.deploy_0(Unknown Source)
	at io.quarkus.deployment.steps.InterceptedStaticMethodsProcessor$callInitializer254957675.deploy(Unknown Source)
	... 17 more
Caused by: java.lang.RuntimeException: Error injecting io.quarkus.security.runtime.interceptor.SecurityHandler io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor.handler
	at io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor_Bean.doCreate(Unknown Source)
	at io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor_Bean.create(Unknown Source)
	at io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor_Bean.get(Unknown Source)
	at io.quarkus.security.runtime.interceptor.RolesAllowedInterceptor_Bean.get(Unknown Source)
	at com.mycompany.support.site.models.FailedLogin_InterceptorInitializer.init_getAllAsJson_5319fad9b8acc28b3114644ae068ada7a9e9968b(Unknown Source)
	at com.mycompany.support.site.models.FailedLogin_InterceptorInitializer.init_static_intercepted_methods(Unknown Source)
	at io.quarkus.arc.runtime.InterceptedStaticMethodsInitializer.<clinit>(Unknown Source)
	... 23 more
Caused by: java.lang.RuntimeException: Error injecting io.quarkus.security.runtime.interceptor.SecurityConstrainer io.quarkus.security.runtime.interceptor.SecurityHandler.constrainer
	at io.quarkus.security.runtime.interceptor.SecurityHandler_Bean.doCreate(Unknown Source)
	at io.quarkus.security.runtime.interceptor.SecurityHandler_Bean.create(Unknown Source)
	at io.quarkus.security.runtime.interceptor.SecurityHandler_Bean.create(Unknown Source)
	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:32)
	at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
	at io.quarkus.arc.impl.ComputingCacheContextInstances.computeIfAbsent(ComputingCacheContextInstances.java:19)
	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
	at io.quarkus.security.runtime.interceptor.SecurityHandler_Bean.get(Unknown Source)
	at io.quarkus.security.runtime.interceptor.SecurityHandler_Bean.get(Unknown Source)
	... 30 more
Caused by: jakarta.enterprise.inject.CreationException: Error creating synthetic bean [ZeFb0vDY5xnrxzmnnh0N7F_PFtw]: java.util.NoSuchElementException: SRCFG00027: Could not find a mapping for io.quarkus.security.runtime.SecurityConfig
	at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.doCreate(Unknown Source)
	at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.create(Unknown Source)
	at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.get(Unknown Source)
	at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.get(Unknown Source)
	at io.quarkus.arc.impl.CurrentInjectionPointProvider.get(CurrentInjectionPointProvider.java:48)
	at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.doCreate(Unknown Source)
	at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.create(Unknown Source)
	at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.create(Unknown Source)
	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:32)
	at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
	at io.quarkus.arc.impl.ComputingCacheContextInstances.computeIfAbsent(ComputingCacheContextInstances.java:19)
	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
	at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.get(Unknown Source)
	at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Bean.get(Unknown Source)
	... 42 more
Caused by: java.util.NoSuchElementException: SRCFG00027: Could not find a mapping for io.quarkus.security.runtime.SecurityConfig
	at io.smallrye.config.SmallRyeConfig.getConfigMapping(SmallRyeConfig.java:525)
	at io.quarkus.arc.runtime.ConfigMappingCreator.create(ConfigMappingCreator.java:30)
	at io.quarkus.security.runtime.SecurityConfig_ZeFb0vDY5xnrxzmnnh0N7F_PFtw_Synthetic_Bean.createSynthetic(Unknown Source)
	... 59 more

This is the line in that stacktrace:

com.mycompany.support.site.models.FailedLogin_InterceptorInitializer.init_getAllAsJson_5319fad9b8acc28b3114644ae068ada7a9e9968b(Unknown Source)
	at com.mycompany.support.site.models.FailedLogin_InterceptorInitializer.init_static_intercepted_methods(Unknown Source)

@radcortez
Copy link
Member

Wondering if we need to do the same thing as #40327 in here with SecurityConstrainer?

//cc @sberyozkin @michalvavrik

@michalvavrik
Copy link
Contributor

michalvavrik commented May 3, 2024

Wondering if we need to do the same thing as #40327 in here with SecurityConstrainer?

We have many tests for RolesAllowed on CDI beans and the SecurityHandler should only be initialized when one of standard security interceptors is invoked. I don't understand how could that happen before runtime config is initialized. #40327 was legit and my fault, I apologize for it, but here I think we need to study what is actually happening there.

This comment #40065 (comment) shows a @RolesAllowed annotation on the public static JsonObject getAllAsJson() which is also acceptable https://quarkus.io/guides/cdi-reference#interception-of-static-methods but ---------------> How can there be method invocation before app is ready that requires SecurityIdentity?

My suggestion is that I need to find out when static intercepted methods are initialized and create a reproducer because we can't say it is wrong ATM. We need more info.

@michalvavrik
Copy link
Contributor

michalvavrik commented May 3, 2024

@tmulle thank you for reporting this, do you think it would be feasible to create a simple reproducer? if not, I'll have a look anyway eventually, but it would quicken things (as time as limited....)

@michalvavrik
Copy link
Contributor

Never mind @tmulle , the issue is in static secured methods. It's easy to reproduce it. I'll have a look.

@michalvavrik
Copy link
Contributor

Static interceptors are initialized during static init:

And all beans are singletons, hence the issue. We can initialize the events helper lazily I guess.

@michalvavrik
Copy link
Contributor

michalvavrik commented May 4, 2024

#40457 takes care of it.

@radcortez I didn't find a way to recognize that runtime config / configmapping is ready without listening to StartupEvent (which seemed like overkill in this case as it would initialize bean too early or require a new class; so I didn't do it). This is not a case where I could listen to RuntimeConfigSetupCompleteBuildItem as sometimes it is initialized during static init and I'd have to go with static properties. It would be nice if I could do something like ConfigProvider.getConfig().unwrap(SmallRyeConfig.class).getConfigMapping(SecurityIdentity.class) without exception (maybe some other method that would allow me to check if I can already use the config mapping, hence it is ready for me).

@radcortez
Copy link
Member

What about a recorder method called during runtime init?

@michalvavrik
Copy link
Contributor

What about a recorder method called during runtime init?

That will work, but it require either to initialize bean sooner than required or new static env variable. I just thought it would be nice to find out dynamically, but it is not required. You are right I have options.

@quarkus-bot quarkus-bot bot added this to the 3.11 - main milestone May 6, 2024
@radcortez
Copy link
Member

The issue is that SR Config does not know about static/runtime. We first register the static init config with ConfigProvider.getConfig and replace the instance with the runtime when we switch phases. This should be one of the first operations on the switch.

If getting to a point where the mapping is not available, it means that you are in the static phase, and there is nothing you can do to recover from it unless it is acceptable to read configuration values in static init.

@gsmet gsmet modified the milestones: 3.11 - main, 3.10.1 May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/security kind/bug Something isn't working triage/needs-reproducer We are waiting for a reproducer.
Projects
None yet
5 participants