Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Added LDAP security to get the username, updated the endpoints to ret…
Browse files Browse the repository at this point in the history
…urn exceptions consistent with workflow-service and updated the README
  • Loading branch information
lshannon committed Mar 24, 2023
1 parent e621e3c commit 96ce8c9
Show file tree
Hide file tree
Showing 18 changed files with 453 additions and 171 deletions.
21 changes: 19 additions & 2 deletions notification-service/.flattened-pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,23 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
Expand Down Expand Up @@ -116,6 +128,11 @@
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
12 changes: 12 additions & 0 deletions notification-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ The service uses JPA to persist. Postgres is the recommended DB. For the 'dev' p
The UI for this service can be found as a backstage Plugin for a stand-alone Java service (UI + API) in one Jar, check
out implementation-examples/java-services

## Starting the Service

From the root of the 'notification-service' folder, the follow command will start-up the server locally:

```shell

java -jar -Dspring.profiles.active=local -Dserver.port=8081 target/notification-service-1.0.5-SNAPSHOT.jar

```

The service will run against a local h2 database in when running with way.

## FAQ

### We use Slack, is this required?
Expand Down
22 changes: 20 additions & 2 deletions notification-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,24 @@
<!-- START Spring Security Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
</dependency>
<!-- END Spring Security Dependencies -->
<!-- START Spring Cloud Dependencies -->
Expand Down Expand Up @@ -111,6 +124,11 @@
<scope>test</scope>
</dependency>
<!-- END Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

/**
* Main entry point into the application
*
* @author Richard Wang (Github: RichardW98)
* @author Annel Ketcha (Github: anludke)
* @author Luke Shannon (Github: lshannon)
*/
@SpringBootApplication
@EnableWebSecurity
@EnableConfigurationProperties
@ConfigurationPropertiesScan("com.redhat.parodos")
public class NotificationServiceApplication {

public static void main(String[] args) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,8 @@
*/
package com.redhat.parodos.notification.controller;

import com.redhat.parodos.notification.enums.Operation;
import com.redhat.parodos.notification.enums.State;
import com.redhat.parodos.notification.dto.NotificationAssemblerDTO;
import com.redhat.parodos.notification.util.SecurityUtil;
import com.redhat.parodos.notification.dto.NotificationRecordResponseDTO;
import com.redhat.parodos.notification.jpa.entity.NotificationRecord;
import com.redhat.parodos.notification.service.NotificationRecordService;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.UUID;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
Expand All @@ -39,6 +32,17 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

import com.redhat.parodos.notification.dto.NotificationAssemblerDTO;
import com.redhat.parodos.notification.dto.NotificationRecordResponseDTO;
import com.redhat.parodos.notification.enums.Operation;
import com.redhat.parodos.notification.enums.State;
import com.redhat.parodos.notification.jpa.entity.NotificationRecord;
import com.redhat.parodos.notification.service.NotificationRecordService;
import com.redhat.parodos.notification.util.SecurityUtil;

import io.swagger.v3.oas.annotations.tags.Tag;

/**
* Notification record controller
Expand Down Expand Up @@ -77,6 +81,9 @@ public NotificationRecordController(NotificationRecordService notificationRecord
public PagedModel<NotificationRecordResponseDTO> getNotifications(@PageableDefault(size = 100) Pageable pageable,
@RequestParam(value = "state", required = false) State state,
@RequestParam(value = "searchTerm", required = false) String searchTerm) {
if (securityUtil == null || securityUtil.getUsername() == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "No username associated with this request");
}
Page<NotificationRecord> notificationsRecordPage = this.notificationRecordService
.getNotificationRecords(pageable, securityUtil.getUsername(), state, searchTerm);
return this.notificationRecordPagedResourcesAssembler.toModel(notificationsRecordPage,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 Red Hat Developer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.redhat.parodos.notification.security;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

import lombok.Data;

@ConfigurationProperties(prefix = "spring.ldap.connection")
@ConfigurationPropertiesScan
@Data
public class LdapConnectionProperties {

String userDNPatterns;

String groupSearchBase;

String url;

String managerDN;

String managerPassword;

String passwordAttribute;

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.redhat.parodos.notification.config;
package com.redhat.parodos.notification.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

/**
* Local configuration to run the service with no authentication
*
* @author Annel Ketcha (Github: anludke)
*/
@Profile("local")
@Configuration
public class LocalSecurityConfiguration {
public class LocalSecurityConfiguration extends SecurityConfiguration {

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll());
return http.build();
@Override
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
HttpSecurity httpSec = this.setHttpSecurity(http);
httpSec.cors().disable();
httpSec.csrf().disable();
return httpSec.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2022 Red Hat Developer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.redhat.parodos.notification.security;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.stereotype.Component;

/**
* Security configuration for the application to ensure the main endpoints are locked down
* and an OAuth2 server is enable. The OAuth2 server details can be found in the
* application.yml file
*
* @author Luke Shannon (Github: lshannon)
*
*/

@Component
@Configuration
@Profile("!local")
@DependsOn("org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor")
public class SecurityConfiguration {

@Autowired
private LdapConnectionProperties ldapConnectionProperties;

public HttpSecurity setHttpSecurity(HttpSecurity http) throws Exception {
// @formatter:off
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
http
.authorizeRequests()
.mvcMatchers(HttpMethod.OPTIONS, "/**")
.permitAll()
.mvcMatchers("/api/**")
.fullyAuthenticated()
.and()
.httpBasic(withDefaults())
.headers().frameOptions().disable()
.and()
.formLogin(form -> form.loginProcessingUrl("/login"))
.logout()
.logoutSuccessUrl("/login").permitAll();
// @formatter:on
return http;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
HttpSecurity httpSec = this.setHttpSecurity(http);
return httpSec.build();
}

@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
// @formatter:off
auth.ldapAuthentication()
.userDnPatterns(this.ldapConnectionProperties.getUserDNPatterns())
.groupSearchBase(this.ldapConnectionProperties.getGroupSearchBase()).contextSource()
.url(this.ldapConnectionProperties.getUrl())
.managerDn(this.ldapConnectionProperties.getManagerDN())
.managerPassword(this.ldapConnectionProperties.getManagerPassword())
.and()
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute(this.ldapConnectionProperties.getPasswordAttribute());
// @formatter:on
}

}
Loading

0 comments on commit 96ce8c9

Please sign in to comment.