Skip to content

Commit

Permalink
fix(clouddriver): Use application owner as user in EphemeralServerGro…
Browse files Browse the repository at this point in the history
…upsPoller cleanup executions (#3728)
  • Loading branch information
robzienert committed Jun 9, 2020
1 parent f7ecf3f commit fb81e7e
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import static retrofit.Endpoints.newFixedEndpoint
"com.netflix.spinnaker.orca.kato.tasks"
])
@CompileStatic
@EnableConfigurationProperties(CloudDriverConfigurationProperties)
@EnableConfigurationProperties([CloudDriverConfigurationProperties, PollerConfigurationProperties])
@Slf4j
class CloudDriverConfiguration {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2020 Netflix, 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.orca.clouddriver.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

@Data
@ConfigurationProperties("poller")
public class PollerConfigurationProperties {

@NestedConfigurationProperty
private EphemeralServerGroupsPollerProperties ephemeralServerGroupsPoller =
new EphemeralServerGroupsPollerProperties();

@Data
public static class EphemeralServerGroupsPollerProperties {

/**
* If defined, this username will be used for authorization of the executions created by the
* poller.
*
* <p>If left undefined, the application owner email will be used.
*/
private String username;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@
import com.netflix.spectator.api.Counter;
import com.netflix.spectator.api.Registry;
import com.netflix.spinnaker.kork.core.RetrySupport;
import com.netflix.spinnaker.kork.exceptions.SystemException;
import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType;
import com.netflix.spinnaker.orca.clouddriver.OortService;
import com.netflix.spinnaker.orca.clouddriver.config.PollerConfigurationProperties;
import com.netflix.spinnaker.orca.front50.Front50Service;
import com.netflix.spinnaker.orca.front50.model.Application;
import com.netflix.spinnaker.orca.notifications.AbstractPollingNotificationAgent;
import com.netflix.spinnaker.orca.notifications.NotificationClusterLock;
import com.netflix.spinnaker.orca.pipeline.ExecutionLauncher;
import com.netflix.spinnaker.security.AuthenticatedRequest;
import com.netflix.spinnaker.security.User;
import groovy.util.logging.Slf4j;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
Expand All @@ -42,7 +45,9 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import retrofit.RetrofitError;

@Slf4j
@Component
Expand All @@ -54,6 +59,8 @@ public class EphemeralServerGroupsPoller extends AbstractPollingNotificationAgen
private final OortService oortService;
private final RetrySupport retrySupport;
private final ExecutionLauncher executionLauncher;
private final Front50Service front50Service;
private final PollerConfigurationProperties pollerConfigurationProperties;

private final PollerSupport pollerSupport;

Expand All @@ -67,13 +74,17 @@ public EphemeralServerGroupsPoller(
OortService oortService,
RetrySupport retrySupport,
Registry registry,
ExecutionLauncher executionLauncher) {
ExecutionLauncher executionLauncher,
Front50Service front50Service,
PollerConfigurationProperties pollerConfigurationProperties) {
super(notificationClusterLock);

this.objectMapper = objectMapper;
this.oortService = oortService;
this.retrySupport = retrySupport;
this.executionLauncher = executionLauncher;
this.front50Service = front50Service;
this.pollerConfigurationProperties = pollerConfigurationProperties;

this.pollerSupport = new PollerSupport(objectMapper, retrySupport, oortService);

Expand Down Expand Up @@ -128,16 +139,29 @@ protected void tick() {
Map<String, Object> cleanupOperation = buildCleanupOperation(ephemeralServerGroupTag, jobs);
log.info((String) cleanupOperation.get("name"));

User systemUser = new User();
systemUser.setUsername("spinnaker");
systemUser.setAllowedAccounts(Collections.singletonList(ephemeralServerGroupTag.account));

AuthenticatedRequest.propagate(
String taskUser =
Optional.ofNullable(
pollerConfigurationProperties.getEphemeralServerGroupsPoller().getUsername())
.orElseGet(
() ->
getApplication(ephemeralServerGroupTag.application)
.map(it -> it.email)
.orElseGet(
() -> {
log.warn(
"Failed to find application owner for server group '{}', "
+ "will use static 'spinnaker' user as fallback.",
ephemeralServerGroupTag.serverGroup);
return "spinnaker";
}));

AuthenticatedRequest.runAs(
taskUser,
Collections.singletonList(ephemeralServerGroupTag.account),
() ->
executionLauncher.start(
ExecutionType.ORCHESTRATION,
objectMapper.writeValueAsString(cleanupOperation)),
systemUser)
objectMapper.writeValueAsString(cleanupOperation)))
.call();

triggeredCounter.increment();
Expand Down Expand Up @@ -233,6 +257,17 @@ private Map<String, Object> buildDestroyServerGroupOperation(
return operation;
}

private Optional<Application> getApplication(String applicationName) {
try {
return Optional.of(front50Service.get(applicationName));
} catch (RetrofitError e) {
if (e.getResponse().getStatus() == HttpStatus.NOT_FOUND.value()) {
return Optional.empty();
}
throw new SystemException(format("Failed to retrieve application '%s'", applicationName), e);
}
}

private static class EphemeralServerGroupTag {
public String id;

Expand Down

0 comments on commit fb81e7e

Please sign in to comment.