Skip to content

Commit

Permalink
File based login added
Browse files Browse the repository at this point in the history
  • Loading branch information
mscr06 committed Aug 24, 2020
1 parent 03d2729 commit 46e20a9
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 12 deletions.
5 changes: 4 additions & 1 deletion docker_build/gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
enabled: true
platform:
baseUrl: http://localhost:8095
userGroupApiPath: /platformservice/v1/users/{username}/userGroups/importAndCache
userGroupApiPath: /platformservice/v1/users/{username}/usergroups/importAndCache
enabled: true
dashboard:
baseUrl: http://localhost:8094
Expand All @@ -22,6 +22,9 @@ ldap:
enabled: true
url: ldap://localhost:389/DC=example,DC=com
userDnPattern: uid={0},ou=people
file:
enabled: false
url: /platformservice/v1/users/authenticate
authn:
mode: session
google: {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.netflix.spinnaker.gate.config;

import java.io.Serializable;

public class FileLoginResponse implements Serializable {

private String username;
private String password;
private boolean validUser;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public boolean isValidUser() {
return validUser;
}

public void setValidUser(boolean validUser) {
this.validUser = validUser;
}

public FileLoginResponse() {}

public FileLoginResponse(String username, String password, boolean validUser) {
this.setUsername(username);
this.setPassword(password);
this.setValidUser(validUser);
}
}
5 changes: 5 additions & 0 deletions gate-file/gate-file.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dependencies {
implementation project(":gate-core")
implementation "org.apache.commons:commons-lang3"
implementation "org.springframework.session:spring-session-core"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.netflix.spinnaker.gate.security.file

import com.netflix.spinnaker.gate.config.AuthConfig
import com.netflix.spinnaker.gate.security.SpinnakerAuthConfig
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
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.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder

@ConditionalOnExpression('${file.enabled:false}')
@Configuration
@SpinnakerAuthConfig
@EnableWebSecurity
class FileSsoConfig extends WebSecurityConfigurerAdapter {

@Autowired
AuthConfig authConfig

@Autowired
private UserDetailsService userDataService

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDataService).passwordEncoder(passwordEncoder());
}

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

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.getDefaultUserDetailsService()
}

@Override
protected void configure(HttpSecurity http) throws Exception {
authConfig.jwtconfigure(http)
}

@Override
void configure(WebSecurity web) throws Exception {
authConfig.configure(web)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.netflix.spinnaker.gate.services.UserDataService
import com.netflix.spinnaker.gate.util.OesRestApi
import groovy.util.logging.Slf4j
import io.swagger.annotations.ApiOperation
import org.apache.tomcat.websocket.AuthenticationException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
Expand All @@ -23,7 +24,7 @@ import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController

@Slf4j
@ConditionalOnExpression('${ldap.enabled:false}')
@ConditionalOnExpression('${ldap.enabled:false} or ${file.enabled:false}')
@RestController
@RequestMapping("/auth")
class TokenAuthController {
Expand All @@ -33,35 +34,47 @@ class TokenAuthController {
@Autowired
UserDataService userDetailsService

@Autowired
@Autowired(required=false)
AuthenticationManager authenticationManager

@Value('${services.platform.enabled:false}')
boolean isPlatformEnabled;

@Value('${file.enabled:false}')
boolean isFileEnabled;

@Value('${file.url:null}')
String fileApiPath;

@Value('${services.platform.baseUrl:null}')
String url;

@Value('${services.platform.userGroupApiPath:null}')
String apiPath;
String groupApiPath;


@ApiOperation(value = "New Login for Jwt")
@RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> authenticateUser(@RequestBody AuthenticationRequest authenticationRequest ) {

try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
);
if (isFileEnabled && isPlatformEnabled){
if(!OesRestApi.initiateFileLoginInPlatform(url+fileApiPath, authenticationRequest)) throw new AuthenticationException("File Login Failed");
}
catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
else {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
);
}
catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
}
}

final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());

if (isPlatformEnabled) {
String path = apiPath.replace("{username}",userDetails.getUsername());
String path = groupApiPath.replace("{username}",userDetails.getUsername());
boolean isSuccessful = OesRestApi.initiateUserGroupInPlatform(url+path);
if (isSuccessful) {
final String jwt = jwtTokenUtil.generateToken(userDetails);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.netflix.spinnaker.gate.util;

import com.google.gson.Gson;
import com.netflix.spinnaker.gate.config.AuthenticationRequest;
import com.netflix.spinnaker.gate.config.FileLoginResponse;
import java.io.IOException;
import okhttp3.*;

Expand All @@ -15,4 +18,21 @@ public static boolean initiateUserGroupInPlatform(String url) throws IOException
return response.isSuccessful();
}
}

public static boolean initiateFileLoginInPlatform(
String url, AuthenticationRequest authenticationRequest) throws IOException {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
Gson gson = new Gson();
String data = gson.toJson(authenticationRequest);
RequestBody body = RequestBody.create(JSON, data);
Request request = new Request.Builder().url(url).post(body).build();
boolean isValidUser = false;
try (Response response = httpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
FileLoginResponse entity = gson.fromJson(response.body().string(), FileLoginResponse.class);
isValidUser = entity.isValidUser();
}
}
return isValidUser;
}
}
4 changes: 3 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ include "gate-api",
"gate-saml",
"gate-web",
"gate-x509",
"gate-integrations-gremlin"
"gate-integrations-gremlin",
"gate-file"

def setBuildFile(project) {
project.buildFileName = "${project.name}.gradle"
Expand All @@ -51,3 +52,4 @@ rootProject.children.each {
}

gradle.ext.includedProviderProjects = includeProviders.split(',').collect{ ':gate-' + it.toLowerCase() }
include 'gate-file'

0 comments on commit 46e20a9

Please sign in to comment.