Skip to content

Commit

Permalink
Merge pull request #241 from ttomsu/google-new-user
Browse files Browse the repository at this point in the history
Makes anonymous principal's allowedAccounts updated periodically
  • Loading branch information
Travis Tomsu committed Jun 6, 2016
2 parents c763d21 + 52c01a3 commit 7c0ed2c
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 12 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ allprojects {
apply plugin: 'groovy'

spinnaker {
dependenciesVersion = "0.36.0"
dependenciesVersion = "0.39.0"
}

configurations.all {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,58 @@
package com.netflix.spinnaker.gate.security.anonymous

import com.netflix.spinnaker.gate.security.SpinnakerAuthConfig
import com.netflix.spinnaker.gate.services.AccountsService
import com.netflix.spinnaker.security.User
import groovy.util.logging.Slf4j
import org.apache.commons.lang.exception.ExceptionUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity

import java.util.concurrent.CopyOnWriteArrayList

@ConditionalOnMissingBean(annotation = SpinnakerAuthConfig.class)
@Configuration
@Slf4j
@EnableWebMvcSecurity
class AnonymousConfig extends WebSecurityConfigurerAdapter {
static String key = "spinnaker-anonymous"
static String defaultEmail = "anonymous"

@Autowired
AccountsService accountsService

List<String> anonymousAllowedAccounts = new CopyOnWriteArrayList<>()

void configure(HttpSecurity http) {
def principal = new User(
email: defaultEmail,
roles: ["anonymous"],
allowedAccounts: []
)
// Not using the ImmutableUser version in order to update allowedAccounts.
def principal = new User(email: defaultEmail, allowedAccounts: anonymousAllowedAccounts)

http.anonymous()
http
.anonymous()
.key(key)
.authorities("anonymous")
.principal(principal)
.and()
.csrf().disable()
.csrf()
.disable()
}

@Scheduled(fixedDelay = 60000L)
void updateAnonymousAccounts() {
try {
def newAnonAccounts = accountsService.getAllowedAccounts([]) ?: []

def toAdd = newAnonAccounts - anonymousAllowedAccounts
def toRemove = anonymousAllowedAccounts - newAnonAccounts

anonymousAllowedAccounts.removeAll(toRemove)
anonymousAllowedAccounts.addAll(toAdd)
} catch (Exception e) {
log.warn(ExceptionUtils.getStackTrace(e))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class OAuth2SsoConfig extends OAuth2SsoConfigurerAdapter {
lastName: details[userInfoMapping.lastName] as String,
allowedAccounts: accountsService.getAllowedAccounts(roles),
roles: roles,
username: username)
username: username).asImmutable()

PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(
spinnakerUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class SamlSsoConfig extends WebSecurityConfigurerAdapter {
lastName: attributes[userAttributeMapping.lastName]?.get(0),
roles: roles,
allowedAccounts: accountsService.getAllowedAccounts(roles),
username: attributes[userAttributeMapping.username] ?: email)
username: attributes[userAttributeMapping.username] ?: email).asImmutable()
}

Set<String> extractRoles(String email,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class X509AuthenticationUserDetailsService implements AuthenticationUserDetailsS
email: email,
allowedAccounts: accountsService.getAllowedAccounts(roles),
roles: roles
)
).asImmutable()
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2016 Google, Inc.
*
* 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
*
* http://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.netflix.spinnaker.gate.security.anonymous

import com.netflix.spinnaker.gate.services.AccountsService
import spock.lang.Specification
import spock.lang.Subject
import spock.lang.Unroll

import java.util.concurrent.CopyOnWriteArrayList

class AnonymousConfigSpec extends Specification {

@Unroll
def "should update accounts correctly"() {
setup:
AccountsService accountsService = Mock(AccountsService) {
getAllowedAccounts(*_) >> newAccounts
}
@Subject
AnonymousConfig config = new AnonymousConfig(
anonymousAllowedAccounts: new CopyOnWriteArrayList<String>(oldAccounts),
accountsService: accountsService
)


when:
config.updateAnonymousAccounts()

then:
config.anonymousAllowedAccounts == newAccounts

where:
oldAccounts || newAccounts
[] || ["a"]
["a"] || ["a", "b"]
["a"] || ["b"]
["a"] || []
}
}

0 comments on commit 7c0ed2c

Please sign in to comment.