Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Runs Elasticsearch
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build with Maven
Expand All @@ -39,10 +39,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Test with Maven
Expand All @@ -59,10 +59,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Runs Elasticsearch
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# syntax=docker/dockerfile:1

FROM eclipse-temurin:17-jdk AS builder
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y maven
COPY . .
RUN mvn --batch-mode --update-snapshots clean package -DskipTests

FROM eclipse-temurin:17-jre AS runner
FROM eclipse-temurin:21-jre AS runner
WORKDIR /app
COPY --from=builder /build/target/ChannelFinder-*.jar ./channelfinder.jar
CMD ["java", "-jar", "/app/channelfinder.jar", "--spring.config.name=application"]
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ For using docker containers there is a barebones [docker compose file](./compose

* Prerequisites

* JDK 17
* JDK 21
* Elastic version 8.11.x
* **For authN/authZ using LDAP:** LDAP server, e.g. OpenLDAP

Expand All @@ -62,7 +62,7 @@ Options:
#### Running

```bash
sudo apt-get install openjdk-17-jre git curl wget
sudo apt-get install openjdk-21-jre git curl wget
sudo systemctl start elasticsearch # Or other command to run elastic search

# Replace verison with the release you want
Expand Down Expand Up @@ -98,7 +98,7 @@ and [Eclipse](https://eclipseide.org/).

* Prerequisites

* JDK 17
* JDK 21
* Maven (via package manager or via the wrapper `./mvnw`) (version specified
in [the wrapper properties](./.mvn/wrapper/maven-wrapper.properties))
Copy link
Contributor

@anderslindho anderslindho Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you need to update also this? (maven wrapper)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I upgrade it to 3.9+?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep it out of scope - please create a backlog task re maven version


Expand Down
16 changes: 9 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.boot-version>2.7.18</spring.boot-version>
<spring.boot-version>3.4.4</spring.boot-version>
<jackson.version>2.18.3</jackson.version>
<elasticsearch.version>8.11.2</elasticsearch.version>
<junit-jupiter.version>5.10.0</junit-jupiter.version>
<skipITs>true</skipITs>
<skipITCoverage>true</skipITCoverage>
<jacoco.skip>true</jacoco.skip>
<java.version>21</java.version>
<!--suppress UnresolvedMavenProperty -->
<project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp>
</properties>
Expand Down Expand Up @@ -84,12 +86,12 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.0</version>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.16.0</version>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
Expand Down Expand Up @@ -347,10 +349,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.14.0</version>
<configuration>
<source>17</source>
<target>17</target>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
Expand Down Expand Up @@ -452,7 +454,7 @@
<additionalOptions>
<additionalOption>-Xdoclint:none</additionalOption>
</additionalOptions>
<source>17</source>
<source>${java.version}</source>
</configuration>
</execution>
</executions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
import co.elastic.clients.transport.endpoints.BooleanResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,50 @@
package org.phoebus.channelfinder.configuration;

import static org.springframework.security.config.Customizer.withDefaults;

import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.authentication.BindAuthenticator;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().anyRequest().authenticated();
http.httpBasic();
public class WebSecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf(csrf -> csrf.disable())
.sessionManagement(
session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.httpBasic(withDefaults())
.build();
}

@Override
public void configure(WebSecurity web) throws Exception {
@Bean
public WebSecurityCustomizer ignoringCustomizer() {
// Authentication and Authorization is only needed for non search/query operations
web.ignoring().antMatchers(HttpMethod.GET, "/**");
return web -> web.ignoring().requestMatchers(HttpMethod.GET, "/**");
}

/** External LDAP configuration properties */
Expand Down Expand Up @@ -83,71 +99,99 @@ public void configure(WebSecurity web) throws Exception {
@Value("${file.auth.enabled:true}")
boolean file_enabled;

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration configuration, List<AuthenticationProvider> providers) {
return new ProviderManager(providers);
}

if (ldap_enabled) {
DefaultSpringSecurityContextSource contextSource =
new DefaultSpringSecurityContextSource(ldap_url);
contextSource.afterPropertiesSet();
@Bean
@ConditionalOnProperty(name = "ldap.enabled", havingValue = "true")
public AuthenticationProvider ldapAuthProvider() {

DefaultLdapAuthoritiesPopulator myAuthPopulator =
new DefaultLdapAuthoritiesPopulator(contextSource, ldap_groups_search_base);
myAuthPopulator.setGroupSearchFilter(ldap_groups_search_pattern);
myAuthPopulator.setSearchSubtree(true);
myAuthPopulator.setIgnorePartialResultException(true);
DefaultSpringSecurityContextSource contextSource =
new DefaultSpringSecurityContextSource(ldap_url);
contextSource.afterPropertiesSet();

auth.ldapAuthentication()
.userDnPatterns(ldap_user_dn_pattern)
.ldapAuthoritiesPopulator(myAuthPopulator)
.contextSource(contextSource);
}
DefaultLdapAuthoritiesPopulator authPopulator =
new DefaultLdapAuthoritiesPopulator(contextSource, ldap_groups_search_base);
authPopulator.setGroupSearchFilter(ldap_groups_search_pattern);
authPopulator.setSearchSubtree(true);
authPopulator.setIgnorePartialResultException(true);

if (embedded_ldap_enabled) {
DefaultSpringSecurityContextSource contextSource =
new DefaultSpringSecurityContextSource(embedded_ldap_url);
contextSource.afterPropertiesSet();

DefaultLdapAuthoritiesPopulator myAuthPopulator =
new DefaultLdapAuthoritiesPopulator(contextSource, embedded_ldap_groups_search_base);
myAuthPopulator.setGroupSearchFilter(embedded_ldap_groups_search_pattern);
myAuthPopulator.setSearchSubtree(true);
myAuthPopulator.setIgnorePartialResultException(true);

auth.ldapAuthentication()
.userDnPatterns(embedded_ldap_user_dn_pattern)
.ldapAuthoritiesPopulator(myAuthPopulator)
.groupSearchBase("ou=Group")
.contextSource(contextSource);
}
BindAuthenticator bindAuthenticator = new BindAuthenticator(contextSource);
bindAuthenticator.setUserDnPatterns(new String[] {ldap_user_dn_pattern});

return new LdapAuthenticationProvider(bindAuthenticator, authPopulator);
}

@Bean
@ConditionalOnProperty(name = "embedded_ldap.enabled", havingValue = "true")
public AuthenticationProvider embeddedLdapAuthProvider() {

DefaultSpringSecurityContextSource contextSource =
new DefaultSpringSecurityContextSource(embedded_ldap_url);
contextSource.afterPropertiesSet();

DefaultLdapAuthoritiesPopulator authPopulator =
new DefaultLdapAuthoritiesPopulator(contextSource, embedded_ldap_groups_search_base);
authPopulator.setGroupSearchFilter(embedded_ldap_groups_search_pattern);
authPopulator.setSearchSubtree(true);
authPopulator.setIgnorePartialResultException(true);

if (demo_auth_enabled) {
// read from configuration, no default content
// interpret users, pwds, roles
// user may have multiple roles

if (demo_auth_users != null
&& demo_auth_pwds != null
&& demo_auth_roles != null
&& demo_auth_users.length > 0
&& demo_auth_users.length == demo_auth_pwds.length
&& demo_auth_pwds.length == demo_auth_roles.length) {

for (int i = 0; i < demo_auth_users.length; i++) {
String[] userroles = demo_auth_roles[i].split(demo_auth_delimiter_roles);
if (userroles != null && userroles.length > 0) {
auth.inMemoryAuthentication()
.withUser(demo_auth_users[i])
.password(encoder().encode(demo_auth_pwds[i]))
.roles(userroles);
}
}
}
BindAuthenticator bindAuthenticator = new BindAuthenticator(contextSource);
bindAuthenticator.setUserDnPatterns(new String[] {embedded_ldap_user_dn_pattern});

return new LdapAuthenticationProvider(bindAuthenticator, authPopulator);
}

@Bean
@Conditional(EmbeddedLdapCondition.class)
public AuthenticationProvider demoAuthProvider() {

InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
PasswordEncoder encoder = encoder();

for (int i = 0; i < demo_auth_users.length; i++) {
String[] userroles = demo_auth_roles[i].split(demo_auth_delimiter_roles);

manager.createUser(
User.withUsername(demo_auth_users[i])
.password(encoder.encode(demo_auth_pwds[i]))
.roles(userroles)
.build());
}

DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(manager);
provider.setPasswordEncoder(encoder);
return provider;
}

@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}

private static class EmbeddedLdapCondition implements Condition {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems mixed up with demo auth and embedded ldap. They should be separate beans.


@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

Environment environment = context.getEnvironment();

Boolean isDemoAuthEnabled =
environment.getProperty("demo_auth.enabled", Boolean.class, false);
String[] demoAuthPwds = environment.getProperty("demo_auth.pwds", String[].class);
String[] demoAuthRoles = environment.getProperty("demo_auth.roles", String[].class);
String[] demoAuthUsers = environment.getProperty("demo_auth.users", String[].class);

return isDemoAuthEnabled
&& !ArrayUtils.isEmpty(demoAuthUsers)
&& !ArrayUtils.isEmpty(demoAuthPwds)
&& !ArrayUtils.isEmpty(demoAuthRoles)
&& demoAuthUsers.length == demoAuthPwds.length
&& demoAuthPwds.length == demoAuthRoles.length;
}
}
}
Loading
Loading