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

Feature implement o auth for sec hub web UI #3406 #3473

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion gradle/libraries.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ ext {
springboot_starter_mail: "org.springframework.boot:spring-boot-starter-mail",
springboot_starter_validation: "org.springframework.boot:spring-boot-starter-validation",
springboot_starter_webflux: "org.springframework.boot:spring-boot-starter-webflux",

springboot_starter_oauth2_client: "org.springframework.boot:spring-boot-starter-oauth2-client",
springframework_restdocs: "org.springframework.restdocs:spring-restdocs-mockmvc",
springframework_security_test: "org.springframework.security:spring-security-test",
springframework_web: "org.springframework:spring-web",
Expand Down
6 changes: 3 additions & 3 deletions sechub-webui-solution/helm/sechub-webui/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ webui:
appenderName: "LOGSTASH_JSON"
spring:
# Spring profiles (comma-separated list):
# - Server mode: 'webui_localserver' (self-signed cert) or 'webui_server' (provide SSL certificate)
# - SecHub connection: 'webui_mocked' or leave empty for connect to configured SecHub server
profiles: "webui_localserver"
# - Server mode: 'ssl-cert-provided' (self-signed SSL cert included) or 'ssl-cert-required' (SSL certificate required by external config)
# - SecHub connection: 'basic-auth-mocked' or leave empty for connect to configured SecHub server
profiles: "ssl-cert-provided"
# Configure Spring Boot's embedded Tomcat
embeddedTomcat:
logging:
Expand Down
2 changes: 2 additions & 0 deletions sechub-webui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
application-local.*.yaml
application-local.*.yml
61 changes: 61 additions & 0 deletions sechub-webui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!-- SPDX-License-Identifier: MIT -->

# SecHub WebUI

## Overview

SecHub WebUI is a web-based user interface for managing and interacting with the SecHub application.

## Profiles

To start the application locally use the `webui_local` profile.

This will include the following profiles:

- `ssl-cert-provided`: a default ssl certificate will be used by the WebUI server
- `basic-auth-mocked`: mock the SecHub Server & enable login with preconfigured credentials at `/login/classic`)
- `local`: includes any local configurations matching `application-local.${USER}.yml`

If you want to provide local configurations, create a file named `application-local.${USER}.yml` in the `src/main/resources` directory.
Make sure that the ${USER} part matches your system username.

This will enable configurations suitable for local development and testing.

## Running the application in OAuth2 Mode

To run the application in OAuth2 mode, include the `oauth2-enabled` profile.

Note: The `webui_prod` profile includes the `oauth2-enabled` profile.

Make sure that you either provide a valid `application-oauth2-enabled.yml` file in the `src/main/resources` directory or set the required environment variables.

Example `application-oauth2-enabled.yml`:

```yaml
sechub:
security:
oauth2:
client-id: example-client-id
client-secret: example-client-secret
provider: example-provider
redirect-uri: {baseUrl}/login/oauth2/code/{provider}
issuer-uri: https://sso.example-provider.com
authorization-uri: https://sso.example-provider.com/as/authorization.oauth2
token-uri: https://sso.example-provider.com/as/token.oauth2
user-info-uri: https://sso.example-provider.com/idp/userinfo.openid
jwk-set-uri: https://sso.example-provider.com/pf/JWKS
```

Alternatively, you can provide the following environment variables:

```bash
SECHUB_SECURITY_OAUTH2_CLIENT_ID=example-client-id
SECHUB_SECURITY_OAUTH2_CLIENT_SECRET=example-client-secret
SECHUB_SECURITY_OAUTH2_PROVIDER=example-provider
SECHUB_SECURITY_OAUTH2_REDIRECT_URI={baseUrl}/login/oauth2/code/{provider}
SECHUB_SECURITY_OAUTH2_ISSUER_URI=https://sso.example-provider.com
SECHUB_SECURITY_OAUTH2_AUTHORIZATION_URI=https://sso.example-provider.com/as/authorization.oauth2
SECHUB_SECURITY_OAUTH2_TOKEN_URI=https://sso.example-provider.com/as/token.oauth2
SECHUB_SECURITY_OAUTH2_USER_INFO_URI=https://sso.example-provider.com/idp/userinfo.openid
SECHUB_SECURITY_OAUTH2_JWK_SET_URI=https://sso.example-provider.com/pf/JWKS
```
7 changes: 6 additions & 1 deletion sechub-webui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ plugins {
dependencies {
implementation project(':sechub-commons-core')
implementation project(':sechub-api-java')
implementation library.springboot_starter_web
implementation library.springboot_starter_security
implementation library.springboot_starter_thymeleaf
implementation library.logstashLogbackEncoder
implementation library.springboot_starter_webflux
implementation library.thymeleaf_extras_springsecurity5
implementation library.springboot_starter_oauth2_client
implementation library.findbugs

testImplementation library.springboot_starter_test
testImplementation library.springframework_security_test

developmentOnly library.springboot_devtoolssf
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.webui;

public final class ApplicationProfiles {

public static final String BASIC_AUTH_MOCKED = "basic-auth-mocked";
public static final String INTEGRATION_TEST_DATA = "integrationtest-data";
public static final String LOCAL = "local";
public static final String OAUTH2_ENABLED = "oauth2-enabled";
public static final String SSL_CERT_PROVIDED = "ssl-cert-provided";
public static final String SSL_CERT_REQUIRED = "ssl-cert-required";
public static final String TEST = "test";

private ApplicationProfiles() {
// Prevent instantiation
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.webui;

public class RequestConstants {
public final class RequestConstants {

public static final String ROOT = "/";

public static final String PROJECTS = "/projects";
public static final String PROJECT_SCANS = "/projects/{projectId}/scans";
public static final String STATUS = "/status";
public static final String LOGIN = "/login";
public static final String LOGIN_CLASSIC = "/login/classic";
public static final String LOGIN_OAUTH2 = "/login/oauth2";
public static final String HOME = "/home";
public static final String LOGOUT = "/logout";

public static final String REQUEST_NEW_APITOKEN = "/request-new-apitoken";
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.webui.page.credentials;
package com.mercedesbenz.sechub.webui.credentials;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.mercedesbenz.sechub.webui.RequestConstants;
import com.mercedesbenz.sechub.webui.page.user.UserInfoService;
import com.mercedesbenz.sechub.webui.sechubaccess.SecHubAccessService;
import com.mercedesbenz.sechub.webui.user.UserInfoService;

@Controller
public class NewApiTokenController {
class NewApiTokenController {

@Autowired
NewApiTokenService newApiTokenService;
private final NewApiTokenService newApiTokenService;
private final SecHubAccessService accessService;
private final UserInfoService userInfoService;

@Autowired
SecHubAccessService accessService;

@Autowired
UserInfoService userInfoService;
NewApiTokenController(NewApiTokenService newApiTokenService, SecHubAccessService accessService, UserInfoService userInfoService) {
this.newApiTokenService = newApiTokenService;
this.accessService = accessService;
this.userInfoService = userInfoService;
}

@GetMapping(RequestConstants.REQUEST_NEW_APITOKEN)
String requestNewApiToken(Model model) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.webui.page.credentials;
package com.mercedesbenz.sechub.webui.credentials;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mercedesbenz.sechub.webui.sechubaccess.SecHubAccessService;

@Service
public class NewApiTokenService {
class NewApiTokenService {

@Autowired
SecHubAccessService accessService;
private final SecHubAccessService accessService;

NewApiTokenService(SecHubAccessService accessService) {
this.accessService = accessService;
}

/**
* Request new API token as described in
*
* <a href=
* Request new API token as described in <a href=
* "https://mercedes-benz.github.io/sechub/latest/sechub-restapi.html#user-
* requests-new-api-token">documentation</a>
*
Expand All @@ -25,9 +25,10 @@ public class NewApiTokenService {
* com' -i -X POST -H 'Content-Type: application/json;charset=UTF-8'
* </pre>
*/
public boolean requestNewApiToken(String emailAddress) {
boolean requestNewApiToken(String emailAddress) {
/* @formatter:off */
Boolean succesfulSendNewApiToken = accessService.createExecutorForResult(Boolean.class).

return accessService.createExecutorForResult(Boolean.class).
whenDoing("request a new api token").
callAndReturn(client -> {
client.requestNewApiToken(emailAddress);
Expand All @@ -36,8 +37,6 @@ public boolean requestNewApiToken(String emailAddress) {
onErrorReturn(exception -> Boolean.FALSE).
execute();

return succesfulSendNewApiToken;

/* @formatter:on */
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.webui.page;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.mercedesbenz.sechub.webui.RequestConstants;

@Controller
public class HomeController {

@GetMapping({ RequestConstants.ROOT, RequestConstants.HOME })
public String home(@AuthenticationPrincipal OidcUser principal, Model model) {
if (principal != null) {
model.addAttribute("principal", principal.getAttribute("name"));
}
return "home";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import com.mercedesbenz.sechub.webui.RequestConstants;

@Controller
public class LoginController {
public class LoginClassicController {

@GetMapping(RequestConstants.LOGIN)
@GetMapping(RequestConstants.LOGIN_CLASSIC)
String login() {
return "login";
return "login-classic";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.webui.page;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.mercedesbenz.sechub.webui.ApplicationProfiles;
import com.mercedesbenz.sechub.webui.RequestConstants;

@Controller
@Profile(ApplicationProfiles.OAUTH2_ENABLED)
class LoginOAuth2Controller {

@GetMapping(RequestConstants.LOGIN_OAUTH2)
String login(Model model) {
// TODO: make this configurable later for multiple client registrations
String registrationId = "mercedes-benz";
model.addAttribute("registrationId", registrationId);
return "login-oauth2";
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading